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

Commit 60037302 authored by Jinsuk Kim's avatar Jinsuk Kim Committed by Android Git Automerger
Browse files

am 8fe27e88: Merge "Move logical address allocation logic into native service...

am 8fe27e88: Merge "Move logical address allocation logic into native service from HAL" into klp-modular-dev

* commit '8fe27e88':
  Move logical address allocation logic into native service from HAL
parents 86af7745 8fe27e88
Loading
Loading
Loading
Loading
+167 −49
Original line number Diff line number Diff line
@@ -67,10 +67,10 @@ public:

    cec_logical_address_t getLogicalAddress(cec_device_type_t deviceType);
    uint16_t getPhysicalAddress();
    int getDeviceType(cec_logical_address_t addr);
    cec_device_type_t getDeviceType(cec_logical_address_t addr);
    void queueMessage(const MessageEntry& message);
    void queueOutgoingMessage(const cec_message_t& message);
    void sendReportPhysicalAddress();
    void sendReportPhysicalAddress(cec_logical_address_t srcAddr);
    void sendActiveSource(cec_logical_address_t srcAddr);
    void sendFeatureAbort(cec_logical_address_t srcAddr, cec_logical_address_t dstAddr,
            int opcode, int reason);
@@ -93,15 +93,41 @@ private:
        EVENT_TYPE_STANDBY
    };

    /*
     * logical address pool for each device type.
     */
    static const cec_logical_address_t TV_ADDR_POOL[];
    static const cec_logical_address_t PLAYBACK_ADDR_POOL[];
    static const cec_logical_address_t RECORDER_ADDR_POOL[];
    static const cec_logical_address_t TUNER_ADDR_POOL[];

    static const unsigned int MAX_BUFFER_SIZE = 256;
    static const uint16_t INVALID_PHYSICAL_ADDRESS = 0xFFFF;
    static const int INACTIVE_DEVICE_TYPE = -1;

    static void onReceived(const hdmi_event_t* event, void* arg);
    static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName);

    void updatePhysicalAddress();
    void updateLogicalAddress();

    // Allocate logical address. The CEC standard recommends that we try to use the address
    // we have ever used before, in case this is to allocate an address afte the cable is
    // connected again. If preferredAddr is given a valid one (not CEC_ADDR_UNREGISTERED), then
    // this method checks if the address is available first. If not, it tries other addresses
    // int the address pool available for the given type.
    cec_logical_address_t allocateLogicalAddress(cec_device_type_t type,
            cec_logical_address_t preferredAddr);

    // Send a CEC ping message. Returns true if successful.
    bool sendPing(cec_logical_address_t addr);

    // Return the pool of logical addresses that are used for a given device type.
    // One of the addresses in the pool will be chosen in the allocation logic.
    bool getLogicalAddressPool(cec_device_type_t type, const cec_logical_address_t** addrPool,
            size_t* poolSize);

    // Handles the message retrieved from internal message queue. The message can be
    // for either rx or tx.
    void dispatchMessage(const MessageEntry& message);
    void processIncomingMessage(const cec_message_t& msg);

@@ -159,6 +185,29 @@ private:
    std::string mOsdName;
};

    const cec_logical_address_t HdmiCecHandler::TV_ADDR_POOL[] = {
        CEC_ADDR_TV,
        CEC_ADDR_FREE_USE,
    };

    const cec_logical_address_t HdmiCecHandler::PLAYBACK_ADDR_POOL[] = {
        CEC_ADDR_PLAYBACK_1,
        CEC_ADDR_PLAYBACK_2,
        CEC_ADDR_PLAYBACK_3
    };

    const cec_logical_address_t HdmiCecHandler::RECORDER_ADDR_POOL[] = {
        CEC_ADDR_RECORDER_1,
        CEC_ADDR_RECORDER_2,
        CEC_ADDR_RECORDER_3
    };

    const cec_logical_address_t HdmiCecHandler::TUNER_ADDR_POOL[] = {
        CEC_ADDR_TUNER_1,
        CEC_ADDR_TUNER_2,
        CEC_ADDR_TUNER_3,
        CEC_ADDR_TUNER_4
    };

