Loading services/core/java/com/android/server/hdmi/HdmiCecController.java +42 −53 Original line number Diff line number Diff line Loading @@ -21,7 +21,6 @@ import android.hardware.hdmi.HdmiCecDeviceInfo; import android.hardware.hdmi.HdmiCecMessage; import android.os.Handler; import android.util.SparseArray; import android.util.SparseIntArray; import libcore.util.EmptyArray; Loading Loading @@ -75,14 +74,12 @@ final class HdmiCecController { // used as key of container. private final SparseArray<HdmiCecDeviceInfo> mDeviceInfos = new SparseArray<HdmiCecDeviceInfo>(); // Set-like container for all local devices' logical address. // Key and value are same. private final SparseIntArray mLocalAddresses = new SparseIntArray(); // Stores the local CEC devices in the system. private final ArrayList<HdmiCecLocalDevice> mLocalDevices = new ArrayList<>(); // Private constructor. Use HdmiCecController.create(). private HdmiCecController() { // TODO: Consider restoring the local device addresses from persistent storage // to allocate the same addresses again if possible. } /** Loading @@ -96,53 +93,41 @@ final class HdmiCecController { * returns {@code null}. */ static HdmiCecController create(HdmiControlService service) { HdmiCecController handler = new HdmiCecController(); long nativePtr = nativeInit(handler); HdmiCecController controller = new HdmiCecController(); long nativePtr = nativeInit(controller); if (nativePtr == 0L) { handler = null; controller = null; return null; } handler.init(service, nativePtr); return handler; controller.init(service, nativePtr); return controller; } /** * Initialize {@link #mLocalAddresses} by allocating logical addresses for each hosted type. * * @param deviceTypes local device types */ void initializeLocalDevices(int[] deviceTypes) { for (int deviceType : deviceTypes) { int preferred = getPreferredAddress(deviceType); allocateLogicalAddress(deviceType, preferred, new AllocateLogicalAddressCallback() { @Override public void onAllocated(int deviceType, int logicalAddress) { addLogicalAddress(logicalAddress); } }); } private void init(HdmiControlService service, long nativePtr) { mService = service; mIoHandler = new Handler(service.getServiceLooper()); mControlHandler = new Handler(service.getServiceLooper()); mNativePtr = nativePtr; } /** * Get the preferred address for a given type. * Perform initialization for each hosted device. * * @param deviceType logical device type to get the address for * @return preferred address; {@link HdmiCec#ADDR_UNREGISTERED} if not available. * @param deviceTypes array of device types */ private int getPreferredAddress(int deviceType) { // Uses the data restored from persistent memory at boot up if they are available. // Otherwise we return UNREGISTERED indicating there is no preferred address. // Note that for address SPECIFIC_USE(14), HdmiCec.getTypeFromAddress() returns DEVICE_TV, // meaning that we do not support device type video processor yet. for (int i = 0; i < mLocalAddresses.size(); ++i) { int address = mLocalAddresses.keyAt(i); int type = HdmiCec.getTypeFromAddress(address); if (type == deviceType) { return address; void initializeLocalDevices(int[] deviceTypes) { for (int type : deviceTypes) { HdmiCecLocalDevice device = HdmiCecLocalDevice.create(this, type); 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.add(device); device.init(); } return HdmiCec.ADDR_UNREGISTERED; } /** Loading Loading @@ -310,7 +295,6 @@ final class HdmiCecController { */ int addLogicalAddress(int newLogicalAddress) { if (HdmiCec.isValidAddress(newLogicalAddress)) { mLocalAddresses.put(newLogicalAddress, newLogicalAddress); return nativeAddLogicalAddress(mNativePtr, newLogicalAddress); } else { return -1; Loading @@ -325,7 +309,9 @@ final class HdmiCecController { void clearLogicalAddress() { // TODO: consider to backup logical address so that new logical address // allocation can use it as preferred address. mLocalAddresses.clear(); for (HdmiCecLocalDevice device : mLocalDevices) { device.clearAddress(); } nativeClearLogicalAddress(mNativePtr); } Loading Loading @@ -367,18 +353,17 @@ final class HdmiCecController { mControlHandler.post(runnable); } private void init(HdmiControlService service, long nativePtr) { mService = service; mIoHandler = new Handler(service.getServiceLooper()); mControlHandler = new Handler(service.getServiceLooper()); mNativePtr = nativePtr; } private boolean isAcceptableAddress(int address) { // Can access command targeting devices available in local device or // broadcast command. return address == HdmiCec.ADDR_BROADCAST || mLocalAddresses.indexOfKey(address) < 0; // Can access command targeting devices available in local device or broadcast command. if (address == HdmiCec.ADDR_BROADCAST) { return true; } for (HdmiCecLocalDevice device : mLocalDevices) { if (device.isAddressOf(address)) { return true; } } return false; } private void onReceiveCommand(HdmiCecMessage message) { Loading @@ -397,6 +382,10 @@ final class HdmiCecController { sendCommand(cecMessage, null); } void sendCommand(HdmiCecMessage cecMessage) { sendCommand(cecMessage, null); } void sendCommand(final HdmiCecMessage cecMessage, final HdmiControlService.SendMessageCallback callback) { runOnIoThread(new Runnable() { Loading services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java 0 → 100644 +78 −0 Original line number Diff line number Diff line /* * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.hdmi; import com.android.server.hdmi.HdmiCecController.AllocateLogicalAddressCallback; import android.hardware.hdmi.HdmiCec; /** * Class that models a logical CEC device hosted in this system. Handles initialization, * CEC commands that call for actions customized per device type. */ abstract class HdmiCecLocalDevice { protected final HdmiCecController mController; protected final int mDeviceType; protected int mAddress; protected int mPreferredAddress; protected HdmiCecLocalDevice(HdmiCecController controller, int deviceType) { mController = controller; mDeviceType = deviceType; mAddress = HdmiCec.ADDR_UNREGISTERED; } // Factory method that returns HdmiCecLocalDevice of corresponding type. static HdmiCecLocalDevice create(HdmiCecController controller, int deviceType) { switch (deviceType) { case HdmiCec.DEVICE_TV: return new HdmiCecLocalDeviceTv(controller); case HdmiCec.DEVICE_PLAYBACK: return new HdmiCecLocalDevicePlayback(controller); default: return null; } } abstract void init(); protected void allocateAddress(int type) { mController.allocateLogicalAddress(type, mPreferredAddress, new AllocateLogicalAddressCallback() { @Override public void onAllocated(int deviceType, int logicalAddress) { mAddress = mPreferredAddress = logicalAddress; mController.addLogicalAddress(logicalAddress); } }); } // Returns true if the logical address is same as the argument. boolean isAddressOf(int addr) { return addr == mAddress; } // Resets the logical address to unregistered(15), meaning the logical device is invalid. void clearAddress() { mAddress = HdmiCec.ADDR_UNREGISTERED; } void setPreferredAddress(int addr) { mPreferredAddress = addr; } } services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java 0 → 100644 +36 −0 Original line number Diff line number Diff line /* * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.hdmi; import android.hardware.hdmi.HdmiCec; /** * Represent a logical device of type Playback residing in Android system. */ final class HdmiCecLocalDevicePlayback extends HdmiCecLocalDevice { HdmiCecLocalDevicePlayback(HdmiCecController controller) { super(controller, HdmiCec.DEVICE_PLAYBACK); } @Override void init() { allocateAddress(mDeviceType); mController.sendCommand(HdmiCecMessageBuilder.buildReportPhysicalAddressCommand( mAddress, mController.getPhysicalAddress(), mDeviceType)); } } services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java 0 → 100644 +43 −0 Original line number Diff line number Diff line /* * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.hdmi; import android.hardware.hdmi.HdmiCec; /** * Represent a logical device of type TV residing in Android system. */ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { HdmiCecLocalDeviceTv(HdmiCecController controller) { super(controller, HdmiCec.DEVICE_TV); } @Override void init() { allocateAddress(mDeviceType); // TODO: vendor-specific initialization here. mController.sendCommand(HdmiCecMessageBuilder.buildReportPhysicalAddressCommand( mAddress, mController.getPhysicalAddress(), mDeviceType)); mController.sendCommand(HdmiCecMessageBuilder.buildDeviceVendorIdCommand( mAddress, mController.getVendorId())); // TODO: Start routing control action, device discovery action. } } Loading
services/core/java/com/android/server/hdmi/HdmiCecController.java +42 −53 Original line number Diff line number Diff line Loading @@ -21,7 +21,6 @@ import android.hardware.hdmi.HdmiCecDeviceInfo; import android.hardware.hdmi.HdmiCecMessage; import android.os.Handler; import android.util.SparseArray; import android.util.SparseIntArray; import libcore.util.EmptyArray; Loading Loading @@ -75,14 +74,12 @@ final class HdmiCecController { // used as key of container. private final SparseArray<HdmiCecDeviceInfo> mDeviceInfos = new SparseArray<HdmiCecDeviceInfo>(); // Set-like container for all local devices' logical address. // Key and value are same. private final SparseIntArray mLocalAddresses = new SparseIntArray(); // Stores the local CEC devices in the system. private final ArrayList<HdmiCecLocalDevice> mLocalDevices = new ArrayList<>(); // Private constructor. Use HdmiCecController.create(). private HdmiCecController() { // TODO: Consider restoring the local device addresses from persistent storage // to allocate the same addresses again if possible. } /** Loading @@ -96,53 +93,41 @@ final class HdmiCecController { * returns {@code null}. */ static HdmiCecController create(HdmiControlService service) { HdmiCecController handler = new HdmiCecController(); long nativePtr = nativeInit(handler); HdmiCecController controller = new HdmiCecController(); long nativePtr = nativeInit(controller); if (nativePtr == 0L) { handler = null; controller = null; return null; } handler.init(service, nativePtr); return handler; controller.init(service, nativePtr); return controller; } /** * Initialize {@link #mLocalAddresses} by allocating logical addresses for each hosted type. * * @param deviceTypes local device types */ void initializeLocalDevices(int[] deviceTypes) { for (int deviceType : deviceTypes) { int preferred = getPreferredAddress(deviceType); allocateLogicalAddress(deviceType, preferred, new AllocateLogicalAddressCallback() { @Override public void onAllocated(int deviceType, int logicalAddress) { addLogicalAddress(logicalAddress); } }); } private void init(HdmiControlService service, long nativePtr) { mService = service; mIoHandler = new Handler(service.getServiceLooper()); mControlHandler = new Handler(service.getServiceLooper()); mNativePtr = nativePtr; } /** * Get the preferred address for a given type. * Perform initialization for each hosted device. * * @param deviceType logical device type to get the address for * @return preferred address; {@link HdmiCec#ADDR_UNREGISTERED} if not available. * @param deviceTypes array of device types */ private int getPreferredAddress(int deviceType) { // Uses the data restored from persistent memory at boot up if they are available. // Otherwise we return UNREGISTERED indicating there is no preferred address. // Note that for address SPECIFIC_USE(14), HdmiCec.getTypeFromAddress() returns DEVICE_TV, // meaning that we do not support device type video processor yet. for (int i = 0; i < mLocalAddresses.size(); ++i) { int address = mLocalAddresses.keyAt(i); int type = HdmiCec.getTypeFromAddress(address); if (type == deviceType) { return address; void initializeLocalDevices(int[] deviceTypes) { for (int type : deviceTypes) { HdmiCecLocalDevice device = HdmiCecLocalDevice.create(this, type); 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.add(device); device.init(); } return HdmiCec.ADDR_UNREGISTERED; } /** Loading Loading @@ -310,7 +295,6 @@ final class HdmiCecController { */ int addLogicalAddress(int newLogicalAddress) { if (HdmiCec.isValidAddress(newLogicalAddress)) { mLocalAddresses.put(newLogicalAddress, newLogicalAddress); return nativeAddLogicalAddress(mNativePtr, newLogicalAddress); } else { return -1; Loading @@ -325,7 +309,9 @@ final class HdmiCecController { void clearLogicalAddress() { // TODO: consider to backup logical address so that new logical address // allocation can use it as preferred address. mLocalAddresses.clear(); for (HdmiCecLocalDevice device : mLocalDevices) { device.clearAddress(); } nativeClearLogicalAddress(mNativePtr); } Loading Loading @@ -367,18 +353,17 @@ final class HdmiCecController { mControlHandler.post(runnable); } private void init(HdmiControlService service, long nativePtr) { mService = service; mIoHandler = new Handler(service.getServiceLooper()); mControlHandler = new Handler(service.getServiceLooper()); mNativePtr = nativePtr; } private boolean isAcceptableAddress(int address) { // Can access command targeting devices available in local device or // broadcast command. return address == HdmiCec.ADDR_BROADCAST || mLocalAddresses.indexOfKey(address) < 0; // Can access command targeting devices available in local device or broadcast command. if (address == HdmiCec.ADDR_BROADCAST) { return true; } for (HdmiCecLocalDevice device : mLocalDevices) { if (device.isAddressOf(address)) { return true; } } return false; } private void onReceiveCommand(HdmiCecMessage message) { Loading @@ -397,6 +382,10 @@ final class HdmiCecController { sendCommand(cecMessage, null); } void sendCommand(HdmiCecMessage cecMessage) { sendCommand(cecMessage, null); } void sendCommand(final HdmiCecMessage cecMessage, final HdmiControlService.SendMessageCallback callback) { runOnIoThread(new Runnable() { Loading
services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java 0 → 100644 +78 −0 Original line number Diff line number Diff line /* * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.hdmi; import com.android.server.hdmi.HdmiCecController.AllocateLogicalAddressCallback; import android.hardware.hdmi.HdmiCec; /** * Class that models a logical CEC device hosted in this system. Handles initialization, * CEC commands that call for actions customized per device type. */ abstract class HdmiCecLocalDevice { protected final HdmiCecController mController; protected final int mDeviceType; protected int mAddress; protected int mPreferredAddress; protected HdmiCecLocalDevice(HdmiCecController controller, int deviceType) { mController = controller; mDeviceType = deviceType; mAddress = HdmiCec.ADDR_UNREGISTERED; } // Factory method that returns HdmiCecLocalDevice of corresponding type. static HdmiCecLocalDevice create(HdmiCecController controller, int deviceType) { switch (deviceType) { case HdmiCec.DEVICE_TV: return new HdmiCecLocalDeviceTv(controller); case HdmiCec.DEVICE_PLAYBACK: return new HdmiCecLocalDevicePlayback(controller); default: return null; } } abstract void init(); protected void allocateAddress(int type) { mController.allocateLogicalAddress(type, mPreferredAddress, new AllocateLogicalAddressCallback() { @Override public void onAllocated(int deviceType, int logicalAddress) { mAddress = mPreferredAddress = logicalAddress; mController.addLogicalAddress(logicalAddress); } }); } // Returns true if the logical address is same as the argument. boolean isAddressOf(int addr) { return addr == mAddress; } // Resets the logical address to unregistered(15), meaning the logical device is invalid. void clearAddress() { mAddress = HdmiCec.ADDR_UNREGISTERED; } void setPreferredAddress(int addr) { mPreferredAddress = addr; } }
services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java 0 → 100644 +36 −0 Original line number Diff line number Diff line /* * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.hdmi; import android.hardware.hdmi.HdmiCec; /** * Represent a logical device of type Playback residing in Android system. */ final class HdmiCecLocalDevicePlayback extends HdmiCecLocalDevice { HdmiCecLocalDevicePlayback(HdmiCecController controller) { super(controller, HdmiCec.DEVICE_PLAYBACK); } @Override void init() { allocateAddress(mDeviceType); mController.sendCommand(HdmiCecMessageBuilder.buildReportPhysicalAddressCommand( mAddress, mController.getPhysicalAddress(), mDeviceType)); } }
services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java 0 → 100644 +43 −0 Original line number Diff line number Diff line /* * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.hdmi; import android.hardware.hdmi.HdmiCec; /** * Represent a logical device of type TV residing in Android system. */ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { HdmiCecLocalDeviceTv(HdmiCecController controller) { super(controller, HdmiCec.DEVICE_TV); } @Override void init() { allocateAddress(mDeviceType); // TODO: vendor-specific initialization here. mController.sendCommand(HdmiCecMessageBuilder.buildReportPhysicalAddressCommand( mAddress, mController.getPhysicalAddress(), mDeviceType)); mController.sendCommand(HdmiCecMessageBuilder.buildDeviceVendorIdCommand( mAddress, mController.getVendorId())); // TODO: Start routing control action, device discovery action. } }