一次内核优化引发的XTS错误分析
说明
在一次性能优化的提交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导致用例失败。这个测试用例本身应该不应该受是否有触摸屏而影响到,更何况触摸屏判断还有误判的情况。
更多推荐
所有评论(0)