From 4ef776eefaf7845b17831797db8a3e00cd000c62 Mon Sep 17 00:00:00 2001 From: PythonLimited Date: Sun, 28 Feb 2021 18:20:53 +0100 Subject: [PATCH] camera: add wrapper and build camera2 instead of snap camera2 fixes the flash bugging when taking a photo the wrapper isnt needed but ill keep it to debug cam later on R --- camera/Android.bp | 43 +++ camera/CallbackWorkerThread.cpp | 259 +++++++++++++ camera/CallbackWorkerThread.h | 93 +++++ camera/Camera2Wrapper.cpp | 633 ++++++++++++++++++++++++++++++++ camera/Camera2Wrapper.h | 20 + camera/Camera3Wrapper.cpp | 264 +++++++++++++ camera/Camera3Wrapper.h | 19 + camera/CameraWrapper.cpp | 148 ++++++++ camera/CameraWrapper.h | 24 ++ device-common.mk | 3 +- 10 files changed, 1505 insertions(+), 1 deletion(-) create mode 100644 camera/Android.bp create mode 100644 camera/CallbackWorkerThread.cpp create mode 100644 camera/CallbackWorkerThread.h create mode 100644 camera/Camera2Wrapper.cpp create mode 100644 camera/Camera2Wrapper.h create mode 100644 camera/Camera3Wrapper.cpp create mode 100644 camera/Camera3Wrapper.h create mode 100644 camera/CameraWrapper.cpp create mode 100644 camera/CameraWrapper.h diff --git a/camera/Android.bp b/camera/Android.bp new file mode 100644 index 0000000..addf298 --- /dev/null +++ b/camera/Android.bp @@ -0,0 +1,43 @@ +cc_library_shared { + name: "camera.universal8895", + vendor: true, + relative_install_path: "hw", + + srcs: [ + "CameraWrapper.cpp", + "Camera2Wrapper.cpp", + "Camera3Wrapper.cpp", + "CallbackWorkerThread.cpp", + ], + + export_shared_lib_headers: [ + "android.hardware.graphics.bufferqueue@1.0", + "android.hardware.graphics.bufferqueue@2.0", + ], + + generated_headers: [ + "android.hardware.graphics.bufferqueue@1.0_genc++_headers", + "android.hardware.graphics.bufferqueue@2.0_genc++_headers", + ], + + shared_libs: [ + "libhardware", + "liblog", + "libcamera_client", + "libutils", + "libcutils", + "android.hidl.token@1.0-utils", + "android.hardware.graphics.bufferqueue@1.0", + "android.hardware.graphics.bufferqueue@2.0", + ], + + include_dirs: [ + "frameworks/native/libs/nativewindow/include", + "frameworks/native/libs/arect/include", + "frameworks/av/media/ndk/include", + ], + + header_libs: [ + "libnativebase_headers", + ], +} diff --git a/camera/CallbackWorkerThread.cpp b/camera/CallbackWorkerThread.cpp new file mode 100644 index 0000000..fedafbb --- /dev/null +++ b/camera/CallbackWorkerThread.cpp @@ -0,0 +1,259 @@ +/* + * Copyright (C) 2019, The LineageOS Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Camera HAL "CallbackWorkerThread" workaround description + * + * The camera HAL of the Exynos7580 (A3, A5, ... 2016) reguralry deadlocks when using + * most camera apps, this happens a lot when using Google Camera but does occur + * occasionally in Snap. + * + * The issue was tracked down to the way that Samsung operates their HAL, all operations + * are run in multiple threads and the different callbacks are executed from one of these + * threads. + * + * The deadlocks occur when the camera client executes a function like cancel_auto_focus + * or stop_preview and a callback from the HAL occurs at around the same time. The HAL + * waits for the callback functions to return before they finish processing the client + * calls and the client stops processing callbacks until their calling function completes. + * + * You end up in a state when both the HAL and the client are waiting for the other + * process to finish and so end up with a deadlock of the HAL/Client which only a reboot + * can cure. + * + * This worker thread offloads the actual callbacks to another thread which allows the + * HAL to finish the client calls and avoid the deadlock scenario. + * + */ + +#define LOG_NDEBUG 0 +#define LOG_TAG "Camera2WrapperCbThread" + +#include "CallbackWorkerThread.h" +#include +#include + +using namespace std; + +#define MSG_EXIT_THREAD 1 +#define MSG_EXECUTE_CALLBACK 2 +#define MSG_UPDATE_CALLBACKS 3 + +struct ThreadMsg +{ + ThreadMsg(int i, const void* m, long long ts) { id = i; msg = m; CallerTS = ts; } + int id; + const void* msg; + long long CallerTS; +}; + +CallbackWorkerThread::CallbackWorkerThread() : m_thread(0) { +} + +CallbackWorkerThread::~CallbackWorkerThread() { + ExitThread(); +} + +bool CallbackWorkerThread::CreateThread() { + if (!m_thread) + m_thread = new thread(&CallbackWorkerThread::Process, this); + return true; +} + +void CallbackWorkerThread::ExitThread() { + if (!m_thread) + return; + + /* Create the exit thread worker message */ + ThreadMsg* threadMsg = new ThreadMsg(MSG_EXIT_THREAD, 0, GetTimestamp()); + + /* Add it to the message queue */ + { + lock_guard lock(m_mutex); + m_queue.push(threadMsg); + m_cv.notify_one(); + } + + /* Join the thread and then cleanup */ + m_thread->join(); + delete m_thread; + m_thread = 0; +} + +void CallbackWorkerThread::AddCallback(const WorkerMessage* data) { + /* Assert that the thread exists */ + ALOG_ASSERT(m_thread != NULL); + + /* Create a new worker thread message from the data */ + ThreadMsg* threadMsg = new ThreadMsg(MSG_EXECUTE_CALLBACK, data, GetTimestamp()); + + /* Add it to our worker queue and notify the worker */ + std::unique_lock lk(m_mutex); + m_queue.push(threadMsg); + m_cv.notify_one(); +} + +void CallbackWorkerThread::SetCallbacks(const CallbackData* data) { + /* Assert that the thread exists */ + ALOG_ASSERT(m_thread != NULL); + + /* Create a new worker thread message from the callback data */ + ThreadMsg* threadMsg = new ThreadMsg(MSG_UPDATE_CALLBACKS, data, GetTimestamp()); + + /* Add it to our worker queue and notify the worker */ + std::unique_lock lk(m_mutex); + m_queue.push(threadMsg); + m_cv.notify_one(); +} + +void CallbackWorkerThread::ClearCallbacks() { + /* Assert that the thread exists */ + ALOG_ASSERT(m_thread != NULL); + + /* Lock the mutex and clear the message queue */ + std::unique_lock lk(m_mutex); + + ALOGV("%s: Clearing %i messages", __FUNCTION__, m_queue.size()); + + /* Whilst the queue is not empty */ + while (!m_queue.empty()) { + /* Pop the message from the queue and delete the allocated data */ + ThreadMsg* msg = m_queue.front(); + m_queue.pop(); + delete msg; + } + + m_cv.notify_one(); +} + +void CallbackWorkerThread::Process() { + camera_notify_callback UserNotifyCb = NULL; + camera_data_callback UserDataCb = NULL; + + while (1) { + ThreadMsg* msg = 0; + { + /* Wait for a message to be added to the queue */ + std::unique_lock lk(m_mutex); + while (m_queue.empty()) + m_cv.wait(lk); + + if (m_queue.empty()) + continue; + + msg = m_queue.front(); + m_queue.pop(); + } + + switch (msg->id) { + case MSG_EXECUTE_CALLBACK: + { + /* Assert that we have a valid message */ + ALOG_ASSERT(msg->msg != NULL); + + /* Cast the the ThreadMsg void* data back to a WorkerMessage* */ + const WorkerMessage* userData = static_cast(msg->msg); + + /* If the callback is not stale (newer than 5mS) */ + if(GetTimestamp() - msg->CallerTS < 5) { + /* If the callback type is set to notifycb */ + if(userData->CbType == CB_TYPE_NOTIFY) { + /* Execute the users notify callback if it is valid */ + if(UserNotifyCb != NULL) { + ALOGV("%s: UserNotifyCb: %i %i %i %p", __FUNCTION__, userData->msg_type, userData->ext1, userData->ext2, userData->user); + UserNotifyCb(userData->msg_type, userData->ext1, userData->ext2, userData->user); + } + } /* If the callback type is set to notifycb */ + else if(userData->CbType == CB_TYPE_DATA) { + /* Execute the users data callback if it is valid */ + if(UserDataCb != NULL) { + ALOGV("%s: UserDataCb: %i %p %i %p %p", __FUNCTION__, userData->msg_type, userData->data, userData->index, userData->metadata, userData->user); + UserDataCb(userData->msg_type, userData->data, userData->index, userData->metadata, userData->user); + } + } + } else { + /* If the callback type is set to notifycb */ + if(userData->CbType == CB_TYPE_NOTIFY) { + ALOGV("%s: UserNotifyCb Stale: %llimS old", __FUNCTION__, GetTimestamp() - msg->CallerTS); + } /* If the callback type is set to notifycb */ + else if(userData->CbType == CB_TYPE_DATA) { + ALOGV("%s: UserDataCb Stale: %llimS old", __FUNCTION__, GetTimestamp() - msg->CallerTS); + } + } + + /* Cleanup allocated data */ + delete userData; + delete msg; + break; + } + + case MSG_UPDATE_CALLBACKS: + { + /* Assert that we have a valid message */ + ALOG_ASSERT(msg->msg != NULL); + + /* Cast the the ThreadMsg void* data back to a CallbackData* */ + const CallbackData* callbackData = static_cast(msg->msg); + + ALOGV("%s: UpdateCallbacks", __FUNCTION__); + + /* Copy the new callback pointers */ + UserNotifyCb = callbackData->NewUserNotifyCb; + UserDataCb = callbackData->NewUserDataCb; + + /* Cleanup allocated data */ + delete callbackData; + delete msg; + break; + } + + case MSG_EXIT_THREAD: + { + /* Delete current message */ + delete msg; + /* Then delete all pending messages in the queue */ + std::unique_lock lk(m_mutex); + /* Whilst the queue is not empty */ + while (!m_queue.empty()) { + /* Pop the message from the queue and delete the allocated data */ + msg = m_queue.front(); + m_queue.pop(); + delete msg; + } + + ALOGV("%s: Exit Thread", __FUNCTION__); + return; + } + + default: + /* Error if we get here */ + ALOG_ASSERT(0); + } + } +} + + +/* based on current_timestamp() function from stack overflow: + * https://stackoverflow.com/questions/3756323/how-to-get-the-current-time-in-milliseconds-from-c-in-linux/17083824 + */ + +long long CallbackWorkerThread::GetTimestamp() { + struct timeval te; + gettimeofday(&te, NULL); // get current time + long long milliseconds = te.tv_sec*1000LL + te.tv_usec/1000; // calculate milliseconds + return milliseconds; +} + diff --git a/camera/CallbackWorkerThread.h b/camera/CallbackWorkerThread.h new file mode 100644 index 0000000..e0df0a1 --- /dev/null +++ b/camera/CallbackWorkerThread.h @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2019, The LineageOS Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _THREAD_STD_H +#define _THREAD_STD_H + +#include +#include +#include +#include +#include + +#include + +#include +#include + +#define CB_TYPE_NONE 0 +#define CB_TYPE_NOTIFY 1 +#define CB_TYPE_DATA 2 + +struct WorkerMessage { + /* Worker callback type */ + int32_t CbType; + + /* Callback data */ + int32_t msg_type; + const camera_memory_t *data; + unsigned int index; + camera_frame_metadata_t *metadata; + void *user; + int32_t ext1; + int32_t ext2; +}; + +struct CallbackData { + camera_notify_callback NewUserNotifyCb; + camera_data_callback NewUserDataCb; +}; + +struct ThreadMsg; + +class CallbackWorkerThread { +public: + CallbackWorkerThread(); + ~CallbackWorkerThread(); + + /* Creates our worker, returns true on success */ + bool CreateThread(); + + /* Exits the worker thread */ + void ExitThread(); + + /* Sends a new callback to our worker thread */ + void AddCallback(const WorkerMessage* data); + + /* Sets the callback function pointers for our worker to call */ + void SetCallbacks(const CallbackData* data); + + /* Clears the worker message queue */ + void ClearCallbacks(void); + +private: + CallbackWorkerThread(const CallbackWorkerThread&); + CallbackWorkerThread& operator=(const CallbackWorkerThread&); + + long long GetTimestamp(); + + /* Entry point for the worker thread */ + void Process(); + + std::thread* m_thread; + std::queue m_queue; + std::mutex m_mutex; + std::condition_variable m_cv; + const char* m_name; +}; + +#endif + diff --git a/camera/Camera2Wrapper.cpp b/camera/Camera2Wrapper.cpp new file mode 100644 index 0000000..db3d8da --- /dev/null +++ b/camera/Camera2Wrapper.cpp @@ -0,0 +1,633 @@ +/* + * Copyright (C) 2017, The LineageOS Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_NDEBUG 0 +#define LOG_PARAMETERS + +#define LOG_TAG "Camera2Wrapper" +#include + +#include +#include + +#include "CameraWrapper.h" +#include "Camera2Wrapper.h" +#include "CallbackWorkerThread.h" + +CallbackWorkerThread cbThread; + +#include + +/* current_timestamp() function from stack overflow: + * https://stackoverflow.com/questions/3756323/how-to-get-the-current-time-in-milliseconds-from-c-in-linux/17083824 + */ + +long long current_timestamp() { + struct timeval te; + gettimeofday(&te, NULL); // get current time + long long milliseconds = te.tv_sec*1000LL + te.tv_usec/1000; // calculate milliseconds + // printf("milliseconds: %lld\n", milliseconds); + return milliseconds; +} + +typedef struct wrapper_camera2_device { + camera_device_t base; + int id; + camera_device_t *vendor; +} wrapper_camera2_device_t; + +#define VENDOR_CALL(device, func, ...) ({ \ + wrapper_camera2_device_t *__wrapper_dev = (wrapper_camera2_device_t*) device; \ + __wrapper_dev->vendor->ops->func(__wrapper_dev->vendor, ##__VA_ARGS__); \ +}) + +#define CAMERA_ID(device) (((wrapper_camera2_device_t *)(device))->id) + +static camera_module_t *gVendorModule = 0; + +static int check_vendor_module() +{ + int rv = 0; + ALOGV("%s", __FUNCTION__); + + if(gVendorModule) + return 0; + + rv = hw_get_module_by_class("camera", "vendor", (const hw_module_t **)&gVendorModule); + if (rv) + ALOGE("failed to open vendor camera module"); + return rv; +} + +/******************************************************************* + * Camera2 wrapper fixup functions + *******************************************************************/ + +static char * camera2_fixup_getparams(int id __unused, const char * settings) +{ + bool videoMode = false; + const char* isoMode; + char *manipBuf; + + android::CameraParameters params; + params.unflatten(android::String8(settings)); + +#ifdef LOG_PARAMETERS + ALOGV("%s: Original parameters:", __FUNCTION__); + params.dump(); +#endif + + params.set("video-size-values", "3840x2160,2560x1440,1920x1080,1440x1080,1088x1088,1280x720,960x720,800x450,720x480,640x480,480x320,352x288,320x240,256x144,176x144"); + +#ifdef LOG_PARAMETERS + ALOGV("%s: Fixed parameters:", __FUNCTION__); + params.dump(); +#endif + + android::String8 strParams = params.flatten(); + char *ret = strdup(strParams.string()); + + return ret; +} + +static char * camera2_fixup_setparams(int id __unused, const char * settings) +{ + bool videoMode = false; + const char* isoMode; + + android::CameraParameters params; + params.unflatten(android::String8(settings)); + +#ifdef LOG_PARAMETERS + ALOGV("%s: Original parameters:", __FUNCTION__); + params.dump(); +#endif + +#ifdef LOG_PARAMETERS + ALOGV("%s: Fixed parameters:", __FUNCTION__); + params.dump(); +#endif + + android::String8 strParams = params.flatten(); + char *ret = strdup(strParams.string()); + + return ret; +} + +/******************************************************************* + * implementation of camera_device_ops functions + *******************************************************************/ + +static int camera2_set_preview_window(struct camera_device * device, + struct preview_stream_ops *window) +{ + ALOGV("%s->%08X->%08X", __FUNCTION__, (uintptr_t)device, (uintptr_t)(((wrapper_camera2_device_t*)device)->vendor)); + + if(!device) + return -EINVAL; + + return VENDOR_CALL(device, set_preview_window, window); +} + +atomic_int BlockCbs; + +void WrappedNotifyCb (int32_t msg_type, int32_t ext1, int32_t ext2, void *user) { + ALOGV("%s->In", __FUNCTION__); + + /* Print a log message and return if we currently blocking adding callbacks */ + if(BlockCbs == 1) { + ALOGV("%s->BlockCbs == 1", __FUNCTION__); + return; + } + + /* Create message to send to the callback worker */ + WorkerMessage* newWorkerMessage = new WorkerMessage(); + newWorkerMessage->CbType = CB_TYPE_NOTIFY; + + /* Copy the callback data to our worker message */ + newWorkerMessage->msg_type = msg_type; + newWorkerMessage->ext1 = ext1; + newWorkerMessage->ext2 = ext2; + newWorkerMessage->user = user; + + /* Post the message to the callback worker */ + cbThread.AddCallback(newWorkerMessage); + + /* 5mS delay to slow down the camera hal thread */ + usleep(5000); + ALOGV("%s->Out", __FUNCTION__); +} + +void WrappedDataCb (int32_t msg_type, const camera_memory_t *data, unsigned int index, + camera_frame_metadata_t *metadata, void *user) { + ALOGV("%s->In, %i, %u", __FUNCTION__, msg_type, index); + + /* Print a log message and return if we currently blocking adding callbacks */ + if(BlockCbs == 1) { + ALOGV("%s->BlockCbs == 1", __FUNCTION__); + return; + } + + /* Create message to send to the callback worker */ + WorkerMessage* newWorkerMessage = new WorkerMessage(); + newWorkerMessage->CbType = CB_TYPE_DATA; + + /* Copy the callback data to our worker message */ + newWorkerMessage->msg_type = msg_type; + newWorkerMessage->data = data; + newWorkerMessage->index= index; + newWorkerMessage->metadata = metadata; + newWorkerMessage->user = user; + + /* Post the message to the callback worker */ + cbThread.AddCallback(newWorkerMessage); + + /* 20mS delay to slow down the camera hal thread */ + usleep(20000); + ALOGV("%s->Out", __FUNCTION__); +} + +static void camera2_set_callbacks(struct camera_device * device, + camera_notify_callback notify_cb, + camera_data_callback data_cb, + camera_data_timestamp_callback data_cb_timestamp, + camera_request_memory get_memory, + void *user) +{ + ALOGV("%s->%08X->%08X", __FUNCTION__, (uintptr_t)device, (uintptr_t)(((wrapper_camera2_device_t*)device)->vendor)); + + if(!device) + return; + + /* Create and populate a new callback data structure */ + CallbackData* newCallbackData = new CallbackData(); + newCallbackData->NewUserNotifyCb = notify_cb; + newCallbackData->NewUserDataCb = data_cb; + + /* Send it to our worker thread */ + cbThread.SetCallbacks(newCallbackData); + + /* Call the set_callbacks function substituting the notify callback with our wrapper */ + VENDOR_CALL(device, set_callbacks, WrappedNotifyCb, WrappedDataCb, data_cb_timestamp, get_memory, user); +} + +static void camera2_enable_msg_type(struct camera_device * device, int32_t msg_type) +{ + ALOGV("%s->%08X->%08X", __FUNCTION__, (uintptr_t)device, (uintptr_t)(((wrapper_camera2_device_t*)device)->vendor)); + + if(!device) + return; + + VENDOR_CALL(device, enable_msg_type, msg_type); +} + +static void camera2_disable_msg_type(struct camera_device * device, int32_t msg_type) +{ + ALOGV("%s->%08X->%08X", __FUNCTION__, (uintptr_t)device, (uintptr_t)(((wrapper_camera2_device_t*)device)->vendor)); + + if(!device) + return; + + VENDOR_CALL(device, disable_msg_type, msg_type); +} + +static int camera2_msg_type_enabled(struct camera_device * device, int32_t msg_type) +{ + ALOGV("%s->%08X->%08X", __FUNCTION__, (uintptr_t)device, (uintptr_t)(((wrapper_camera2_device_t*)device)->vendor)); + + if(!device) + return 0; + + return VENDOR_CALL(device, msg_type_enabled, msg_type); +} + +static int camera2_start_preview(struct camera_device * device) +{ + int rc = 0; + ALOGV("%s->%08X->%08X", __FUNCTION__, (uintptr_t)device, (uintptr_t)(((wrapper_camera2_device_t*)device)->vendor)); + + if(!device) + return -EINVAL; + + return VENDOR_CALL(device, start_preview); +} + +static void camera2_stop_preview(struct camera_device * device) +{ + ALOGV("%s->%08X->%08X", __FUNCTION__, (uintptr_t)device, (uintptr_t)(((wrapper_camera2_device_t*)device)->vendor)); + + if(!device) + return; + + /* Block queueing more callbacks */ + BlockCbs = 1; + + /* Clear the callback queue */ + cbThread.ClearCallbacks(); + /* Execute stop_preview */ + VENDOR_CALL(device, stop_preview); + + /* Unblock queueing more callbacks */ + BlockCbs = 0; +} + +static int camera2_preview_enabled(struct camera_device * device) +{ + ALOGV("%s->%08X->%08X", __FUNCTION__, (uintptr_t)device, (uintptr_t)(((wrapper_camera2_device_t*)device)->vendor)); + + if(!device) + return -EINVAL; + + return VENDOR_CALL(device, preview_enabled); +} + +static int camera2_store_meta_data_in_buffers(struct camera_device * device, int enable) +{ + ALOGV("%s->%08X->%08X", __FUNCTION__, (uintptr_t)device, (uintptr_t)(((wrapper_camera2_device_t*)device)->vendor)); + + if(!device) + return -EINVAL; + + return VENDOR_CALL(device, store_meta_data_in_buffers, enable); +} + +static int camera2_start_recording(struct camera_device * device) +{ + ALOGV("%s->%08X->%08X", __FUNCTION__, (uintptr_t)device, (uintptr_t)(((wrapper_camera2_device_t*)device)->vendor)); + + if(!device) + return -EINVAL; + + return VENDOR_CALL(device, start_recording); +} + +static void camera2_stop_recording(struct camera_device * device) +{ + ALOGV("%s->%08X->%08X", __FUNCTION__, (uintptr_t)device, (uintptr_t)(((wrapper_camera2_device_t*)device)->vendor)); + + if(!device) + return; + + VENDOR_CALL(device, stop_recording); +} + +static int camera2_recording_enabled(struct camera_device * device) +{ + ALOGV("%s->%08X->%08X", __FUNCTION__, (uintptr_t)device, (uintptr_t)(((wrapper_camera2_device_t*)device)->vendor)); + + if(!device) + return -EINVAL; + + return VENDOR_CALL(device, recording_enabled); +} + +static void camera2_release_recording_frame(struct camera_device * device, + const void *opaque) +{ + ALOGV("%s->%08X->%08X", __FUNCTION__, (uintptr_t)device, (uintptr_t)(((wrapper_camera2_device_t*)device)->vendor)); + + if(!device) + return; + + VENDOR_CALL(device, release_recording_frame, opaque); +} + +long long CancelAFTimeGuard = 0; + +static int camera2_auto_focus(struct camera_device * device) +{ + int Ret; + ALOGV("%s->%08X->%08X", __FUNCTION__, (uintptr_t)device, (uintptr_t)(((wrapper_camera2_device_t*)device)->vendor)); + + if(!device) + return -EINVAL; + + /* Clear the callback queue */ + cbThread.ClearCallbacks(); + + /* Call the auto_focus function */ + Ret = VENDOR_CALL(device, auto_focus); + + /* Set the cancel_auto_focus time guard to now plus 500mS */ + CancelAFTimeGuard = current_timestamp() + 500; + + return Ret; +} + +static int camera2_cancel_auto_focus(struct camera_device * device) +{ + int Ret; + ALOGV("%s->%08X->%08X", __FUNCTION__, (uintptr_t)device, (uintptr_t)(((wrapper_camera2_device_t*)device)->vendor)); + + if(!device) + return -EINVAL; + + /* Block queueing more callbacks */ + BlockCbs = 1; + + /* Clear the callback queue */ + cbThread.ClearCallbacks(); + + /* Calculate the difference between our guard time and now */ + long long TimeDiff = CancelAFTimeGuard - current_timestamp(); + /* Post a log message and return success (skipping the call) if the diff is greater than 0 */ + if(TimeDiff > 0) { + ALOGV("%s: CancelAFTimeGuard for %lli mS\n", __FUNCTION__, TimeDiff * 1000); + return 0; + } + + /* No active time guard so call the vendor function */ + Ret = VENDOR_CALL(device, cancel_auto_focus); + + /* Unblock queueing more callbacks */ + BlockCbs = 0; + + return Ret; +} + +static int camera2_take_picture(struct camera_device * device) +{ + ALOGV("%s->%08X->%08X", __FUNCTION__, (uintptr_t)device, (uintptr_t)(((wrapper_camera2_device_t*)device)->vendor)); + + if(!device) + return -EINVAL; + + return VENDOR_CALL(device, take_picture); +} + +static int camera2_cancel_picture(struct camera_device * device) +{ + ALOGV("%s->%08X->%08X", __FUNCTION__, (uintptr_t)device, (uintptr_t)(((wrapper_camera2_device_t*)device)->vendor)); + + if(!device) + return -EINVAL; + + return VENDOR_CALL(device, cancel_picture); +} + +static int camera2_set_parameters(struct camera_device * device, const char *params) +{ + ALOGV("%s->%08X->%08X", __FUNCTION__, (uintptr_t)device, (uintptr_t)(((wrapper_camera2_device_t*)device)->vendor)); + + if(!device) + return -EINVAL; + + char *tmp = NULL; + tmp = camera2_fixup_setparams(CAMERA_ID(device), params); + + int ret = VENDOR_CALL(device, set_parameters, tmp); + + return ret; +} + +static char* camera2_get_parameters(struct camera_device * device) +{ + ALOGV("%s->%08X->%08X", __FUNCTION__, (uintptr_t)device, (uintptr_t)(((wrapper_camera2_device_t*)device)->vendor)); + + if(!device) + return NULL; + + char* params = VENDOR_CALL(device, get_parameters); + + char * tmp = camera2_fixup_getparams(CAMERA_ID(device), params); + VENDOR_CALL(device, put_parameters, params); + params = tmp; + + return params; +} + +static void camera2_put_parameters(struct camera_device *device, char *params) +{ + ALOGV("%s->%08X->%08X", __FUNCTION__, (uintptr_t)device, (uintptr_t)(((wrapper_camera2_device_t*)device)->vendor)); + + if(params) + free(params); +} + +static int camera2_send_command(struct camera_device * device, + int32_t cmd, int32_t arg1, int32_t arg2) +{ + ALOGV("%s->%08X->%08X", __FUNCTION__, (uintptr_t)device, (uintptr_t)(((wrapper_camera2_device_t*)device)->vendor)); + + if(!device) + return -EINVAL; + + return VENDOR_CALL(device, send_command, cmd, arg1, arg2); +} + +static void camera2_release(struct camera_device * device) +{ + ALOGV("%s->%08X->%08X", __FUNCTION__, (uintptr_t)device, (uintptr_t)(((wrapper_camera2_device_t*)device)->vendor)); + + if(!device) + return; + + VENDOR_CALL(device, release); +} + +static int camera2_dump(struct camera_device * device, int fd) +{ + ALOGV("%s->%08X->%08X", __FUNCTION__, (uintptr_t)device, (uintptr_t)(((wrapper_camera2_device_t*)device)->vendor)); + + if(!device) + return -EINVAL; + + return VENDOR_CALL(device, dump, fd); +} + +static int camera2_device_close(hw_device_t* device) +{ + int ret = 0; + wrapper_camera2_device_t *wrapper_dev = NULL; + + ALOGV("%s", __FUNCTION__); + + android::Mutex::Autolock lock(gCameraWrapperLock); + + if (!device) { + ret = -EINVAL; + goto done; + } + + wrapper_dev = (wrapper_camera2_device_t*) device; + + wrapper_dev->vendor->common.close((hw_device_t*)wrapper_dev->vendor); + if (wrapper_dev->base.ops) + free(wrapper_dev->base.ops); + free(wrapper_dev); +done: + + /* Exit our callback dispatch thread */ + cbThread.ExitThread(); + + return ret; +} + +/******************************************************************* + * implementation of camera_module functions + *******************************************************************/ + +/* open device handle to one of the cameras + * + * assume camera service will keep singleton of each camera + * so this function will always only be called once per camera instance + */ + +int camera2_device_open(const hw_module_t* module, const char* name, + hw_device_t** device) +{ + int rv = 0; + int num_cameras = 0; + int cameraid; + wrapper_camera2_device_t* camera2_device = NULL; + camera_device_ops_t* camera2_ops = NULL; + + android::Mutex::Autolock lock(gCameraWrapperLock); + + /* Create our callback dispatch thread */ + cbThread.CreateThread(); + BlockCbs = 0; + + ALOGV("%s", __FUNCTION__); + + if (name != NULL) { + if (check_vendor_module()) + return -EINVAL; + + cameraid = atoi(name); + num_cameras = gVendorModule->get_number_of_cameras(); + + if (cameraid > num_cameras) { + ALOGE("camera service provided cameraid out of bounds, " + "cameraid = %d, num supported = %d", + cameraid, num_cameras); + rv = -EINVAL; + goto fail; + } + + camera2_device = (wrapper_camera2_device_t*)malloc(sizeof(*camera2_device)); + if (!camera2_device) { + ALOGE("camera2_device allocation fail"); + rv = -ENOMEM; + goto fail; + } + memset(camera2_device, 0, sizeof(*camera2_device)); + camera2_device->id = cameraid; + + rv = gVendorModule->open_legacy((const hw_module_t*)gVendorModule, name, CAMERA_DEVICE_API_VERSION_1_0, (hw_device_t**)&(camera2_device->vendor)); + if (rv) + { + ALOGE("vendor camera open fail"); + goto fail; + } + ALOGV("%s: got vendor camera device 0x%08X", __FUNCTION__, (uintptr_t)(camera2_device->vendor)); + + camera2_ops = (camera_device_ops_t*)malloc(sizeof(*camera2_ops)); + if (!camera2_ops) { + ALOGE("camera_ops allocation fail"); + rv = -ENOMEM; + goto fail; + } + + memset(camera2_ops, 0, sizeof(*camera2_ops)); + + camera2_device->base.common.tag = HARDWARE_DEVICE_TAG; + camera2_device->base.common.version = CAMERA_DEVICE_API_VERSION_1_0; + camera2_device->base.common.module = (hw_module_t *)(module); + camera2_device->base.common.close = camera2_device_close; + camera2_device->base.ops = camera2_ops; + + camera2_ops->set_preview_window = camera2_set_preview_window; + camera2_ops->set_callbacks = camera2_set_callbacks; + camera2_ops->enable_msg_type = camera2_enable_msg_type; + camera2_ops->disable_msg_type = camera2_disable_msg_type; + camera2_ops->msg_type_enabled = camera2_msg_type_enabled; + camera2_ops->start_preview = camera2_start_preview; + camera2_ops->stop_preview = camera2_stop_preview; + camera2_ops->preview_enabled = camera2_preview_enabled; + camera2_ops->store_meta_data_in_buffers = camera2_store_meta_data_in_buffers; + camera2_ops->start_recording = camera2_start_recording; + camera2_ops->stop_recording = camera2_stop_recording; + camera2_ops->recording_enabled = camera2_recording_enabled; + camera2_ops->release_recording_frame = camera2_release_recording_frame; + camera2_ops->auto_focus = camera2_auto_focus; + camera2_ops->cancel_auto_focus = camera2_cancel_auto_focus; + camera2_ops->take_picture = camera2_take_picture; + camera2_ops->cancel_picture = camera2_cancel_picture; + camera2_ops->set_parameters = camera2_set_parameters; + camera2_ops->get_parameters = camera2_get_parameters; + camera2_ops->put_parameters = camera2_put_parameters; + camera2_ops->send_command = camera2_send_command; + camera2_ops->release = camera2_release; + camera2_ops->dump = camera2_dump; + + *device = &camera2_device->base.common; + } + + return rv; + +fail: + if(camera2_device) { + free(camera2_device); + camera2_device = NULL; + } + if(camera2_ops) { + free(camera2_ops); + camera2_ops = NULL; + } + *device = NULL; + return rv; +} diff --git a/camera/Camera2Wrapper.h b/camera/Camera2Wrapper.h new file mode 100644 index 0000000..20121a5 --- /dev/null +++ b/camera/Camera2Wrapper.h @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2017, The LineageOS Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +int camera2_device_open(const hw_module_t* module, const char* name, hw_device_t** device); diff --git a/camera/Camera3Wrapper.cpp b/camera/Camera3Wrapper.cpp new file mode 100644 index 0000000..4e9b8a4 --- /dev/null +++ b/camera/Camera3Wrapper.cpp @@ -0,0 +1,264 @@ +/* + * Copyright (C) 2017, The LineageOS Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_NDEBUG 0 +#define LOG_TAG "Camera3Wrapper" +#include + +#include "CameraWrapper.h" +#include "Camera3Wrapper.h" + +typedef struct wrapper_camera3_device { + camera3_device_t base; + int id; + camera3_device_t *vendor; +} wrapper_camera3_device_t; + +#define VENDOR_CALL(device, func, ...) ({ \ + wrapper_camera3_device_t *__wrapper_dev = (wrapper_camera3_device_t*) device; \ + __wrapper_dev->vendor->ops->func(__wrapper_dev->vendor, ##__VA_ARGS__); \ +}) + +#define CAMERA_ID(device) (((wrapper_camera3_device_t *)(device))->id) + +static camera_module_t *gVendorModule = 0; + +static int check_vendor_module() +{ + int rv = 0; + ALOGV("%s", __FUNCTION__); + + if(gVendorModule) + return 0; + + rv = hw_get_module_by_class("camera", "vendor", (const hw_module_t **)&gVendorModule); + if (rv) + ALOGE("failed to open vendor camera module"); + return rv; +} + +/******************************************************************* + * implementation of camera_device_ops functions + *******************************************************************/ + +static int camera3_initialize(const camera3_device_t *device, const camera3_callback_ops_t *callback_ops) +{ + ALOGV("%s->%08X->%08X", __FUNCTION__, (uintptr_t)device, + (uintptr_t)(((wrapper_camera3_device_t*)device)->vendor)); + + if (!device) + return -1; + + return VENDOR_CALL(device, initialize, callback_ops); +} + +static int camera3_configure_streams(const camera3_device *device, camera3_stream_configuration_t *stream_list) +{ + ALOGV("%s->%08X->%08X", __FUNCTION__, (uintptr_t)device, + (uintptr_t)(((wrapper_camera3_device_t*)device)->vendor)); + + if (!device) + return -1; + + return VENDOR_CALL(device, configure_streams, stream_list); +} + +static int camera3_register_stream_buffers(const camera3_device *device, const camera3_stream_buffer_set_t *buffer_set) +{ + ALOGV("%s->%08X->%08X", __FUNCTION__, (uintptr_t)device, + (uintptr_t)(((wrapper_camera3_device_t*)device)->vendor)); + + if (!device) + return -1; + + return VENDOR_CALL(device, register_stream_buffers, buffer_set); +} + +static const camera_metadata_t *camera3_construct_default_request_settings(const camera3_device_t *device, int type) +{ + ALOGV("%s->%08X->%08X", __FUNCTION__, (uintptr_t)device, + (uintptr_t)(((wrapper_camera3_device_t*)device)->vendor)); + + if (!device) + return NULL; + + return VENDOR_CALL(device, construct_default_request_settings, type); +} + +static int camera3_process_capture_request(const camera3_device_t *device, camera3_capture_request_t *request) +{ + ALOGV("%s->%08X->%08X", __FUNCTION__, (uintptr_t)device, + (uintptr_t)(((wrapper_camera3_device_t*)device)->vendor)); + + if (!device) + return -1; + + return VENDOR_CALL(device, process_capture_request, request); +} + +static void camera3_get_metadata_vendor_tag_ops(const camera3_device *device, vendor_tag_query_ops_t* ops) +{ + ALOGV("%s->%08X->%08X", __FUNCTION__, (uintptr_t)device, + (uintptr_t)(((wrapper_camera3_device_t*)device)->vendor)); + + if (!device) + return; + + VENDOR_CALL(device, get_metadata_vendor_tag_ops, ops); +} + +static void camera3_dump(const camera3_device_t *device, int fd) +{ + ALOGV("%s->%08X->%08X", __FUNCTION__, (uintptr_t)device, + (uintptr_t)(((wrapper_camera3_device_t*)device)->vendor)); + + if (!device) + return; + + VENDOR_CALL(device, dump, fd); +} + +static int camera3_flush(const camera3_device_t* device) +{ + ALOGV("%s->%08X->%08X", __FUNCTION__, (uintptr_t)device, + (uintptr_t)(((wrapper_camera3_device_t*)device)->vendor)); + + if (!device) + return -1; + + return VENDOR_CALL(device, flush); +} + +static int camera3_device_close(hw_device_t *device) +{ + int ret = 0; + wrapper_camera3_device_t *wrapper_dev = NULL; + + ALOGV("%s", __FUNCTION__); + + android::Mutex::Autolock lock(gCameraWrapperLock); + + if (!device) { + ret = -EINVAL; + goto done; + } + + wrapper_dev = (wrapper_camera3_device_t*) device; + + wrapper_dev->vendor->common.close((hw_device_t*)wrapper_dev->vendor); + if (wrapper_dev->base.ops) + free(wrapper_dev->base.ops); + free(wrapper_dev); +done: + return ret; +} + +/******************************************************************* + * implementation of camera_module functions + *******************************************************************/ + +/* open device handle to one of the cameras + * + * assume camera service will keep singleton of each camera + * so this function will always only be called once per camera instance + */ + +int camera3_device_open(const hw_module_t *module, const char *name, + hw_device_t **device) +{ + int rv = 0; + int num_cameras = 0; + int cameraid; + wrapper_camera3_device_t *camera3_device = NULL; + camera3_device_ops_t *camera3_ops = NULL; + + android::Mutex::Autolock lock(gCameraWrapperLock); + + ALOGV("%s", __FUNCTION__); + + if (name != NULL) { + if (check_vendor_module()) + return -EINVAL; + + cameraid = atoi(name); + num_cameras = gVendorModule->get_number_of_cameras(); + + if (cameraid > num_cameras) { + ALOGE("camera service provided cameraid out of bounds, " + "cameraid = %d, num supported = %d", + cameraid, num_cameras); + rv = -EINVAL; + goto fail; + } + + camera3_device = (wrapper_camera3_device_t*)malloc(sizeof(*camera3_device)); + if (!camera3_device) { + ALOGE("camera3_device allocation fail"); + rv = -ENOMEM; + goto fail; + } + memset(camera3_device, 0, sizeof(*camera3_device)); + camera3_device->id = cameraid; + + rv = gVendorModule->common.methods->open((const hw_module_t*)gVendorModule, name, (hw_device_t**)&(camera3_device->vendor)); + if (rv) + { + ALOGE("vendor camera open fail"); + goto fail; + } + ALOGV("%s: got vendor camera device 0x%08X", __FUNCTION__, (uintptr_t)(camera3_device->vendor)); + + camera3_ops = (camera3_device_ops_t*)malloc(sizeof(*camera3_ops)); + if (!camera3_ops) { + ALOGE("camera3_ops allocation fail"); + rv = -ENOMEM; + goto fail; + } + + memset(camera3_ops, 0, sizeof(*camera3_ops)); + + camera3_device->base.common.tag = HARDWARE_DEVICE_TAG; + camera3_device->base.common.version = CAMERA_DEVICE_API_VERSION_3_4; + camera3_device->base.common.module = (hw_module_t *)(module); + camera3_device->base.common.close = camera3_device_close; + camera3_device->base.ops = camera3_ops; + + camera3_ops->initialize = camera3_initialize; + camera3_ops->configure_streams = camera3_configure_streams; + camera3_ops->register_stream_buffers = NULL; + camera3_ops->construct_default_request_settings = camera3_construct_default_request_settings; + camera3_ops->process_capture_request = camera3_process_capture_request; + camera3_ops->get_metadata_vendor_tag_ops = camera3_get_metadata_vendor_tag_ops; + camera3_ops->dump = camera3_dump; + camera3_ops->flush = camera3_flush; + + *device = &camera3_device->base.common; + } + + return rv; + +fail: + if (camera3_device) { + free(camera3_device); + camera3_device = NULL; + } + if (camera3_ops) { + free(camera3_ops); + camera3_ops = NULL; + } + *device = NULL; + return rv; +} diff --git a/camera/Camera3Wrapper.h b/camera/Camera3Wrapper.h new file mode 100644 index 0000000..bf815ca --- /dev/null +++ b/camera/Camera3Wrapper.h @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2017, The LineageOS Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +int camera3_device_open(const hw_module_t *module, const char *name, hw_device_t **device); diff --git a/camera/CameraWrapper.cpp b/camera/CameraWrapper.cpp new file mode 100644 index 0000000..3b7d348 --- /dev/null +++ b/camera/CameraWrapper.cpp @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2017, The LineageOS Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_NDEBUG 0 +#define LOG_PARAMETERS + +#define LOG_TAG "CameraWrapper" +#include + +#include "CameraWrapper.h" +#include "Camera2Wrapper.h" +#include "Camera3Wrapper.h" + +static camera_module_t *gVendorModule = 0; + +static int camera_device_open(const hw_module_t* module, const char* name, + hw_device_t** device); +static int camera_get_number_of_cameras(void); +static int camera_get_camera_info(int camera_id, struct camera_info *info); +static int camera_set_callbacks(const camera_module_callbacks_t *callbacks); +static void camera_get_vendor_tag_ops(vendor_tag_ops_t* ops); +static int camera_open_legacy(const struct hw_module_t* module, const char* id, + uint32_t halVersion, struct hw_device_t** device); +static int camera_set_torch_mode(const char* camera_id, bool enabled); +static int camera_init(); + +static int check_vendor_module() +{ + int rv = 0; + ALOGV("%s", __FUNCTION__); + + if(gVendorModule) + return 0; + + rv = hw_get_module_by_class("camera", "vendor", (const hw_module_t **)&gVendorModule); + if (rv) + ALOGE("failed to open vendor camera module"); + return rv; +} + +static struct hw_module_methods_t camera_module_methods = { + .open = camera_device_open +}; + +camera_module_t HAL_MODULE_INFO_SYM = { + .common = { + .tag = HARDWARE_MODULE_TAG, + .module_api_version = CAMERA_MODULE_API_VERSION_2_4, + .hal_api_version = HARDWARE_HAL_API_VERSION, + .id = CAMERA_HARDWARE_MODULE_ID, + .name = "Zero Camera Wrapper", + .author = "The LineageOS Project", + .methods = &camera_module_methods, + .dso = NULL, + .reserved = {0}, + }, + .get_number_of_cameras = camera_get_number_of_cameras, + .get_camera_info = camera_get_camera_info, + .set_callbacks = camera_set_callbacks, + .get_vendor_tag_ops = camera_get_vendor_tag_ops, + .open_legacy = camera_open_legacy, + .set_torch_mode = camera_set_torch_mode, + .init = camera_init, + .reserved = {0}, +}; + +static int camera_device_open(const hw_module_t* module, const char* name, + hw_device_t** device) +{ + int rv = -EINVAL; + + if (name != NULL) { + if (check_vendor_module()) + return -EINVAL; + rv = camera3_device_open(module, name, device); + } + + return rv; +} + +static int camera_get_number_of_cameras(void) +{ + ALOGV("%s", __FUNCTION__); + if (check_vendor_module()) + return 0; + return gVendorModule->get_number_of_cameras(); +} + +static int camera_get_camera_info(int camera_id, struct camera_info *info) +{ + ALOGV("%s", __FUNCTION__); + if (check_vendor_module()) + return 0; + return gVendorModule->get_camera_info(camera_id, info); +} + +static int camera_set_callbacks(const camera_module_callbacks_t *callbacks) +{ + ALOGV("%s", __FUNCTION__); + if (check_vendor_module()) + return 0; + return gVendorModule->set_callbacks(callbacks); +} + +static void camera_get_vendor_tag_ops(vendor_tag_ops_t* ops) +{ + ALOGV("%s", __FUNCTION__); + if (check_vendor_module()) + return; + return gVendorModule->get_vendor_tag_ops(ops); +} + +static int camera_open_legacy(const struct hw_module_t* module, const char* id, uint32_t halVersion, struct hw_device_t** device) +{ + ALOGV("%s", __FUNCTION__); + if (check_vendor_module()) + return 0; + return camera2_device_open(module, id, device); +} + +static int camera_set_torch_mode(const char* camera_id, bool enabled) +{ + ALOGV("%s", __FUNCTION__); + if (check_vendor_module()) + return 0; + return gVendorModule->set_torch_mode(camera_id, enabled); +} + +static int camera_init() +{ + ALOGV("%s", __FUNCTION__); + if (check_vendor_module()) + return 0; + return gVendorModule->init(); +} diff --git a/camera/CameraWrapper.h b/camera/CameraWrapper.h new file mode 100644 index 0000000..2514fc8 --- /dev/null +++ b/camera/CameraWrapper.h @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2017, The LineageOS Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include + +static android::Mutex gCameraWrapperLock; + diff --git a/device-common.mk b/device-common.mk index 0244335..e33ea68 100644 --- a/device-common.mk +++ b/device-common.mk @@ -76,7 +76,8 @@ PRODUCT_PACKAGES += \ android.hardware.camera.device@3.3 \ android.hardware.camera.device@3.4 \ android.hardware.camera.provider@2.4 \ - Snap + camera.universal8895 \ + Camera2 # Camera configurations PRODUCT_COPY_FILES += \ -- 2.20.1