最近在调试Android Auto版本的evs_app程序。
evs_app相关参考:
《Android P Auto版本evs_app解析之一:evs_app代码架构和通信机制》
《Android P Auto版本evs_app解析之二:evs_app启动和运行》
一、检查摄像头设备
驱动层生成的摄像头设备节点在dev下面查看。adb进入系统目录dev下,ls -l查看摄像头;
生成的摄像头为:dev/video0,dev/video1,dev/video2,dev/video3;
我做实验这里有四个摄像头。
二、运行evs_app程序报错
evs_app是可执行的二进制文件,在system/bin目录下。
adb shell进入系统目录,执行start evs_app启动evs_app.
1、驱动层代码报错
看下面的打印,没有权限对video*设备进行访问。所以没有找到有效的摄像头设备
2019-06-13 18:14:16.420 1909-1963/? I/EvsDriver: Starting dev/video* enumeration
2019-06-13 18:14:16.428 1909-1909/? W/VideoFile-Poll-: type=1400 audit(0.0:2044): avc: denied { read write } for name="video3" dev="tmpfs" ino=9980 scontext=u:r:hal_evs_driver:s0 tcontext=u:object_r:ad_camera_device:s0 tclass=chr_file permissive=0
2019-06-13 18:14:16.428 1909-1909/? W/VideoFile-Poll-: type=1400 audit(0.0:2045): avc: denied { read write } for name="video2" dev="tmpfs" ino=9979 scontext=u:r:hal_evs_driver:s0 tcontext=u:object_r:ad_camera_device:s0 tclass=chr_file permissive=0
2019-06-13 18:14:16.428 1909-1909/? W/VideoFile-Poll-: type=1400 audit(0.0:2046): avc: denied { read write } for name="video1" dev="tmpfs" ino=9978 scontext=u:r:hal_evs_driver:s0 tcontext=u:object_r:ad_camera_device:s0 tclass=chr_file permissive=0
2019-06-13 18:14:16.428 1909-1909/? W/VideoFile-Poll-: type=1400 audit(0.0:2047): avc: denied { read write } for name="video0" dev="tmpfs" ino=20016 scontext=u:r:hal_evs_driver:s0 tcontext=u:object_r:ad_camera_device:s0 tclass=chr_file permissive=0
2019-06-13 18:14:16.431 1909-1963/? I/EvsDriver: enum name:mxc_isi.0.m2m
path:/dev/video4
2019-06-13 18:14:16.434 1909-1963/? I/EvsDriver: Found 1 qualified video capture devices of 7 checked
2、evs_app应用层也报错提示没有找到摄像头
2019-06-13 18:53:38.331 1909-1909/? D/EvsDriver: openCamera
2019-06-13 18:53:38.331 1909-1909/? E/EvsDriver: Requested camera mxc_isi.0.capture not found
2019-06-13 18:53:38.332 3272-3274/? E/EvsApp: Failed to allocate new EVS Camera interface for mxc_isi.0.capture
2019-06-13 18:53:38.332 3272-3274/? E/EvsApp: Failed to set up video texture for mxc_isi.0.capture (reverse,park)
2019-06-13 18:53:38.332 3272-3274/? E/EvsApp: New renderer failed to activate
2019-06-13 18:53:38.332 3272-3274/? E/EvsApp: selectStateForCurrentConditions failed so we're going to die
2019-06-13 18:53:38.332 3272-3274/? W/EvsApp: EvsStateControl update loop ending
2019-06-13 18:53:38.332 3272-3274/? E/EvsApp: KILLING THE APP FROM THE EvsStateControl LOOP ON DRAW FAILURE!!!
2019-06-13 18:53:38.346 1909-1909/? D/EvsDriver: EvsDisplay being destroyed
2019-06-13 18:53:38.346 1909-1909/? D/EvsDriver: EvsDisplay forceShutdown
三、修改驱动层代码
代码路径:packages\services\Car\evs\sampleDriver\EvsEnumerator.cpp
sampleDriver是android提供的示例驱动,运行evs_app之前,要保证驱动程序先正常运行,驱动程序也在system/bin目录下。
修改一下代码:
bool EvsEnumerator::EnumAvailableVideo() {
unsigned videoCount = 0;
unsigned captureCount = 0;
bool videoReady = false;
int enableFake = property_get_int32(EVS_FAKE_PROP, 0);
if (enableFake != 0) {
sCameraList.emplace_back(EVS_FAKE_SENSOR, EVS_FAKE_NAME);
captureCount++;
}
// For every video* entry in the dev folder, see if it reports suitable capabilities
// WARNING: Depending on the driver implementations this could be slow, especially if
// there are timeouts or round trips to hardware required to collect the needed
// information. Platform implementers should consider hard coding this list of
// known good devices to speed up the startup time of their EVS implementation.
// For example, this code might be replaced with nothing more than:
// sCameraList.emplace_back("/dev/video0");
// sCameraList.emplace_back("/dev/video1");
ALOGI("Starting dev/video* enumeration");
/*由于没有video*的访问权限,导致了该驱动没有找到摄像头设备
/*解决方法:1、在SElinux赋给驱动层权限,以便访问video*设备
2、注释掉这段代码,直接给sCameraList.emplace_back("/dev/video0")方式添加设备
/*********delete start*********/
/*
DIR* dir = opendir("/dev");
if (!dir) {
LOG_FATAL("Failed to open /dev folder\n");
}
struct dirent* entry;
FILE *fp = NULL;
char devPath[HWC_PATH_LENGTH];
char value[HWC_PATH_LENGTH];
while ((entry = readdir(dir)) != nullptr) {
// We're only looking for entries starting with 'video'
if (strncmp(entry->d_name, "video", 5) == 0) {
std::string deviceName("/dev/");
deviceName += entry->d_name;
videoCount++;
if (qualifyCaptureDevice(deviceName.c_str())) {
snprintf(devPath, HWC_PATH_LENGTH,
"/sys/class/video4linux/%s/name", entry->d_name);
if ((fp = fopen(devPath, "r")) == nullptr) {
ALOGE("can't open %s", devPath);
continue;
}
if(fgets(value, sizeof(value), fp) == nullptr) {
fclose(fp);
ALOGE("can't read %s", devPath);
continue;
}
fclose(fp);
ALOGI("enum name:%s path:%s", value, deviceName.c_str());
sCameraList.emplace_back(value, deviceName.c_str());
captureCount++;
}
}
}*/
/*********delete end*********/
/*********add start*********/
sCameraList.emplace_back("mxc_isi.0.capture","/dev/video0");
sCameraList.emplace_back("mxc_isi.1.capture","/dev/video1");
sCameraList.emplace_back("mxc_isi.2.capture","/dev/video2");
sCameraList.emplace_back("mxc_isi.3.capture","/dev/video3");
captureCount = 4;
videoCount = 4;
/*********add end*********/
if (captureCount != 0) {
videoReady = true;
if (property_set(EVS_VIDEO_READY, "1") < 0)
ALOGE("Can not set property %s", EVS_VIDEO_READY);
}
//delete
//closedir(dir);
ALOGI("Found %d qualified video capture devices of %d checked\n", captureCount, videoCount);
return videoReady;
}
修改上面代码为直接增加摄像头,当然最好的办法是给驱动赋予权限。
sCameraList.emplace_back(“mxc_isi.1.capture”,"/dev/video1");
mxc_isi.1.capture为packages\services\Car\evs\app\config.json中对应的camer_id
video1为我们一直的摄像头。
编译驱动程序放进系统中,重启,可以看到驱动启动的打印:
打印正常,找到4个摄像头设备,EvsEnumeratorHw is ready.
1970-01-01 08:00:10.818 1908-1908/? I/EvsDriver: EVS Hardware Enumerator service is starting
1970-01-01 08:00:10.818 1908-1908/? D/EvsDriver: EvsEnumerator created
1970-01-01 08:00:10.818 1908-1908/? I/EvsDriver: Starting dev/video* enumeration
1970-01-01 08:00:10.842 1908-1908/? I/EvsDriver: Found 4 qualified video capture devices of 4 checked
1970-01-01 08:00:10.843 1908-1908/? I/ServiceManagement: Removing namespace from process name [email protected] to [email protected].
1970-01-01 08:00:10.845 1908-1908/? D/EvsDriver: EvsEnumeratorHw is ready.
四、再次运行evs_app,赋予权限
再次运行evs_app,开始提示 (13 = Permission denied),说明驱动没有对摄像头的读写权限。
提示没有权限打开设备
2019-06-13 18:16:26.756 1908-1908/? D/EvsDriver: openCamera
2019-06-13 18:16:26.756 1908-1908/? D/EvsDriver: EvsCamera instantiated
2019-06-13 18:16:26.756 1908-1908/? E/EvsDriver: failed to open device /dev/video0 (13 = Permission denied)
2019-06-13 18:16:26.756 1908-1908/? E/EvsDriver: Failed to open v4l device /dev/video0
SELinux权限问题请参考:
https://blog.csdn.net/Sunxiaolin2016/article/details/91039775
关闭SeLinux防火墙:setenforce 0
再次运行evs_app,进入摄像头画面,evs运行成功。
运行stop evs_app退出evs程序。