Loading services/core/java/com/android/server/hdmi/HdmiCecController.java +20 −37 Original line number Diff line number Diff line Loading @@ -47,6 +47,21 @@ import java.util.List; 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. Loading Loading @@ -116,45 +131,13 @@ final class HdmiCecController { 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. * Loading @@ -166,7 +149,7 @@ final class HdmiCecController { * @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() { Loading @@ -178,7 +161,7 @@ final class HdmiCecController { } 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 Loading services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java +18 −57 Original line number Diff line number Diff line Loading @@ -16,8 +16,6 @@ package com.android.server.hdmi; import com.android.server.hdmi.HdmiCecController.AllocateLogicalAddressCallback; import android.hardware.hdmi.HdmiCec; import android.hardware.hdmi.HdmiCecDeviceInfo; Loading @@ -27,84 +25,43 @@ 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) { final void handleAddressAllocated(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); } HdmiCecDeviceInfo getDeviceInfo() { Loading @@ -128,4 +85,8 @@ abstract class HdmiCecLocalDevice { void setPreferredAddress(int addr) { mPreferredAddress = addr; } int getPreferredAddress() { return mPreferredAddress; } } services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java +4 −9 Original line number Diff line number Diff line Loading @@ -23,18 +23,13 @@ import android.hardware.hdmi.HdmiCec; */ 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)); } } services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java +7 −11 Original line number Diff line number Diff line Loading @@ -23,24 +23,20 @@ import android.hardware.hdmi.HdmiCec; */ 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. } } services/core/java/com/android/server/hdmi/HdmiControlService.java +97 −44 Original line number Diff line number Diff line Loading @@ -30,12 +30,13 @@ import android.os.IBinder; 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; Loading Loading @@ -134,23 +135,9 @@ public final class HdmiControlService extends SystemService { 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."); } Loading @@ -166,6 +153,46 @@ public final class HdmiControlService extends SystemService { // 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. * Loading @@ -185,6 +212,20 @@ public final class HdmiControlService extends SystemService { return mHandler.getLooper(); } /** * 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. * Loading Loading @@ -352,6 +393,45 @@ public final class HdmiControlService extends SystemService { 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)) { Loading Loading @@ -505,33 +585,6 @@ public final class HdmiControlService extends SystemService { 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); Loading Loading
services/core/java/com/android/server/hdmi/HdmiCecController.java +20 −37 Original line number Diff line number Diff line Loading @@ -47,6 +47,21 @@ import java.util.List; 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. Loading Loading @@ -116,45 +131,13 @@ final class HdmiCecController { 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. * Loading @@ -166,7 +149,7 @@ final class HdmiCecController { * @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() { Loading @@ -178,7 +161,7 @@ final class HdmiCecController { } 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 Loading
services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java +18 −57 Original line number Diff line number Diff line Loading @@ -16,8 +16,6 @@ package com.android.server.hdmi; import com.android.server.hdmi.HdmiCecController.AllocateLogicalAddressCallback; import android.hardware.hdmi.HdmiCec; import android.hardware.hdmi.HdmiCecDeviceInfo; Loading @@ -27,84 +25,43 @@ 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) { final void handleAddressAllocated(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); } HdmiCecDeviceInfo getDeviceInfo() { Loading @@ -128,4 +85,8 @@ abstract class HdmiCecLocalDevice { void setPreferredAddress(int addr) { mPreferredAddress = addr; } int getPreferredAddress() { return mPreferredAddress; } }
services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java +4 −9 Original line number Diff line number Diff line Loading @@ -23,18 +23,13 @@ import android.hardware.hdmi.HdmiCec; */ 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)); } }
services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java +7 −11 Original line number Diff line number Diff line Loading @@ -23,24 +23,20 @@ import android.hardware.hdmi.HdmiCec; */ 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. } }
services/core/java/com/android/server/hdmi/HdmiControlService.java +97 −44 Original line number Diff line number Diff line Loading @@ -30,12 +30,13 @@ import android.os.IBinder; 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; Loading Loading @@ -134,23 +135,9 @@ public final class HdmiControlService extends SystemService { 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."); } Loading @@ -166,6 +153,46 @@ public final class HdmiControlService extends SystemService { // 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. * Loading @@ -185,6 +212,20 @@ public final class HdmiControlService extends SystemService { return mHandler.getLooper(); } /** * 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. * Loading Loading @@ -352,6 +393,45 @@ public final class HdmiControlService extends SystemService { 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)) { Loading Loading @@ -505,33 +585,6 @@ public final class HdmiControlService extends SystemService { 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); Loading