HdmiCecHandler::HdmiCecHandler(hdmi_cec_device_t* device, jobject callbacksObj) :
    mDevice(device),
@@ -176,39 +225,15 @@ uint16_t HdmiCecHandler::getPhysicalAddress() {
    return mPhysicalAddress;
}

void HdmiCecHandler::updatePhysicalAddress() {
    uint16_t addr;
    if (!mDevice->get_physical_address(mDevice, &addr)) {
        mPhysicalAddress = addr;
    } else {
        mPhysicalAddress = INVALID_PHYSICAL_ADDRESS;
    }
}

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);

    if (res != 0) {
        ALOGE("Logical Address Allocation failed: %d", res);
    } else {
        ALOGV("Logical Address Allocation success: %d", addr);
    cec_logical_address addr = allocateLogicalAddress(type, CEC_ADDR_UNREGISTERED);
    if (addr != CEC_ADDR_UNREGISTERED && !mDevice->add_logical_address(mDevice, addr)) {
        mLogicalDevices.insert(std::pair<cec_device_type_t, cec_logical_address_t>(type, addr));

        // Broadcast <Report Physical Address> when a new logical address was allocated to let
        // other devices discover the new logical device and its logical - physical address
        // association.
        sendReportPhysicalAddress();
        sendReportPhysicalAddress(addr);
    }
    return addr;
}
@@ -229,14 +254,14 @@ cec_logical_address_t HdmiCecHandler::getLogicalAddress(cec_device_type_t type)
    return CEC_ADDR_UNREGISTERED;
}

int HdmiCecHandler::getDeviceType(cec_logical_address_t addr) {
cec_device_type_t HdmiCecHandler::getDeviceType(cec_logical_address_t addr) {
    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;
        }
    }
    return INACTIVE_DEVICE_TYPE;
    return CEC_DEVICE_INACTIVE;
}

