summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--media/java/android/media/tv/ITvInputManager.aidl5
-rw-r--r--media/java/android/media/tv/ITvInputService.aidl7
-rw-r--r--media/java/android/media/tv/ITvInputServiceCallback.aidl3
-rw-r--r--media/java/android/media/tv/TvInputInfo.java17
-rw-r--r--media/java/android/media/tv/TvInputService.java111
-rw-r--r--services/core/java/com/android/server/tv/TvInputHardwareManager.java127
-rw-r--r--services/core/java/com/android/server/tv/TvInputManagerService.java122
7 files changed, 273 insertions, 119 deletions
diff --git a/media/java/android/media/tv/ITvInputManager.aidl b/media/java/android/media/tv/ITvInputManager.aidl
index ccfc484..8e64693 100644
--- a/media/java/android/media/tv/ITvInputManager.aidl
+++ b/media/java/android/media/tv/ITvInputManager.aidl
@@ -64,11 +64,6 @@ interface ITvInputManager {
// For TV input hardware binding
List<TvInputHardwareInfo> getHardwareList();
- /*
- * All TvInputServices which want to use hardware must call this method on
- * BOOT_COMPLETE.
- */
- void registerTvInputInfo(in TvInputInfo info, int deviceId);
ITvInputHardware acquireTvInputHardware(int deviceId, in ITvInputHardwareCallback callback,
in TvInputInfo info, int userId);
void releaseTvInputHardware(int deviceId, in ITvInputHardware hardware, int userId);
diff --git a/media/java/android/media/tv/ITvInputService.aidl b/media/java/android/media/tv/ITvInputService.aidl
index 158223a..651669b 100644
--- a/media/java/android/media/tv/ITvInputService.aidl
+++ b/media/java/android/media/tv/ITvInputService.aidl
@@ -16,6 +16,7 @@
package android.media.tv;
+import android.hardware.hdmi.HdmiCecDeviceInfo;
import android.media.tv.ITvInputServiceCallback;
import android.media.tv.ITvInputSessionCallback;
import android.media.tv.TvInputHardwareInfo;
@@ -32,6 +33,8 @@ oneway interface ITvInputService {
in String inputId);
// For hardware TvInputService
- void notifyHardwareAdded(in TvInputHardwareInfo info);
- void notifyHardwareRemoved(int deviceId);
+ void notifyHardwareAdded(in TvInputHardwareInfo hardwareInfo);
+ void notifyHardwareRemoved(in TvInputHardwareInfo hardwareInfo);
+ void notifyHdmiCecDeviceAdded(in HdmiCecDeviceInfo cecDeviceInfo);
+ void notifyHdmiCecDeviceRemoved(in HdmiCecDeviceInfo cecDeviceInfo);
}
diff --git a/media/java/android/media/tv/ITvInputServiceCallback.aidl b/media/java/android/media/tv/ITvInputServiceCallback.aidl
index 287da71..df648e7 100644
--- a/media/java/android/media/tv/ITvInputServiceCallback.aidl
+++ b/media/java/android/media/tv/ITvInputServiceCallback.aidl
@@ -24,6 +24,7 @@ import android.media.tv.TvInputInfo;
* @hide
*/
oneway interface ITvInputServiceCallback {
- void addTvInput(in TvInputInfo inputInfo);
+ void addHardwareTvInput(in int deviceID, in TvInputInfo inputInfo);
+ void addHdmiCecTvInput(in int logicalAddress, in TvInputInfo inputInfo);
void removeTvInput(in String inputId);
}
diff --git a/media/java/android/media/tv/TvInputInfo.java b/media/java/android/media/tv/TvInputInfo.java
index 77cfc32..86fd4ff 100644
--- a/media/java/android/media/tv/TvInputInfo.java
+++ b/media/java/android/media/tv/TvInputInfo.java
@@ -122,7 +122,8 @@ public final class TvInputInfo implements Parcelable {
public static TvInputInfo createTvInputInfo(Context context, ResolveInfo service)
throws XmlPullParserException, IOException {
return createTvInputInfo(context, service, generateInputIdForComponentName(
- new ComponentName(service.serviceInfo.packageName, service.serviceInfo.name)));
+ new ComponentName(service.serviceInfo.packageName, service.serviceInfo.name)),
+ null);
}
/**
@@ -134,10 +135,10 @@ public final class TvInputInfo implements Parcelable {
* @hide
*/
public static TvInputInfo createTvInputInfo(Context context, ResolveInfo service,
- HdmiCecDeviceInfo cecInfo) throws XmlPullParserException, IOException {
+ HdmiCecDeviceInfo cecInfo, String parentId) throws XmlPullParserException, IOException {
return createTvInputInfo(context, service, generateInputIdForHdmiCec(
new ComponentName(service.serviceInfo.packageName, service.serviceInfo.name),
- cecInfo));
+ cecInfo), parentId);
}
/**
@@ -152,11 +153,11 @@ public final class TvInputInfo implements Parcelable {
TvInputHardwareInfo hardwareInfo) throws XmlPullParserException, IOException {
return createTvInputInfo(context, service, generateInputIdForHardware(
new ComponentName(service.serviceInfo.packageName, service.serviceInfo.name),
- hardwareInfo));
+ hardwareInfo), null);
}
private static TvInputInfo createTvInputInfo(Context context, ResolveInfo service,
- String id) throws XmlPullParserException, IOException {
+ String id, String parentId) throws XmlPullParserException, IOException {
ServiceInfo si = service.serviceInfo;
PackageManager pm = context.getPackageManager();
XmlResourceParser parser = null;
@@ -181,7 +182,7 @@ public final class TvInputInfo implements Parcelable {
"Meta-data does not start with tv-input-service tag in " + si.name);
}
- TvInputInfo input = new TvInputInfo(context, service, id, null);
+ TvInputInfo input = new TvInputInfo(service, id, parentId);
TypedArray sa = res.obtainAttributes(attrs,
com.android.internal.R.styleable.TvInputService);
input.mSetupActivity = sa.getString(
@@ -222,9 +223,8 @@ public final class TvInputInfo implements Parcelable {
* @param id ID of this TV input. Should be generated via generateInputId*().
* @param parentId ID of this TV input's parent input. {@code null} if none exists.
*/
- private TvInputInfo(Context context, ResolveInfo service, String id, String parentId) {
+ private TvInputInfo(ResolveInfo service, String id, String parentId) {
mService = service;
- ServiceInfo si = service.serviceInfo;
mId = id;
mParentId = parentId;
}
@@ -429,7 +429,6 @@ public final class TvInputInfo implements Parcelable {
/**
* Used to make this class parcelable.
- *
* @hide
*/
public static final Parcelable.Creator<TvInputInfo> CREATOR =
diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java
index 39e7f9d..db07b65 100644
--- a/media/java/android/media/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -23,6 +23,7 @@ import android.content.Context;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.graphics.Rect;
+import android.hardware.hdmi.HdmiCecDeviceInfo;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
@@ -121,21 +122,32 @@ public abstract class TvInputService extends Service {
@Override
public void notifyHardwareAdded(TvInputHardwareInfo hardwareInfo) {
- mHandler.obtainMessage(ServiceHandler.DO_ADD_TV_INPUT_FROM_HARDWARE,
+ mHandler.obtainMessage(ServiceHandler.DO_ADD_HARDWARE_TV_INPUT,
hardwareInfo).sendToTarget();
}
@Override
- public void notifyHardwareRemoved(int deviceId) {
- mHandler.obtainMessage(ServiceHandler.DO_REMOVE_TV_INPUT_FROM_HARDWARE,
- deviceId, 0).sendToTarget();
+ public void notifyHardwareRemoved(TvInputHardwareInfo hardwareInfo) {
+ mHandler.obtainMessage(ServiceHandler.DO_REMOVE_HARDWARE_TV_INPUT,
+ hardwareInfo).sendToTarget();
+ }
+
+ @Override
+ public void notifyHdmiCecDeviceAdded(HdmiCecDeviceInfo cecDeviceInfo) {
+ mHandler.obtainMessage(ServiceHandler.DO_ADD_HDMI_CEC_TV_INPUT,
+ cecDeviceInfo).sendToTarget();
+ }
+
+ @Override
+ public void notifyHdmiCecDeviceRemoved(HdmiCecDeviceInfo cecDeviceInfo) {
+ mHandler.obtainMessage(ServiceHandler.DO_REMOVE_HDMI_CEC_TV_INPUT,
+ cecDeviceInfo).sendToTarget();
}
};
}
/**
* Get the number of callbacks that are registered.
- *
* @hide
*/
@VisibleForTesting
@@ -153,11 +165,11 @@ public abstract class TvInputService extends Service {
public abstract Session onCreateSession(String inputId);
/**
- * Returns a new TvInputInfo object if this service is responsible for {@code hardwareInfo};
- * otherwise, return {@code null}. Override to modify default behavior of ignoring all input.
- *
- * @param hardwareInfo TvInputHardwareInfo object just added.
+ * Returns a new {@link TvInputInfo} object if this service is responsible for
+ * {@code hardwareInfo}; otherwise, return {@code null}. Override to modify default behavior of
+ * ignoring all hardware input.
*
+ * @param hardwareInfo {@link TvInputHardwareInfo} object just added.
* @hide
*/
@SystemApi
@@ -167,12 +179,40 @@ public abstract class TvInputService extends Service {
/**
* Returns the input ID for {@code deviceId} if it is handled by this service;
- * otherwise, return {@code null}. Override to modify default behavior of ignoring all input.
+ * otherwise, return {@code null}. Override to modify default behavior of ignoring all hardware
+ * input.
*
+ * @param hardwareInfo {@link TvInputHardwareInfo} object just removed.
* @hide
*/
@SystemApi
- public String onHardwareRemoved(int deviceId) {
+ public String onHardwareRemoved(TvInputHardwareInfo hardwareInfo) {
+ return null;
+ }
+
+ /**
+ * Returns a new {@link TvInputInfo} object if this service is responsible for
+ * {@code cecDeviceInfo}; otherwise, return {@code null}. Override to modify default behavior
+ * of ignoring all HDMI CEC logical input device.
+ *
+ * @param cecDeviceInfo {@link HdmiCecDeviceInfo} object just added.
+ * @hide
+ */
+ @SystemApi
+ public TvInputInfo onHdmiCecDeviceAdded(HdmiCecDeviceInfo cecDeviceInfo) {
+ return null;
+ }
+
+ /**
+ * Returns the input ID for {@code logicalAddress} if it is handled by this service;
+ * otherwise, return {@code null}. Override to modify default behavior of ignoring all HDMI CEC
+ * logical input device.
+ *
+ * @param cecDeviceInfo {@link HdmiCecDeviceInfo} object just removed.
+ * @hide
+ */
+ @SystemApi
+ public String onHdmiCecDeviceRemoved(HdmiCecDeviceInfo cecDeviceInfo) {
return null;
}
@@ -899,14 +939,29 @@ public abstract class TvInputService extends Service {
@SuppressLint("HandlerLeak")
private final class ServiceHandler extends Handler {
private static final int DO_CREATE_SESSION = 1;
- private static final int DO_ADD_TV_INPUT_FROM_HARDWARE = 2;
- private static final int DO_REMOVE_TV_INPUT_FROM_HARDWARE = 3;
+ private static final int DO_ADD_HARDWARE_TV_INPUT = 2;
+ private static final int DO_REMOVE_HARDWARE_TV_INPUT = 3;
+ private static final int DO_ADD_HDMI_CEC_TV_INPUT = 4;
+ private static final int DO_REMOVE_HDMI_CEC_TV_INPUT = 5;
+
+ private void broadcastAddHardwareTvInput(int deviceId, TvInputInfo inputInfo) {
+ int n = mCallbacks.beginBroadcast();
+ for (int i = 0; i < n; ++i) {
+ try {
+ mCallbacks.getBroadcastItem(i).addHardwareTvInput(deviceId, inputInfo);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error while broadcasting: " + e);
+ }
+ }
+ mCallbacks.finishBroadcast();
+ }
- private void broadcastAddTvInput(TvInputInfo inputInfo) {
+ private void broadcastAddHdmiCecTvInput(
+ int logicalAddress, TvInputInfo inputInfo) {
int n = mCallbacks.beginBroadcast();
for (int i = 0; i < n; ++i) {
try {
- mCallbacks.getBroadcastItem(i).addTvInput(inputInfo);
+ mCallbacks.getBroadcastItem(i).addHdmiCecTvInput(logicalAddress, inputInfo);
} catch (RemoteException e) {
Log.e(TAG, "Error while broadcasting: " + e);
}
@@ -951,17 +1006,33 @@ public abstract class TvInputService extends Service {
args.recycle();
return;
}
- case DO_ADD_TV_INPUT_FROM_HARDWARE: {
+ case DO_ADD_HARDWARE_TV_INPUT: {
TvInputHardwareInfo hardwareInfo = (TvInputHardwareInfo) msg.obj;
TvInputInfo inputInfo = onHardwareAdded(hardwareInfo);
if (inputInfo != null) {
- broadcastAddTvInput(inputInfo);
+ broadcastAddHardwareTvInput(hardwareInfo.getDeviceId(), inputInfo);
+ }
+ return;
+ }
+ case DO_REMOVE_HARDWARE_TV_INPUT: {
+ TvInputHardwareInfo hardwareInfo = (TvInputHardwareInfo) msg.obj;
+ String inputId = onHardwareRemoved(hardwareInfo);
+ if (inputId != null) {
+ broadcastRemoveTvInput(inputId);
+ }
+ return;
+ }
+ case DO_ADD_HDMI_CEC_TV_INPUT: {
+ HdmiCecDeviceInfo cecDeviceInfo = (HdmiCecDeviceInfo) msg.obj;
+ TvInputInfo inputInfo = onHdmiCecDeviceAdded(cecDeviceInfo);
+ if (inputInfo != null) {
+ broadcastAddHdmiCecTvInput(cecDeviceInfo.getLogicalAddress(), inputInfo);
}
return;
}
- case DO_REMOVE_TV_INPUT_FROM_HARDWARE: {
- int deviceId = msg.arg1;
- String inputId = onHardwareRemoved(deviceId);
+ case DO_REMOVE_HDMI_CEC_TV_INPUT: {
+ HdmiCecDeviceInfo cecDeviceInfo = (HdmiCecDeviceInfo) msg.obj;
+ String inputId = onHdmiCecDeviceRemoved(cecDeviceInfo);
if (inputId != null) {
broadcastRemoveTvInput(inputId);
}
diff --git a/services/core/java/com/android/server/tv/TvInputHardwareManager.java b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
index 332e426..0a9c646 100644
--- a/services/core/java/com/android/server/tv/TvInputHardwareManager.java
+++ b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
@@ -42,6 +42,7 @@ import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.util.ArrayMap;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
@@ -51,8 +52,10 @@ import android.view.Surface;
import com.android.server.SystemService;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
import java.util.Set;
/**
@@ -65,20 +68,27 @@ import java.util.Set;
*/
class TvInputHardwareManager implements TvInputHal.Callback {
private static final String TAG = TvInputHardwareManager.class.getSimpleName();
+
+ private final Context mContext;
+ private final Listener mListener;
private final TvInputHal mHal = new TvInputHal(this);
private final SparseArray<Connection> mConnections = new SparseArray<Connection>();
private final List<TvInputHardwareInfo> mInfoList = new ArrayList<TvInputHardwareInfo>();
- private final Context mContext;
- private final Listener mListener;
- private final Set<Integer> mActiveHdmiSources = new HashSet<Integer>();
+ /* A map from a device ID to the matching TV input ID. */
+ private final SparseArray<String> mHardwareInputIdMap = new SparseArray<String>();
+ /* A map from a HDMI logical address to the matching TV input ID. */
+ private final SparseArray<String> mHdmiCecInputIdMap = new SparseArray<String>();
+ private final Map<String, TvInputInfo> mInputMap = new ArrayMap<String, TvInputInfo>();
+
private final AudioManager mAudioManager;
- private final SparseBooleanArray mHdmiStateMap = new SparseBooleanArray();
- // TODO: Should handle INACTIVE case.
- private final SparseArray<TvInputInfo> mTvInputInfoMap = new SparseArray<TvInputInfo>();
- private final IHdmiDeviceEventListener mHdmiDeviceEventListener = new HdmiDeviceEventListener();
+ private IHdmiControlService mHdmiControlService;
private final IHdmiHotplugEventListener mHdmiHotplugEventListener =
new HdmiHotplugEventListener();
+ private final IHdmiDeviceEventListener mHdmiDeviceEventListener = new HdmiDeviceEventListener();
private final IHdmiInputChangeListener mHdmiInputChangeListener = new HdmiInputChangeListener();
+ private final Set<Integer> mActiveHdmiSources = new HashSet<Integer>();
+ // TODO: Should handle INACTIVE case.
+ private final SparseBooleanArray mHdmiStateMap = new SparseBooleanArray();
// Calls to mListener should happen here.
private final Handler mHandler = new ListenerHandler();
@@ -94,23 +104,22 @@ class TvInputHardwareManager implements TvInputHal.Callback {
public void onBootPhase(int phase) {
if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
- IHdmiControlService hdmiControlService = IHdmiControlService.Stub.asInterface(
- ServiceManager.getService(Context.HDMI_CONTROL_SERVICE));
- if (hdmiControlService != null) {
+ mHdmiControlService = IHdmiControlService.Stub.asInterface(ServiceManager.getService(
+ Context.HDMI_CONTROL_SERVICE));
+ if (mHdmiControlService != null) {
try {
- hdmiControlService.addHotplugEventListener(mHdmiHotplugEventListener);
- hdmiControlService.addDeviceEventListener(mHdmiDeviceEventListener);
- hdmiControlService.setInputChangeListener(mHdmiInputChangeListener);
+ mHdmiControlService.addHotplugEventListener(mHdmiHotplugEventListener);
+ mHdmiControlService.addDeviceEventListener(mHdmiDeviceEventListener);
+ mHdmiControlService.setInputChangeListener(mHdmiInputChangeListener);
} catch (RemoteException e) {
- Slog.w(TAG, "Error registering listeners to HdmiControlService:" + e);
+ Slog.w(TAG, "Error registering listeners to HdmiControlService:", e);
}
}
}
}
@Override
- public void onDeviceAvailable(
- TvInputHardwareInfo info, TvStreamConfig[] configs) {
+ public void onDeviceAvailable(TvInputHardwareInfo info, TvStreamConfig[] configs) {
synchronized (mLock) {
Connection connection = new Connection(info);
connection.updateConfigsLocked(configs);
@@ -139,8 +148,9 @@ class TvInputHardwareManager implements TvInputHal.Callback {
connection.resetLocked(null, null, null, null, null);
mConnections.remove(deviceId);
buildInfoListLocked();
+ TvInputHardwareInfo info = connection.getHardwareInfoLocked();
mHandler.obtainMessage(
- ListenerHandler.HARDWARE_DEVICE_REMOVED, deviceId, 0).sendToTarget();
+ ListenerHandler.HARDWARE_DEVICE_REMOVED, 0, 0, info).sendToTarget();
}
}
@@ -157,7 +167,7 @@ class TvInputHardwareManager implements TvInputHal.Callback {
try {
connection.getCallbackLocked().onStreamConfigChanged(configs);
} catch (RemoteException e) {
- Slog.e(TAG, "onStreamConfigurationChanged: " + e);
+ Slog.e(TAG, "error in onStreamConfigurationChanged", e);
}
}
}
@@ -168,6 +178,17 @@ class TvInputHardwareManager implements TvInputHal.Callback {
}
}
+ public List<HdmiCecDeviceInfo> getHdmiCecInputDeviceList() {
+ if (mHdmiControlService != null) {
+ try {
+ return mHdmiControlService.getInputDevices();
+ } catch (RemoteException e) {
+ Slog.e(TAG, "error in getHdmiCecInputDeviceList", e);
+ }
+ }
+ return Collections.emptyList();
+ }
+
private boolean checkUidChangedLocked(
Connection connection, int callingUid, int resolvedUserId) {
Integer connectionCallingUid = connection.getCallingUidLocked();
@@ -189,17 +210,19 @@ class TvInputHardwareManager implements TvInputHal.Callback {
}
}
- public void registerTvInputInfo(TvInputInfo info, int deviceId) {
+ public void addHardwareTvInput(int deviceId, TvInputInfo info) {
if (info.getType() == TvInputInfo.TYPE_VIRTUAL) {
throw new IllegalArgumentException("info (" + info + ") has virtual type.");
}
synchronized (mLock) {
- if (mTvInputInfoMap.indexOfKey(deviceId) >= 0) {
+ String oldInputId = mHardwareInputIdMap.get(deviceId);
+ if (oldInputId != null) {
Slog.w(TAG, "Trying to override previous registration: old = "
- + mTvInputInfoMap.get(deviceId) + ":" + deviceId + ", new = "
+ + mInputMap.get(oldInputId) + ":" + deviceId + ", new = "
+ info + ":" + deviceId);
}
- mTvInputInfoMap.put(deviceId, info);
+ mHardwareInputIdMap.put(deviceId, info.getId());
+ mInputMap.put(info.getId(), info);
for (int i = 0; i < mHdmiStateMap.size(); ++i) {
String inputId = findInputIdForHdmiPortLocked(mHdmiStateMap.keyAt(i));
@@ -212,6 +235,41 @@ class TvInputHardwareManager implements TvInputHal.Callback {
}
}
+ public void addHdmiCecTvInput(int logicalAddress, TvInputInfo info) {
+ if (info.getType() != TvInputInfo.TYPE_HDMI) {
+ throw new IllegalArgumentException("info (" + info + ") has non-HDMI type.");
+ }
+ synchronized (mLock) {
+ String parentId = info.getParentId();
+ int parentIndex = mHardwareInputIdMap.indexOfValue(parentId);
+ if (parentIndex < 0 || !parentId.equals(mHardwareInputIdMap.valueAt(parentIndex))) {
+ throw new IllegalArgumentException("info (" + info + ") has invalid parentId.");
+ }
+ String oldInputId = mHdmiCecInputIdMap.get(logicalAddress);
+ if (oldInputId != null) {
+ Slog.w(TAG, "Trying to override previous registration: old = "
+ + mInputMap.get(oldInputId) + ":" + logicalAddress + ", new = "
+ + info + ":" + logicalAddress);
+ }
+ mHdmiCecInputIdMap.put(logicalAddress, info.getId());
+ mInputMap.put(info.getId(), info);
+ }
+ }
+
+ public void removeTvInput(String inputId) {
+ synchronized (mLock) {
+ mInputMap.remove(inputId);
+ int hardwareIndex = mHardwareInputIdMap.indexOfValue(inputId);
+ if (hardwareIndex >= 0) {
+ mHardwareInputIdMap.removeAt(hardwareIndex);
+ }
+ int cecIndex = mHdmiCecInputIdMap.indexOfValue(inputId);
+ if (cecIndex >= 0) {
+ mHdmiCecInputIdMap.removeAt(cecIndex);
+ }
+ }
+ }
+
/**
* Create a TvInputHardware object with a specific deviceId. One service at a time can access
* the object, and if more than one process attempts to create hardware with the same deviceId,
@@ -267,8 +325,7 @@ class TvInputHardwareManager implements TvInputHal.Callback {
for (TvInputHardwareInfo hardwareInfo : mInfoList) {
if (hardwareInfo.getType() == TvInputHardwareInfo.TV_INPUT_TYPE_HDMI
&& hardwareInfo.getHdmiPortId() == port) {
- TvInputInfo info = mTvInputInfoMap.get(hardwareInfo.getDeviceId());
- return (info == null) ? null : info.getId();
+ return mHardwareInputIdMap.get(hardwareInfo.getDeviceId());
}
}
return null;
@@ -295,7 +352,7 @@ class TvInputHardwareManager implements TvInputHal.Callback {
try {
mCallback.onReleased();
} catch (RemoteException e) {
- Slog.e(TAG, "Connection::resetHardware: " + e);
+ Slog.e(TAG, "error in Connection::resetLocked", e);
}
mHardware.release();
}
@@ -309,7 +366,7 @@ class TvInputHardwareManager implements TvInputHal.Callback {
try {
mCallback.onStreamConfigChanged(getConfigsLocked());
} catch (RemoteException e) {
- Slog.e(TAG, "Connection::resetHardware: " + e);
+ Slog.e(TAG, "error in Connection::resetLocked", e);
}
}
}
@@ -501,7 +558,7 @@ class TvInputHardwareManager implements TvInputHal.Callback {
interface Listener {
public void onStateChanged(String inputId, int state);
public void onHardwareDeviceAdded(TvInputHardwareInfo info);
- public void onHardwareDeviceRemoved(int deviceId);
+ public void onHardwareDeviceRemoved(TvInputHardwareInfo info);
public void onHdmiCecDeviceAdded(HdmiCecDeviceInfo cecDevice);
public void onHdmiCecDeviceRemoved(HdmiCecDeviceInfo cecDevice);
}
@@ -510,8 +567,8 @@ class TvInputHardwareManager implements TvInputHal.Callback {
private static final int STATE_CHANGED = 1;
private static final int HARDWARE_DEVICE_ADDED = 2;
private static final int HARDWARE_DEVICE_REMOVED = 3;
- private static final int CEC_DEVICE_ADDED = 4;
- private static final int CEC_DEVICE_REMOVED = 5;
+ private static final int HDMI_CEC_DEVICE_ADDED = 4;
+ private static final int HDMI_CEC_DEVICE_REMOVED = 5;
@Override
public final void handleMessage(Message msg) {
@@ -528,16 +585,16 @@ class TvInputHardwareManager implements TvInputHal.Callback {
break;
}
case HARDWARE_DEVICE_REMOVED: {
- int deviceId = msg.arg1;
- mListener.onHardwareDeviceRemoved(deviceId);
+ TvInputHardwareInfo info = (TvInputHardwareInfo) msg.obj;
+ mListener.onHardwareDeviceRemoved(info);
break;
}
- case CEC_DEVICE_ADDED: {
+ case HDMI_CEC_DEVICE_ADDED: {
HdmiCecDeviceInfo info = (HdmiCecDeviceInfo) msg.obj;
mListener.onHdmiCecDeviceAdded(info);
break;
}
- case CEC_DEVICE_REMOVED: {
+ case HDMI_CEC_DEVICE_REMOVED: {
HdmiCecDeviceInfo info = (HdmiCecDeviceInfo) msg.obj;
mListener.onHdmiCecDeviceRemoved(info);
break;
@@ -571,8 +628,8 @@ class TvInputHardwareManager implements TvInputHal.Callback {
@Override
public void onStatusChanged(HdmiCecDeviceInfo deviceInfo, boolean activated) {
mHandler.obtainMessage(
- activated ? ListenerHandler.CEC_DEVICE_ADDED
- : ListenerHandler.CEC_DEVICE_REMOVED,
+ activated ? ListenerHandler.HDMI_CEC_DEVICE_ADDED
+ : ListenerHandler.HDMI_CEC_DEVICE_REMOVED,
0, 0, deviceInfo).sendToTarget();
}
}
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index c112b13..01aaca0 100644
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -220,7 +220,7 @@ public final class TvInputManagerService extends SystemService {
List<ResolveInfo> services = pm.queryIntentServices(
new Intent(TvInputService.SERVICE_INTERFACE),
PackageManager.GET_SERVICES | PackageManager.GET_META_DATA);
- List<TvInputInfo> infoList = new ArrayList<TvInputInfo>();
+ List<TvInputInfo> inputList = new ArrayList<TvInputInfo>();
for (ResolveInfo ri : services) {
ServiceInfo si = ri.serviceInfo;
if (!android.Manifest.permission.BIND_TV_INPUT.equals(si.permission)) {
@@ -229,7 +229,7 @@ public final class TvInputManagerService extends SystemService {
continue;
}
try {
- infoList.clear();
+ inputList.clear();
ComponentName service = new ComponentName(si.packageName, si.name);
if (hasHardwarePermission(pm, service)) {
ServiceState serviceState = userState.serviceStateMap.get(service);
@@ -240,13 +240,13 @@ public final class TvInputManagerService extends SystemService {
serviceState = new ServiceState(service, userId);
userState.serviceStateMap.put(service, serviceState);
} else {
- infoList.addAll(serviceState.mInputList);
+ inputList.addAll(serviceState.mInputList);
}
} else {
- infoList.add(TvInputInfo.createTvInputInfo(mContext, ri));
+ inputList.add(TvInputInfo.createTvInputInfo(mContext, ri));
}
- for (TvInputInfo info : infoList) {
+ for (TvInputInfo info : inputList) {
if (DEBUG) Slog.d(TAG, "add " + info.getId());
TvInputState state = userState.inputMap.get(info.getId());
if (state == null) {
@@ -1213,22 +1213,6 @@ public final class TvInputManagerService extends SystemService {
}
@Override
- public void registerTvInputInfo(TvInputInfo info, int deviceId) {
- // TODO: Revisit to sort out deviceId ownership.
- if (mContext.checkCallingPermission(android.Manifest.permission.TV_INPUT_HARDWARE)
- != PackageManager.PERMISSION_GRANTED) {
- return;
- }
-
- final long identity = Binder.clearCallingIdentity();
- try {
- mTvInputHardwareManager.registerTvInputInfo(info, deviceId);
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
-
- @Override
public ITvInputHardware acquireTvInputHardware(int deviceId,
ITvInputHardwareCallback callback, TvInputInfo info, int userId)
throws RemoteException {
@@ -1550,8 +1534,6 @@ public final class TvInputManagerService extends SystemService {
Slog.d(TAG, "onServiceConnected(name=" + name + ")");
}
synchronized (mLock) {
- List<TvInputHardwareInfo> hardwareInfoList =
- mTvInputHardwareManager.getHardwareList();
UserState userState = getUserStateLocked(mUserId);
ServiceState serviceState = userState.serviceStateMap.get(mName);
serviceState.mService = ITvInputService.Stub.asInterface(service);
@@ -1580,6 +1562,8 @@ public final class TvInputManagerService extends SystemService {
}
if (serviceState.mIsHardware) {
+ List<TvInputHardwareInfo> hardwareInfoList =
+ mTvInputHardwareManager.getHardwareList();
for (TvInputHardwareInfo hardwareInfo : hardwareInfoList) {
try {
serviceState.mService.notifyHardwareAdded(hardwareInfo);
@@ -1588,7 +1572,15 @@ public final class TvInputManagerService extends SystemService {
}
}
- // TODO: Grab CEC devices and notify them to the service.
+ List<HdmiCecDeviceInfo> cecDeviceInfoList =
+ mTvInputHardwareManager.getHdmiCecInputDeviceList();
+ for (HdmiCecDeviceInfo cecDeviceInfo : cecDeviceInfoList) {
+ try {
+ serviceState.mService.notifyHdmiCecDeviceAdded(cecDeviceInfo);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "error in notifyHdmiCecDeviceAdded", e);
+ }
+ }
}
}
}
@@ -1642,32 +1634,49 @@ public final class TvInputManagerService extends SystemService {
mUserId = userId;
}
+ private void ensureHardwarePermission() {
+ if (mContext.checkCallingPermission(android.Manifest.permission.TV_INPUT_HARDWARE)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("The caller does not have hardware permission");
+ }
+ }
+
+ private void ensureValidInput(TvInputInfo inputInfo) {
+ if (inputInfo.getId() == null || !mName.equals(inputInfo.getComponent())) {
+ throw new IllegalArgumentException("Invalid TvInputInfo");
+ }
+ }
+
+ private void addTvInputLocked(TvInputInfo inputInfo) {
+ ServiceState serviceState = getServiceStateLocked(mName, mUserId);
+ serviceState.mInputList.add(inputInfo);
+ buildTvInputListLocked(mUserId);
+ }
+
@Override
- public void addTvInput(TvInputInfo inputInfo) {
+ public void addHardwareTvInput(int deviceId, TvInputInfo inputInfo) {
+ ensureHardwarePermission();
+ ensureValidInput(inputInfo);
synchronized (mLock) {
- if (mContext.checkCallingPermission(android.Manifest.permission.TV_INPUT_HARDWARE)
- != PackageManager.PERMISSION_GRANTED) {
- Slog.w(TAG, "The caller does not have permission to add a TV input ("
- + inputInfo + ").");
- return;
- }
+ mTvInputHardwareManager.addHardwareTvInput(deviceId, inputInfo);
+ addTvInputLocked(inputInfo);
+ }
+ }
- ServiceState serviceState = getServiceStateLocked(mName, mUserId);
- serviceState.mInputList.add(inputInfo);
- buildTvInputListLocked(mUserId);
+ @Override
+ public void addHdmiCecTvInput(int logicalAddress, TvInputInfo inputInfo) {
+ ensureHardwarePermission();
+ ensureValidInput(inputInfo);
+ synchronized (mLock) {
+ mTvInputHardwareManager.addHdmiCecTvInput(logicalAddress, inputInfo);
+ addTvInputLocked(inputInfo);
}
}
@Override
public void removeTvInput(String inputId) {
+ ensureHardwarePermission();
synchronized (mLock) {
- if (mContext.checkCallingPermission(android.Manifest.permission.TV_INPUT_HARDWARE)
- != PackageManager.PERMISSION_GRANTED) {
- Slog.w(TAG, "The caller does not have permission to remove a TV input ("
- + inputId + ").");
- return;
- }
-
ServiceState serviceState = getServiceStateLocked(mName, mUserId);
boolean removed = false;
for (Iterator<TvInputInfo> it = serviceState.mInputList.iterator();
@@ -1680,6 +1689,7 @@ public final class TvInputManagerService extends SystemService {
}
if (removed) {
buildTvInputListLocked(mUserId);
+ mTvInputHardwareManager.removeTvInput(inputId);
} else {
Slog.e(TAG, "TvInputInfo with inputId=" + inputId + " not found.");
}
@@ -1856,14 +1866,14 @@ public final class TvInputManagerService extends SystemService {
}
@Override
- public void onHardwareDeviceRemoved(int deviceId) {
+ public void onHardwareDeviceRemoved(TvInputHardwareInfo info) {
synchronized (mLock) {
UserState userState = getUserStateLocked(mCurrentUserId);
// Broadcast the event to all hardware inputs.
for (ServiceState serviceState : userState.serviceStateMap.values()) {
if (!serviceState.mIsHardware || serviceState.mService == null) continue;
try {
- serviceState.mService.notifyHardwareRemoved(deviceId);
+ serviceState.mService.notifyHardwareRemoved(info);
} catch (RemoteException e) {
Slog.e(TAG, "error in notifyHardwareRemoved", e);
}
@@ -1872,16 +1882,34 @@ public final class TvInputManagerService extends SystemService {
}
@Override
- public void onHdmiCecDeviceAdded(HdmiCecDeviceInfo cecDevice) {
+ public void onHdmiCecDeviceAdded(HdmiCecDeviceInfo cecDeviceInfo) {
synchronized (mLock) {
- // TODO
+ UserState userState = getUserStateLocked(mCurrentUserId);
+ // Broadcast the event to all hardware inputs.
+ for (ServiceState serviceState : userState.serviceStateMap.values()) {
+ if (!serviceState.mIsHardware || serviceState.mService == null) continue;
+ try {
+ serviceState.mService.notifyHdmiCecDeviceAdded(cecDeviceInfo);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "error in notifyHdmiCecDeviceAdded", e);
+ }
+ }
}
}
@Override
- public void onHdmiCecDeviceRemoved(HdmiCecDeviceInfo cecDevice) {
+ public void onHdmiCecDeviceRemoved(HdmiCecDeviceInfo cecDeviceInfo) {
synchronized (mLock) {
- // TODO
+ UserState userState = getUserStateLocked(mCurrentUserId);
+ // Broadcast the event to all hardware inputs.
+ for (ServiceState serviceState : userState.serviceStateMap.values()) {
+ if (!serviceState.mIsHardware || serviceState.mService == null) continue;
+ try {
+ serviceState.mService.notifyHdmiCecDeviceRemoved(cecDeviceInfo);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "error in notifyHdmiCecDeviceRemoved", e);
+ }
+ }
}
}
}