说明

        在一次性能优化的提交https://gitee.com/openharmony/drivers_hdf_core/pulls/2181 将触摸屏异步初始化之后引发一系列的xts错误。HatsHdfInputPassthroughTest、HatsHdfInputTest、HatsHdfInputPassthroughAdditionalTest都出现测试失败。

分析结果如下

drivers/hdf_core/framework/model/input/driver/hdf_input_device_manager.c       

static int32_t CreateDeviceNode(InputDevice *inputDev)
{
    static bool existNonHid = false ;
    if (IsHidDevice(inputDev)) {
        if (!existNonHid) {
            CacheHid(inputDev);
            HDF_LOGI("%s: is first hid dev add cache, devId is %d ", __func__, inputDev->devId);
            return HDF_SUCCESS;
        }
        HDF_LOGI("%s: prepare to register hdf device", __func__);
        inputDev->hdfDevObj = HidRegisterHdfDevice(inputDev);
        if (inputDev->hdfDevObj == NULL) {
            return HDF_DEV_ERR_NO_DEVICE;
        }
        inputDev->hdfDevObj->priv = (void *)inputDev;
    } else {
        existNonHid = true ;
    }

    HDF_LOGI("%s: create node succ, devId is %d ", __func__, inputDev->devId);
    return HDF_SUCCESS;
}

此函数存在明显的逻辑问题,如果第一个调用设备是HID设备那么就会导致调用CacheHid新建设备,就会多出一系列的设备,而如果第一个是触摸屏由于existNonHid会是true,后续的所有的设备都不会调用CacheHid。异步优化就是陷入这个局面,同样如果是没有触摸屏的设备(机顶盒)也可能会面对这种局面。此出会导致一系列的HatsHdfInputPassthroughTest HatsHdfInputPassthroughAdditionalTest失败。

test/xts/hats/hdf/input/hdi_input/common/hdi_input_test.cpp

/**
  * @tc.number: SUB_Driver_Input_Hdi_1700
  * @tc.name: get input device id info test
  * @tc.desc: [C- SOFTWARE -0010]
  * @tc.size: Medium
  * @tc.level: level 0
  */
HWTEST_F(HdiInputTest, SUB_Driver_Input_Hdi_1700, Function | MediumTest | Level0)
{
    if (g_allDev[0].devType == INDEV_TYPE_TOUCH) {
        ASSERT_EQ(g_HasDev, true);
        int32_t ret = 0;
        InputDeviceInfo *dev = nullptr;
        INPUT_CHECK_NULL_POINTER(g_inputInterface, INPUT_NULL_PTR);
        INPUT_CHECK_NULL_POINTER(g_inputInterface->iInputManager, INPUT_NULL_PTR);

        ret = g_inputInterface->iInputManager->OpenInputDevice(TOUCH_INDEX);
        if (ret) {
            HDF_LOGE("%s: open device1 failed, ret %d\n", __func__, ret);
        }
        ASSERT_EQ(ret, INPUT_SUCCESS);
        ret = g_inputInterface->iInputManager->GetInputDevice(TOUCH_INDEX, &dev);
        EXPECT_EQ(ret, INPUT_SUCCESS);
        EXPECT_EQ((uint32_t)TOUCH_INDEX, dev->devIndex);
        HDF_LOGI("devindex = %u, devType = %u\n", dev->devIndex, dev->devType);
        HDF_LOGI("chipInfo = %s, VendorName = %s,chipName = %s\n", dev->chipInfo, dev->vendorName, dev->chipName);
    }
    int32_t ret = INPUT_SUCCESS;
    EXPECT_EQ(ret, INPUT_SUCCESS);
}

g_allDev[0].devType == INDEV_TYPE_TOUCH如果触摸屏不是第一个那么这个测试用例就是无效的,甚至会调至之后的SUB_Driver_Input_Hdi_1500测试用例失败。正确逻辑应该要素有的设备里遍历。

 


/**
  * @tc.number: SUB_Driver_Input_Hdi_1500
  * @tc.name: get input device list info error test
  * @tc.desc: [C- SOFTWARE -0010]
  * @tc.size: Medium
  * @tc.level: level 0
  */
HWTEST_F(HdiInputTest, SUB_Driver_Input_Hdi_1500, Function | MediumTest | Level0)
{
    ASSERT_EQ(g_HasDev, true);
    int32_t ret;
    uint32_t num = 0;
    InputDeviceInfo *dev[MAX_INPUT_DEV_NUM] = {0}; 

    ret = g_inputInterface->iInputManager->GetInputDeviceList(nullptr, dev, MAX_INPUT_DEV_NUM);
    EXPECT_NE(ret, INPUT_SUCCESS);
    ret = g_inputInterface->iInputManager->GetInputDeviceList(&num, nullptr, MAX_INPUT_DEV_NUM);
    EXPECT_NE(ret, INPUT_SUCCESS);
    ret = g_inputInterface->iInputManager->GetInputDeviceList(&num, dev, 0);
    EXPECT_NE(ret, INPUT_SUCCESS);
}

 

ret = g_inputInterface->iInputManager->GetInputDeviceList(&num, dev, 0);这个函数会调用到GetInputDeviceList

static int32_t GetInputDeviceList(uint32_t *devNum, InputDeviceInfo **deviceList, uint32_t size)
{
    DeviceInfoNode *pos = NULL;
    DeviceInfoNode *next = NULL;
    InputDevManager *manager = NULL;
    uint32_t tempSize = 0;
    InputDeviceInfo **tempList = NULL;

    if (devNum == NULL || deviceList == NULL) {
        HDF_LOGE("%s: invalid param", __func__);
        return INPUT_INVALID_PARAM;
    }
    tempList = deviceList;
    GET_MANAGER_CHECK_RETURN(manager);

    pthread_mutex_lock(&manager->mutex);
    DLIST_FOR_EACH_ENTRY_SAFE(pos, next, &manager->devList, DeviceInfoNode, node) {
        if (tempSize >= size) {
            *devNum = manager->attachedDevNum;
            pthread_mutex_unlock(&manager->mutex);
            HDF_LOGE("%s: size is not enough, size = %u, devNum = %u", __func__,
                size, *devNum);
            return INPUT_FAILURE;
        }
        *tempList = &pos->payload;
        tempList++;
        tempSize++;
    }
    *devNum = manager->attachedDevNum;
    pthread_mutex_unlock(&manager->mutex);
    return INPUT_SUCCESS;
}

DLIST_FOR_EACH_ENTRY_SAFE 这个当devList如果出现因为触摸屏的误判导致其为空,这个测试用例也会返回INPUT_SUCCESS导致用例失败。这个测试用例本身应该不应该受是否有触摸屏而影响到,更何况触摸屏判断还有误判的情况。

Logo

社区规范:仅讨论OpenHarmony相关问题。

更多推荐