void HdmiCecHandler::queueMessage(const MessageEntry& entry) {
@@ -256,26 +281,26 @@ void HdmiCecHandler::queueOutgoingMessage(const cec_message_t& message) {
    queueMessage(entry);
}

void HdmiCecHandler::sendReportPhysicalAddress() {
void HdmiCecHandler::sendReportPhysicalAddress(cec_logical_address_t addr) {
    if (mPhysicalAddress == INVALID_PHYSICAL_ADDRESS) {
        ALOGE("Invalid physical address.");
        return;
    }
    cec_device_type_t deviceType = getDeviceType(addr);
    if (deviceType == CEC_DEVICE_INACTIVE) {
        ALOGE("Invalid logical address: %d", addr);
        return;
    }

    // Report physical address for each logical one hosted in it.
    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.initiator = addr;
    msg.destination = CEC_ADDR_BROADCAST;
    msg.length = 4;
    msg.body[0] = CEC_MESSAGE_REPORT_PHYSICAL_ADDRESS;
    msg.body[1] = (mPhysicalAddress >> 8) & 0xff;
    msg.body[2] = mPhysicalAddress & 0xff;
        msg.body[3] = it->first;  // device type
    msg.body[3] = deviceType;
    queueOutgoingMessage(msg);
        ++it;
    }
}

void HdmiCecHandler::sendActiveSource(cec_logical_address_t srcAddr) {
@@ -410,6 +435,99 @@ void HdmiCecHandler::checkAndClearExceptionFromCallback(JNIEnv* env, const char*
    }
}

void HdmiCecHandler::updatePhysicalAddress() {
    uint16_t addr;
    if (!mDevice->get_physical_address(mDevice, &addr)) {
        mPhysicalAddress = addr;
    } else {
        mPhysicalAddress = INVALID_PHYSICAL_ADDRESS;
    }
}

void HdmiCecHandler::updateLogicalAddress() {
    mDevice->clear_logical_address(mDevice);
    std::map<cec_device_type_t, cec_logical_address_t>::iterator it = mLogicalDevices.begin();
    for (; it != mLogicalDevices.end(); ++it) {
        cec_logical_address_t addr;
        cec_logical_address_t preferredAddr = it->second;
        cec_device_type_t deviceType = it->first;
        addr = allocateLogicalAddress(deviceType, preferredAddr);
        if (!mDevice->add_logical_address(mDevice, addr)) {
            it->second = addr;
        } else {
            it->second = CEC_ADDR_UNREGISTERED;
        }
    }
}

cec_logical_address_t HdmiCecHandler::allocateLogicalAddress(cec_device_type_t type,
        cec_logical_address_t preferredAddr) {
    const cec_logical_address_t* addrPool;
    size_t poolSize;
    if (getLogicalAddressPool(type, &addrPool, &poolSize) < 0) {
        return CEC_ADDR_UNREGISTERED;
    }
    unsigned start = 0;

    // Find the index of preferred address in the pool. If not found, the start
    // position will be 0. This happens when the passed preferredAddr is set to
    // CEC_ADDR_UNREGISTERED, meaning that no preferred address is given.
    for (unsigned i = 0; i < poolSize; i++) {
        if (addrPool[i] == preferredAddr) {
            start = i;
            break;
        }
    }
    for (unsigned i = 0; i < poolSize; i++) {
        cec_logical_address_t addr = addrPool[(start + i) % poolSize];
        if (!sendPing(addr)) {
            // Failure in pinging means the address is available, not taken by any device.
            ALOGV("Logical Address Allocation success: %d", addr);
            return addr;
        }
    }
    ALOGE("Logical Address Allocation failed");
    return CEC_ADDR_UNREGISTERED;
}

bool HdmiCecHandler::sendPing(cec_logical_address addr) {
    cec_message_t msg;
    msg.initiator = msg.destination = addr;
    msg.length = 0;
    return !mDevice->send_message(mDevice, &msg);

}

#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))

bool HdmiCecHandler::getLogicalAddressPool(cec_device_type_t deviceType,
        const cec_logical_address_t** addrPool, size_t* poolSize) {
    switch (deviceType) {
    case CEC_DEVICE_TV:
        *addrPool = TV_ADDR_POOL;
        *poolSize = ARRAY_SIZE(TV_ADDR_POOL);
        break;
    case CEC_DEVICE_RECORDER:
        *addrPool = RECORDER_ADDR_POOL;
        *poolSize = ARRAY_SIZE(RECORDER_ADDR_POOL);
        break;
    case CEC_DEVICE_TUNER:
        *addrPool = TUNER_ADDR_POOL;
        *poolSize = ARRAY_SIZE(TUNER_ADDR_POOL);
        break;
    case CEC_DEVICE_PLAYBACK:
        *addrPool = PLAYBACK_ADDR_POOL;
        *poolSize = ARRAY_SIZE(PLAYBACK_ADDR_POOL);
        break;
    default:
        ALOGE("Unsupported device type: %d", deviceType);
        return false;
    }
    return true;
}

#undef ARRAY_SIZE

void HdmiCecHandler::dispatchMessage(const MessageEntry& entry) {
    int type = entry.first;
    mMessageQueueLock.unlock();
@@ -434,7 +552,7 @@ void HdmiCecHandler::dispatchMessage(const MessageEntry& entry) {
void HdmiCecHandler::processIncomingMessage(const cec_message_t& msg) {
    int opcode = msg.body[0];
    if (opcode == CEC_MESSAGE_GIVE_PHYSICAL_ADDRESS) {
        sendReportPhysicalAddress();
        sendReportPhysicalAddress(msg.destination);
    } else if (opcode == CEC_MESSAGE_REQUEST_ACTIVE_SOURCE) {
        handleRequestActiveSource();
    } else if (opcode == CEC_MESSAGE_GET_OSD_NAME) {
@@ -507,7 +625,7 @@ void HdmiCecHandler::handleRequestActiveSource() {
    JNIEnv* env = AndroidRuntime::getJNIEnv();
    jint activeDeviceType = env->CallIntMethod(mCallbacksObj,
            gHdmiCecServiceClassInfo.getActiveSource);
    if (activeDeviceType != INACTIVE_DEVICE_TYPE) {
    if (activeDeviceType != CEC_DEVICE_INACTIVE) {
        sendActiveSource(getLogicalAddress(static_cast<cec_device_type_t>(activeDeviceType)));
    }
    checkAndClearExceptionFromCallback(env, __FUNCTION__);