diff options
Diffstat (limited to 'services')
-rw-r--r-- | services/core/java/com/android/server/hdmi/HdmiCecController.java | 25 | ||||
-rw-r--r-- | services/core/java/com/android/server/hdmi/HdmiControlService.java | 97 |
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); + } + } } |