summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/system-current.txt5
-rw-r--r--media/java/android/media/tv/TvInputHardwareInfo.java54
-rw-r--r--media/java/android/media/tv/TvInputManager.java8
-rw-r--r--services/core/java/com/android/server/tv/TvInputHardwareManager.java62
-rw-r--r--services/core/java/com/android/server/tv/TvInputManagerService.java18
-rw-r--r--services/core/jni/com_android_server_tv_TvInputHal.cpp8
6 files changed, 119 insertions, 36 deletions
diff --git a/api/system-current.txt b/api/system-current.txt
index 7c63e774e079..32fc2880ba67 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -26305,11 +26305,15 @@ package android.media.tv {
method public int describeContents();
method public java.lang.String getAudioAddress();
method public int getAudioType();
+ method public int getCableConnectionStatus();
method public int getDeviceId();
method public int getHdmiPortId();
method public int getType();
method public void readFromParcel(android.os.Parcel);
method public void writeToParcel(android.os.Parcel, int);
+ field public static final int CABLE_CONNECTION_STATUS_CONNECTED = 1; // 0x1
+ field public static final int CABLE_CONNECTION_STATUS_DISCONNECTED = 2; // 0x2
+ field public static final int CABLE_CONNECTION_STATUS_UNKNOWN = 0; // 0x0
field public static final android.os.Parcelable.Creator<android.media.tv.TvInputHardwareInfo> CREATOR;
field public static final int TV_INPUT_TYPE_COMPONENT = 6; // 0x6
field public static final int TV_INPUT_TYPE_COMPOSITE = 3; // 0x3
@@ -26328,6 +26332,7 @@ package android.media.tv {
method public android.media.tv.TvInputHardwareInfo.Builder audioAddress(java.lang.String);
method public android.media.tv.TvInputHardwareInfo.Builder audioType(int);
method public android.media.tv.TvInputHardwareInfo build();
+ method public android.media.tv.TvInputHardwareInfo.Builder cableConnectionStatus(int);
method public android.media.tv.TvInputHardwareInfo.Builder deviceId(int);
method public android.media.tv.TvInputHardwareInfo.Builder hdmiPortId(int);
method public android.media.tv.TvInputHardwareInfo.Builder type(int);
diff --git a/media/java/android/media/tv/TvInputHardwareInfo.java b/media/java/android/media/tv/TvInputHardwareInfo.java
index 51fa036a77c4..957c5820838e 100644
--- a/media/java/android/media/tv/TvInputHardwareInfo.java
+++ b/media/java/android/media/tv/TvInputHardwareInfo.java
@@ -16,11 +16,15 @@
package android.media.tv;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import android.annotation.IntDef;
import android.annotation.SystemApi;
import android.media.AudioManager;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;
+import java.lang.annotation.Retention;
/**
* Simple container for information about TV input hardware.
@@ -44,6 +48,28 @@ public final class TvInputHardwareInfo implements Parcelable {
public static final int TV_INPUT_TYPE_HDMI = 9;
public static final int TV_INPUT_TYPE_DISPLAY_PORT = 10;
+ /** @hide */
+ @Retention(SOURCE)
+ @IntDef({CABLE_CONNECTION_STATUS_UNKNOWN, CABLE_CONNECTION_STATUS_CONNECTED,
+ CABLE_CONNECTION_STATUS_DISCONNECTED})
+ public @interface CableConnectionStatus {}
+
+ // Match hardware/interfaces/tv/input/1.0/types.hal
+ /**
+ * The hardware is unsure about the connection status or does not support cable detection.
+ */
+ public static final int CABLE_CONNECTION_STATUS_UNKNOWN = 0;
+
+ /**
+ * Cable is connected to the hardware.
+ */
+ public static final int CABLE_CONNECTION_STATUS_CONNECTED = 1;
+
+ /**
+ * Cable is disconnected to the hardware.
+ */
+ public static final int CABLE_CONNECTION_STATUS_DISCONNECTED = 2;
+
public static final Parcelable.Creator<TvInputHardwareInfo> CREATOR =
new Parcelable.Creator<TvInputHardwareInfo>() {
@Override
@@ -69,6 +95,8 @@ public final class TvInputHardwareInfo implements Parcelable {
private int mAudioType;
private String mAudioAddress;
private int mHdmiPortId;
+ @CableConnectionStatus
+ private int mCableConnectionStatus;
private TvInputHardwareInfo() {
}
@@ -96,6 +124,19 @@ public final class TvInputHardwareInfo implements Parcelable {
return mHdmiPortId;
}
+ /**
+ * Gets the cable connection status of the hardware.
+ *
+ * @return {@code CABLE_CONNECTION_STATUS_CONNECTED} if cable is connected.
+ * {@code CABLE_CONNECTION_STATUS_DISCONNECTED} if cable is disconnected.
+ * {@code CABLE_CONNECTION_STATUS_UNKNOWN} if the hardware is unsure about the
+ * connection status or does not support cable detection.
+ */
+ @CableConnectionStatus
+ public int getCableConnectionStatus() {
+ return mCableConnectionStatus;
+ }
+
@Override
public String toString() {
StringBuilder b = new StringBuilder(128);
@@ -106,6 +147,7 @@ public final class TvInputHardwareInfo implements Parcelable {
if (mType == TV_INPUT_TYPE_HDMI) {
b.append(", hdmi_port=").append(mHdmiPortId);
}
+ b.append(", cable_connection_status=").append(mCableConnectionStatus);
b.append("}");
return b.toString();
}
@@ -125,6 +167,7 @@ public final class TvInputHardwareInfo implements Parcelable {
if (mType == TV_INPUT_TYPE_HDMI) {
dest.writeInt(mHdmiPortId);
}
+ dest.writeInt(mCableConnectionStatus);
}
public void readFromParcel(Parcel source) {
@@ -135,6 +178,7 @@ public final class TvInputHardwareInfo implements Parcelable {
if (mType == TV_INPUT_TYPE_HDMI) {
mHdmiPortId = source.readInt();
}
+ mCableConnectionStatus = source.readInt();
}
public static final class Builder {
@@ -143,6 +187,7 @@ public final class TvInputHardwareInfo implements Parcelable {
private int mAudioType = AudioManager.DEVICE_NONE;
private String mAudioAddress = "";
private Integer mHdmiPortId = null;
+ private Integer mCableConnectionStatus = CABLE_CONNECTION_STATUS_UNKNOWN;
public Builder() {
}
@@ -172,6 +217,14 @@ public final class TvInputHardwareInfo implements Parcelable {
return this;
}
+ /**
+ * Sets cable connection status.
+ */
+ public Builder cableConnectionStatus(@CableConnectionStatus int cableConnectionStatus) {
+ mCableConnectionStatus = cableConnectionStatus;
+ return this;
+ }
+
public TvInputHardwareInfo build() {
if (mDeviceId == null || mType == null) {
throw new UnsupportedOperationException();
@@ -191,6 +244,7 @@ public final class TvInputHardwareInfo implements Parcelable {
if (mHdmiPortId != null) {
info.mHdmiPortId = mHdmiPortId;
}
+ info.mCableConnectionStatus = mCableConnectionStatus;
return info;
}
}
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index 1eae8db60833..09b2050b1b1a 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -224,9 +224,8 @@ public final class TvInputManager {
* {@link TvInputCallback#onInputStateChanged(String, int)}: The input source is connected.
*
* <p>This state indicates that a source device is connected to the input port and is in the
- * normal operation mode. It is mostly relevant to hardware inputs such as HDMI input. This is
- * the default state for any hardware inputs where their states are unknown. Non-hardware inputs
- * are considered connected all the time.
+ * normal operation mode. It is mostly relevant to hardware inputs such as HDMI input.
+ * Non-hardware inputs are considered connected all the time.
*/
public static final int INPUT_STATE_CONNECTED = 0;
@@ -236,7 +235,8 @@ public final class TvInputManager {
* in standby mode.
*
* <p>This state indicates that a source device is connected to the input port but is in standby
- * mode. It is mostly relevant to hardware inputs such as HDMI input.
+ * or low power mode. It is mostly relevant to hardware inputs such as HDMI input and Component
+ * inputs.
*/
public static final int INPUT_STATE_CONNECTED_STANDBY = 1;
diff --git a/services/core/java/com/android/server/tv/TvInputHardwareManager.java b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
index 8043c651751c..08eca73e1702 100644
--- a/services/core/java/com/android/server/tv/TvInputHardwareManager.java
+++ b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
@@ -17,6 +17,7 @@
package com.android.server.tv;
import static android.media.tv.TvInputManager.INPUT_STATE_CONNECTED;
+import static android.media.tv.TvInputManager.INPUT_STATE_CONNECTED_STANDBY;
import static android.media.tv.TvInputManager.INPUT_STATE_DISCONNECTED;
import android.content.BroadcastReceiver;
@@ -109,7 +110,6 @@ class TvInputHardwareManager implements TvInputHal.Callback {
private int mCurrentIndex = 0;
private int mCurrentMaxIndex = 0;
- // TODO: Should handle STANDBY case.
private final SparseBooleanArray mHdmiStateMap = new SparseBooleanArray();
private final List<Message> mPendingHdmiDeviceEvents = new LinkedList<>();
@@ -209,11 +209,13 @@ class TvInputHardwareManager implements TvInputHal.Callback {
+ deviceId);
return;
}
+ int previousConfigsLength = connection.getConfigsLengthLocked();
connection.updateConfigsLocked(configs);
String inputId = mHardwareInputIdMap.get(deviceId);
- if (inputId != null) {
+ if (inputId != null
+ && (previousConfigsLength == 0) != (connection.getConfigsLengthLocked() == 0)) {
mHandler.obtainMessage(ListenerHandler.STATE_CHANGED,
- convertConnectedToState(configs.length > 0), 0, inputId).sendToTarget();
+ connection.getInputStateLocked(), 0, inputId).sendToTarget();
}
ITvInputHardwareCallback callback = connection.getCallbackLocked();
if (callback != null) {
@@ -263,14 +265,6 @@ class TvInputHardwareManager implements TvInputHal.Callback {
|| connectionCallingUid != callingUid || connectionResolvedUserId != resolvedUserId;
}
- private int convertConnectedToState(boolean connected) {
- if (connected) {
- return INPUT_STATE_CONNECTED;
- } else {
- return INPUT_STATE_DISCONNECTED;
- }
- }
-
public void addHardwareInput(int deviceId, TvInputInfo info) {
synchronized (mLock) {
String oldInputId = mHardwareInputIdMap.get(deviceId);
@@ -293,18 +287,22 @@ class TvInputHardwareManager implements TvInputHal.Callback {
}
String inputId = mHardwareInputIdMap.get(hardwareInfo.getDeviceId());
if (inputId != null && inputId.equals(info.getId())) {
- mHandler.obtainMessage(ListenerHandler.STATE_CHANGED,
- convertConnectedToState(mHdmiStateMap.valueAt(i)), 0,
- inputId).sendToTarget();
+ // No HDMI hotplug does not necessarily mean disconnected, as old devices may
+ // not report hotplug state correctly. Using INPUT_STATE_CONNECTED_STANDBY to
+ // denote unknown state.
+ int state = mHdmiStateMap.valueAt(i)
+ ? INPUT_STATE_CONNECTED
+ : INPUT_STATE_CONNECTED_STANDBY;
+ mHandler.obtainMessage(
+ ListenerHandler.STATE_CHANGED, state, 0, inputId).sendToTarget();
return;
}
}
- // For the rest of the devices, we can tell by the number of available streams.
+ // For the rest of the devices, we can tell by the cable connection status.
Connection connection = mConnections.get(deviceId);
if (connection != null) {
mHandler.obtainMessage(ListenerHandler.STATE_CHANGED,
- convertConnectedToState(connection.getConfigsLocked().length > 0), 0,
- info.getId()).sendToTarget();
+ connection.getInputStateLocked(), 0, info.getId()).sendToTarget();
}
}
}
@@ -716,6 +714,26 @@ class TvInputHardwareManager implements TvInputHal.Callback {
+ ", mResolvedUserId: " + mResolvedUserId
+ " }";
}
+
+ private int getConfigsLengthLocked() {
+ return mConfigs == null ? 0 : mConfigs.length;
+ }
+
+ private int getInputStateLocked() {
+ int configsLength = getConfigsLengthLocked();
+ if (configsLength > 0) {
+ return INPUT_STATE_CONNECTED;
+ }
+ switch (mHardwareInfo.getCableConnectionStatus()) {
+ case TvInputHardwareInfo.CABLE_CONNECTION_STATUS_CONNECTED:
+ return INPUT_STATE_CONNECTED;
+ case TvInputHardwareInfo.CABLE_CONNECTION_STATUS_DISCONNECTED:
+ return INPUT_STATE_DISCONNECTED;
+ case TvInputHardwareInfo.CABLE_CONNECTION_STATUS_UNKNOWN:
+ default:
+ return INPUT_STATE_CONNECTED_STANDBY;
+ }
+ }
}
private class TvInputHardwareImpl extends ITvInputHardware.Stub {
@@ -1199,8 +1217,14 @@ class TvInputHardwareManager implements TvInputHal.Callback {
if (inputId == null) {
return;
}
- mHandler.obtainMessage(ListenerHandler.STATE_CHANGED,
- convertConnectedToState(event.isConnected()), 0, inputId).sendToTarget();
+ // No HDMI hotplug does not necessarily mean disconnected, as old devices may
+ // not report hotplug state correctly. Using INPUT_STATE_CONNECTED_STANDBY to
+ // denote unknown state.
+ int state = event.isConnected()
+ ? INPUT_STATE_CONNECTED
+ : INPUT_STATE_CONNECTED_STANDBY;
+ mHandler.obtainMessage(
+ ListenerHandler.STATE_CHANGED, state, 0, inputId).sendToTarget();
}
}
}
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index e0261304f0f0..52763a179e73 100644
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -288,7 +288,7 @@ public final class TvInputManagerService extends SystemService {
userState.serviceStateMap.put(component, serviceState);
updateServiceConnectionLocked(component, userId);
} else {
- inputList.addAll(serviceState.hardwareInputList);
+ inputList.addAll(serviceState.hardwareInputMap.values());
}
} else {
try {
@@ -2105,7 +2105,7 @@ public final class TvInputManagerService extends SystemService {
private final ServiceConnection connection;
private final ComponentName component;
private final boolean isHardware;
- private final List<TvInputInfo> hardwareInputList = new ArrayList<>();
+ private final Map<String, TvInputInfo> hardwareInputMap = new HashMap<>();
private ITvInputService service;
private ServiceCallback callback;
@@ -2216,7 +2216,7 @@ public final class TvInputManagerService extends SystemService {
}
if (serviceState.isHardware) {
- serviceState.hardwareInputList.clear();
+ serviceState.hardwareInputMap.clear();
for (TvInputHardwareInfo hardware : mTvInputHardwareManager.getHardwareList()) {
try {
serviceState.service.notifyHardwareAdded(hardware);
@@ -2283,7 +2283,7 @@ public final class TvInputManagerService extends SystemService {
private void addHardwareInputLocked(TvInputInfo inputInfo) {
ServiceState serviceState = getServiceStateLocked(mComponent, mUserId);
- serviceState.hardwareInputList.add(inputInfo);
+ serviceState.hardwareInputMap.put(inputInfo.getId(), inputInfo);
buildTvInputListLocked(mUserId, null);
}
@@ -2309,15 +2309,7 @@ public final class TvInputManagerService extends SystemService {
ensureHardwarePermission();
synchronized (mLock) {
ServiceState serviceState = getServiceStateLocked(mComponent, mUserId);
- boolean removed = false;
- for (Iterator<TvInputInfo> it = serviceState.hardwareInputList.iterator();
- it.hasNext(); ) {
- if (it.next().getId().equals(inputId)) {
- it.remove();
- removed = true;
- break;
- }
- }
+ boolean removed = serviceState.hardwareInputMap.remove(inputId) != null;
if (removed) {
buildTvInputListLocked(mUserId, null);
mTvInputHardwareManager.removeHardwareInput(inputId);
diff --git a/services/core/jni/com_android_server_tv_TvInputHal.cpp b/services/core/jni/com_android_server_tv_TvInputHal.cpp
index 9f528b1bec6a..b4333508a84a 100644
--- a/services/core/jni/com_android_server_tv_TvInputHal.cpp
+++ b/services/core/jni/com_android_server_tv_TvInputHal.cpp
@@ -81,6 +81,7 @@ static struct {
jmethodID deviceId;
jmethodID type;
jmethodID hdmiPortId;
+ jmethodID cableConnectionStatus;
jmethodID audioType;
jmethodID audioAddress;
jmethodID build;
@@ -469,6 +470,9 @@ void JTvInputHal::onDeviceAvailable(const TvInputDeviceInfo& info) {
builder, gTvInputHardwareInfoBuilderClassInfo.hdmiPortId, info.portId);
}
env->CallObjectMethod(
+ builder, gTvInputHardwareInfoBuilderClassInfo.cableConnectionStatus,
+ info.cableConnectionStatus);
+ env->CallObjectMethod(
builder, gTvInputHardwareInfoBuilderClassInfo.audioType, info.audioType);
if (info.audioType != AudioDevice::NONE) {
uint8_t buffer[info.audioAddress.size() + 1];
@@ -743,6 +747,10 @@ int register_android_server_tv_TvInputHal(JNIEnv* env) {
gTvInputHardwareInfoBuilderClassInfo.clazz,
"hdmiPortId", "(I)Landroid/media/tv/TvInputHardwareInfo$Builder;");
GET_METHOD_ID(
+ gTvInputHardwareInfoBuilderClassInfo.cableConnectionStatus,
+ gTvInputHardwareInfoBuilderClassInfo.clazz,
+ "cableConnectionStatus", "(I)Landroid/media/tv/TvInputHardwareInfo$Builder;");
+ GET_METHOD_ID(
gTvInputHardwareInfoBuilderClassInfo.audioType,
gTvInputHardwareInfoBuilderClassInfo.clazz,
"audioType", "(I)Landroid/media/tv/TvInputHardwareInfo$Builder;");