Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 40a00a34 authored by Jinsuk Kim's avatar Jinsuk Kim
Browse files

Replace individual methods with a consolidated CEC nativeSendmessage

It saves us from having to add numerous native methods to HdmiCecService.
A new native method that reports physical address was added in consequence
to be able to build the message in Java side.

Other changes:
 - Substituted more concrete type (cec_device_type_t) to int.
 - Fixed the issue about byte endianness in handling physical
   address/vendor id. The bytes of variable mPhysicalAddress in native
   service were being reversed previously but still worked because they
   were reversed again when copied out to outgoing messages. Vendor id
   had a bug of bytes being reversed. In order to fix the issue, the way
   they are copied to byte array was changed so that it becomes
   independent to byte endianness.
 - CL's for header/HAL implementation changes are:
   https://googleplex-android-review.git.corp.google.com/#/c/437667
   https://googleplex-android-review.git.corp.google.com/#/c/437668

Change-Id: Id1ac683fe54597a2c707f30492c7f86e5392504d
parent c01e1aeb
Loading
Loading
Loading
Loading
+20 −11
Original line number Diff line number Diff line
@@ -37,6 +37,8 @@ import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Locale;

import libcore.util.EmptyArray;

/**
 * Provides a service for sending and processing HDMI-CEC messages, and providing
 * the information on HDMI settings in general.
@@ -63,6 +65,8 @@ public final class HdmiCecService extends SystemService {

    private static final String PERMISSION = "android.permission.HDMI_CEC";

    private static final byte[] EMPTY_PARAM = EmptyArray.BYTE;

    public HdmiCecService(Context context) {
        super(context);
    }
@@ -285,7 +289,13 @@ public final class HdmiCecService extends SystemService {
            synchronized (mLock) {
                HdmiCecDevice device = getLogicalDeviceLocked(b);
                device.setIsActiveSource(true);
                nativeSendActiveSource(mNativePtr, device.getType());
                int physicalAddress = nativeGetPhysicalAddress(mNativePtr);
                byte[] param = new byte[] {
                    (byte) ((physicalAddress >> 8) & 0xff),
                    (byte) (physicalAddress & 0xff)
                };
                nativeSendMessage(mNativePtr, device.getType(), HdmiCec.ADDR_BROADCAST,
                        HdmiCec.MESSAGE_ACTIVE_SOURCE, param);
            }
        }

@@ -295,7 +305,8 @@ public final class HdmiCecService extends SystemService {
            synchronized (mLock) {
                HdmiCecDevice device = getLogicalDeviceLocked(b);
                device.setIsActiveSource(false);
                nativeSendInactiveSource(mNativePtr, device.getType());
                nativeSendMessage(mNativePtr, device.getType(), HdmiCec.ADDR_BROADCAST,
                        HdmiCec.MESSAGE_INACTIVE_SOURCE, EMPTY_PARAM);
            }
        }

@@ -304,7 +315,8 @@ public final class HdmiCecService extends SystemService {
            enforceAccessPermission();
            synchronized (mLock) {
                HdmiCecDevice device = getLogicalDeviceLocked(b);
                nativeSendImageViewOn(mNativePtr, device.getType());
                nativeSendMessage(mNativePtr, device.getType(), HdmiCec.ADDR_TV,
                        HdmiCec.MESSAGE_IMAGE_VIEW_ON, EMPTY_PARAM);
            }
        }

@@ -313,7 +325,8 @@ public final class HdmiCecService extends SystemService {
            enforceAccessPermission();
            synchronized (mLock) {
                HdmiCecDevice device = getLogicalDeviceLocked(b);
                nativeSendTextViewOn(mNativePtr, device.getType());
                nativeSendMessage(mNativePtr, device.getType(), HdmiCec.ADDR_TV,
                        HdmiCec.MESSAGE_TEXT_VIEW_ON, EMPTY_PARAM);
            }
        }

@@ -322,7 +335,8 @@ public final class HdmiCecService extends SystemService {
            enforceAccessPermission();
            synchronized (mLock) {
                HdmiCecDevice device = getLogicalDeviceLocked(b);
                nativeSendGiveDevicePowerStatus(mNativePtr, device.getType(), address);
                nativeSendMessage(mNativePtr, device.getType(), address,
                        HdmiCec.MESSAGE_GIVE_DEVICE_POWER_STATUS, EMPTY_PARAM);
            }
        }

@@ -382,10 +396,5 @@ public final class HdmiCecService extends SystemService {
    private static native void nativeRemoveLogicalAddress(long handler, int deviceType);
    private static native void nativeSendMessage(long handler, int deviceType, int destination,
            int opcode, byte[] params);
    private static native void nativeSendActiveSource(long handler, int deviceType);
    private static native void nativeSendInactiveSource(long handler, int deviceType);
    private static native void nativeSendImageViewOn(long handler, int deviceType);
    private static native void nativeSendTextViewOn(long handler, int deviceType);
    private static native void nativeSendGiveDevicePowerStatus(long handler, int deviceType,
            int address);
    private static native int nativeGetPhysicalAddress(long handler);
}
+55 −116
Original line number Diff line number Diff line
@@ -63,24 +63,21 @@ public:
    void initialize();

    // initialize individual logical device.
    int initLogicalDevice(int type);
    void releaseLogicalDevice(int type);
    cec_logical_address_t initLogicalDevice(cec_device_type_t type);
    void releaseLogicalDevice(cec_device_type_t type);

    cec_logical_address_t getLogicalAddress(int deviceType);
    cec_logical_address_t getLogicalAddress(cec_device_type_t deviceType);
    uint16_t getPhysicalAddress();
    int getDeviceType(cec_logical_address_t addr);
    void queueMessage(const MessageEntry& message);
    void queueOutgoingMessage(const cec_message_t& message);
    void sendReportPhysicalAddress();
    void sendActiveSource(cec_logical_address_t srcAddr);
    void sendInactiveSource(cec_logical_address_t srcAddr);
    void sendImageViewOn(cec_logical_address_t srcAddr);
    void sendTextViewOn(cec_logical_address_t srcAddr);
    void sendGiveDevicePowerStatus(cec_logical_address_t srcAddr, cec_logical_address_t dstAddr);
    void sendFeatureAbort(cec_logical_address_t srcAddr, cec_logical_address_t dstAddr,
            int opcode, int reason);
    void sendCecVersion(cec_logical_address_t srcAddr, cec_logical_address_t dstAddr,
            int version);
    void sendDeviceVendorID(cec_logical_address_t srcAddr, cec_logical_address_t dstAddr);
    void sendDeviceVendorId(cec_logical_address_t srcAddr, cec_logical_address_t dstAddr);
    void sendGiveDeviceVendorID(cec_logical_address_t srcAddr, cec_logical_address_t dstAddr);
    void sendSetOsdName(cec_logical_address_t srcAddr, cec_logical_address_t dstAddr,
            const char* name, size_t len);
@@ -104,6 +101,7 @@ private:
    static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName);

    void updatePhysicalAddress();
    void updateLogicalAddress();
    void dispatchMessage(const MessageEntry& message);
    void processIncomingMessage(const cec_message_t& msg);

@@ -147,7 +145,7 @@ private:
    };

    // device type -> logical address mapping
    std::map<int, cec_logical_address_t> mLogicalDevices;
    std::map<cec_device_type_t, cec_logical_address_t> mLogicalDevices;

    hdmi_cec_device_t* mDevice;
    jobject mCallbacksObj;
@@ -173,6 +171,10 @@ void HdmiCecHandler::initialize() {
    updatePhysicalAddress();
}

uint16_t HdmiCecHandler::getPhysicalAddress() {
    return mPhysicalAddress;
}

void HdmiCecHandler::updatePhysicalAddress() {
    uint16_t addr;
    if (!mDevice->get_physical_address(mDevice, &addr)) {
@@ -182,7 +184,17 @@ void HdmiCecHandler::updatePhysicalAddress() {
    }
}

int HdmiCecHandler::initLogicalDevice(int type) {
void HdmiCecHandler::updateLogicalAddress() {
    std::map<cec_device_type_t, cec_logical_address_t>::iterator it = mLogicalDevices.begin();
    for (; it != mLogicalDevices.end(); ++it) {
        cec_logical_address_t addr;
        if (!mDevice->get_logical_address(mDevice, it->first, &addr)) {
            it->second = addr;
        }
    }
}

cec_logical_address_t HdmiCecHandler::initLogicalDevice(cec_device_type_t type) {
    cec_logical_address_t addr;
    int res = mDevice->allocate_logical_address(mDevice, type, &addr);

@@ -190,21 +202,21 @@ int HdmiCecHandler::initLogicalDevice(int type) {
        ALOGE("Logical Address Allocation failed: %d", res);
    } else {
        ALOGV("Logical Address Allocation success: %d", addr);
        mLogicalDevices.insert(std::pair<int, cec_logical_address_t>(type, addr));
        mLogicalDevices.insert(std::pair<cec_device_type_t, cec_logical_address_t>(type, addr));
    }
    return addr;
}

void HdmiCecHandler::releaseLogicalDevice(int type) {
    std::map<int, cec_logical_address_t>::iterator it = mLogicalDevices.find(type);
void HdmiCecHandler::releaseLogicalDevice(cec_device_type_t type) {
    std::map<cec_device_type_t, cec_logical_address_t>::iterator it = mLogicalDevices.find(type);
    if (it != mLogicalDevices.end()) {
        mLogicalDevices.erase(it);
    }
    // TODO: remove the address monitored in HAL as well.
}

cec_logical_address_t HdmiCecHandler::getLogicalAddress(int mDevicetype) {
    std::map<int, cec_logical_address_t>::iterator it = mLogicalDevices.find(mDevicetype);
cec_logical_address_t HdmiCecHandler::getLogicalAddress(cec_device_type_t type) {
    std::map<cec_device_type_t, cec_logical_address_t>::iterator it = mLogicalDevices.find(type);
    if (it != mLogicalDevices.end()) {
        return it->second;
    }
@@ -212,7 +224,7 @@ cec_logical_address_t HdmiCecHandler::getLogicalAddress(int mDevicetype) {
}

int HdmiCecHandler::getDeviceType(cec_logical_address_t addr) {
    std::map<int, cec_logical_address_t>::iterator it = mLogicalDevices.begin();
    std::map<cec_device_type_t, cec_logical_address_t>::iterator it = mLogicalDevices.begin();
    for (; it != mLogicalDevices.end(); ++it) {
        if (it->second == addr) {
            return it->first;
@@ -245,14 +257,15 @@ void HdmiCecHandler::sendReportPhysicalAddress() {
    }

    // Report physical address for each logical one hosted in it.
    std::map<int, cec_logical_address_t>::iterator it = mLogicalDevices.begin();
    std::map<cec_device_type_t, cec_logical_address_t>::iterator it = mLogicalDevices.begin();
    while (it != mLogicalDevices.end()) {
        cec_message_t msg;
        msg.initiator = it->second;  // logical address
        msg.destination = CEC_ADDR_BROADCAST;
        msg.length = 4;
        msg.body[0] = CEC_MESSAGE_REPORT_PHYSICAL_ADDRESS;
        std::memcpy(msg.body + 1, &mPhysicalAddress, 2);
        msg.body[1] = (mPhysicalAddress >> 8) & 0xff;
        msg.body[2] = mPhysicalAddress & 0xff;
        msg.body[3] = it->first;  // device type
        queueOutgoingMessage(msg);
        ++it;
@@ -269,47 +282,8 @@ void HdmiCecHandler::sendActiveSource(cec_logical_address_t srcAddr) {
    msg.destination = CEC_ADDR_BROADCAST;
    msg.length = 3;
    msg.body[0] = CEC_MESSAGE_ACTIVE_SOURCE;
    std::memcpy(msg.body + 1, &mPhysicalAddress, 2);
    queueOutgoingMessage(msg);
}

void HdmiCecHandler::sendInactiveSource(cec_logical_address_t srcAddr) {
    cec_message_t msg;
    msg.initiator = srcAddr;
    msg.destination = CEC_ADDR_TV;
    msg.length = 3;
    msg.body[0] = CEC_MESSAGE_INACTIVE_SOURCE;
    if (mPhysicalAddress != INVALID_PHYSICAL_ADDRESS) {
        std::memcpy(msg.body + 1, &mPhysicalAddress, 2);
        queueOutgoingMessage(msg);
    }
}

void HdmiCecHandler::sendImageViewOn(cec_logical_address_t srcAddr) {
    cec_message_t msg;
    msg.initiator = srcAddr;
    msg.destination = CEC_ADDR_TV;
    msg.length = 1;
    msg.body[0] = CEC_MESSAGE_IMAGE_VIEW_ON;
    queueOutgoingMessage(msg);
}

void HdmiCecHandler::sendTextViewOn(cec_logical_address_t srcAddr) {
    cec_message_t msg;
    msg.initiator = srcAddr;
    msg.destination = CEC_ADDR_TV;
    msg.length = 1;
    msg.body[0] = CEC_MESSAGE_TEXT_VIEW_ON;
    queueOutgoingMessage(msg);
}

void HdmiCecHandler::sendGiveDevicePowerStatus(cec_logical_address_t srcAddr,
        cec_logical_address_t dstAddr) {
    cec_message_t msg;
    msg.initiator = srcAddr;
    msg.destination = dstAddr;
    msg.length = 1;
    msg.body[0] = CEC_MESSAGE_GIVE_DEVICE_POWER_STATUS;
    msg.body[1] = (mPhysicalAddress >> 8) & 0xff;
    msg.body[2] = mPhysicalAddress & 0xff;
    queueOutgoingMessage(msg);
}

@@ -346,7 +320,7 @@ void HdmiCecHandler::sendGiveDeviceVendorID(cec_logical_address_t srcAddr,
    queueOutgoingMessage(msg);
}

void HdmiCecHandler::sendDeviceVendorID(cec_logical_address_t srcAddr,
void HdmiCecHandler::sendDeviceVendorId(cec_logical_address_t srcAddr,
        cec_logical_address_t dstAddr) {
    cec_message_t msg;
    msg.initiator = srcAddr;
@@ -355,7 +329,9 @@ void HdmiCecHandler::sendDeviceVendorID(cec_logical_address_t srcAddr,
    msg.body[0] = CEC_MESSAGE_DEVICE_VENDOR_ID;
    uint32_t vendor_id;
    mDevice->get_vendor_id(mDevice, &vendor_id);
    std::memcpy(msg.body + 1, &vendor_id, 3);
    msg.body[1] = (vendor_id >> 16) & 0xff;
    msg.body[2] = (vendor_id >> 8) & 0xff;
    msg.body[3] = vendor_id & 0xff;
    queueOutgoingMessage(msg);
}

@@ -437,9 +413,8 @@ void HdmiCecHandler::dispatchMessage(const MessageEntry& entry) {
        mMessageQueue.pop_front();
        bool connected = entry.second.hotplug.connected;
        if (connected) {
            // TODO: Update logical addresses as well, since they also could have
            // changed while the cable was disconnected.
            updatePhysicalAddress();
            updateLogicalAddress();
        }
        propagateHotplug(connected);
    }
@@ -460,6 +435,9 @@ void HdmiCecHandler::processIncomingMessage(const cec_message_t& msg) {
        handleGetCECVersion(msg);
    } else if (opcode == CEC_MESSAGE_GET_MENU_LANGUAGE) {
        handleGetMenuLanguage(msg);
    } else if (opcode == CEC_MESSAGE_ABORT) {
        // Compliance testing requires that abort message be responded with feature abort.
        sendFeatureAbort(msg.destination, msg.initiator, msg.body[0], ABORT_REFUSED);
    } else {
        if (precheckMessage(msg)) {
            propagateMessage(msg);
@@ -480,8 +458,7 @@ bool HdmiCecHandler::precheckMessage(const cec_message_t& msg) {
            (opcode == CEC_MESSAGE_ACTIVE_SOURCE ||
             opcode == CEC_MESSAGE_SET_STREAM_PATH ||
             opcode == CEC_MESSAGE_INACTIVE_SOURCE)) {
        uint16_t senderAddr;
        std::memcpy(&senderAddr, &msg.body[1], 2);
        uint16_t senderAddr = (msg.body[1] << 8) + msg.body[2];
        if (senderAddr == mPhysicalAddress) {
            return false;
        }
@@ -521,7 +498,7 @@ void HdmiCecHandler::handleRequestActiveSource() {
    jint activeDeviceType = env->CallIntMethod(mCallbacksObj,
            gHdmiCecServiceClassInfo.getActiveSource);
    if (activeDeviceType != INACTIVE_DEVICE_TYPE) {
        sendActiveSource(getLogicalAddress(activeDeviceType));
        sendActiveSource(getLogicalAddress(static_cast<cec_device_type_t>(activeDeviceType)));
    }
    checkAndClearExceptionFromCallback(env, __FUNCTION__);
}
@@ -542,7 +519,7 @@ void HdmiCecHandler::handleGetOsdName(const cec_message_t& msg) {
}

void HdmiCecHandler::handleGiveDeviceVendorID(const cec_message_t& msg) {
    sendDeviceVendorID(msg.destination, msg.initiator);
    sendDeviceVendorId(msg.destination, msg.initiator);
}

void HdmiCecHandler::handleGetCECVersion(const cec_message_t& msg) {
@@ -596,64 +573,34 @@ static jlong nativeInit(JNIEnv* env, jclass clazz, jobject callbacksObj) {
static void nativeSendMessage(JNIEnv* env, jclass clazz, jlong handlerPtr, jint deviceType,
        jint dstAddr, jint opcode, jbyteArray params) {
    HdmiCecHandler *handler = reinterpret_cast<HdmiCecHandler *>(handlerPtr);
    cec_logical_address_t srcAddr = handler->getLogicalAddress(deviceType);
    cec_logical_address_t srcAddr = handler->getLogicalAddress(
            static_cast<cec_device_type_t>(deviceType));
    jsize len = env->GetArrayLength(params);
    ScopedByteArrayRO paramsPtr(env, params);
    cec_message_t message;
    message.initiator = srcAddr;
    message.destination = static_cast<cec_logical_address_t>(dstAddr);
    message.length = len + 1;
    message.length = min(len + 1, CEC_MESSAGE_BODY_MAX_LENGTH);
    message.body[0] = opcode;
    std::memcpy(message.body + 1, paramsPtr.get(), len);
    std::memcpy(message.body + 1, paramsPtr.get(), message.length - 1);
    handler->sendCecMessage(message);
}

static int nativeAllocateLogicalAddress(JNIEnv* env, jclass clazz, jlong handlerPtr,
static jint nativeAllocateLogicalAddress(JNIEnv* env, jclass clazz, jlong handlerPtr,
        jint deviceType) {
    HdmiCecHandler *handler = reinterpret_cast<HdmiCecHandler *>(handlerPtr);
    return handler->initLogicalDevice(deviceType);
    return handler->initLogicalDevice(static_cast<cec_device_type_t>(deviceType));
}

static void nativeRemoveLogicalAddress(JNIEnv* env, jclass clazz, jlong handlerPtr,
       jint deviceType) {
    HdmiCecHandler *handler = reinterpret_cast<HdmiCecHandler *>(handlerPtr);
    return handler->releaseLogicalDevice(deviceType);
}

static void nativeSendActiveSource(JNIEnv* env, jclass clazz, jlong handlerPtr,
        jint deviceType) {
    HdmiCecHandler *handler = reinterpret_cast<HdmiCecHandler *>(handlerPtr);
    cec_logical_address_t srcAddr = handler->getLogicalAddress(deviceType);
    handler->sendActiveSource(srcAddr);
}

static void nativeSendInactiveSource(JNIEnv* env, jclass clazz, jlong handlerPtr,
        jint deviceType) {
    HdmiCecHandler *handler = reinterpret_cast<HdmiCecHandler *>(handlerPtr);
    cec_logical_address_t srcAddr = handler->getLogicalAddress(deviceType);
    handler->sendInactiveSource(srcAddr);
}

static void nativeSendImageViewOn(JNIEnv* env, jclass clazz, jlong handlerPtr,
        jint deviceType) {
    HdmiCecHandler *handler = reinterpret_cast<HdmiCecHandler *>(handlerPtr);
    cec_logical_address_t srcAddr = handler->getLogicalAddress(deviceType);
    handler->sendImageViewOn(srcAddr);
}

static void nativeSendTextViewOn(JNIEnv* env, jclass clazz, jlong handlerPtr,
        jint deviceType) {
    HdmiCecHandler *handler = reinterpret_cast<HdmiCecHandler *>(handlerPtr);
    cec_logical_address_t srcAddr = handler->getLogicalAddress(deviceType);
    handler->sendTextViewOn(srcAddr);
    return handler->releaseLogicalDevice(static_cast<cec_device_type_t>(deviceType));
}

static void nativeSendGiveDevicePowerStatus(JNIEnv* env, jclass clazz, jlong handlerPtr,
        jint deviceType, jint destination) {
static jint nativeGetPhysicalAddress(JNIEnv* env, jclass clazz, jlong handlerPtr) {
    HdmiCecHandler *handler = reinterpret_cast<HdmiCecHandler *>(handlerPtr);
    cec_logical_address_t srcAddr = handler->getLogicalAddress(deviceType);
    cec_logical_address_t dstAddr = static_cast<cec_logical_address_t>(destination);
    handler->sendGiveDevicePowerStatus(srcAddr, dstAddr);
    return handler->getPhysicalAddress();
}

static JNINativeMethod sMethods[] = {
@@ -666,16 +613,8 @@ static JNINativeMethod sMethods[] = {
            (void *)nativeAllocateLogicalAddress },
    { "nativeRemoveLogicalAddress", "(JI)V",
            (void *)nativeRemoveLogicalAddress },
    { "nativeSendActiveSource", "(JI)V",
            (void *)nativeSendActiveSource },
    { "nativeSendInactiveSource", "(JI)V",
            (void *)nativeSendInactiveSource },
    { "nativeSendImageViewOn", "(JI)V",
            (void *)nativeSendImageViewOn },
    { "nativeSendTextViewOn", "(JI)V",
            (void *)nativeSendTextViewOn },
    { "nativeSendGiveDevicePowerStatus", "(JII)V",
            (void *)nativeSendGiveDevicePowerStatus }
    { "nativeGetPhysicalAddress", "(J)I",
            (void *)nativeGetPhysicalAddress },
};

#define CLASS_PATH "com/android/server/hdmi/HdmiCecService"