summaryrefslogtreecommitdiff
authorJiyu Yang <jiyu.yang@amlogic.com>2014-12-18 10:37:56 (GMT)
committer Jiyu Yang <jiyu.yang@amlogic.com>2014-12-19 03:06:59 (GMT)
commit2f94d9f19040fa25253d048edd160cda1e6ccb6d (patch)
treeace5348414ec32bb1bebf7d7c49e357a2c600b31
parentd4e040391bb40198882de5463242a0c6bc8c495a (diff)
downloadcamera-2f94d9f19040fa25253d048edd160cda1e6ccb6d.zip
camera-2f94d9f19040fa25253d048edd160cda1e6ccb6d.tar.gz
camera-2f94d9f19040fa25253d048edd160cda1e6ccb6d.tar.bz2
PD#100964 add hotplug
use socket() to read the uevent. TODO use Inputflinger instead. this also fixed PD#101175 sleep 10ms when /dev/video* created Change-Id: I7f41377e7b55313b62d95bcf1237a8def859c943 Signed-off-by: Jiyu Yang <jiyu.yang@amlogic.com>
Diffstat
-rw-r--r--v3/EmulatedCamera3.cpp3
-rw-r--r--v3/EmulatedCamera3.h1
-rwxr-xr-xv3/EmulatedCameraFactory.cpp161
-rwxr-xr-xv3/EmulatedCameraFactory.h21
-rw-r--r--v3/EmulatedCameraHotplugThread.cpp147
-rw-r--r--v3/EmulatedCameraHotplugThread.h4
-rwxr-xr-xv3/EmulatedFakeCamera3.cpp52
-rwxr-xr-xv3/EmulatedFakeCamera3.h4
8 files changed, 248 insertions, 145 deletions
diff --git a/v3/EmulatedCamera3.cpp b/v3/EmulatedCamera3.cpp
index 588aa77..3a54794 100644
--- a/v3/EmulatedCamera3.cpp
+++ b/v3/EmulatedCamera3.cpp
@@ -44,7 +44,8 @@ EmulatedCamera3::EmulatedCamera3(int cameraId,
CAMERA_DEVICE_API_VERSION_3_2,
&common,
module),
- mStatus(STATUS_ERROR)
+ mStatus(STATUS_ERROR),
+ mPlugged(false)
{
common.close = EmulatedCamera3::close;
ops = &sDeviceOps;
diff --git a/v3/EmulatedCamera3.h b/v3/EmulatedCamera3.h
index 16d0667..1cf5f33 100644
--- a/v3/EmulatedCamera3.h
+++ b/v3/EmulatedCamera3.h
@@ -187,6 +187,7 @@ private:
STATUS_ACTIVE
} mStatus;
+ bool mPlugged;
/**
* Callbacks back to the framework
*/
diff --git a/v3/EmulatedCameraFactory.cpp b/v3/EmulatedCameraFactory.cpp
index 0084c90..94501e6 100755
--- a/v3/EmulatedCameraFactory.cpp
+++ b/v3/EmulatedCameraFactory.cpp
@@ -41,32 +41,32 @@ volatile int32_t gCamHal_LogLevel = 6;
android::EmulatedCameraFactory gEmulatedCameraFactory;
default_camera_hal::VendorTags gVendorTags;
-const char *SENSOR_PATH[]={
- "/dev/video0",
- "/dev/video1",
- "/dev/video2",
- };
-#define DEVICE_PATH(_sensor_index) (SENSOR_PATH[_sensor_index])
-#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
-extern "C" int Get_CameraNum() {
+static const char *SENSOR_PATH[]={
+ "/dev/video0",
+ "/dev/video1",
+ "/dev/video2",
+ "/dev/video3",
+ "/dev/video4",
+ "/dev/video5",
+};
+
+static int getCameraNum() {
int iCamerasNum = 0;
- for( int i = 0; i < (int)ARRAY_SIZE(SENSOR_PATH); i++ ) {
- if( access(DEVICE_PATH(i), 0) == 0 ) {
- int camera_fd;
- if((camera_fd = open(DEVICE_PATH(i), O_RDWR)) != -1){
- ALOGV("try open %s\n", DEVICE_PATH(i));
- close(camera_fd);
- iCamerasNum++;
- }
+ for (int i = 0; i < (int)ARRAY_SIZE(SENSOR_PATH); i++ ) {
+ int camera_fd;
+ CAMHAL_LOGDB("try access %s\n", SENSOR_PATH[i]);
+ if (0 == access(SENSOR_PATH[i], F_OK | R_OK | W_OK)) {
+ CAMHAL_LOGDB("access %s success\n", SENSOR_PATH[i]);
+ iCamerasNum++;
}
}
+
return iCamerasNum;
}
namespace android {
EmulatedCameraFactory::EmulatedCameraFactory()
: mQemuClient(),
- mEmulatedCameras(NULL),
mEmulatedCameraNum(0),
mFakeCameraNum(0),
mConstructedOK(false),
@@ -75,25 +75,19 @@ EmulatedCameraFactory::EmulatedCameraFactory()
status_t res;
/* Connect to the factory service in the emulator, and create Qemu cameras. */
bool facingback = true;
- mEmulatedCameraNum = Get_CameraNum();
- ALOGV("Camera num = %d",mEmulatedCameraNum);
- if (mEmulatedCameras == NULL) {
- mEmulatedCameras = new EmulatedBaseCamera*[mEmulatedCameraNum];
- if (mEmulatedCameras == NULL) {
- ALOGE("%s: Unable to allocate emulated camera array for %d entries",
- __FUNCTION__, mEmulatedCameraNum);
- return;
- }
- memset(mEmulatedCameras, 0,(mEmulatedCameraNum) * sizeof(EmulatedBaseCamera*));
- }
-
+ int cameraId = 0;
+
+ memset(mEmulatedCameras, 0,(MAX_CAMERA_NUM) * sizeof(EmulatedBaseCamera*));
+ mEmulatedCameraNum = getCameraNum();
+ CAMHAL_LOGDB("Camera num = %d", mEmulatedCameraNum);
+
for( int i = 0; i < mEmulatedCameraNum; i++ ) {
- if (i%mEmulatedCameraNum == 1)
- facingback = false;
- mEmulatedCameras[i] = new EmulatedFakeCamera3(i, facingback,&HAL_MODULE_INFO_SYM.common);
+ cameraId = i;
+ facingback = isFakeCameraFacingBack(cameraId);
+ mEmulatedCameras[i] = new EmulatedFakeCamera3(cameraId, facingback,&HAL_MODULE_INFO_SYM.common);
if (mEmulatedCameras[i] != NULL) {
- ALOGV("%s: Back camera device version is %d", __FUNCTION__,
- getBackCameraHalVersion());
+ ALOGV("%s: camera device version is %d", __FUNCTION__,
+ getFakeCameraHalVersion(cameraId));
res = mEmulatedCameras[i]->Initialize();
if (res != NO_ERROR) {
ALOGE("%s: Unable to intialize back camera %d: %s (%d)",
@@ -102,9 +96,9 @@ EmulatedCameraFactory::EmulatedCameraFactory()
}
}
}
-
- ALOGV("%d cameras are being emulated. %d of them are fake cameras.",
- mEmulatedCameraNum, mFakeCameraNum);
+
+ CAMHAL_LOGDB("%d cameras are being created",
+ mEmulatedCameraNum);
/* Create hotplug thread */
{
@@ -122,13 +116,11 @@ EmulatedCameraFactory::EmulatedCameraFactory()
EmulatedCameraFactory::~EmulatedCameraFactory()
{
- if (mEmulatedCameras != NULL) {
- for (int n = 0; n < mEmulatedCameraNum; n++) {
- if (mEmulatedCameras[n] != NULL) {
- delete mEmulatedCameras[n];
- }
+ CAMHAL_LOGDA("Camera Factory deconstruct the BaseCamera\n");
+ for (int n = 0; n < mEmulatedCameraNum; n++) {
+ if (mEmulatedCameras[n] != NULL) {
+ delete mEmulatedCameras[n];
}
- delete[] mEmulatedCameras;
}
if (mHotplugThread != NULL) {
@@ -286,6 +278,7 @@ static const char lListDirToken[] = "dir=";
void EmulatedCameraFactory::createQemuCameras()
{
+#if 0
/* Obtain camera list. */
char* camera_list = NULL;
status_t res = mQemuClient.listCameras(&camera_list);
@@ -385,9 +378,20 @@ void EmulatedCameraFactory::createQemuCameras()
}
mEmulatedCameraNum = index;
+#else
+ CAMHAL_LOGDA("delete this function");
+#endif
+}
+
+bool EmulatedCameraFactory::isFakeCameraFacingBack(int cameraId)
+{
+ if (cameraId%mEmulatedCameraNum == 1)
+ return false;
+
+ return true;
}
-int EmulatedCameraFactory::getBackCameraHalVersion()
+int EmulatedCameraFactory::getFakeCameraHalVersion(int cameraId)
{
/* Defined by 'qemu.sf.back_camera_hal_version' boot property: if the
* property doesn't exist, it is assumed to be 1. */
@@ -404,59 +408,78 @@ int EmulatedCameraFactory::getBackCameraHalVersion()
}
return 1;
#else
+ cameraId = cameraId;
return 3;
#endif
}
-int EmulatedCameraFactory::getFrontCameraHalVersion()
+void EmulatedCameraFactory::onStatusChanged(int cameraId, int newStatus)
{
- /* Defined by 'qemu.sf.front_camera_hal_version' boot property: if the
- * property doesn't exist, it is assumed to be 1. */
-#if 0
- char prop[PROPERTY_VALUE_MAX];
- if (property_get("qemu.sf.front_camera_hal", prop, NULL) > 0) {
- char *prop_end = prop;
- int val = strtol(prop, &prop_end, 10);
- if (*prop_end == '\0') {
- return val;
- }
- // Badly formatted property, should just be a number
- ALOGE("qemu.sf.front_camera_hal is not a number: %s", prop);
- }
- return 1;
-#else
- return 3;
-#endif
-}
-
-void EmulatedCameraFactory::onStatusChanged(int cameraId, int newStatus) {
+ status_t res;
EmulatedBaseCamera *cam = mEmulatedCameras[cameraId];
+ const camera_module_callbacks_t* cb = mCallbacks;
+
+ CAMHAL_LOGDB("mEmulatedCameraNum =%d\n", mEmulatedCameraNum);
+
if (!cam) {
- ALOGE("%s: Invalid camera ID %d", __FUNCTION__, cameraId);
- return;
+ /*suppose only usb camera produce uevent, and it is facing back*/
+ cam = new EmulatedFakeCamera3(cameraId,
+ /*facingback*/true,&HAL_MODULE_INFO_SYM.common);
+ if (cam != NULL) {
+ CAMHAL_LOGDB("%s: new camera device version is %d", __FUNCTION__,
+ getFakeCameraHalVersion(cameraId));
+ //sleep 10ms for /dev/video* create
+ usleep(10000);
+ res = cam->Initialize();
+ if (res != NO_ERROR) {
+ ALOGE("%s: Unable to intialize back camera %d: %s (%d)",
+ __FUNCTION__, cameraId, strerror(-res), res);
+ delete cam;
+ }
+ }
+
+ /* Open the camera. then send the callback to framework*/
+ mEmulatedCameras[cameraId] = cam;
+ mEmulatedCameraNum ++;
+ cam->plugCamera();
+ if (cb != NULL && cb->camera_device_status_change != NULL) {
+ cb->camera_device_status_change(cb, cameraId, newStatus);
+ }
+
+ return ;
}
+ CAMHAL_LOGDB("mEmulatedCameraNum =%d\n", mEmulatedCameraNum);
+
/**
* (Order is important)
* Send the callback first to framework, THEN close the camera.
*/
if (newStatus == cam->getHotplugStatus()) {
- ALOGW("%s: Ignoring transition to the same status", __FUNCTION__);
+ CAMHAL_LOGDB("%s: Ignoring transition to the same status", __FUNCTION__);
return;
}
- const camera_module_callbacks_t* cb = mCallbacks;
+ CAMHAL_LOGDB("mEmulatedCameraNum =%d\n", mEmulatedCameraNum);
if (cb != NULL && cb->camera_device_status_change != NULL) {
cb->camera_device_status_change(cb, cameraId, newStatus);
}
+ CAMHAL_LOGDB("mEmulatedCameraNum =%d\n", mEmulatedCameraNum);
if (newStatus == CAMERA_DEVICE_STATUS_NOT_PRESENT) {
cam->unplugCamera();
+////
+ delete mEmulatedCameras[cameraId];
+ mEmulatedCameras[cameraId] = NULL;
+ mEmulatedCameraNum --;
+////
} else if (newStatus == CAMERA_DEVICE_STATUS_PRESENT) {
+ CAMHAL_LOGDA("camera plugged again?\n");
cam->plugCamera();
}
+ CAMHAL_LOGDB("mEmulatedCameraNum =%d\n", mEmulatedCameraNum);
}
diff --git a/v3/EmulatedCameraFactory.h b/v3/EmulatedCameraFactory.h
index abf5cf2..504f842 100755
--- a/v3/EmulatedCameraFactory.h
+++ b/v3/EmulatedCameraFactory.h
@@ -27,8 +27,13 @@
#include "VendorTags.h"
namespace android {
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+#endif
+
struct EmulatedCameraHotplugThread;
+
/*
* Contains declaration of a class EmulatedCameraFactory that manages cameras
* available for the emulation. A global instance of this class is statically
@@ -52,6 +57,10 @@ struct EmulatedCameraHotplugThread;
* - camera_module_t::get_camera_info entry point
*
*/
+
+#ifndef MAX_CAMERA_NUM
+#define MAX_CAMERA_NUM 6
+#endif
class EmulatedCameraFactory {
public:
/* Constructs EmulatedCameraFactory instance.
@@ -154,17 +163,11 @@ private:
*/
void createQemuCameras();
- /* Checks if fake camera emulation is on for the camera facing back. */
- bool isBackFakeCameraEmulationOn();
-
- /* Gets camera device version number to use for back camera emulation */
- int getBackCameraHalVersion();
-
/* Checks if fake camera emulation is on for the camera facing front. */
- bool isFrontFakeCameraEmulationOn();
+ bool isFakeCameraFacingBack(int cameraId);
/* Gets camera device version number to use for front camera emulation */
- int getFrontCameraHalVersion();
+ int getFakeCameraHalVersion(int cameraId);
/****************************************************************************
* Data members.
@@ -175,7 +178,7 @@ private:
FactoryQemuClient mQemuClient;
/* Array of cameras available for the emulation. */
- EmulatedBaseCamera** mEmulatedCameras;
+ EmulatedBaseCamera* mEmulatedCameras[MAX_CAMERA_NUM];
/* Number of emulated cameras (including the fake ones). */
int mEmulatedCameraNum;
diff --git a/v3/EmulatedCameraHotplugThread.cpp b/v3/EmulatedCameraHotplugThread.cpp
index 0ce2aeb..ecdcb0d 100644
--- a/v3/EmulatedCameraHotplugThread.cpp
+++ b/v3/EmulatedCameraHotplugThread.cpp
@@ -40,14 +40,15 @@ EmulatedCameraHotplugThread::EmulatedCameraHotplugThread(
Thread(/*canCallJava*/false) {
mRunning = true;
- mInotifyFd = 0;
+ //mInotifyFd = 0;
for (size_t i = 0; i < size; ++i) {
int id = cameraIdArray[i];
-
+#if 0
if (createFileIfNotExists(id)) {
mSubscribedCameraIds.push_back(id);
}
+#endif
}
}
@@ -70,6 +71,7 @@ void EmulatedCameraHotplugThread::requestExit() {
Vector<SubscriberInfo>::iterator it;
for (it = mSubscribers.begin(); it != mSubscribers.end(); ++it) {
+#if 0
if (inotify_rm_watch(mInotifyFd, it->WatchID) == -1) {
ALOGE("%s: Could not remove watch for camID '%d',"
@@ -82,6 +84,7 @@ void EmulatedCameraHotplugThread::requestExit() {
ALOGV("%s: Removed watch for camID '%d'",
__FUNCTION__, it->CameraID);
}
+#endif
}
if (rmWatchFailed) { // unlikely
@@ -92,6 +95,12 @@ void EmulatedCameraHotplugThread::requestExit() {
__FUNCTION__, strerror(errno), errno);
}
}
+ if (shutdown(mSocketFd, SHUT_RD) < 0) {
+ CAMHAL_LOGDB("shutdown socket failed errno=%s", strerror(errno));
+ }
+ if (close(mSocketFd) < 0) {
+ CAMHAL_LOGDB("close socket failed errno=%s", strerror(errno));
+ }
ALOGV("%s: Request exit complete.", __FUNCTION__);
}
@@ -104,6 +113,7 @@ status_t EmulatedCameraHotplugThread::readyToRun() {
do {
ALOGV("%s: Initializing inotify", __FUNCTION__);
+#if 0
mInotifyFd = inotify_init();
if (mInotifyFd == -1) {
ALOGE("%s: inotify_init failure error: '%s' (%d)",
@@ -111,6 +121,22 @@ status_t EmulatedCameraHotplugThread::readyToRun() {
mRunning = false;
break;
}
+#endif
+ memset(&sa,0,sizeof(sa));
+ sa.nl_family = AF_NETLINK;
+ sa.nl_groups = NETLINK_KOBJECT_UEVENT;
+ sa.nl_pid = 0;//getpid(); both is ok
+
+ mSocketFd = socket(AF_NETLINK,SOCK_RAW,NETLINK_KOBJECT_UEVENT);
+ if (mSocketFd == -1) {
+ mRunning = false;
+ CAMHAL_LOGEB("socket creating failed:%s, disable the hotplug thread\n",strerror(errno));
+ }
+
+ if (bind(mSocketFd,(struct sockaddr *)&sa,sizeof(sa)) == -1) {
+ mRunning = false;
+ CAMHAL_LOGEB("bind error:%s, disable the hotplug thread\n",strerror(errno));
+ }
/**
* For each fake camera file, add a watch for when
@@ -131,9 +157,11 @@ status_t EmulatedCameraHotplugThread::readyToRun() {
if (!mRunning) {
status_t err = -errno;
+#if 0
if (mInotifyFd != -1) {
TEMP_FAILURE_RETRY(close(mInotifyFd));
}
+#endif
return err;
}
@@ -144,75 +172,67 @@ status_t EmulatedCameraHotplugThread::readyToRun() {
bool EmulatedCameraHotplugThread::threadLoop() {
// If requestExit was already called, mRunning will be false
+ int len;
+ char buf[4096];
+ struct iovec iov;
+ struct msghdr msg;
+ char *video4linux_string;
+ char *action_string;
+ int i;
+ int cameraId;
+ int halStatus;
+
while (mRunning) {
- char buffer[EVENT_BUF_LEN];
- int length = TEMP_FAILURE_RETRY(
- read(mInotifyFd, buffer, EVENT_BUF_LEN));
+ memset(&msg,0,sizeof(msg));
+ iov.iov_base=(void *)buf;
+ iov.iov_len=sizeof(buf);
+ msg.msg_name=(void *)&sa;
+ msg.msg_namelen=sizeof(sa);
+ msg.msg_iov=&iov;
+ msg.msg_iovlen=1;
+
+ len = recvmsg(mSocketFd, &msg, 0);
+ if (len < 0) {
+ break;
+ } else if ((len<32) || (len > (int)sizeof(buf))) {
+ CAMHAL_LOGDA("invalid message");
+ break;
+ }
+ buf[len] = '\0';
- if (length < 0) {
- ALOGE("%s: Error reading from inotify FD, error: '%s' (%d)",
- __FUNCTION__, strerror(errno),
- errno);
- mRunning = false;
+ CAMHAL_LOGDB("buf=%s\n", buf);
+ video4linux_string = strstr(buf, "video4linux");
+ CAMHAL_LOGVB("video4linux=%s\n", video4linux_string);
+ if (video4linux_string == NULL) {
+ CAMHAL_LOGDA("not video event\n");
break;
}
- ALOGV("%s: Read %d bytes from inotify FD", __FUNCTION__, length);
-
- int i = 0;
- while (i < length) {
- inotify_event* event = (inotify_event*) &buffer[i];
-
- if (event->mask & IN_IGNORED) {
- Mutex::Autolock al(mMutex);
- if (!mRunning) {
- ALOGV("%s: Shutting down thread", __FUNCTION__);
- break;
- } else {
- ALOGE("%s: File was deleted, aborting",
- __FUNCTION__);
- mRunning = false;
- break;
- }
- } else if (event->mask & IN_CLOSE_WRITE) {
- int cameraId = getCameraId(event->wd);
-
- if (cameraId < 0) {
- ALOGE("%s: Got bad camera ID from WD '%d",
- __FUNCTION__, event->wd);
- } else {
- // Check the file for the new hotplug event
- String8 filePath = getFilePath(cameraId);
- /**
- * NOTE: we carefully avoid getting an inotify
- * for the same exact file because it's opened for
- * read-only, but our inotify is for write-only
- */
- int newStatus = readFile(filePath);
-
- if (newStatus < 0) {
- mRunning = false;
- break;
- }
-
- int halStatus = newStatus ?
- CAMERA_DEVICE_STATUS_PRESENT :
- CAMERA_DEVICE_STATUS_NOT_PRESENT;
- gEmulatedCameraFactory.onStatusChanged(cameraId,
- halStatus);
- }
-
- } else {
- ALOGW("%s: Unknown mask 0x%x",
- __FUNCTION__, event->mask);
- }
+ CAMHAL_LOGVB("video=%s\n", video4linux_string);
+ action_string = strchr(video4linux_string, '\0');
+ action_string ++;
+ CAMHAL_LOGDB("action string=%s\n", action_string);
- i += EVENT_SIZE + event->len;
+ if (strstr(action_string, "ACTION=add") != NULL) {
+ halStatus = CAMERA_DEVICE_STATUS_PRESENT;
+ } else if (strstr(action_string, "ACTION=remove") != NULL) {
+ halStatus = CAMERA_DEVICE_STATUS_NOT_PRESENT;
+ } else {
+ CAMHAL_LOGDA("no find add or remove\n");
+ break;
}
+
+ //string like that: add@/devices/lm1/usb1/1-1/1-1.3/1-1.3:1.0/video4linux/video0
+ video4linux_string += 17;
+ cameraId = strtol(video4linux_string, NULL, 10);
+
+ gEmulatedCameraFactory.onStatusChanged(cameraId,
+ halStatus);
+
}
if (!mRunning) {
- TEMP_FAILURE_RETRY(close(mInotifyFd));
+ //TEMP_FAILURE_RETRY(close(mInotifyFd));
return false;
}
@@ -285,6 +305,8 @@ SubscriberInfo* EmulatedCameraHotplugThread::getSubscriberInfo(int cameraId)
bool EmulatedCameraHotplugThread::addWatch(int cameraId) {
String8 camPath = getFilePath(cameraId);
+ int wd = 0;
+#if 0
int wd = inotify_add_watch(mInotifyFd,
camPath.string(),
IN_CLOSE_WRITE);
@@ -297,6 +319,7 @@ bool EmulatedCameraHotplugThread::addWatch(int cameraId) {
mRunning = false;
return false;
}
+#endif
ALOGV("%s: Watch added for camID='%d', wd='%d'",
__FUNCTION__, cameraId, wd);
@@ -312,6 +335,7 @@ bool EmulatedCameraHotplugThread::removeWatch(int cameraId) {
if (!si) return false;
+#if 0
if (inotify_rm_watch(mInotifyFd, si->WatchID) == -1) {
ALOGE("%s: Could not remove watch for camID '%d', error: '%s' (%d)",
@@ -320,6 +344,7 @@ bool EmulatedCameraHotplugThread::removeWatch(int cameraId) {
return false;
}
+#endif
Vector<SubscriberInfo>::iterator it;
for (it = mSubscribers.begin(); it != mSubscribers.end(); ++it) {
diff --git a/v3/EmulatedCameraHotplugThread.h b/v3/EmulatedCameraHotplugThread.h
index 3e26e71..86c63b6 100644
--- a/v3/EmulatedCameraHotplugThread.h
+++ b/v3/EmulatedCameraHotplugThread.h
@@ -28,6 +28,8 @@
#include "EmulatedCamera2.h"
#include <utils/String8.h>
#include <utils/Vector.h>
+#include <sys/socket.h>
+#include <linux/netlink.h>
namespace android {
class EmulatedCameraHotplugThread : public Thread {
@@ -71,6 +73,8 @@ class EmulatedCameraHotplugThread : public Thread {
Mutex mMutex;
bool mRunning; // guarding only when it's important
+ int mSocketFd;
+ struct sockaddr_nl sa;
};
} // namespace android
diff --git a/v3/EmulatedFakeCamera3.cpp b/v3/EmulatedFakeCamera3.cpp
index d42ef60..669f6b5 100755
--- a/v3/EmulatedFakeCamera3.cpp
+++ b/v3/EmulatedFakeCamera3.cpp
@@ -45,8 +45,6 @@
#define ALOGVV(...) ((void)0)
#endif
-#define ARRAY_SIZE(x) (sizeof((x))/sizeof(((x)[0])))
-
namespace android {
/**
@@ -190,6 +188,12 @@ EmulatedFakeCamera3::~EmulatedFakeCamera3() {
free_camera_metadata(mDefaultTemplates[i]);
}
}
+
+ if (mCameraInfo != NULL) {
+ CAMHAL_LOGIA("free mCameraInfo");
+ free_camera_metadata(mCameraInfo);
+ mCameraInfo = NULL;
+ }
}
status_t EmulatedFakeCamera3::Initialize() {
@@ -240,8 +244,9 @@ status_t EmulatedFakeCamera3::connectCamera(hw_device_t** device) {
Mutex::Autolock l(mLock);
status_t res;
- if (mStatus != STATUS_CLOSED) {
- ALOGE("%s: Can't connect in state %d", __FUNCTION__, mStatus);
+ if ((mStatus != STATUS_CLOSED) || !mPlugged) {
+ ALOGE("%s: Can't connect in state %d, mPlugged=%d",
+ __FUNCTION__, mStatus, mPlugged);
return INVALID_OPERATION;
}
@@ -280,8 +285,41 @@ status_t EmulatedFakeCamera3::connectCamera(hw_device_t** device) {
return EmulatedCamera3::connectCamera(device);
}
+status_t EmulatedFakeCamera3::plugCamera() {
+ {
+ Mutex::Autolock l(mLock);
+
+ if (!mPlugged) {
+ CAMHAL_LOGIB("%s: Plugged back in", __FUNCTION__);
+ mPlugged = true;
+ }
+ }
+
+ return NO_ERROR;
+}
+
+status_t EmulatedFakeCamera3::unplugCamera() {
+ {
+ Mutex::Autolock l(mLock);
+
+ if (mPlugged) {
+ CAMHAL_LOGIB("%s: Unplugged camera", __FUNCTION__);
+ mPlugged = false;
+ }
+ }
+
+ return closeCamera();
+}
+
+camera_device_status_t EmulatedFakeCamera3::getHotplugStatus() {
+ Mutex::Autolock l(mLock);
+ return mPlugged ?
+ CAMERA_DEVICE_STATUS_PRESENT :
+ CAMERA_DEVICE_STATUS_NOT_PRESENT;
+}
+
status_t EmulatedFakeCamera3::closeCamera() {
- ALOGV("%s: E", __FUNCTION__);
+ CAMHAL_LOGVB("%s, %d\n", __FUNCTION__, __LINE__);
status_t res;
{
Mutex::Autolock l(mLock);
@@ -1965,6 +2003,9 @@ status_t EmulatedFakeCamera3::constructStaticInfo() {
getAvailableChKeys(&info, supportedHardwareLevel);
+ if (mCameraInfo != NULL) {
+ CAMHAL_LOGDA("mCameraInfo is not null, mem leak?");
+ }
mCameraInfo = info.release();
DBG_LOGB("mCameraID=%d,mCameraInfo=%p\n", mCameraID, mCameraInfo);
@@ -1974,6 +2015,7 @@ status_t EmulatedFakeCamera3::constructStaticInfo() {
s->shutDown();
s.clear();
+ mPlugged = true;
return OK;
}
diff --git a/v3/EmulatedFakeCamera3.h b/v3/EmulatedFakeCamera3.h
index 8bf94d2..7de6a4e 100755
--- a/v3/EmulatedFakeCamera3.h
+++ b/v3/EmulatedFakeCamera3.h
@@ -70,6 +70,10 @@ public:
public:
virtual status_t connectCamera(hw_device_t** device);
+ virtual status_t plugCamera();
+ virtual status_t unplugCamera();
+ virtual camera_device_status_t getHotplugStatus();
+
virtual status_t closeCamera();
virtual status_t getCameraInfo(struct camera_info *info);