diff options
19 files changed, 286 insertions, 262 deletions
diff --git a/services/core/Android.mk b/services/core/Android.mk index 11586eedfee4..88a83855bbb0 100644 --- a/services/core/Android.mk +++ b/services/core/Android.mk @@ -19,8 +19,9 @@ LOCAL_AIDL_INCLUDES += \ LOCAL_JAVA_LIBRARIES := \ services.net \ telephony-common \ + android.hardware.light@2.0-java \ android.hardware.power@1.0-java \ - android.hardware.light@2.0-java + android.hardware.tv.cec@1.0-java LOCAL_STATIC_JAVA_LIBRARIES := tzdata_update diff --git a/services/core/java/com/android/server/hdmi/Constants.java b/services/core/java/com/android/server/hdmi/Constants.java index 603402e32bfb..a2a55e532ef4 100644 --- a/services/core/java/com/android/server/hdmi/Constants.java +++ b/services/core/java/com/android/server/hdmi/Constants.java @@ -188,12 +188,6 @@ final class Constants { static final int INVALID_PHYSICAL_ADDRESS = HdmiDeviceInfo.PATH_INVALID; static final int PATH_INTERNAL = HdmiDeviceInfo.PATH_INTERNAL; - // Send result codes. It should be consistent with hdmi_cec.h's send_message error code. - static final int SEND_RESULT_SUCCESS = 0; - static final int SEND_RESULT_NAK = 1; - static final int SEND_RESULT_BUSY = 2; - static final int SEND_RESULT_FAILURE = 3; - // Strategy for device polling. // Should use "OR(|) operation of POLL_STRATEGY_XXX and POLL_ITERATION_XXX. static final int POLL_STRATEGY_MASK = 0x3; // first and second bit. @@ -231,26 +225,7 @@ final class Constants { static final int RECORDING_TYPE_OWN_SOURCE = 4; // Definitions used for setOption(). These should be in sync with the definition - // in hardware/libhardware/include/hardware/{hdmi_cec.h,mhl.h}. - - // TV gets turned on by incoming <Text/Image View On>. enabled by default. - // If set to disabled, TV won't turn on automatically. - static final int OPTION_CEC_AUTO_WAKEUP = 1; - - // If set to disabled, all CEC commands are discarded. - static final int OPTION_CEC_ENABLE = 2; - - // If set to disabled, system service yields control of CEC to sub-microcontroller. - // If enabled, it takes the control back. - static final int OPTION_CEC_SERVICE_CONTROL = 3; - - // Put other devices to standby when TV goes to standby. enabled by default. - // If set to disabled, TV doesn't send <Standby> to other devices. - static final int OPTION_CEC_AUTO_DEVICE_OFF = 4; - - // Passes the language used in the system when updated. The value to use is the 3 byte - // code as defined in ISO/FDIS 639-2. - static final int OPTION_CEC_SET_LANGUAGE = 5; + // in hardware/libhardware/include/hardware/mhl.h. // If set to disabled, TV does not switch ports when mobile device is connected. static final int OPTION_MHL_INPUT_SWITCHING = 101; diff --git a/services/core/java/com/android/server/hdmi/DeviceSelectAction.java b/services/core/java/com/android/server/hdmi/DeviceSelectAction.java index 5a1d896c74a6..c684a56ec5d4 100644 --- a/services/core/java/com/android/server/hdmi/DeviceSelectAction.java +++ b/services/core/java/com/android/server/hdmi/DeviceSelectAction.java @@ -16,13 +16,13 @@ package com.android.server.hdmi; -import android.hardware.hdmi.HdmiDeviceInfo; import android.hardware.hdmi.HdmiControlManager; +import android.hardware.hdmi.HdmiDeviceInfo; import android.hardware.hdmi.HdmiTvClient; import android.hardware.hdmi.IHdmiControlCallback; +import android.hardware.tv.cec.V1_0.SendMessageResult; import android.os.RemoteException; import android.util.Slog; - import com.android.server.hdmi.HdmiControlService.SendMessageCallback; /** @@ -95,7 +95,7 @@ final class DeviceSelectAction extends HdmiCecFeatureAction { sendCommand(mGivePowerStatus, new SendMessageCallback() { @Override public void onSendCompleted(int error) { - if (error != Constants.SEND_RESULT_SUCCESS) { + if (error != SendMessageResult.SUCCESS) { invokeCallback(HdmiControlManager.RESULT_COMMUNICATION_FAILED); finish(); return; diff --git a/services/core/java/com/android/server/hdmi/HdmiCecController.java b/services/core/java/com/android/server/hdmi/HdmiCecController.java index 687aaa1f4b22..461a9b0636e4 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecController.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecController.java @@ -17,23 +17,23 @@ package com.android.server.hdmi; import android.hardware.hdmi.HdmiPortInfo; +import android.hardware.tv.cec.V1_0.Result; +import android.hardware.tv.cec.V1_0.SendMessageResult; import android.os.Handler; import android.os.Looper; import android.os.MessageQueue; import android.util.Slog; import android.util.SparseArray; - import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.Predicate; import com.android.server.hdmi.HdmiAnnotations.IoThreadOnly; import com.android.server.hdmi.HdmiAnnotations.ServiceThreadOnly; import com.android.server.hdmi.HdmiControlService.DevicePollingCallback; - -import libcore.util.EmptyArray; - import java.util.ArrayList; import java.util.LinkedList; import java.util.List; +import libcore.util.EmptyArray; +import sun.util.locale.LanguageTag; /** * Manages HDMI-CEC command and behaviors. It converts user's command into CEC command @@ -256,7 +256,7 @@ final class HdmiCecController { if (HdmiUtils.isValidAddress(newLogicalAddress)) { return nativeAddLogicalAddress(mNativePtr, newLogicalAddress); } else { - return -1; + return Result.FAILURE_INVALID_ARGS; } } @@ -320,13 +320,27 @@ final class HdmiCecController { * Set an option to CEC HAL. * * @param flag key of option - * @param value value of option + * @param enabled whether to enable/disable the given option. + */ + @ServiceThreadOnly + void setOption(int flag, boolean enabled) { + assertRunOnServiceThread(); + HdmiLogger.debug("setOption: [flag:%d, enabled:%b]", flag, enabled); + nativeSetOption(mNativePtr, flag, enabled); + } + + /** + * Informs CEC HAL about the current system language. + * + * @param language Three-letter code defined in ISO/FDIS 639-2. Must be lowercase letters. */ @ServiceThreadOnly - void setOption(int flag, int value) { + void setLanguage(String language) { assertRunOnServiceThread(); - HdmiLogger.debug("setOption: [flag:%d, value:%d]", flag, value); - nativeSetOption(mNativePtr, flag, value); + if (!LanguageTag.isLanguage(language)) { + return; + } + nativeSetLanguage(mNativePtr, language); } /** @@ -336,9 +350,9 @@ final class HdmiCecController { * @param enabled whether to enable/disable ARC */ @ServiceThreadOnly - void setAudioReturnChannel(int port, boolean enabled) { + void enableAudioReturnChannel(int port, boolean enabled) { assertRunOnServiceThread(); - nativeSetAudioReturnChannel(mNativePtr, port, enabled); + nativeEnableAudioReturnChannel(mNativePtr, port, enabled); } /** @@ -472,9 +486,9 @@ final class HdmiCecController { // <Polling Message> is a message which has empty body. int ret = nativeSendCecCommand(mNativePtr, sourceAddress, destinationAddress, EMPTY_BODY); - if (ret == Constants.SEND_RESULT_SUCCESS) { + if (ret == SendMessageResult.SUCCESS) { return true; - } else if (ret != Constants.SEND_RESULT_NAK) { + } else if (ret != SendMessageResult.NACK) { // Unusual failure HdmiLogger.warning("Failed to send a polling message(%d->%d) with return code %d", sourceAddress, destinationAddress, ret); @@ -572,17 +586,17 @@ final class HdmiCecController { HdmiLogger.debug("[S]:" + cecMessage); byte[] body = buildBody(cecMessage.getOpcode(), cecMessage.getParams()); int i = 0; - int errorCode = Constants.SEND_RESULT_SUCCESS; + int errorCode = SendMessageResult.SUCCESS; do { errorCode = nativeSendCecCommand(mNativePtr, cecMessage.getSource(), cecMessage.getDestination(), body); - if (errorCode == Constants.SEND_RESULT_SUCCESS) { + if (errorCode == SendMessageResult.SUCCESS) { break; } } while (i++ < HdmiConfig.RETRANSMISSION_COUNT); final int finalError = errorCode; - if (finalError != Constants.SEND_RESULT_SUCCESS) { + if (finalError != SendMessageResult.SUCCESS) { Slog.w(TAG, "Failed to send " + cecMessage); } if (callback != null) { @@ -636,7 +650,8 @@ final class HdmiCecController { private static native int nativeGetVersion(long controllerPtr); private static native int nativeGetVendorId(long controllerPtr); private static native HdmiPortInfo[] nativeGetPortInfos(long controllerPtr); - private static native void nativeSetOption(long controllerPtr, int flag, int value); - private static native void nativeSetAudioReturnChannel(long controllerPtr, int port, boolean flag); + private static native void nativeSetOption(long controllerPtr, int flag, boolean enabled); + private static native void nativeSetLanguage(long controllerPtr, String language); + private static native void nativeEnableAudioReturnChannel(long controllerPtr, int port, boolean flag); private static native boolean nativeIsConnected(long controllerPtr, int port); } diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java index 43d8bac73a50..c85d97962a22 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java @@ -36,6 +36,7 @@ import android.hardware.hdmi.HdmiPortInfo; import android.hardware.hdmi.HdmiRecordSources; import android.hardware.hdmi.HdmiTimerRecordSources; import android.hardware.hdmi.IHdmiControlCallback; +import android.hardware.tv.cec.V1_0.SendMessageResult; import android.media.AudioManager; import android.media.AudioSystem; import android.media.tv.TvInputInfo; @@ -46,7 +47,6 @@ import android.util.ArraySet; import android.util.Slog; import android.util.SparseArray; import android.util.SparseBooleanArray; - import com.android.internal.annotations.GuardedBy; import com.android.internal.util.IndentingPrintWriter; import com.android.server.hdmi.DeviceDiscoveryAction.DeviceDiscoveryCallback; @@ -57,9 +57,9 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.HashMap; import java.util.Iterator; import java.util.List; -import java.util.HashMap; /** * Represent a logical device of type TV residing in Android system. @@ -910,7 +910,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { HdmiLogger.debug("Set Arc Status[old:%b new:%b]", mArcEstablished, enabled); boolean oldStatus = mArcEstablished; // 1. Enable/disable ARC circuit. - setAudioReturnChannel(enabled); + enableAudioReturnChannel(enabled); // 2. Notify arc status to audio service. notifyArcStatusToAudioService(enabled); // 3. Update arc status; @@ -922,11 +922,11 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { * Switch hardware ARC circuit in the system. */ @ServiceThreadOnly - void setAudioReturnChannel(boolean enabled) { + void enableAudioReturnChannel(boolean enabled) { assertRunOnServiceThread(); HdmiDeviceInfo avr = getAvrDeviceInfo(); if (avr != null) { - mService.setAudioReturnChannel(avr.getPortId(), enabled); + mService.enableAudioReturnChannel(avr.getPortId(), enabled); } } @@ -1870,7 +1870,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { mService.sendCecCommand(message, new SendMessageCallback() { @Override public void onSendCompleted(int error) { - if (error != Constants.SEND_RESULT_SUCCESS) { + if (error != SendMessageResult.SUCCESS) { announceClearTimerRecordingResult(recorderAddress, CLEAR_TIMER_STATUS_FAIL_TO_CLEAR_SELECTED_SOURCE); } diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java index 72ee218fba2c..18f1b6c0513c 100644 --- a/services/core/java/com/android/server/hdmi/HdmiControlService.java +++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java @@ -20,10 +20,6 @@ import static android.hardware.hdmi.HdmiControlManager.DEVICE_EVENT_ADD_DEVICE; import static android.hardware.hdmi.HdmiControlManager.DEVICE_EVENT_REMOVE_DEVICE; import static com.android.server.hdmi.Constants.DISABLED; import static com.android.server.hdmi.Constants.ENABLED; -import static com.android.server.hdmi.Constants.OPTION_CEC_AUTO_WAKEUP; -import static com.android.server.hdmi.Constants.OPTION_CEC_ENABLE; -import static com.android.server.hdmi.Constants.OPTION_CEC_SERVICE_CONTROL; -import static com.android.server.hdmi.Constants.OPTION_CEC_SET_LANGUAGE; import static com.android.server.hdmi.Constants.OPTION_MHL_ENABLE; import static com.android.server.hdmi.Constants.OPTION_MHL_INPUT_SWITCHING; import static com.android.server.hdmi.Constants.OPTION_MHL_POWER_CHARGE; @@ -49,6 +45,8 @@ import android.hardware.hdmi.IHdmiMhlVendorCommandListener; import android.hardware.hdmi.IHdmiRecordListener; import android.hardware.hdmi.IHdmiSystemAudioModeChangeListener; import android.hardware.hdmi.IHdmiVendorCommandListener; +import android.hardware.tv.cec.V1_0.OptionKey; +import android.hardware.tv.cec.V1_0.SendMessageResult; import android.media.AudioManager; import android.media.tv.TvInputManager; import android.media.tv.TvInputManager.TvInputCallback; @@ -69,7 +67,6 @@ import android.util.ArraySet; import android.util.Slog; import android.util.SparseArray; import android.util.SparseIntArray; - import com.android.internal.annotations.GuardedBy; import com.android.internal.util.IndentingPrintWriter; import com.android.server.SystemService; @@ -77,11 +74,6 @@ import com.android.server.hdmi.HdmiAnnotations.ServiceThreadOnly; import com.android.server.hdmi.HdmiCecController.AllocateAddressCallback; import com.android.server.hdmi.HdmiCecLocalDevice.ActiveSource; import com.android.server.hdmi.HdmiCecLocalDevice.PendingActionClearedCallback; -import com.android.server.hdmi.SelectRequestBuffer.DeviceSelectRequest; -import com.android.server.hdmi.SelectRequestBuffer.PortSelectRequest; - -import libcore.util.EmptyArray; - import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; @@ -89,6 +81,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Locale; +import libcore.util.EmptyArray; /** * Provides a service for sending and processing HDMI control messages, @@ -123,9 +116,10 @@ public final class HdmiControlService extends SystemService { * * @param error result of send request. * <ul> - * <li>{@link Constants#SEND_RESULT_SUCCESS} - * <li>{@link Constants#SEND_RESULT_NAK} - * <li>{@link Constants#SEND_RESULT_FAILURE} + * <li>{@link SendMessageResult#SUCCESS} + * <li>{@link SendMessageResult#NACK} + * <li>{@link SendMessageResult#BUSY} + * <li>{@link SendMessageResult#FAIL} * </ul> */ void onSendCompleted(int error); @@ -466,7 +460,7 @@ public final class HdmiControlService extends SystemService { mWakeUpMessageReceived = false; if (isTvDeviceEnabled()) { - mCecController.setOption(OPTION_CEC_AUTO_WAKEUP, toInt(tv().getAutoWakeup())); + mCecController.setOption(OptionKey.WAKEUP, tv().getAutoWakeup()); } int reason = -1; switch (initiatedBy) { @@ -519,7 +513,7 @@ public final class HdmiControlService extends SystemService { if (isTvDeviceEnabled()) { tv().setAutoWakeup(enabled); } - setCecOption(OPTION_CEC_AUTO_WAKEUP, toInt(enabled)); + setCecOption(OptionKey.WAKEUP, enabled); break; case Global.HDMI_CONTROL_AUTO_DEVICE_OFF_ENABLED: for (int type : mLocalDevices) { @@ -556,8 +550,8 @@ public final class HdmiControlService extends SystemService { private void initializeCec(int initiatedBy) { mAddressAllocated = false; - mCecController.setOption(OPTION_CEC_SERVICE_CONTROL, ENABLED); - mCecController.setOption(OPTION_CEC_SET_LANGUAGE, HdmiUtils.languageToInt(mLanguage)); + mCecController.setOption(OptionKey.SYSTEM_CEC_CONTROL, true); + mCecController.setLanguage(mLanguage); initializeLocalDevices(initiatedBy); } @@ -842,7 +836,7 @@ public final class HdmiControlService extends SystemService { } else { HdmiLogger.error("Invalid message type:" + command); if (callback != null) { - callback.onSendCompleted(Constants.SEND_RESULT_FAILURE); + callback.onSendCompleted(SendMessageResult.FAIL); } } } @@ -884,8 +878,8 @@ public final class HdmiControlService extends SystemService { return dispatchMessageToLocalDevice(message); } - void setAudioReturnChannel(int portId, boolean enabled) { - mCecController.setAudioReturnChannel(portId, enabled); + void enableAudioReturnChannel(int portId, boolean enabled) { + mCecController.enableAudioReturnChannel(portId, enabled); } @ServiceThreadOnly @@ -2079,7 +2073,7 @@ public final class HdmiControlService extends SystemService { if (isTvDeviceEnabled()) { tv().broadcastMenuLanguage(language); - mCecController.setOption(OPTION_CEC_SET_LANGUAGE, HdmiUtils.languageToInt(language)); + mCecController.setLanguage(language); } } @@ -2123,7 +2117,7 @@ public final class HdmiControlService extends SystemService { } mStandbyMessageReceived = false; mAddressAllocated = false; - mCecController.setOption(OPTION_CEC_SERVICE_CONTROL, DISABLED); + mCecController.setOption(OptionKey.SYSTEM_CEC_CONTROL, false); mMhlController.setOption(OPTION_MHL_SERVICE_CONTROL, DISABLED); } @@ -2216,7 +2210,7 @@ public final class HdmiControlService extends SystemService { } @ServiceThreadOnly - void setCecOption(int key, int value) { + void setCecOption(int key, boolean value) { assertRunOnServiceThread(); mCecController.setOption(key, value); } @@ -2249,7 +2243,7 @@ public final class HdmiControlService extends SystemService { @ServiceThreadOnly private void enableHdmiControlService() { - mCecController.setOption(OPTION_CEC_ENABLE, ENABLED); + mCecController.setOption(OptionKey.SYSTEM_CEC_CONTROL, true); mMhlController.setOption(OPTION_MHL_ENABLE, ENABLED); initializeCec(INITIATED_BY_ENABLE_CEC); @@ -2264,7 +2258,7 @@ public final class HdmiControlService extends SystemService { mCecController.flush(new Runnable() { @Override public void run() { - mCecController.setOption(OPTION_CEC_ENABLE, DISABLED); + mCecController.setOption(OptionKey.ENABLE_CEC, false); mMhlController.setOption(OPTION_MHL_ENABLE, DISABLED); clearLocalDevices(); } diff --git a/services/core/java/com/android/server/hdmi/HdmiUtils.java b/services/core/java/com/android/server/hdmi/HdmiUtils.java index 9aa9290e7f72..8b1641187ac8 100644 --- a/services/core/java/com/android/server/hdmi/HdmiUtils.java +++ b/services/core/java/com/android/server/hdmi/HdmiUtils.java @@ -291,18 +291,4 @@ final class HdmiUtils { info.getPhysicalAddress(), info.getPortId(), info.getDeviceType(), info.getVendorId(), info.getDisplayName(), newPowerStatus); } - - /** - * Convert 3 byte-long language code in string to integer representation. - * English(eng), for example, is converted to 0x656e67. - * - * @param language language code in string - * @return language code in integer representation - */ - static int languageToInt(String language) { - String normalized = language.toLowerCase(); - return ((normalized.charAt(0) & 0xFF) << 16) - | ((normalized.charAt(1) & 0xFF) << 8) - | (normalized.charAt(2) & 0xFF); - } } diff --git a/services/core/java/com/android/server/hdmi/HotplugDetectionAction.java b/services/core/java/com/android/server/hdmi/HotplugDetectionAction.java index 5f2d65172180..e1bcd9952457 100644 --- a/services/core/java/com/android/server/hdmi/HotplugDetectionAction.java +++ b/services/core/java/com/android/server/hdmi/HotplugDetectionAction.java @@ -265,7 +265,7 @@ final class HotplugDetectionAction extends HdmiCecFeatureAction { // Turn off system audio mode and update settings. tv().setSystemAudioMode(false, true); if (tv().isArcEstablished()) { - tv().setAudioReturnChannel(false); + tv().enableAudioReturnChannel(false); addAndStartAction(new RequestArcTerminationAction(localDevice(), address)); } } diff --git a/services/core/java/com/android/server/hdmi/OneTouchRecordAction.java b/services/core/java/com/android/server/hdmi/OneTouchRecordAction.java index d80b81f6fe4a..39de8ffa2a75 100644 --- a/services/core/java/com/android/server/hdmi/OneTouchRecordAction.java +++ b/services/core/java/com/android/server/hdmi/OneTouchRecordAction.java @@ -22,8 +22,8 @@ import static android.hardware.hdmi.HdmiControlManager.ONE_TOUCH_RECORD_RECORDIN import static android.hardware.hdmi.HdmiControlManager.ONE_TOUCH_RECORD_RECORDING_DIGITAL_SERVICE; import static android.hardware.hdmi.HdmiControlManager.ONE_TOUCH_RECORD_RECORDING_EXTERNAL_INPUT; +import android.hardware.tv.cec.V1_0.SendMessageResult; import android.util.Slog; - import com.android.server.hdmi.HdmiControlService.SendMessageCallback; /** @@ -62,7 +62,7 @@ public class OneTouchRecordAction extends HdmiCecFeatureAction { @Override public void onSendCompleted(int error) { // if failed to send <Record On>, display error message and finish action. - if (error != Constants.SEND_RESULT_SUCCESS) { + if (error != SendMessageResult.SUCCESS) { tv().announceOneTouchRecordResult( mRecorderAddress, ONE_TOUCH_RECORD_CHECK_RECORDER_CONNECTION); diff --git a/services/core/java/com/android/server/hdmi/PowerStatusMonitorAction.java b/services/core/java/com/android/server/hdmi/PowerStatusMonitorAction.java index fd7a7f9a887a..6893012342f9 100644 --- a/services/core/java/com/android/server/hdmi/PowerStatusMonitorAction.java +++ b/services/core/java/com/android/server/hdmi/PowerStatusMonitorAction.java @@ -18,10 +18,9 @@ package com.android.server.hdmi; import static android.hardware.hdmi.HdmiControlManager.POWER_STATUS_UNKNOWN; import android.hardware.hdmi.HdmiDeviceInfo; +import android.hardware.tv.cec.V1_0.SendMessageResult; import android.util.SparseIntArray; - import com.android.server.hdmi.HdmiControlService.SendMessageCallback; - import java.util.List; /** @@ -123,7 +122,7 @@ public class PowerStatusMonitorAction extends HdmiCecFeatureAction { public void onSendCompleted(int error) { // If fails to send <Give Device Power Status>, // update power status into UNKNOWN. - if (error != Constants.SEND_RESULT_SUCCESS) { + if (error != SendMessageResult.SUCCESS) { updatePowerStatus(logicalAddress, POWER_STATUS_UNKNOWN, true); } } diff --git a/services/core/java/com/android/server/hdmi/RequestArcInitiationAction.java b/services/core/java/com/android/server/hdmi/RequestArcInitiationAction.java index f69f975a4b67..4eb220fd65ee 100644 --- a/services/core/java/com/android/server/hdmi/RequestArcInitiationAction.java +++ b/services/core/java/com/android/server/hdmi/RequestArcInitiationAction.java @@ -16,6 +16,8 @@ package com.android.server.hdmi; +import android.hardware.tv.cec.V1_0.SendMessageResult; + /** * Feature action that handles ARC action initiated by TV devices. * @@ -44,7 +46,7 @@ final class RequestArcInitiationAction extends RequestArcAction { sendCommand(command, new HdmiControlService.SendMessageCallback() { @Override public void onSendCompleted(int error) { - if (error != Constants.SEND_RESULT_SUCCESS) { + if (error != SendMessageResult.SUCCESS) { // Turn off ARC status if <Request ARC Initiation> fails. tv().setArcStatus(false); finish(); diff --git a/services/core/java/com/android/server/hdmi/RequestArcTerminationAction.java b/services/core/java/com/android/server/hdmi/RequestArcTerminationAction.java index f5a01156cc92..8b5a29310233 100644 --- a/services/core/java/com/android/server/hdmi/RequestArcTerminationAction.java +++ b/services/core/java/com/android/server/hdmi/RequestArcTerminationAction.java @@ -16,6 +16,8 @@ package com.android.server.hdmi; +import android.hardware.tv.cec.V1_0.SendMessageResult; + /** * Feature action to handle <Request ARC Termination>. * @@ -43,7 +45,7 @@ final class RequestArcTerminationAction extends RequestArcAction { sendCommand(command, new HdmiControlService.SendMessageCallback() { @Override public void onSendCompleted(int error) { - if (error != Constants.SEND_RESULT_SUCCESS) { + if (error != SendMessageResult.SUCCESS) { // If failed to send <Request ARC Termination>, start "Disabled" ARC // transmission action. disableArcTransmission(); diff --git a/services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java b/services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java index 9b4950b5b1ba..6633789ffc06 100644 --- a/services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java +++ b/services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java @@ -17,6 +17,7 @@ package com.android.server.hdmi; import android.hardware.hdmi.HdmiDeviceInfo; +import android.hardware.tv.cec.V1_0.SendMessageResult; import android.util.Slog; /** @@ -81,14 +82,14 @@ final class SetArcTransmissionStateAction extends HdmiCecFeatureAction { @Override public void onSendCompleted(int error) { switch (error) { - case Constants.SEND_RESULT_SUCCESS: - case Constants.SEND_RESULT_BUSY: - case Constants.SEND_RESULT_FAILURE: + case SendMessageResult.SUCCESS: + case SendMessageResult.BUSY: + case SendMessageResult.FAIL: // The result of the command transmission, unless it is an obvious // failure indicated by the target device (or lack thereof), should // not affect the ARC status. Ignores it silently. break; - case Constants.SEND_RESULT_NAK: + case SendMessageResult.NACK: // If <Report ARC Initiated> is negatively ack'ed, disable ARC and // send <Report ARC Terminated> directly. setArcStatus(false); diff --git a/services/core/java/com/android/server/hdmi/SystemAudioAction.java b/services/core/java/com/android/server/hdmi/SystemAudioAction.java index a209cd0cca73..af1a85d31443 100644 --- a/services/core/java/com/android/server/hdmi/SystemAudioAction.java +++ b/services/core/java/com/android/server/hdmi/SystemAudioAction.java @@ -17,12 +17,12 @@ package com.android.server.hdmi; import android.annotation.Nullable; -import android.hardware.hdmi.HdmiDeviceInfo; import android.hardware.hdmi.HdmiControlManager; +import android.hardware.hdmi.HdmiDeviceInfo; import android.hardware.hdmi.IHdmiControlCallback; +import android.hardware.tv.cec.V1_0.SendMessageResult; import android.os.RemoteException; import android.util.Slog; - import java.util.List; /** @@ -96,7 +96,7 @@ abstract class SystemAudioAction extends HdmiCecFeatureAction { sendCommand(command, new HdmiControlService.SendMessageCallback() { @Override public void onSendCompleted(int error) { - if (error != Constants.SEND_RESULT_SUCCESS) { + if (error != SendMessageResult.SUCCESS) { HdmiLogger.debug("Failed to send <System Audio Mode Request>:" + error); setSystemAudioMode(false); finishWithCallback(HdmiControlManager.RESULT_COMMUNICATION_FAILED); diff --git a/services/core/java/com/android/server/hdmi/SystemAudioAutoInitiationAction.java b/services/core/java/com/android/server/hdmi/SystemAudioAutoInitiationAction.java index 78b40fd1892d..01063b757d43 100644 --- a/services/core/java/com/android/server/hdmi/SystemAudioAutoInitiationAction.java +++ b/services/core/java/com/android/server/hdmi/SystemAudioAutoInitiationAction.java @@ -16,6 +16,7 @@ package com.android.server.hdmi; +import android.hardware.tv.cec.V1_0.SendMessageResult; import com.android.server.hdmi.HdmiControlService.SendMessageCallback; /** @@ -48,7 +49,7 @@ final class SystemAudioAutoInitiationAction extends HdmiCecFeatureAction { mAvrAddress), new SendMessageCallback() { @Override public void onSendCompleted(int error) { - if (error != Constants.SEND_RESULT_SUCCESS) { + if (error != SendMessageResult.SUCCESS) { tv().setSystemAudioMode(false, true); finish(); } diff --git a/services/core/java/com/android/server/hdmi/SystemAudioStatusAction.java b/services/core/java/com/android/server/hdmi/SystemAudioStatusAction.java index 2ae5c979690d..cab8439b6f92 100644 --- a/services/core/java/com/android/server/hdmi/SystemAudioStatusAction.java +++ b/services/core/java/com/android/server/hdmi/SystemAudioStatusAction.java @@ -19,9 +19,9 @@ package com.android.server.hdmi; import android.annotation.Nullable; import android.hardware.hdmi.HdmiControlManager; import android.hardware.hdmi.IHdmiControlCallback; +import android.hardware.tv.cec.V1_0.SendMessageResult; import android.os.RemoteException; import android.util.Slog; - import com.android.server.hdmi.HdmiControlService.SendMessageCallback; /** @@ -56,7 +56,7 @@ final class SystemAudioStatusAction extends HdmiCecFeatureAction { new SendMessageCallback() { @Override public void onSendCompleted(int error) { - if (error != Constants.SEND_RESULT_SUCCESS) { + if (error != SendMessageResult.SUCCESS) { handleSendGiveAudioStatusFailure(); } } diff --git a/services/core/java/com/android/server/hdmi/TimerRecordingAction.java b/services/core/java/com/android/server/hdmi/TimerRecordingAction.java index 16fc25fb1917..525e223b2528 100644 --- a/services/core/java/com/android/server/hdmi/TimerRecordingAction.java +++ b/services/core/java/com/android/server/hdmi/TimerRecordingAction.java @@ -22,10 +22,9 @@ import static android.hardware.hdmi.HdmiControlManager.TIMER_RECORDING_TYPE_ANAL import static android.hardware.hdmi.HdmiControlManager.TIMER_RECORDING_TYPE_DIGITAL; import static android.hardware.hdmi.HdmiControlManager.TIMER_RECORDING_TYPE_EXTERNAL; +import android.hardware.tv.cec.V1_0.SendMessageResult; import android.util.Slog; - import com.android.server.hdmi.HdmiControlService.SendMessageCallback; - import java.util.Arrays; /** @@ -82,7 +81,7 @@ public class TimerRecordingAction extends HdmiCecFeatureAction { sendCommand(message, new SendMessageCallback() { @Override public void onSendCompleted(int error) { - if (error != Constants.SEND_RESULT_SUCCESS) { + if (error != SendMessageResult.SUCCESS) { tv().announceTimerRecordingResult(mRecorderAddress, TIMER_RECORDING_RESULT_EXTRA_CHECK_RECORDER_CONNECTION); finish(); diff --git a/services/core/jni/Android.mk b/services/core/jni/Android.mk index 3a9ff5fe8734..a4b5e6afdc8a 100644 --- a/services/core/jni/Android.mk +++ b/services/core/jni/Android.mk @@ -67,10 +67,11 @@ LOCAL_SHARED_LIBRARIES += \ libhidl \ libhwbinder \ libutils \ + android.hardware.audio.common@2.0 \ + android.hardware.light@2.0 \ android.hardware.power@1.0 \ + android.hardware.thermal@1.0 \ + android.hardware.tv.cec@1.0 \ + android.hardware.tv.input@1.0 \ android.hardware.vibrator@1.0 \ - android.hardware.light@2.0 \ android.hardware.vr@1.0 \ - android.hardware.audio.common@2.0 \ - android.hardware.tv.input@1.0 \ - android.hardware.thermal@1.0 \ diff --git a/services/core/jni/com_android_server_hdmi_HdmiCecController.cpp b/services/core/jni/com_android_server_hdmi_HdmiCecController.cpp index a23fbcbd42c7..0c5729e9b32c 100644 --- a/services/core/jni/com_android_server_hdmi_HdmiCecController.cpp +++ b/services/core/jni/com_android_server_hdmi_HdmiCecController.cpp @@ -21,16 +21,32 @@ #include <JNIHelp.h> #include <ScopedPrimitiveArray.h> -#include <cstring> - +#include <android/hardware/tv/cec/1.0/IHdmiCec.h> +#include <android/hardware/tv/cec/1.0/IHdmiCecCallback.h> +#include <android/hardware/tv/cec/1.0/types.h> #include <android_os_MessageQueue.h> #include <android_runtime/AndroidRuntime.h> #include <android_runtime/Log.h> -#include <hardware/hdmi_cec.h> #include <sys/param.h> +#include <utils/Errors.h> #include <utils/Looper.h> #include <utils/RefBase.h> +using ::android::hardware::tv::cec::V1_0::CecLogicalAddress; +using ::android::hardware::tv::cec::V1_0::CecMessage; +using ::android::hardware::tv::cec::V1_0::HdmiPortInfo; +using ::android::hardware::tv::cec::V1_0::HotplugEvent; +using ::android::hardware::tv::cec::V1_0::IHdmiCec; +using ::android::hardware::tv::cec::V1_0::IHdmiCecCallback; +using ::android::hardware::tv::cec::V1_0::MaxLength; +using ::android::hardware::tv::cec::V1_0::OptionKey; +using ::android::hardware::tv::cec::V1_0::Result; +using ::android::hardware::tv::cec::V1_0::SendMessageResult; +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::hardware::hidl_vec; +using ::android::hardware::hidl_string; + namespace android { static struct { @@ -40,15 +56,13 @@ static struct { class HdmiCecController { public: - HdmiCecController(hdmi_cec_device_t* device, jobject callbacksObj, - const sp<Looper>& looper); - - void init(); + HdmiCecController(sp<IHdmiCec> hdmiCec, jobject callbacksObj, const sp<Looper>& looper); + ~HdmiCecController(); // Send message to other device. Note that it runs in IO thread. - int sendMessage(const cec_message_t& message); + int sendMessage(const CecMessage& message); // Add a logical address to device. - int addLogicalAddress(cec_logical_address_t address); + int addLogicalAddress(CecLogicalAddress address); // Clear all logical address registered to the device. void clearLogicaladdress(); // Get physical address of device. @@ -59,10 +73,12 @@ public: uint32_t getVendorId(); // Get Port information on all the HDMI ports. jobjectArray getPortInfos(); - // Set a flag and its value. - void setOption(int flag, int value); - // Set audio return channel status. - void setAudioReturnChannel(int port, bool flag); + // Set an option to CEC HAL. + void setOption(OptionKey key, bool enabled); + // Informs CEC HAL about the current system language. + void setLanguage(hidl_string language); + // Enable audio return channel. + void enableAudioReturnChannel(int port, bool flag); // Whether to hdmi device is connected to the given port. bool isConnected(int port); @@ -71,69 +87,48 @@ public: } private: + class HdmiCecCallback : public IHdmiCecCallback { + public: + HdmiCecCallback(HdmiCecController* controller) : mController(controller) {}; + Return<void> onCecMessage(const CecMessage& event) override; + Return<void> onHotplugEvent(const HotplugEvent& event) override; + private: + HdmiCecController* mController; + }; + static const int INVALID_PHYSICAL_ADDRESS = 0xFFFF; - static void onReceived(const hdmi_event_t* event, void* arg); - hdmi_cec_device_t* mDevice; + sp<IHdmiCec> mHdmiCec; jobject mCallbacksObj; + sp<IHdmiCecCallback> mHdmiCecCallback; sp<Looper> mLooper; }; -// RefBase wrapper for hdmi_event_t. As hdmi_event_t coming from HAL -// may keep its own lifetime, we need to copy it in order to delegate -// it to service thread. -class CecEventWrapper : public LightRefBase<CecEventWrapper> { -public: - explicit CecEventWrapper(const hdmi_event_t& event) { - // Copy message. - switch (event.type) { - case HDMI_EVENT_CEC_MESSAGE: - mEvent.cec.initiator = event.cec.initiator; - mEvent.cec.destination = event.cec.destination; - mEvent.cec.length = event.cec.length; - std::memcpy(mEvent.cec.body, event.cec.body, event.cec.length); - break; - case HDMI_EVENT_HOT_PLUG: - mEvent.hotplug.connected = event.hotplug.connected; - mEvent.hotplug.port_id = event.hotplug.port_id; - break; - default: - // TODO: add more type whenever new type is introduced. - break; - } - } - - const cec_message_t& cec() const { - return mEvent.cec; - } - - const hotplug_event_t& hotplug() const { - return mEvent.hotplug; - } - - virtual ~CecEventWrapper() {} - -private: - hdmi_event_t mEvent; -}; - // Handler class to delegate incoming message to service thread. class HdmiCecEventHandler : public MessageHandler { public: - HdmiCecEventHandler(HdmiCecController* controller, const sp<CecEventWrapper>& event) - : mController(controller), - mEventWrapper(event) { - } + enum EventType { + CEC_MESSAGE, + HOT_PLUG + }; + + HdmiCecEventHandler(HdmiCecController* controller, const CecMessage& cecMessage) + : mController(controller), + mCecMessage(cecMessage) {} + + HdmiCecEventHandler(HdmiCecController* controller, const HotplugEvent& hotplugEvent) + : mController(controller), + mHotplugEvent(hotplugEvent) {} virtual ~HdmiCecEventHandler() {} void handleMessage(const Message& message) { switch (message.what) { - case HDMI_EVENT_CEC_MESSAGE: - propagateCecCommand(mEventWrapper->cec()); + case EventType::CEC_MESSAGE: + propagateCecCommand(mCecMessage); break; - case HDMI_EVENT_HOT_PLUG: - propagateHotplugEvent(mEventWrapper->hotplug()); + case EventType::HOT_PLUG: + propagateHotplugEvent(mHotplugEvent); break; default: // TODO: add more type whenever new type is introduced. @@ -143,14 +138,13 @@ public: private: // Propagate the message up to Java layer. - void propagateCecCommand(const cec_message_t& message) { - jint srcAddr = message.initiator; - jint dstAddr = message.destination; + void propagateCecCommand(const CecMessage& message) { JNIEnv* env = AndroidRuntime::getJNIEnv(); - jbyteArray body = env->NewByteArray(message.length); - const jbyte* bodyPtr = reinterpret_cast<const jbyte *>(message.body); - env->SetByteArrayRegion(body, 0, message.length, bodyPtr); - + jint srcAddr = static_cast<jint>(message.initiator); + jint dstAddr = static_cast<jint>(message.destination); + jbyteArray body = env->NewByteArray(message.body.size()); + const jbyte* bodyPtr = reinterpret_cast<const jbyte *>(message.body.data()); + env->SetByteArrayRegion(body, 0, message.body.size(), bodyPtr); env->CallVoidMethod(mController->getCallbacksObj(), gHdmiCecControllerClassInfo.handleIncomingCecCommand, srcAddr, dstAddr, body); @@ -159,10 +153,10 @@ private: checkAndClearExceptionFromCallback(env, __FUNCTION__); } - void propagateHotplugEvent(const hotplug_event_t& event) { + void propagateHotplugEvent(const HotplugEvent& event) { // Note that this method should be called in service thread. JNIEnv* env = AndroidRuntime::getJNIEnv(); - jint port = event.port_id; + jint port = static_cast<jint>(event.portId); jboolean connected = (jboolean) event.connected; env->CallVoidMethod(mController->getCallbacksObj(), gHdmiCecControllerClassInfo.handleHotplug, port, connected); @@ -180,51 +174,83 @@ private: } HdmiCecController* mController; - sp<CecEventWrapper> mEventWrapper; + CecMessage mCecMessage; + HotplugEvent mHotplugEvent; }; -HdmiCecController::HdmiCecController(hdmi_cec_device_t* device, - jobject callbacksObj, const sp<Looper>& looper) : - mDevice(device), - mCallbacksObj(callbacksObj), - mLooper(looper) { +HdmiCecController::HdmiCecController(sp<IHdmiCec> hdmiCec, + jobject callbacksObj, const sp<Looper>& looper) + : mHdmiCec(hdmiCec), + mCallbacksObj(callbacksObj), + mLooper(looper) { + mHdmiCecCallback = new HdmiCecCallback(this); + Return<void> ret = mHdmiCec->setCallback(mHdmiCecCallback); + if (!ret.getStatus().isOk()) { + ALOGE("Failed to set a cec callback."); + } } -void HdmiCecController::init() { - mDevice->register_event_callback(mDevice, HdmiCecController::onReceived, this); +HdmiCecController::~HdmiCecController() { + Return<void> ret = mHdmiCec->setCallback(nullptr); + if (!ret.getStatus().isOk()) { + ALOGE("Failed to set a cec callback."); + } } -int HdmiCecController::sendMessage(const cec_message_t& message) { +int HdmiCecController::sendMessage(const CecMessage& message) { // TODO: propagate send_message's return value. - return mDevice->send_message(mDevice, &message); + Return<SendMessageResult> ret = mHdmiCec->sendMessage(message); + if (!ret.getStatus().isOk()) { + ALOGE("Failed to send CEC message."); + return static_cast<int>(SendMessageResult::FAIL); + } + return static_cast<int>((SendMessageResult) ret); } -int HdmiCecController::addLogicalAddress(cec_logical_address_t address) { - return mDevice->add_logical_address(mDevice, address); +int HdmiCecController::addLogicalAddress(CecLogicalAddress address) { + Return<Result> ret = mHdmiCec->addLogicalAddress(address); + if (!ret.getStatus().isOk()) { + ALOGE("Failed to add a logical address."); + return static_cast<int>(Result::FAILURE_UNKNOWN); + } + return static_cast<int>((Result) ret); } void HdmiCecController::clearLogicaladdress() { - mDevice->clear_logical_address(mDevice); + Return<void> ret = mHdmiCec->clearLogicalAddress(); + if (!ret.getStatus().isOk()) { + ALOGE("Failed to clear logical address."); + } } int HdmiCecController::getPhysicalAddress() { + Result result; uint16_t addr; - if (!mDevice->get_physical_address(mDevice, &addr)) { - return addr; + Return<void> ret = mHdmiCec->getPhysicalAddress([&result, &addr](Result res, uint16_t paddr) { + result = res; + addr = paddr; + }); + if (!ret.getStatus().isOk()) { + ALOGE("Failed to get physical address."); + return INVALID_PHYSICAL_ADDRESS; } - return INVALID_PHYSICAL_ADDRESS; + return result == Result::SUCCESS ? addr : INVALID_PHYSICAL_ADDRESS; } int HdmiCecController::getVersion() { - int version = 0; - mDevice->get_version(mDevice, &version); - return version; + Return<int32_t> ret = mHdmiCec->getCecVersion(); + if (!ret.getStatus().isOk()) { + ALOGE("Failed to get cec version."); + } + return ret; } uint32_t HdmiCecController::getVendorId() { - uint32_t vendorId = 0; - mDevice->get_vendor_id(mDevice, &vendorId); - return vendorId; + Return<uint32_t> ret = mHdmiCec->getVendorId(); + if (!ret.getStatus().isOk()) { + ALOGE("Failed to get vendor id."); + } + return ret; } jobjectArray HdmiCecController::getPortInfos() { @@ -237,48 +263,69 @@ jobjectArray HdmiCecController::getPortInfos() { if (ctor == NULL) { return NULL; } - hdmi_port_info* ports; - int numPorts; - mDevice->get_port_info(mDevice, &ports, &numPorts); - jobjectArray res = env->NewObjectArray(numPorts, hdmiPortInfo, NULL); + hidl_vec<HdmiPortInfo> ports; + Return<void> ret = mHdmiCec->getPortInfo([&ports](hidl_vec<HdmiPortInfo> list) { + ports = list; + }); + if (!ret.getStatus().isOk()) { + ALOGE("Failed to get port information."); + return NULL; + } + jobjectArray res = env->NewObjectArray(ports.size(), hdmiPortInfo, NULL); // MHL support field will be obtained from MHL HAL. Leave it to false. jboolean mhlSupported = (jboolean) 0; - for (int i = 0; i < numPorts; ++i) { - hdmi_port_info* info = &ports[i]; - jboolean cecSupported = (jboolean) info->cec_supported; - jboolean arcSupported = (jboolean) info->arc_supported; - jobject infoObj = env->NewObject(hdmiPortInfo, ctor, info->port_id, info->type, - info->physical_address, cecSupported, mhlSupported, arcSupported); + for (size_t i = 0; i < ports.size(); ++i) { + jboolean cecSupported = (jboolean) ports[i].cecSupported; + jboolean arcSupported = (jboolean) ports[i].arcSupported; + jobject infoObj = env->NewObject(hdmiPortInfo, ctor, ports[i].portId, ports[i].type, + ports[i].physicalAddress, cecSupported, mhlSupported, arcSupported); env->SetObjectArrayElement(res, i, infoObj); } return res; } -void HdmiCecController::setOption(int flag, int value) { - mDevice->set_option(mDevice, flag, value); +void HdmiCecController::setOption(OptionKey key, bool enabled) { + Return<void> ret = mHdmiCec->setOption(key, enabled); + if (!ret.getStatus().isOk()) { + ALOGE("Failed to set option."); + } } -// Set audio return channel status. - void HdmiCecController::setAudioReturnChannel(int port, bool enabled) { - mDevice->set_audio_return_channel(mDevice, port, enabled ? 1 : 0); +void HdmiCecController::setLanguage(hidl_string language) { + Return<void> ret = mHdmiCec->setLanguage(language); + if (!ret.getStatus().isOk()) { + ALOGE("Failed to set language."); + } +} + +// Enable audio return channel. +void HdmiCecController::enableAudioReturnChannel(int port, bool enabled) { + Return<void> ret = mHdmiCec->enableAudioReturnChannel(port, enabled); + if (!ret.getStatus().isOk()) { + ALOGE("Failed to enable/disable ARC."); + } } // Whether to hdmi device is connected to the given port. bool HdmiCecController::isConnected(int port) { - return mDevice->is_connected(mDevice, port) == HDMI_CONNECTED; + Return<bool> ret = mHdmiCec->isConnected(port); + if (!ret.getStatus().isOk()) { + ALOGE("Failed to get connection info."); + } + return ret; } -// static -void HdmiCecController::onReceived(const hdmi_event_t* event, void* arg) { - HdmiCecController* controller = static_cast<HdmiCecController*>(arg); - if (controller == NULL) { - return; - } +Return<void> HdmiCecController::HdmiCecCallback::onCecMessage(const CecMessage& message) { + sp<HdmiCecEventHandler> handler(new HdmiCecEventHandler(mController, message)); + mController->mLooper->sendMessage(handler, HdmiCecEventHandler::EventType::CEC_MESSAGE); + return Void(); +} - sp<CecEventWrapper> spEvent(new CecEventWrapper(*event)); - sp<HdmiCecEventHandler> handler(new HdmiCecEventHandler(controller, spEvent)); - controller->mLooper->sendMessage(handler, event->type); +Return<void> HdmiCecController::HdmiCecCallback::onHotplugEvent(const HotplugEvent& event) { + sp<HdmiCecEventHandler> handler(new HdmiCecEventHandler(mController, event)); + mController->mLooper->sendMessage(handler, HdmiCecEventHandler::EventType::HOT_PLUG); + return Void(); } //------------------------------------------------------------------------------ @@ -288,30 +335,19 @@ void HdmiCecController::onReceived(const hdmi_event_t* event, void* arg) { static jlong nativeInit(JNIEnv* env, jclass clazz, jobject callbacksObj, jobject messageQueueObj) { - int err; - hw_module_t* module; - err = hw_get_module(HDMI_CEC_HARDWARE_MODULE_ID, - const_cast<const hw_module_t **>(&module)); - if (err != 0) { - ALOGE("Error acquiring hardware module: %d", err); - return 0; - } - - hw_device_t* device; - err = module->methods->open(module, HDMI_CEC_HARDWARE_INTERFACE, &device); - if (err != 0) { - ALOGE("Error opening hardware module: %d", err); + // TODO(b/31632518) + sp<IHdmiCec> hdmiCec = IHdmiCec::getService("tv.cec"); + if (hdmiCec == nullptr) { + ALOGE("Couldn't get tv.cec service."); return 0; } - sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj); HdmiCecController* controller = new HdmiCecController( - reinterpret_cast<hdmi_cec_device*>(device), + hdmiCec, env->NewGlobalRef(callbacksObj), messageQueue->getLooper()); - controller->init(); GET_METHOD_ID(gHdmiCecControllerClassInfo.handleIncomingCecCommand, clazz, "handleIncomingCecCommand", "(II[B)V"); @@ -323,14 +359,18 @@ static jlong nativeInit(JNIEnv* env, jclass clazz, jobject callbacksObj, static jint nativeSendCecCommand(JNIEnv* env, jclass clazz, jlong controllerPtr, jint srcAddr, jint dstAddr, jbyteArray body) { - cec_message_t message; - message.initiator = static_cast<cec_logical_address_t>(srcAddr); - message.destination = static_cast<cec_logical_address_t>(dstAddr); + CecMessage message; + message.initiator = static_cast<CecLogicalAddress>(srcAddr); + message.destination = static_cast<CecLogicalAddress>(dstAddr); jsize len = env->GetArrayLength(body); - message.length = MIN(len, CEC_MESSAGE_BODY_MAX_LENGTH); ScopedByteArrayRO bodyPtr(env, body); - std::memcpy(message.body, bodyPtr.get(), message.length); + size_t bodyLength = MIN(static_cast<size_t>(len), + static_cast<size_t>(MaxLength::MESSAGE_BODY)); + message.body.resize(bodyLength); + for (size_t i = 0; i < bodyLength; ++i) { + message.body[i] = static_cast<uint8_t>(bodyPtr[i]); + } HdmiCecController* controller = reinterpret_cast<HdmiCecController*>(controllerPtr); @@ -340,7 +380,7 @@ static jint nativeSendCecCommand(JNIEnv* env, jclass clazz, jlong controllerPtr, static jint nativeAddLogicalAddress(JNIEnv* env, jclass clazz, jlong controllerPtr, jint logicalAddress) { HdmiCecController* controller = reinterpret_cast<HdmiCecController*>(controllerPtr); - return controller->addLogicalAddress(static_cast<cec_logical_address_t>(logicalAddress)); + return controller->addLogicalAddress(static_cast<CecLogicalAddress>(logicalAddress)); } static void nativeClearLogicalAddress(JNIEnv* env, jclass clazz, jlong controllerPtr) { @@ -370,13 +410,20 @@ static jobjectArray nativeGetPortInfos(JNIEnv* env, jclass clazz, jlong controll static void nativeSetOption(JNIEnv* env, jclass clazz, jlong controllerPtr, jint flag, jint value) { HdmiCecController* controller = reinterpret_cast<HdmiCecController*>(controllerPtr); - controller->setOption(flag, value); + controller->setOption(static_cast<OptionKey>(flag), value > 0 ? true : false); +} + +static void nativeSetLanguage(JNIEnv* env, jclass clazz, jlong controllerPtr, jstring language) { + HdmiCecController* controller = reinterpret_cast<HdmiCecController*>(controllerPtr); + const char *languageStr = env->GetStringUTFChars(language, NULL); + controller->setLanguage(languageStr); + env->ReleaseStringUTFChars(language, languageStr); } -static void nativeSetAudioReturnChannel(JNIEnv* env, jclass clazz, jlong controllerPtr, +static void nativeEnableAudioReturnChannel(JNIEnv* env, jclass clazz, jlong controllerPtr, jint port, jboolean enabled) { HdmiCecController* controller = reinterpret_cast<HdmiCecController*>(controllerPtr); - controller->setAudioReturnChannel(port, enabled == JNI_TRUE); + controller->enableAudioReturnChannel(port, enabled == JNI_TRUE); } static jboolean nativeIsConnected(JNIEnv* env, jclass clazz, jlong controllerPtr, jint port) { @@ -398,8 +445,9 @@ static const JNINativeMethod sMethods[] = { { "nativeGetPortInfos", "(J)[Landroid/hardware/hdmi/HdmiPortInfo;", (void *) nativeGetPortInfos }, - { "nativeSetOption", "(JII)V", (void *) nativeSetOption }, - { "nativeSetAudioReturnChannel", "(JIZ)V", (void *) nativeSetAudioReturnChannel }, + { "nativeSetOption", "(JIZ)V", (void *) nativeSetOption }, + { "nativeSetLanguage", "(JLjava/lang/String;)V", (void *) nativeSetLanguage }, + { "nativeEnableAudioReturnChannel", "(JIZ)V", (void *) nativeEnableAudioReturnChannel }, { "nativeIsConnected", "(JI)Z", (void *) nativeIsConnected }, }; |