author | Jiyu 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) |
commit | 2f94d9f19040fa25253d048edd160cda1e6ccb6d (patch) | |
tree | ace5348414ec32bb1bebf7d7c49e357a2c600b31 | |
parent | d4e040391bb40198882de5463242a0c6bc8c495a (diff) | |
download | camera-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>
-rw-r--r-- | v3/EmulatedCamera3.cpp | 3 | ||||
-rw-r--r-- | v3/EmulatedCamera3.h | 1 | ||||
-rwxr-xr-x | v3/EmulatedCameraFactory.cpp | 161 | ||||
-rwxr-xr-x | v3/EmulatedCameraFactory.h | 21 | ||||
-rw-r--r-- | v3/EmulatedCameraHotplugThread.cpp | 147 | ||||
-rw-r--r-- | v3/EmulatedCameraHotplugThread.h | 4 | ||||
-rwxr-xr-x | v3/EmulatedFakeCamera3.cpp | 52 | ||||
-rwxr-xr-x | v3/EmulatedFakeCamera3.h | 4 |
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); |