1. Factor out logical allocation logic to HdmiControlService.
2. Contains a reference to HdmiControlService rather than
HdmiCecController so that it enables to access service's logic
directly.
3. Move launch device discovery logic to HdmiCecLocalDeviceTv.
Change-Id: Ic97b4d51311a3c18f6d586c2245cac410cbd370e
final class HdmiCecController {
private static final String TAG = "HdmiCecController";
+ /**
+ * Interface to report allocated logical address.
+ */
+ interface AllocateAddressCallback {
+ /**
+ * Called when a new logical address is allocated.
+ *
+ * @param deviceType requested device type to allocate logical address
+ * @param logicalAddress allocated logical address. If it is
+ * {@link HdmiCec#ADDR_UNREGISTERED}, it means that
+ * it failed to allocate logical address for the given device type
+ */
+ void onAllocated(int deviceType, int logicalAddress);
+ }
+
private static final byte[] EMPTY_BODY = EmptyArray.BYTE;
// A message to pass cec send command to IO looper.
mNativePtr = nativePtr;
}
- /**
- * Perform initialization for each hosted device.
- *
- * @param deviceTypes array of device types
- */
- void initializeLocalDevices(int[] deviceTypes,
- HdmiCecLocalDevice.AddressAllocationCallback callback) {
- assertRunOnServiceThread();
- for (int type : deviceTypes) {
- HdmiCecLocalDevice device = HdmiCecLocalDevice.create(this, type, callback);
- if (device == null) {
- continue;
- }
- // TODO: Consider restoring the local device addresses from persistent storage
- // to allocate the same addresses again if possible.
- device.setPreferredAddress(HdmiCec.ADDR_UNREGISTERED);
- mLocalDevices.put(type, device);
- device.init();
- }
- }
-
- /**
- * Interface to report allocated logical address.
- */
- interface AllocateLogicalAddressCallback {
- /**
- * Called when a new logical address is allocated.
- *
- * @param deviceType requested device type to allocate logical address
- * @param logicalAddress allocated logical address. If it is
- * {@link HdmiCec#ADDR_UNREGISTERED}, it means that
- * it failed to allocate logical address for the given device type
- */
- void onAllocated(int deviceType, int logicalAddress);
+ void addLocalDevice(int deviceType, HdmiCecLocalDevice device) {
+ mLocalDevices.put(deviceType, device);
}
/**
* Allocate a new logical address of the given device type. Allocated
- * address will be reported through {@link AllocateLogicalAddressCallback}.
+ * address will be reported through {@link AllocateAddressCallback}.
*
* <p> Declared as package-private, accessed by {@link HdmiControlService} only.
*
* @param callback callback interface to report allocated logical address to caller
*/
void allocateLogicalAddress(final int deviceType, final int preferredAddress,
- final AllocateLogicalAddressCallback callback) {
+ final AllocateAddressCallback callback) {
assertRunOnServiceThread();
runOnIoThread(new Runnable() {
}
private void handleAllocateLogicalAddress(final int deviceType, int preferredAddress,
- final AllocateLogicalAddressCallback callback) {
+ final AllocateAddressCallback callback) {
assertRunOnIoThread();
int startAddress = preferredAddress;
// If preferred address is "unregistered", start address will be the smallest
package com.android.server.hdmi;
-import com.android.server.hdmi.HdmiCecController.AllocateLogicalAddressCallback;
-
import android.hardware.hdmi.HdmiCec;
import android.hardware.hdmi.HdmiCecDeviceInfo;
*/
abstract class HdmiCecLocalDevice {
- protected final HdmiCecController mController;
+ protected final HdmiControlService mService;
protected final int mDeviceType;
- protected final AddressAllocationCallback mAllocationCallback;
protected int mAddress;
protected int mPreferredAddress;
protected HdmiCecDeviceInfo mDeviceInfo;
- /**
- * Callback interface to notify newly allocated logical address of the given
- * local device.
- */
- interface AddressAllocationCallback {
- /**
- * Called when a logical address of the given device is allocated.
- *
- * @param deviceType original device type
- * @param logicalAddress newly allocated logical address
- */
- void onAddressAllocated(int deviceType, int logicalAddress);
- }
-
- protected HdmiCecLocalDevice(HdmiCecController controller, int deviceType,
- AddressAllocationCallback callback) {
- mController = controller;
+ protected HdmiCecLocalDevice(HdmiControlService service, int deviceType) {
+ mService = service;
mDeviceType = deviceType;
- mAllocationCallback = callback;
mAddress = HdmiCec.ADDR_UNREGISTERED;
}
// Factory method that returns HdmiCecLocalDevice of corresponding type.
- static HdmiCecLocalDevice create(HdmiCecController controller, int deviceType,
- AddressAllocationCallback callback) {
+ static HdmiCecLocalDevice create(HdmiControlService service, int deviceType) {
switch (deviceType) {
case HdmiCec.DEVICE_TV:
- return new HdmiCecLocalDeviceTv(controller, callback);
+ return new HdmiCecLocalDeviceTv(service);
case HdmiCec.DEVICE_PLAYBACK:
- return new HdmiCecLocalDevicePlayback(controller, callback);
+ return new HdmiCecLocalDevicePlayback(service);
default:
return null;
}
}
- abstract void init();
+ void init() {
+ mPreferredAddress = HdmiCec.ADDR_UNREGISTERED;
+ // TODO: load preferred address from permanent storage.
+ }
/**
- * Called when a logical address of the local device is allocated.
- * Note that internal variables are updated before it's called.
+ * Called once a logical address of the local device is allocated.
*/
protected abstract void onAddressAllocated(int logicalAddress);
- protected void allocateAddress(int type) {
- mController.allocateLogicalAddress(type, mPreferredAddress,
- new AllocateLogicalAddressCallback() {
- @Override
- public void onAllocated(int deviceType, int logicalAddress) {
- mAddress = mPreferredAddress = logicalAddress;
-
- // Create and set device info.
- HdmiCecDeviceInfo deviceInfo = createDeviceInfo(mAddress, deviceType);
- setDeviceInfo(deviceInfo);
- mController.addDeviceInfo(deviceInfo);
-
- mController.addLogicalAddress(logicalAddress);
- onAddressAllocated(logicalAddress);
- if (mAllocationCallback != null) {
- mAllocationCallback.onAddressAllocated(deviceType, logicalAddress);
- }
- }
- });
- }
-
- private final HdmiCecDeviceInfo createDeviceInfo(int logicalAddress, int deviceType) {
- int vendorId = mController.getVendorId();
- int physicalAddress = mController.getPhysicalAddress();
- // TODO: get device name read from system configuration.
- String displayName = HdmiCec.getDefaultDeviceName(logicalAddress);
- return new HdmiCecDeviceInfo(logicalAddress,
- physicalAddress, deviceType, vendorId, displayName);
+ final void handleAddressAllocated(int logicalAddress) {
+ mAddress = mPreferredAddress = logicalAddress;
+ onAddressAllocated(logicalAddress);
}
HdmiCecDeviceInfo getDeviceInfo() {
void setPreferredAddress(int addr) {
mPreferredAddress = addr;
}
+
+ int getPreferredAddress() {
+ return mPreferredAddress;
+ }
}
*/
final class HdmiCecLocalDevicePlayback extends HdmiCecLocalDevice {
- HdmiCecLocalDevicePlayback(HdmiCecController controller, AddressAllocationCallback callback) {
- super(controller, HdmiCec.DEVICE_PLAYBACK, callback);
- }
-
- @Override
- void init() {
- allocateAddress(mDeviceType);
+ HdmiCecLocalDevicePlayback(HdmiControlService service) {
+ super(service, HdmiCec.DEVICE_PLAYBACK);
}
@Override
protected void onAddressAllocated(int logicalAddress) {
- mController.sendCommand(HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
- mAddress, mController.getPhysicalAddress(), mDeviceType));
+ mService.sendCecCommand(HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
+ mAddress, mService.getPhysicalAddress(), mDeviceType));
}
}
*/
final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
- HdmiCecLocalDeviceTv(HdmiCecController controller, AddressAllocationCallback callback) {
- super(controller, HdmiCec.DEVICE_TV, callback);
- }
-
- @Override
- void init() {
- allocateAddress(mDeviceType);
+ HdmiCecLocalDeviceTv(HdmiControlService service) {
+ super(service, HdmiCec.DEVICE_TV);
}
@Override
protected void onAddressAllocated(int logicalAddress) {
// TODO: vendor-specific initialization here.
- mController.sendCommand(HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
- mAddress, mController.getPhysicalAddress(), mDeviceType));
- mController.sendCommand(HdmiCecMessageBuilder.buildDeviceVendorIdCommand(
- mAddress, mController.getVendorId()));
+ mService.sendCecCommand(HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
+ mAddress, mService.getPhysicalAddress(), mDeviceType));
+ mService.sendCecCommand(HdmiCecMessageBuilder.buildDeviceVendorIdCommand(
+ mAddress, mService.getVendorId()));
+ mService.launchDeviceDiscovery(mAddress);
// TODO: Start routing control action, device discovery action.
}
}
import android.os.Looper;
import android.os.RemoteException;
import android.util.Slog;
+import android.util.SparseArray;
import android.util.SparseIntArray;
import com.android.internal.annotations.GuardedBy;
import com.android.server.SystemService;
import com.android.server.hdmi.DeviceDiscoveryAction.DeviceDiscoveryCallback;
-import com.android.server.hdmi.HdmiCecLocalDevice.AddressAllocationCallback;
+import com.android.server.hdmi.HdmiCecController.AllocateAddressCallback;
import java.util.ArrayList;
import java.util.Iterator;
public void onStart() {
mIoThread.start();
mCecController = HdmiCecController.create(this);
- if (mCecController != null) {
- mCecController.initializeLocalDevices(mLocalDevices, new AddressAllocationCallback() {
- private final SparseIntArray mAllocated = new SparseIntArray();
- @Override
- public void onAddressAllocated(int deviceType, int logicalAddress) {
- mAllocated.append(deviceType, logicalAddress);
- // TODO: get HdmiLCecLocalDevice and call onAddressAllocated here.
-
- // Once all logical allocation is done, launch device discovery
- // action if one of local device is TV.
- int tvAddress = mAllocated.get(HdmiCec.DEVICE_TV, -1);
- if (mLocalDevices.length == mAllocated.size() && tvAddress != -1) {
- launchDeviceDiscovery(tvAddress);
- }
- }
- });
+ if (mCecController != null) {
+ initializeLocalDevices(mLocalDevices);
} else {
Slog.i(TAG, "Device does not support HDMI-CEC.");
}
// start to monitor the preference value and invoke SystemAudioActionFromTv if needed.
}
+ private void initializeLocalDevices(final int[] deviceTypes) {
+ // A container for [Logical Address, Local device info].
+ final SparseArray<HdmiCecLocalDevice> devices = new SparseArray<>();
+ final SparseIntArray finished = new SparseIntArray();
+ for (int type : deviceTypes) {
+ final HdmiCecLocalDevice localDevice = HdmiCecLocalDevice.create(this, type);
+ localDevice.init();
+ mCecController.allocateLogicalAddress(type,
+ localDevice.getPreferredAddress(), new AllocateAddressCallback() {
+ @Override
+ public void onAllocated(int deviceType, int logicalAddress) {
+ if (logicalAddress == HdmiCec.ADDR_UNREGISTERED) {
+ Slog.e(TAG, "Failed to allocate address:[device_type:" + deviceType + "]");
+ } else {
+ HdmiCecDeviceInfo deviceInfo = createDeviceInfo(logicalAddress, deviceType);
+ localDevice.setDeviceInfo(deviceInfo);
+ mCecController.addLocalDevice(deviceType, localDevice);
+ mCecController.addLogicalAddress(logicalAddress);
+ devices.append(logicalAddress, localDevice);
+ }
+ finished.append(deviceType, logicalAddress);
+
+ // Once finish address allocation for all devices, notify
+ // it to each device.
+ if (deviceTypes.length == finished.size()) {
+ notifyAddressAllocated(devices);
+ }
+ }
+ });
+ }
+ }
+
+ private void notifyAddressAllocated(SparseArray<HdmiCecLocalDevice> devices) {
+ for (int i = 0; i < devices.size(); ++i) {
+ int address = devices.keyAt(i);
+ HdmiCecLocalDevice device = devices.valueAt(i);
+ device.onAddressAllocated(address);
+ }
+ }
+
/**
* Returns {@link Looper} for IO operation.
*
}
/**
+ * Returns physical address of the device.
+ */
+ int getPhysicalAddress() {
+ return mCecController.getPhysicalAddress();
+ }
+
+ /**
+ * Returns vendor id of CEC service.
+ */
+ int getVendorId() {
+ return mCecController.getVendorId();
+ }
+
+ /**
* Add and start a new {@link FeatureAction} to the action queue.
*
* @param action {@link FeatureAction} to add and start
mCecController.pollDevices(callback, retryCount);
}
+
+ /**
+ * Launch device discovery sequence. It starts with clearing the existing device info list.
+ * Note that it assumes that logical address of all local devices is already allocated.
+ *
+ * @param sourceAddress a logical address of tv
+ */
+ void launchDeviceDiscovery(int sourceAddress) {
+ // At first, clear all existing device infos.
+ mCecController.clearDeviceInfoList();
+
+ // TODO: check whether TV is one of local devices.
+ DeviceDiscoveryAction action = new DeviceDiscoveryAction(this, sourceAddress,
+ new DeviceDiscoveryCallback() {
+ @Override
+ public void onDeviceDiscoveryDone(List<HdmiCecDeviceInfo> deviceInfos) {
+ for (HdmiCecDeviceInfo info : deviceInfos) {
+ mCecController.addDeviceInfo(info);
+ }
+
+ // Add device info of all local devices.
+ for (HdmiCecLocalDevice device : mCecController.getLocalDeviceList()) {
+ mCecController.addDeviceInfo(device.getDeviceInfo());
+ }
+
+ // TODO: start hot-plug detection sequence here.
+ // addAndStartAction(new HotplugDetectionAction());
+ }
+ });
+ addAndStartAction(action);
+ }
+
+ private HdmiCecDeviceInfo createDeviceInfo(int logicalAddress, int deviceType) {
+ // TODO: get device name read from system configuration.
+ String displayName = HdmiCec.getDefaultDeviceName(logicalAddress);
+ return new HdmiCecDeviceInfo(logicalAddress,
+ getPhysicalAddress(), deviceType, getVendorId(), displayName);
+ }
+
private void handleReportPhysicalAddress(HdmiCecMessage message) {
// At first, try to consume it.
if (dispatchMessageToAction(message)) {
mCecController.addDeviceInfo(info);
}
- // Launch device discovery sequence.
- // It starts with clearing the existing device info list.
- // Note that it assumes that logical address of all local devices is already allocated.
- private void launchDeviceDiscovery(int sourceAddress) {
- // At first, clear all existing device infos.
- mCecController.clearDeviceInfoList();
-
- // TODO: check whether TV is one of local devices.
- DeviceDiscoveryAction action = new DeviceDiscoveryAction(this, sourceAddress,
- new DeviceDiscoveryCallback() {
- @Override
- public void onDeviceDiscoveryDone(List<HdmiCecDeviceInfo> deviceInfos) {
- for (HdmiCecDeviceInfo info : deviceInfos) {
- mCecController.addDeviceInfo(info);
- }
-
- // Add device info of all local devices.
- for (HdmiCecLocalDevice device : mCecController.getLocalDeviceList()) {
- mCecController.addDeviceInfo(device.getDeviceInfo());
- }
-
- // TODO: start hot-plug detection sequence here.
- // addAndStartAction(new HotplugDetectionAction());
- }
- });
- addAndStartAction(action);
- }
private void enforceAccessPermission() {
getContext().enforceCallingOrSelfPermission(PERMISSION, TAG);