summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
authorJi-Hwan Lee <jihwan@google.com>2014-07-19 22:20:31 +0900
committerJi-Hwan Lee <jihwan@google.com>2014-07-21 17:04:04 +0900
commit4f9f57cede3de2e2aa3045e04b485b176ab22dbd (patch)
tree9aca7841d105915d57edc0781201fbd4564662f1 /services
parent75df3bf9789de68fba88f8faa44b7c0e9b44aafe (diff)
downloadframeworks_base-4f9f57cede3de2e2aa3045e04b485b176ab22dbd.zip
frameworks_base-4f9f57cede3de2e2aa3045e04b485b176ab22dbd.tar.gz
frameworks_base-4f9f57cede3de2e2aa3045e04b485b176ab22dbd.tar.bz2
TIF: Extend multiple TV input per service for HDMI logical devices
Remove ITvInputManager.registerTvInputInfo() and let addTvInputInfo*() cover the registration. Bug: 15570939 Change-Id: Ic36701de96696e7fe32fc1faa0d5f6fde53f6666
Diffstat (limited to 'services')
-rw-r--r--services/core/java/com/android/server/tv/TvInputHardwareManager.java127
-rw-r--r--services/core/java/com/android/server/tv/TvInputManagerService.java122
2 files changed, 167 insertions, 82 deletions
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);
+ }
+ }
}
}
}