Loading services/core/java/com/android/server/hdmi/DeviceDiscoveryAction.java +2 −4 Original line number Diff line number Diff line Loading @@ -259,7 +259,7 @@ final class DeviceDiscoveryAction extends FeatureAction { byte params[] = cmd.getParams(); if (params.length == 3) { current.mPhysicalAddress = ((params[0] & 0xFF) << 8) | (params[1] & 0xFF); current.mPhysicalAddress = HdmiUtils.twoBytesToInt(params); current.mDeviceType = params[2] & 0xFF; increaseProcessedDeviceCount(); Loading Loading @@ -307,9 +307,7 @@ final class DeviceDiscoveryAction extends FeatureAction { byte[] params = cmd.getParams(); if (params.length == 3) { int vendorId = ((params[0] & 0xFF) << 16) | ((params[1] & 0xFF) << 8) | (params[2] & 0xFF); int vendorId = HdmiUtils.threeBytesToInt(params); current.mVendorId = vendorId; } else { Slog.w(TAG, "Invalid vendor id: " + cmd.toString()); Loading services/core/java/com/android/server/hdmi/HdmiCecController.java +39 −0 Original line number Diff line number Diff line Loading @@ -386,6 +386,41 @@ final class HdmiCecController { return nativeGetVendorId(mNativePtr); } /** * Pass a option to CEC HAL. * * @param flag a key of option. For more details, look at * {@link HdmiConstants#FLAG_HDMI_OPTION_WAKEUP} to * {@link HdmiConstants#FLAG_HDMI_OPTION_SYSTEM_CEC_CONTROL} * @param value a value of option. Actual value varies flag. For more * details, look at description of flags */ void setOption(int flag, int value) { assertRunOnServiceThread(); nativeSetOption(mNativePtr, flag, value); } /** * Configure ARC circuit in the hardware logic to start or stop the feature. * * @param enabled whether to enable/disable ARC */ void setAudioReturnChannel(boolean enabled) { assertRunOnServiceThread(); nativeSetAudioReturnChannel(mNativePtr, enabled); } /** * Return the connection status of the specified port * * @param port port number to check connection status * @return true if connected; otherwise, return false */ boolean isConnected(int port) { assertRunOnServiceThread(); return nativeIsConnected(mNativePtr, port); } /** * Poll all remote devices. It sends <Polling Message> to all remote * devices. Loading Loading @@ -606,4 +641,8 @@ final class HdmiCecController { private static native int nativeGetPhysicalAddress(long controllerPtr); private static native int nativeGetVersion(long controllerPtr); private static native int nativeGetVendorId(long controllerPtr); private static native void nativeSetOption(long controllerPtr, int flag, int value); private static native void nativeSetAudioReturnChannel(long controllerPtr, boolean flag); private static native boolean nativeIsConnected(long controllerPtr, int port); } services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java +80 −0 Original line number Diff line number Diff line Loading @@ -18,12 +18,15 @@ package com.android.server.hdmi; import android.hardware.hdmi.HdmiCec; import android.hardware.hdmi.HdmiCecDeviceInfo; import android.hardware.hdmi.HdmiCecMessage; import android.util.Slog; /** * 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 { private static final String TAG = "HdmiCecLocalDevice"; protected final HdmiControlService mService; protected final int mDeviceType; Loading Loading @@ -59,6 +62,83 @@ abstract class HdmiCecLocalDevice { */ protected abstract void onAddressAllocated(int logicalAddress); /** * Dispatch incoming message. * * @param message incoming message * @return true if consumed a message; otherwise, return false. */ final boolean dispatchMessage(HdmiCecMessage message) { int dest = message.getDestination(); if (dest != mAddress && dest != HdmiCec.ADDR_BROADCAST) { return false; } return onMessage(message); } protected boolean onMessage(HdmiCecMessage message) { switch (message.getOpcode()) { case HdmiCec.MESSAGE_GET_MENU_LANGUAGE: return handleGetMenuLanguage(message); case HdmiCec.MESSAGE_GIVE_PHYSICAL_ADDRESS: return handleGivePhysicalAddress(); case HdmiCec.MESSAGE_GIVE_OSD_NAME: return handleGiveOsdName(message); case HdmiCec.MESSAGE_GIVE_DEVICE_VENDOR_ID: return handleGiveDeviceVendorId(); case HdmiCec.MESSAGE_GET_CEC_VERSION: return handleGetCecVersion(message); default: return false; } } protected boolean handleGivePhysicalAddress() { int physicalAddress = mService.getPhysicalAddress(); HdmiCecMessage cecMessage = HdmiCecMessageBuilder.buildReportPhysicalAddressCommand( mAddress, physicalAddress, mDeviceType); mService.sendCecCommand(cecMessage); return true; } protected boolean handleGiveDeviceVendorId() { int vendorId = mService.getVendorId(); HdmiCecMessage cecMessage = HdmiCecMessageBuilder.buildDeviceVendorIdCommand( mAddress, vendorId); mService.sendCecCommand(cecMessage); return true; } protected boolean handleGetCecVersion(HdmiCecMessage message) { int version = mService.getCecVersion(); HdmiCecMessage cecMessage = HdmiCecMessageBuilder.buildCecVersion(message.getDestination(), message.getSource(), version); mService.sendCecCommand(cecMessage); return true; } protected boolean handleGetMenuLanguage(HdmiCecMessage message) { Slog.w(TAG, "Only TV can handle <Get Menu Language>:" + message.toString()); mService.sendCecCommand( HdmiCecMessageBuilder.buildFeatureAbortCommand(mAddress, message.getSource(), HdmiCec.MESSAGE_GET_MENU_LANGUAGE, HdmiConstants.ABORT_UNRECOGNIZED_MODE)); return true; } protected boolean handleGiveOsdName(HdmiCecMessage message) { // Note that since this method is called after logical address allocation is done, // mDeviceInfo should not be null. HdmiCecMessage cecMessage = HdmiCecMessageBuilder.buildSetOsdNameCommand( mAddress, message.getSource(), mDeviceInfo.getDisplayName()); if (cecMessage != null) { mService.sendCecCommand(cecMessage); } else { Slog.w(TAG, "Failed to build <Get Osd Name>:" + mDeviceInfo.getDisplayName()); } return true; } final void handleAddressAllocated(int logicalAddress) { mAddress = mPreferredAddress = logicalAddress; onAddressAllocated(logicalAddress); Loading services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java +43 −0 Original line number Diff line number Diff line Loading @@ -17,11 +17,16 @@ package com.android.server.hdmi; import android.hardware.hdmi.HdmiCec; import android.hardware.hdmi.HdmiCecMessage; import android.util.Slog; import java.util.Locale; /** * Represent a logical device of type TV residing in Android system. */ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { private static final String TAG = "HdmiCecLocalDeviceTv"; HdmiCecLocalDeviceTv(HdmiControlService service) { super(service, HdmiCec.DEVICE_TV); Loading @@ -39,4 +44,42 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { mService.launchDeviceDiscovery(mAddress); // TODO: Start routing control action, device discovery action. } @Override protected boolean onMessage(HdmiCecMessage message) { switch (message.getOpcode()) { case HdmiCec.MESSAGE_REPORT_PHYSICAL_ADDRESS: return handleReportPhysicalAddress(message); default: return super.onMessage(message); } } @Override protected boolean handleGetMenuLanguage(HdmiCecMessage message) { HdmiCecMessage command = HdmiCecMessageBuilder.buildSetMenuLanguageCommand( mAddress, Locale.getDefault().getISO3Language()); // TODO: figure out how to handle failed to get language code. if (command != null) { mService.sendCecCommand(command); } else { Slog.w(TAG, "Failed to respond to <Get Menu Language>: " + message.toString()); } return true; } private boolean handleReportPhysicalAddress(HdmiCecMessage message) { // Ignore if [Device Discovery Action] is going on. if (mService.hasAction(DeviceDiscoveryAction.class)) { Slog.i(TAG, "Ignore unrecognizable <Report Physical Address> " + "because Device Discovery Action is on-going:" + message); return true; } int physicalAddress = HdmiUtils.twoBytesToInt(message.getParams()); mService.addAndStartAction(new NewDeviceAction(mService, mAddress, message.getSource(), physicalAddress)); return true; } } services/core/java/com/android/server/hdmi/HdmiConstants.java +26 −0 Original line number Diff line number Diff line Loading @@ -43,5 +43,31 @@ final class HdmiConstants { static final int UI_COMMAND_MUTE_FUNCTION = 0x65; static final int UI_COMMAND_RESTORE_VOLUME_FUNCTION = 0x66; // Flags used for setOption to CEC HAL. /** * When set to false, HAL does not wake up the system upon receiving * <Image View On> or <Text View On>. Used when user changes the TV * settings to disable the auto TV on functionality. * True by default. */ static final int FLAG_HDMI_OPTION_WAKEUP = 1; /** * When set to false, all the CEC commands are discarded. Used when * user changes the TV settings to disable CEC functionality. * True by default. */ static final int FLAG_HDMI_OPTION_ENABLE_CEC = 2; /** * Setting this flag to false means Android system will stop handling * CEC service and yield the control over to the microprocessor that is * powered on through the standby mode. When set to true, the system * will gain the control over, hence telling the microprocessor to stop * handling the cec commands. This is called when system goes * in and out of standby mode to notify the microprocessor that it should * start/stop handling CEC commands on behalf of the system. * False by default. */ static final int FLAG_HDMI_OPTION_SYSTEM_CEC_CONTROL = 3; private HdmiConstants() { /* cannot be instantiated */ } } Loading
services/core/java/com/android/server/hdmi/DeviceDiscoveryAction.java +2 −4 Original line number Diff line number Diff line Loading @@ -259,7 +259,7 @@ final class DeviceDiscoveryAction extends FeatureAction { byte params[] = cmd.getParams(); if (params.length == 3) { current.mPhysicalAddress = ((params[0] & 0xFF) << 8) | (params[1] & 0xFF); current.mPhysicalAddress = HdmiUtils.twoBytesToInt(params); current.mDeviceType = params[2] & 0xFF; increaseProcessedDeviceCount(); Loading Loading @@ -307,9 +307,7 @@ final class DeviceDiscoveryAction extends FeatureAction { byte[] params = cmd.getParams(); if (params.length == 3) { int vendorId = ((params[0] & 0xFF) << 16) | ((params[1] & 0xFF) << 8) | (params[2] & 0xFF); int vendorId = HdmiUtils.threeBytesToInt(params); current.mVendorId = vendorId; } else { Slog.w(TAG, "Invalid vendor id: " + cmd.toString()); Loading
services/core/java/com/android/server/hdmi/HdmiCecController.java +39 −0 Original line number Diff line number Diff line Loading @@ -386,6 +386,41 @@ final class HdmiCecController { return nativeGetVendorId(mNativePtr); } /** * Pass a option to CEC HAL. * * @param flag a key of option. For more details, look at * {@link HdmiConstants#FLAG_HDMI_OPTION_WAKEUP} to * {@link HdmiConstants#FLAG_HDMI_OPTION_SYSTEM_CEC_CONTROL} * @param value a value of option. Actual value varies flag. For more * details, look at description of flags */ void setOption(int flag, int value) { assertRunOnServiceThread(); nativeSetOption(mNativePtr, flag, value); } /** * Configure ARC circuit in the hardware logic to start or stop the feature. * * @param enabled whether to enable/disable ARC */ void setAudioReturnChannel(boolean enabled) { assertRunOnServiceThread(); nativeSetAudioReturnChannel(mNativePtr, enabled); } /** * Return the connection status of the specified port * * @param port port number to check connection status * @return true if connected; otherwise, return false */ boolean isConnected(int port) { assertRunOnServiceThread(); return nativeIsConnected(mNativePtr, port); } /** * Poll all remote devices. It sends <Polling Message> to all remote * devices. Loading Loading @@ -606,4 +641,8 @@ final class HdmiCecController { private static native int nativeGetPhysicalAddress(long controllerPtr); private static native int nativeGetVersion(long controllerPtr); private static native int nativeGetVendorId(long controllerPtr); private static native void nativeSetOption(long controllerPtr, int flag, int value); private static native void nativeSetAudioReturnChannel(long controllerPtr, boolean flag); private static native boolean nativeIsConnected(long controllerPtr, int port); }
services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java +80 −0 Original line number Diff line number Diff line Loading @@ -18,12 +18,15 @@ package com.android.server.hdmi; import android.hardware.hdmi.HdmiCec; import android.hardware.hdmi.HdmiCecDeviceInfo; import android.hardware.hdmi.HdmiCecMessage; import android.util.Slog; /** * 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 { private static final String TAG = "HdmiCecLocalDevice"; protected final HdmiControlService mService; protected final int mDeviceType; Loading Loading @@ -59,6 +62,83 @@ abstract class HdmiCecLocalDevice { */ protected abstract void onAddressAllocated(int logicalAddress); /** * Dispatch incoming message. * * @param message incoming message * @return true if consumed a message; otherwise, return false. */ final boolean dispatchMessage(HdmiCecMessage message) { int dest = message.getDestination(); if (dest != mAddress && dest != HdmiCec.ADDR_BROADCAST) { return false; } return onMessage(message); } protected boolean onMessage(HdmiCecMessage message) { switch (message.getOpcode()) { case HdmiCec.MESSAGE_GET_MENU_LANGUAGE: return handleGetMenuLanguage(message); case HdmiCec.MESSAGE_GIVE_PHYSICAL_ADDRESS: return handleGivePhysicalAddress(); case HdmiCec.MESSAGE_GIVE_OSD_NAME: return handleGiveOsdName(message); case HdmiCec.MESSAGE_GIVE_DEVICE_VENDOR_ID: return handleGiveDeviceVendorId(); case HdmiCec.MESSAGE_GET_CEC_VERSION: return handleGetCecVersion(message); default: return false; } } protected boolean handleGivePhysicalAddress() { int physicalAddress = mService.getPhysicalAddress(); HdmiCecMessage cecMessage = HdmiCecMessageBuilder.buildReportPhysicalAddressCommand( mAddress, physicalAddress, mDeviceType); mService.sendCecCommand(cecMessage); return true; } protected boolean handleGiveDeviceVendorId() { int vendorId = mService.getVendorId(); HdmiCecMessage cecMessage = HdmiCecMessageBuilder.buildDeviceVendorIdCommand( mAddress, vendorId); mService.sendCecCommand(cecMessage); return true; } protected boolean handleGetCecVersion(HdmiCecMessage message) { int version = mService.getCecVersion(); HdmiCecMessage cecMessage = HdmiCecMessageBuilder.buildCecVersion(message.getDestination(), message.getSource(), version); mService.sendCecCommand(cecMessage); return true; } protected boolean handleGetMenuLanguage(HdmiCecMessage message) { Slog.w(TAG, "Only TV can handle <Get Menu Language>:" + message.toString()); mService.sendCecCommand( HdmiCecMessageBuilder.buildFeatureAbortCommand(mAddress, message.getSource(), HdmiCec.MESSAGE_GET_MENU_LANGUAGE, HdmiConstants.ABORT_UNRECOGNIZED_MODE)); return true; } protected boolean handleGiveOsdName(HdmiCecMessage message) { // Note that since this method is called after logical address allocation is done, // mDeviceInfo should not be null. HdmiCecMessage cecMessage = HdmiCecMessageBuilder.buildSetOsdNameCommand( mAddress, message.getSource(), mDeviceInfo.getDisplayName()); if (cecMessage != null) { mService.sendCecCommand(cecMessage); } else { Slog.w(TAG, "Failed to build <Get Osd Name>:" + mDeviceInfo.getDisplayName()); } return true; } final void handleAddressAllocated(int logicalAddress) { mAddress = mPreferredAddress = logicalAddress; onAddressAllocated(logicalAddress); Loading
services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java +43 −0 Original line number Diff line number Diff line Loading @@ -17,11 +17,16 @@ package com.android.server.hdmi; import android.hardware.hdmi.HdmiCec; import android.hardware.hdmi.HdmiCecMessage; import android.util.Slog; import java.util.Locale; /** * Represent a logical device of type TV residing in Android system. */ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { private static final String TAG = "HdmiCecLocalDeviceTv"; HdmiCecLocalDeviceTv(HdmiControlService service) { super(service, HdmiCec.DEVICE_TV); Loading @@ -39,4 +44,42 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { mService.launchDeviceDiscovery(mAddress); // TODO: Start routing control action, device discovery action. } @Override protected boolean onMessage(HdmiCecMessage message) { switch (message.getOpcode()) { case HdmiCec.MESSAGE_REPORT_PHYSICAL_ADDRESS: return handleReportPhysicalAddress(message); default: return super.onMessage(message); } } @Override protected boolean handleGetMenuLanguage(HdmiCecMessage message) { HdmiCecMessage command = HdmiCecMessageBuilder.buildSetMenuLanguageCommand( mAddress, Locale.getDefault().getISO3Language()); // TODO: figure out how to handle failed to get language code. if (command != null) { mService.sendCecCommand(command); } else { Slog.w(TAG, "Failed to respond to <Get Menu Language>: " + message.toString()); } return true; } private boolean handleReportPhysicalAddress(HdmiCecMessage message) { // Ignore if [Device Discovery Action] is going on. if (mService.hasAction(DeviceDiscoveryAction.class)) { Slog.i(TAG, "Ignore unrecognizable <Report Physical Address> " + "because Device Discovery Action is on-going:" + message); return true; } int physicalAddress = HdmiUtils.twoBytesToInt(message.getParams()); mService.addAndStartAction(new NewDeviceAction(mService, mAddress, message.getSource(), physicalAddress)); return true; } }
services/core/java/com/android/server/hdmi/HdmiConstants.java +26 −0 Original line number Diff line number Diff line Loading @@ -43,5 +43,31 @@ final class HdmiConstants { static final int UI_COMMAND_MUTE_FUNCTION = 0x65; static final int UI_COMMAND_RESTORE_VOLUME_FUNCTION = 0x66; // Flags used for setOption to CEC HAL. /** * When set to false, HAL does not wake up the system upon receiving * <Image View On> or <Text View On>. Used when user changes the TV * settings to disable the auto TV on functionality. * True by default. */ static final int FLAG_HDMI_OPTION_WAKEUP = 1; /** * When set to false, all the CEC commands are discarded. Used when * user changes the TV settings to disable CEC functionality. * True by default. */ static final int FLAG_HDMI_OPTION_ENABLE_CEC = 2; /** * Setting this flag to false means Android system will stop handling * CEC service and yield the control over to the microprocessor that is * powered on through the standby mode. When set to true, the system * will gain the control over, hence telling the microprocessor to stop * handling the cec commands. This is called when system goes * in and out of standby mode to notify the microprocessor that it should * start/stop handling CEC commands on behalf of the system. * False by default. */ static final int FLAG_HDMI_OPTION_SYSTEM_CEC_CONTROL = 3; private HdmiConstants() { /* cannot be instantiated */ } }