summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
Diffstat (limited to 'services')
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiCecController.java25
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiControlService.java97
2 files changed, 105 insertions, 17 deletions
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecController.java b/services/core/java/com/android/server/hdmi/HdmiCecController.java
index 8d0696b..68ce607 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecController.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecController.java
@@ -80,8 +80,8 @@ final class HdmiCecController {
// A logical address of device is used as key of container.
private final SparseArray<HdmiCecDeviceInfo> mDeviceInfos = new SparseArray<>();
- // Stores the local CEC devices in the system.
- private final ArrayList<HdmiCecLocalDevice> mLocalDevices = new ArrayList<>();
+ // Stores the local CEC devices in the system. Device type is used for key.
+ private final SparseArray<HdmiCecLocalDevice> mLocalDevices = new SparseArray<>();
// Private constructor. Use HdmiCecController.create().
private HdmiCecController() {
@@ -131,7 +131,7 @@ final class HdmiCecController {
// TODO: Consider restoring the local device addresses from persistent storage
// to allocate the same addresses again if possible.
device.setPreferredAddress(HdmiCec.ADDR_UNREGISTERED);
- mLocalDevices.add(device);
+ mLocalDevices.put(type, device);
device.init();
}
}
@@ -290,6 +290,17 @@ final class HdmiCecController {
}
/**
+ * Return the locally hosted logical device of a given type.
+ *
+ * @param deviceType logical device type
+ * @return {@link HdmiCecLocalDevice} instance if the instance of the type is available;
+ * otherwise null.
+ */
+ HdmiCecLocalDevice getLocalDevice(int deviceType) {
+ return mLocalDevices.get(deviceType);
+ }
+
+ /**
* Add a new logical address to the device. Device's HW should be notified
* when a new logical address is assigned to a device, so that it can accept
* a command having available destinations.
@@ -317,8 +328,8 @@ final class HdmiCecController {
assertRunOnServiceThread();
// TODO: consider to backup logical address so that new logical address
// allocation can use it as preferred address.
- for (HdmiCecLocalDevice device : mLocalDevices) {
- device.clearAddress();
+ for (int i = 0; i < mLocalDevices.size(); ++i) {
+ mLocalDevices.valueAt(i).clearAddress();
}
nativeClearLogicalAddress(mNativePtr);
}
@@ -379,8 +390,8 @@ final class HdmiCecController {
}
private boolean isAllocatedLocalDeviceAddress(int address) {
- for (HdmiCecLocalDevice device : mLocalDevices) {
- if (device.isAddressOf(address)) {
+ for (int i = 0; i < mLocalDevices.size(); ++i) {
+ if (mLocalDevices.valueAt(i).isAddressOf(address)) {
return true;
}
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 74961fd..475852f 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -178,6 +178,16 @@ public final class HdmiControlService extends SystemService {
});
}
+ // See if we have an action of a given type in progress.
+ private <T extends FeatureAction> boolean hasAction(final Class<T> clazz) {
+ for (FeatureAction action : mActions) {
+ if (action.getClass().equals(clazz)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
/**
* Remove the given {@link FeatureAction} object from the action queue.
*
@@ -415,36 +425,95 @@ public final class HdmiControlService extends SystemService {
}
@Override
- public void oneTouchPlay(IHdmiControlCallback callback) {
+ public void oneTouchPlay(final IHdmiControlCallback callback) {
enforceAccessPermission();
- // TODO: Post a message for HdmiControlService#oneTouchPlay()
+ runOnServiceThread(new Runnable() {
+ @Override
+ public void run() {
+ HdmiControlService.this.oneTouchPlay(callback);
+ }
+ });
}
@Override
- public void queryDisplayStatus(IHdmiControlCallback callback) {
+ public void queryDisplayStatus(final IHdmiControlCallback callback) {
enforceAccessPermission();
- // TODO: Post a message for HdmiControlService#queryDisplayStatus()
+ runOnServiceThread(new Runnable() {
+ @Override
+ public void run() {
+ HdmiControlService.this.queryDisplayStatus(callback);
+ }
+ });
}
@Override
- public void addHotplugEventListener(IHdmiHotplugEventListener listener) {
+ public void addHotplugEventListener(final IHdmiHotplugEventListener listener) {
enforceAccessPermission();
- // TODO: Post a message for HdmiControlService#addHotplugEventListener()
+ runOnServiceThread(new Runnable() {
+ @Override
+ public void run() {
+ HdmiControlService.this.addHotplugEventListener(listener);
+ }
+ });
}
@Override
- public void removeHotplugEventListener(IHdmiHotplugEventListener listener) {
+ public void removeHotplugEventListener(final IHdmiHotplugEventListener listener) {
enforceAccessPermission();
- // TODO: Post a message for HdmiControlService#removeHotplugEventListener()
+ runOnServiceThread(new Runnable() {
+ @Override
+ public void run() {
+ HdmiControlService.this.removeHotplugEventListener(listener);
+ }
+ });
}
}
private void oneTouchPlay(IHdmiControlCallback callback) {
- // TODO: Create a new action
+ if (hasAction(OneTouchPlayAction.class)) {
+ Slog.w(TAG, "oneTouchPlay already in progress");
+ invokeCallback(callback, HdmiCec.RESULT_ALREADY_IN_PROGRESS);
+ return;
+ }
+ HdmiCecLocalDevice source = mCecController.getLocalDevice(HdmiCec.DEVICE_PLAYBACK);
+ if (source == null) {
+ Slog.w(TAG, "Local playback device not available");
+ invokeCallback(callback, HdmiCec.RESULT_SOURCE_NOT_AVAILABLE);
+ return;
+ }
+ // TODO: Consider the case of multiple TV sets. For now we always direct the command
+ // to the primary one.
+ OneTouchPlayAction action = OneTouchPlayAction.create(this,
+ source.getDeviceInfo().getLogicalAddress(),
+ source.getDeviceInfo().getPhysicalAddress(), HdmiCec.ADDR_TV, callback);
+ if (action == null) {
+ Slog.w(TAG, "Cannot initiate oneTouchPlay");
+ invokeCallback(callback, HdmiCec.RESULT_EXCEPTION);
+ return;
+ }
+ addAndStartAction(action);
}
private void queryDisplayStatus(IHdmiControlCallback callback) {
- // TODO: Create a new action
+ if (hasAction(DevicePowerStatusAction.class)) {
+ Slog.w(TAG, "queryDisplayStatus already in progress");
+ invokeCallback(callback, HdmiCec.RESULT_ALREADY_IN_PROGRESS);
+ return;
+ }
+ HdmiCecLocalDevice source = mCecController.getLocalDevice(HdmiCec.DEVICE_PLAYBACK);
+ if (source == null) {
+ Slog.w(TAG, "Local playback device not available");
+ invokeCallback(callback, HdmiCec.RESULT_SOURCE_NOT_AVAILABLE);
+ return;
+ }
+ DevicePowerStatusAction action = DevicePowerStatusAction.create(this,
+ source.getDeviceInfo().getLogicalAddress(), HdmiCec.ADDR_TV, callback);
+ if (action == null) {
+ Slog.w(TAG, "Cannot initiate queryDisplayStatus");
+ invokeCallback(callback, HdmiCec.RESULT_EXCEPTION);
+ return;
+ }
+ addAndStartAction(action);
}
private void addHotplugEventListener(IHdmiHotplugEventListener listener) {
@@ -473,4 +542,12 @@ public final class HdmiControlService extends SystemService {
mHotplugEventListeners.remove(listener);
}
}
+
+ private void invokeCallback(IHdmiControlCallback callback, int result) {
+ try {
+ callback.onComplete(result);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Invoking callback failed:" + e);
+ }
+ }
}