Move virtual camera service to frameworks/av/services
Bug: 311647154
Bug: 301023410
Test: atest virtual_camera_tests
Test: build & flash & adb shell cmd virtual_camera help
Change-Id: I9a7d62430df8c56a68c7d3deafa9ae567c1b30f4
diff --git a/devices/VirtualCamera/Android.bp b/devices/VirtualCamera/Android.bp
deleted file mode 100644
index 0375a7c..0000000
--- a/devices/VirtualCamera/Android.bp
+++ /dev/null
@@ -1,99 +0,0 @@
-package {
- // See: http://go/android-license-faq
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-cc_defaults {
- name: "libvirtualcamera_defaults",
- shared_libs: [
- "android.hardware.common-V2-ndk",
- "android.hardware.common.fmq-V1-ndk",
- "libbinder",
- "libbinder_ndk",
- "libcamera_metadata",
- "liblog",
- "libfmq",
- "libgui",
- "libjpeg",
- "libnativewindow",
- "libbase",
- "libcutils",
- "libui",
- "libutils",
- "libEGL",
- "libGLESv2",
- "libGLESv3",
- ],
- static_libs: [
- "android.hardware.camera.common@1.0-helper",
- "android.hardware.camera.common-V1-ndk",
- "android.hardware.camera.device-V2-ndk",
- "android.hardware.camera.metadata-V2-ndk",
- "android.hardware.camera.provider-V2-ndk",
- "libaidlcommonsupport",
- "virtual_camera_service_aidl-ndk",
- ],
- cflags: [
- "-Wall",
- "-Werror",
- "-Wformat",
- "-Wthread-safety",
- "-DLOG_NDEBUG=0"
- ],
-}
-
-cc_library_static {
- name: "libvirtualcamera_utils",
- srcs: [
- "util/JpegUtil.cc",
- "util/MetadataBuilder.cc",
- "util/Util.cc",
- "util/TestPatternHelper.cc",
- "util/EglDisplayContext.cc",
- "util/EglFramebuffer.cc",
- "util/EglProgram.cc",
- "util/EglSurfaceTexture.cc",
- "util/EglUtil.cc",
- ],
- defaults: [
- "libvirtualcamera_defaults",
- ],
-}
-
-cc_library_static {
- name: "libvirtualcamera",
- srcs: [
- "VirtualCameraProvider.cc",
- "VirtualCameraDevice.cc",
- "VirtualCameraSession.cc",
- "VirtualCameraStream.cc",
- "VirtualCameraService.cc",
- "VirtualCameraSessionContext.cc",
- "VirtualCameraRenderThread.cc",
- ],
- defaults: [
- "libvirtualcamera_defaults",
- ],
- static_libs: [
- "libvirtualcamera_utils",
- ],
- export_include_dirs: ["."],
- min_sdk_version: "current",
-}
-
-cc_binary {
- name: "virtual_camera",
- srcs: ["main.cc"],
- defaults: [
- "libvirtualcamera_defaults",
- ],
- static_libs: [
- "libvirtualcamera",
- "libvirtualcamera_utils",
- ],
- // Remove before flight.
- // We don't want the service to be started and discovered
- // yet - remove comments on the lines below in order to
- // test locally.
- // init_rc: ["virtual_camera.hal.rc"],
-}
diff --git a/devices/VirtualCamera/TEST_MAPPING b/devices/VirtualCamera/TEST_MAPPING
deleted file mode 100644
index fd6bd2b..0000000
--- a/devices/VirtualCamera/TEST_MAPPING
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "presubmit": [
- {
- "name": "virtual_camera_tests"
- }
- ]
-}
diff --git a/devices/VirtualCamera/VirtualCameraDevice.cc b/devices/VirtualCamera/VirtualCameraDevice.cc
deleted file mode 100644
index 6c8c0f7..0000000
--- a/devices/VirtualCamera/VirtualCameraDevice.cc
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source 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 "VirtualCameraDevice"
-#include "VirtualCameraDevice.h"
-
-#include <chrono>
-#include <cstdint>
-#include <string>
-
-#include "VirtualCameraSession.h"
-#include "aidl/android/hardware/camera/common/Status.h"
-#include "aidl/android/hardware/camera/device/CameraMetadata.h"
-#include "android/binder_auto_utils.h"
-#include "android/binder_status.h"
-#include "log/log.h"
-#include "system/camera_metadata.h"
-#include "util/MetadataBuilder.h"
-#include "util/Util.h"
-
-namespace android {
-namespace companion {
-namespace virtualcamera {
-
-using ::aidl::android::companion::virtualcamera::IVirtualCameraCallback;
-using ::aidl::android::hardware::camera::common::CameraResourceCost;
-using ::aidl::android::hardware::camera::common::Status;
-using ::aidl::android::hardware::camera::device::CameraMetadata;
-using ::aidl::android::hardware::camera::device::ICameraDeviceCallback;
-using ::aidl::android::hardware::camera::device::ICameraDeviceSession;
-using ::aidl::android::hardware::camera::device::ICameraInjectionSession;
-using ::aidl::android::hardware::camera::device::StreamConfiguration;
-using ::aidl::android::hardware::camera::device::StreamRotation;
-using ::aidl::android::hardware::camera::device::StreamType;
-using ::aidl::android::hardware::graphics::common::PixelFormat;
-
-namespace {
-
-using namespace std::chrono_literals;
-
-// Prefix of camera name - "device@1.1/virtual/{numerical_id}"
-const char* kDevicePathPrefix = "device@1.1/virtual/";
-
-constexpr int32_t kVgaWidth = 640;
-constexpr int32_t kVgaHeight = 480;
-constexpr std::chrono::nanoseconds kMinFrameDuration30Fps = 1s / 30;
-constexpr int32_t kMaxJpegSize = 3 * 1024 * 1024 /*3MiB*/;
-
-constexpr MetadataBuilder::ControlRegion kDefaultEmptyControlRegion{};
-
-// TODO(b/301023410) - Populate camera characteristics according to camera configuration.
-CameraMetadata initCameraCharacteristics() {
- auto metadata =
- MetadataBuilder()
- .setSupportedHardwareLevel(
- ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL)
- .setFlashAvailable(false)
- .setLensFacing(ANDROID_LENS_FACING_EXTERNAL)
- .setSensorOrientation(0)
- .setAvailableFaceDetectModes({ANDROID_STATISTICS_FACE_DETECT_MODE_OFF})
- .setControlAfAvailableModes({ANDROID_CONTROL_AF_MODE_OFF})
- .setAvailableOutputStreamConfigurations(
- {MetadataBuilder::StreamConfiguration{
- .width = kVgaWidth,
- .height = kVgaHeight,
- .format =
- ANDROID_SCALER_AVAILABLE_FORMATS_IMPLEMENTATION_DEFINED,
- .minFrameDuration = kMinFrameDuration30Fps,
- .minStallDuration = 0s},
- MetadataBuilder::StreamConfiguration{
- .width = kVgaWidth,
- .height = kVgaHeight,
- .format = ANDROID_SCALER_AVAILABLE_FORMATS_YCbCr_420_888,
- .minFrameDuration = kMinFrameDuration30Fps,
- .minStallDuration = 0s},
- {MetadataBuilder::StreamConfiguration{
- .width = kVgaWidth,
- .height = kVgaHeight,
- .format = ANDROID_SCALER_AVAILABLE_FORMATS_BLOB,
- .minFrameDuration = kMinFrameDuration30Fps,
- .minStallDuration = 0s}}})
- .setControlAeAvailableFpsRange(10, 30)
- .setControlMaxRegions(0, 0, 0)
- .setSensorActiveArraySize(0, 0, kVgaWidth, kVgaHeight)
- .setControlAfRegions({kDefaultEmptyControlRegion})
- .setControlAeRegions({kDefaultEmptyControlRegion})
- .setControlAwbRegions({kDefaultEmptyControlRegion})
- .setControlAeCompensationRange(0, 1)
- .setControlAeCompensationStep(camera_metadata_rational_t{0, 1})
- .setMaxJpegSize(kMaxJpegSize)
- .setAvailableRequestKeys({ANDROID_CONTROL_AF_MODE})
- .setAvailableResultKeys({ANDROID_CONTROL_AF_MODE})
- .setAvailableCapabilities(
- {ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE})
- .setAvailableCharacteristicKeys()
- .build();
-
- if (metadata == nullptr) {
- ALOGE("Failed to build metadata!");
- return CameraMetadata();
- }
-
- return std::move(*metadata);
-}
-
-} // namespace
-
-VirtualCameraDevice::VirtualCameraDevice(
- const uint32_t cameraId,
- std::shared_ptr<IVirtualCameraCallback> virtualCameraClientCallback)
- : mCameraId(cameraId),
- mVirtualCameraClientCallback(virtualCameraClientCallback) {
- mCameraCharacteristics = initCameraCharacteristics();
-}
-
-ndk::ScopedAStatus VirtualCameraDevice::getCameraCharacteristics(
- CameraMetadata* _aidl_return) {
- ALOGV("%s", __func__);
- if (_aidl_return == nullptr) {
- return cameraStatus(Status::ILLEGAL_ARGUMENT);
- }
-
- *_aidl_return = mCameraCharacteristics;
- return ndk::ScopedAStatus::ok();
-}
-
-ndk::ScopedAStatus VirtualCameraDevice::getPhysicalCameraCharacteristics(
- const std::string& in_physicalCameraId, CameraMetadata* _aidl_return) {
- ALOGV("%s: physicalCameraId %s", __func__, in_physicalCameraId.c_str());
- (void)_aidl_return;
-
- // VTS tests expect this call to fail with illegal argument status for
- // all publicly advertised camera ids.
- // Because we don't support physical camera ids, we just always
- // fail with illegal argument (there's no valid argument to provide).
- return cameraStatus(Status::ILLEGAL_ARGUMENT);
-}
-
-ndk::ScopedAStatus VirtualCameraDevice::getResourceCost(
- CameraResourceCost* _aidl_return) {
- ALOGV("%s", __func__);
- if (_aidl_return == nullptr) {
- return cameraStatus(Status::ILLEGAL_ARGUMENT);
- }
- _aidl_return->resourceCost = 100; // ¯\_(ツ)_/¯
- return ndk::ScopedAStatus::ok();
-}
-
-ndk::ScopedAStatus VirtualCameraDevice::isStreamCombinationSupported(
- const StreamConfiguration& in_streams, bool* _aidl_return) {
- ALOGV("%s", __func__);
-
- if (_aidl_return == nullptr) {
- return cameraStatus(Status::ILLEGAL_ARGUMENT);
- }
-
- for (const auto& stream : in_streams.streams) {
- ALOGV("%s: Configuration queried: %s", __func__, stream.toString().c_str());
-
- if (stream.streamType == StreamType::INPUT) {
- ALOGW("%s: Input stream type is not supported", __func__);
- *_aidl_return = false;
- return ndk::ScopedAStatus::ok();
- }
-
- // TODO(b/301023410) remove hardcoded format checks, verify against configuration.
- if (stream.width != 640 || stream.height != 480 ||
- stream.rotation != StreamRotation::ROTATION_0 ||
- (stream.format != PixelFormat::IMPLEMENTATION_DEFINED &&
- stream.format != PixelFormat::YCBCR_420_888 &&
- stream.format != PixelFormat::BLOB)) {
- *_aidl_return = false;
- return ndk::ScopedAStatus::ok();
- }
- }
-
- *_aidl_return = true;
- return ndk::ScopedAStatus::ok();
-};
-
-ndk::ScopedAStatus VirtualCameraDevice::open(
- const std::shared_ptr<ICameraDeviceCallback>& in_callback,
- std::shared_ptr<ICameraDeviceSession>* _aidl_return) {
- ALOGV("%s", __func__);
-
- *_aidl_return = ndk::SharedRefBase::make<VirtualCameraSession>(
- std::to_string(mCameraId), in_callback, mVirtualCameraClientCallback);
-
- return ndk::ScopedAStatus::ok();
-};
-
-ndk::ScopedAStatus VirtualCameraDevice::openInjectionSession(
- const std::shared_ptr<ICameraDeviceCallback>& in_callback,
- std::shared_ptr<ICameraInjectionSession>* _aidl_return) {
- ALOGV("%s", __func__);
-
- (void)in_callback;
- (void)_aidl_return;
- return cameraStatus(Status::OPERATION_NOT_SUPPORTED);
-}
-
-ndk::ScopedAStatus VirtualCameraDevice::setTorchMode(bool in_on) {
- ALOGV("%s: on = %s", __func__, in_on ? "on" : "off");
- return cameraStatus(Status::OPERATION_NOT_SUPPORTED);
-}
-
-ndk::ScopedAStatus VirtualCameraDevice::turnOnTorchWithStrengthLevel(
- int32_t in_torchStrength) {
- ALOGV("%s: torchStrength = %d", __func__, in_torchStrength);
- return cameraStatus(Status::OPERATION_NOT_SUPPORTED);
-}
-
-ndk::ScopedAStatus VirtualCameraDevice::getTorchStrengthLevel(
- int32_t* _aidl_return) {
- (void)_aidl_return;
- return cameraStatus(Status::OPERATION_NOT_SUPPORTED);
-}
-
-binder_status_t VirtualCameraDevice::dump(int fd, const char** args,
- uint32_t numArgs) {
- // TODO(b/301023410) Implement.
- (void)fd;
- (void)args;
- (void)numArgs;
- return STATUS_OK;
-}
-
-std::string VirtualCameraDevice::getCameraName() const {
- return std::string(kDevicePathPrefix) + std::to_string(mCameraId);
-}
-
-} // namespace virtualcamera
-} // namespace companion
-} // namespace android
diff --git a/devices/VirtualCamera/VirtualCameraDevice.h b/devices/VirtualCamera/VirtualCameraDevice.h
deleted file mode 100644
index 0c95b7a..0000000
--- a/devices/VirtualCamera/VirtualCameraDevice.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source 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 ANDROID_COMPANION_VIRTUALCAMERA_VIRTUALCAMERADEVICE_H
-#define ANDROID_COMPANION_VIRTUALCAMERA_VIRTUALCAMERADEVICE_H
-
-#include <cstdint>
-#include <memory>
-
-#include "aidl/android/companion/virtualcamera/IVirtualCameraCallback.h"
-#include "aidl/android/hardware/camera/device/BnCameraDevice.h"
-
-namespace android {
-namespace companion {
-namespace virtualcamera {
-
-// Representation of single virtual camera device, implements
-// ICameraDevice AIDL to expose camera to camera framework.
-class VirtualCameraDevice
- : public ::aidl::android::hardware::camera::device::BnCameraDevice {
- public:
- explicit VirtualCameraDevice(
- uint32_t cameraId,
- std::shared_ptr<
- ::aidl::android::companion::virtualcamera::IVirtualCameraCallback>
- virtualCameraClientCallback = nullptr);
-
- virtual ~VirtualCameraDevice() override = default;
-
- ndk::ScopedAStatus getCameraCharacteristics(
- ::aidl::android::hardware::camera::device::CameraMetadata* _aidl_return)
- override;
-
- ndk::ScopedAStatus getPhysicalCameraCharacteristics(
- const std::string& in_physicalCameraId,
- ::aidl::android::hardware::camera::device::CameraMetadata* _aidl_return)
- override;
-
- ndk::ScopedAStatus getResourceCost(
- ::aidl::android::hardware::camera::common::CameraResourceCost*
- _aidl_return) override;
-
- ndk::ScopedAStatus isStreamCombinationSupported(
- const ::aidl::android::hardware::camera::device::StreamConfiguration&
- in_streams,
- bool* _aidl_return) override;
-
- ndk::ScopedAStatus open(
- const std::shared_ptr<
- ::aidl::android::hardware::camera::device::ICameraDeviceCallback>&
- in_callback,
- std::shared_ptr<
- ::aidl::android::hardware::camera::device::ICameraDeviceSession>*
- _aidl_return) override;
-
- ndk::ScopedAStatus openInjectionSession(
- const std::shared_ptr<
- ::aidl::android::hardware::camera::device::ICameraDeviceCallback>&
- in_callback,
- std::shared_ptr<
- ::aidl::android::hardware::camera::device::ICameraInjectionSession>*
- _aidl_return) override;
-
- ndk::ScopedAStatus setTorchMode(bool in_on) override;
-
- ndk::ScopedAStatus turnOnTorchWithStrengthLevel(
- int32_t in_torchStrength) override;
-
- ndk::ScopedAStatus getTorchStrengthLevel(int32_t* _aidl_return) override;
-
- binder_status_t dump(int fd, const char** args, uint32_t numArgs) override;
-
- // Returns unique virtual camera name in form
- // "device@{major}.{minor}/virtual/{numerical_id}"
- std::string getCameraName() const;
-
- private:
- const uint32_t mCameraId;
- const std::shared_ptr<
- ::aidl::android::companion::virtualcamera::IVirtualCameraCallback>
- mVirtualCameraClientCallback;
-
- ::aidl::android::hardware::camera::device::CameraMetadata mCameraCharacteristics;
-};
-
-} // namespace virtualcamera
-} // namespace companion
-} // namespace android
-
-#endif // ANDROID_COMPANION_VIRTUALCAMERA_VIRTUALCAMERADEVICE_H
diff --git a/devices/VirtualCamera/VirtualCameraProvider.cc b/devices/VirtualCamera/VirtualCameraProvider.cc
deleted file mode 100644
index b2bdd06..0000000
--- a/devices/VirtualCamera/VirtualCameraProvider.cc
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source 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 "VirtualCameraProvider"
-#include "VirtualCameraProvider.h"
-
-#include <atomic>
-#include <memory>
-#include <mutex>
-#include <tuple>
-#include <utility>
-
-#include "VirtualCameraDevice.h"
-#include "aidl/android/hardware/camera/common/Status.h"
-#include "log/log.h"
-#include "util/Util.h"
-
-namespace android {
-namespace companion {
-namespace virtualcamera {
-
-using ::aidl::android::companion::virtualcamera::IVirtualCameraCallback;
-using ::aidl::android::hardware::camera::common::CameraDeviceStatus;
-using ::aidl::android::hardware::camera::common::Status;
-using ::aidl::android::hardware::camera::common::VendorTagSection;
-using ::aidl::android::hardware::camera::device::ICameraDevice;
-using ::aidl::android::hardware::camera::provider::CameraIdAndStreamCombination;
-using ::aidl::android::hardware::camera::provider::ConcurrentCameraIdCombination;
-using ::aidl::android::hardware::camera::provider::ICameraProviderCallback;
-
-// TODO(b/301023410) Make camera id range configurable / dynamic
-// based on already registered devices.
-std::atomic_int VirtualCameraProvider::sNextId{42};
-
-ndk::ScopedAStatus VirtualCameraProvider::setCallback(
- const std::shared_ptr<ICameraProviderCallback>& in_callback) {
- ALOGV("%s", __func__);
-
- if (in_callback == nullptr) {
- return cameraStatus(Status::ILLEGAL_ARGUMENT);
- }
-
- {
- const std::lock_guard<std::mutex> lock(mLock);
- mCameraProviderCallback = in_callback;
-
- for (const auto& [cameraName, _] : mCameras) {
- auto ret = mCameraProviderCallback->cameraDeviceStatusChange(
- cameraName, CameraDeviceStatus::PRESENT);
- if (!ret.isOk()) {
- ALOGE("Failed to announce camera status change: %s",
- ret.getDescription().c_str());
- }
- }
- }
- return ndk::ScopedAStatus::ok();
-}
-
-ndk::ScopedAStatus VirtualCameraProvider::getVendorTags(
- std::vector<VendorTagSection>* _aidl_return) {
- ALOGV("%s", __func__);
-
- if (_aidl_return == nullptr) {
- return cameraStatus(Status::ILLEGAL_ARGUMENT);
- }
-
- // No vendor tags supported.
- _aidl_return->clear();
- return ndk::ScopedAStatus::ok();
-}
-
-ndk::ScopedAStatus VirtualCameraProvider::getCameraIdList(
- std::vector<std::string>* _aidl_return) {
- ALOGV("%s", __func__);
-
- if (_aidl_return == nullptr) {
- return cameraStatus(Status::ILLEGAL_ARGUMENT);
- }
-
- {
- const std::lock_guard<std::mutex> lock(mLock);
- _aidl_return->clear();
- _aidl_return->reserve(mCameras.size());
- for (const auto& [cameraName, _] : mCameras) {
- _aidl_return->emplace_back(cameraName);
- }
- }
- return ndk::ScopedAStatus::ok();
-}
-
-ndk::ScopedAStatus VirtualCameraProvider::getCameraDeviceInterface(
- const std::string& in_cameraDeviceName,
- std::shared_ptr<ICameraDevice>* _aidl_return) {
- ALOGV("%s cameraDeviceName %s", __func__, in_cameraDeviceName.c_str());
-
- if (_aidl_return == nullptr) {
- return cameraStatus(Status::ILLEGAL_ARGUMENT);
- }
-
- {
- const std::lock_guard<std::mutex> lock(mLock);
- const auto it = mCameras.find(in_cameraDeviceName);
- *_aidl_return = (it == mCameras.end()) ? nullptr : it->second;
- }
-
- return ndk::ScopedAStatus::ok();
-}
-
-ndk::ScopedAStatus VirtualCameraProvider::notifyDeviceStateChange(
- int64_t in_deviceState) {
- ALOGV("%s", __func__);
- (void)in_deviceState;
- return ndk::ScopedAStatus::ok();
-}
-
-ndk::ScopedAStatus VirtualCameraProvider::getConcurrentCameraIds(
- std::vector<ConcurrentCameraIdCombination>* _aidl_return) {
- ALOGV("%s", __func__);
- if (_aidl_return == nullptr) {
- return cameraStatus(Status::ILLEGAL_ARGUMENT);
- }
-
- // No support for any concurrent combination.
- _aidl_return->clear();
- return ndk::ScopedAStatus::ok();
-}
-
-ndk::ScopedAStatus VirtualCameraProvider::isConcurrentStreamCombinationSupported(
- const std::vector<CameraIdAndStreamCombination>& in_configs,
- bool* _aidl_return) {
- ALOGV("%s", __func__);
- (void)in_configs;
- if (_aidl_return == nullptr) {
- return cameraStatus(Status::ILLEGAL_ARGUMENT);
- }
-
- // No support for any stream combination at the moment.
- *_aidl_return = false;
- return ndk::ScopedAStatus::ok();
-}
-
-std::shared_ptr<VirtualCameraDevice> VirtualCameraProvider::createCamera(
- std::shared_ptr<IVirtualCameraCallback> virtualCameraClientCallback) {
- auto camera = ndk::SharedRefBase::make<VirtualCameraDevice>(
- sNextId++, virtualCameraClientCallback);
- std::shared_ptr<ICameraProviderCallback> callback;
- {
- const std::lock_guard<std::mutex> lock(mLock);
- if (mCameras.find(camera->getCameraName()) != mCameras.end()) {
- ALOGE("Camera with identical name already exists.");
- return nullptr;
- }
- mCameras.emplace(std::piecewise_construct,
- std::forward_as_tuple(camera->getCameraName()),
- std::forward_as_tuple(camera));
- callback = mCameraProviderCallback;
- }
-
- if (callback != nullptr) {
- auto ret = callback->cameraDeviceStatusChange(camera->getCameraName(),
- CameraDeviceStatus::PRESENT);
- if (!ret.isOk()) {
- ALOGE("Failed to announce camera %s status change (PRESENT): %s",
- camera->getCameraName().c_str(), ret.getDescription().c_str());
- }
- }
- return camera;
-}
-
-std::shared_ptr<VirtualCameraDevice> VirtualCameraProvider::getCamera(
- const std::string& cameraName) {
- const std::lock_guard<std::mutex> lock(mLock);
- auto it = mCameras.find(cameraName);
- return it == mCameras.end() ? nullptr : it->second;
-}
-
-bool VirtualCameraProvider::removeCamera(const std::string& name) {
- std::shared_ptr<ICameraProviderCallback> callback;
- {
- const std::lock_guard<std::mutex> lock(mLock);
- auto it = mCameras.find(name);
- if (it == mCameras.end()) {
- ALOGE("Cannot remove camera %s: no such camera", name.c_str());
- return false;
- }
- // TODO(b/301023410) Gracefully shut down camera.
- mCameras.erase(it);
- callback = mCameraProviderCallback;
- }
-
- if (callback != nullptr) {
- auto ret = callback->cameraDeviceStatusChange(
- name, CameraDeviceStatus::NOT_PRESENT);
- if (!ret.isOk()) {
- ALOGE("Failed to announce camera %s status change (NOT_PRESENT): %s",
- name.c_str(), ret.getDescription().c_str());
- }
- }
-
- return true;
-}
-
-} // namespace virtualcamera
-} // namespace companion
-} // namespace android
diff --git a/devices/VirtualCamera/VirtualCameraProvider.h b/devices/VirtualCamera/VirtualCameraProvider.h
deleted file mode 100644
index e0f72fa..0000000
--- a/devices/VirtualCamera/VirtualCameraProvider.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source 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 ANDROID_COMPANION_VIRTUALCAMERA_VIRTUALCAMERAPROVIDER_H
-#define ANDROID_COMPANION_VIRTUALCAMERA_VIRTUALCAMERAPROVIDER_H
-
-#include <atomic>
-#include <map>
-#include <memory>
-#include <mutex>
-
-#include "VirtualCameraDevice.h"
-#include "aidl/android/companion/virtualcamera/BnVirtualCameraCallback.h"
-#include "aidl/android/hardware/camera/common/VendorTagSection.h"
-#include "aidl/android/hardware/camera/device/ICameraDevice.h"
-#include "aidl/android/hardware/camera/provider/BnCameraProvider.h"
-#include "aidl/android/hardware/camera/provider/CameraIdAndStreamCombination.h"
-#include "aidl/android/hardware/camera/provider/ConcurrentCameraIdCombination.h"
-#include "aidl/android/hardware/camera/provider/ICameraProviderCallback.h"
-#include "utils/Mutex.h"
-
-namespace android {
-namespace companion {
-namespace virtualcamera {
-
-// Entry point for virtual camera HAL.
-// Allows to create and keep track of virtual camera and implements
-// IAudioProvider AIDL interface to expose virtual camera devices to camera framework.
-class VirtualCameraProvider
- : public ::aidl::android::hardware::camera::provider::BnCameraProvider {
- public:
- ~VirtualCameraProvider() override = default;
-
- ndk::ScopedAStatus setCallback(
- const std::shared_ptr<
- ::aidl::android::hardware::camera::provider::ICameraProviderCallback>&
- in_callback) override;
-
- ndk::ScopedAStatus getVendorTags(
- std::vector<::aidl::android::hardware::camera::common::VendorTagSection>*
- _aidl_return) override;
-
- ndk::ScopedAStatus getCameraIdList(
- std::vector<std::string>* _aidl_return) override;
-
- ndk::ScopedAStatus getCameraDeviceInterface(
- const std::string& in_cameraDeviceName,
- std::shared_ptr<::aidl::android::hardware::camera::device::ICameraDevice>*
- _aidl_return) override;
-
- ndk::ScopedAStatus notifyDeviceStateChange(int64_t in_deviceState) override;
-
- ndk::ScopedAStatus getConcurrentCameraIds(
- std::vector<::aidl::android::hardware::camera::provider::
- ConcurrentCameraIdCombination>* _aidl_return) override;
-
- ndk::ScopedAStatus isConcurrentStreamCombinationSupported(
- const std::vector<::aidl::android::hardware::camera::provider::
- CameraIdAndStreamCombination>& in_configs,
- bool* _aidl_return) override;
-
- // Create new virtual camera devices
- // Returns nullptr if creation was not successful.
- //
- // TODO(b/301023410) - Add camera configuration.
- std::shared_ptr<VirtualCameraDevice> createCamera(
- std::shared_ptr<aidl::android::companion::virtualcamera::IVirtualCameraCallback>
- virtualCameraClientCallback = nullptr);
-
- std::shared_ptr<VirtualCameraDevice> getCamera(const std::string& name);
-
- bool removeCamera(const std::string& name);
-
- private:
- std::mutex mLock;
-
- std::shared_ptr<
- ::aidl::android::hardware::camera::provider::ICameraProviderCallback>
- mCameraProviderCallback GUARDED_BY(mLock);
-
- std::map<std::string, std::shared_ptr<VirtualCameraDevice>> mCameras
- GUARDED_BY(mLock);
-
- // Numerical id to assign to next created camera.
- static std::atomic_int sNextId;
-};
-
-} // namespace virtualcamera
-} // namespace companion
-} // namespace android
-
-#endif // ANDROID_SERVICES_VIRTUAL_CAMERA_VIRTUALCAMERAPROVIDER_H
diff --git a/devices/VirtualCamera/VirtualCameraRenderThread.cc b/devices/VirtualCamera/VirtualCameraRenderThread.cc
deleted file mode 100644
index 582e47f..0000000
--- a/devices/VirtualCamera/VirtualCameraRenderThread.cc
+++ /dev/null
@@ -1,447 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source 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_TAG "VirtualCameraRenderThread"
-#include "VirtualCameraRenderThread.h"
-
-#include <chrono>
-#include <cstddef>
-#include <future>
-#include <memory>
-#include <mutex>
-#include <thread>
-
-#include "VirtualCameraSessionContext.h"
-#include "aidl/android/hardware/camera/common/Status.h"
-#include "aidl/android/hardware/camera/device/BufferStatus.h"
-#include "aidl/android/hardware/camera/device/CameraMetadata.h"
-#include "aidl/android/hardware/camera/device/CaptureResult.h"
-#include "aidl/android/hardware/camera/device/ErrorCode.h"
-#include "aidl/android/hardware/camera/device/ICameraDeviceCallback.h"
-#include "aidl/android/hardware/camera/device/NotifyMsg.h"
-#include "aidl/android/hardware/camera/device/ShutterMsg.h"
-#include "aidl/android/hardware/camera/device/StreamBuffer.h"
-#include "android-base/thread_annotations.h"
-#include "android/binder_auto_utils.h"
-#include "android/hardware_buffer.h"
-#include "util/EglFramebuffer.h"
-#include "util/JpegUtil.h"
-#include "util/MetadataBuilder.h"
-#include "util/TestPatternHelper.h"
-#include "util/Util.h"
-#include "utils/Errors.h"
-
-namespace android {
-namespace companion {
-namespace virtualcamera {
-
-using ::aidl::android::hardware::camera::common::Status;
-using ::aidl::android::hardware::camera::device::BufferStatus;
-using ::aidl::android::hardware::camera::device::CameraMetadata;
-using ::aidl::android::hardware::camera::device::CaptureResult;
-using ::aidl::android::hardware::camera::device::ErrorCode;
-using ::aidl::android::hardware::camera::device::ErrorMsg;
-using ::aidl::android::hardware::camera::device::ICameraDeviceCallback;
-using ::aidl::android::hardware::camera::device::NotifyMsg;
-using ::aidl::android::hardware::camera::device::ShutterMsg;
-using ::aidl::android::hardware::camera::device::Stream;
-using ::aidl::android::hardware::camera::device::StreamBuffer;
-using ::aidl::android::hardware::graphics::common::PixelFormat;
-using ::android::base::ScopedLockAssertion;
-
-namespace {
-
-using namespace std::chrono_literals;
-
-static constexpr std::chrono::milliseconds kAcquireFenceTimeout = 500ms;
-
-CameraMetadata createCaptureResultMetadata(
- const std::chrono::nanoseconds timestamp) {
- std::unique_ptr<CameraMetadata> metadata =
- MetadataBuilder().setSensorTimestamp(timestamp).build();
- if (metadata == nullptr) {
- ALOGE("%s: Failed to build capture result metadata", __func__);
- return CameraMetadata();
- }
- return std::move(*metadata);
-}
-
-NotifyMsg createShutterNotifyMsg(int frameNumber,
- std::chrono::nanoseconds timestamp) {
- NotifyMsg msg;
- msg.set<NotifyMsg::Tag::shutter>(ShutterMsg{
- .frameNumber = frameNumber,
- .timestamp = timestamp.count(),
- });
- return msg;
-}
-
-NotifyMsg createBufferErrorNotifyMsg(int frameNumber, int streamId) {
- NotifyMsg msg;
- msg.set<NotifyMsg::Tag::error>(ErrorMsg{.frameNumber = frameNumber,
- .errorStreamId = streamId,
- .errorCode = ErrorCode::ERROR_BUFFER});
- return msg;
-}
-
-NotifyMsg createRequestErrorNotifyMsg(int frameNumber) {
- NotifyMsg msg;
- msg.set<NotifyMsg::Tag::error>(ErrorMsg{
- .frameNumber = frameNumber, .errorCode = ErrorCode::ERROR_REQUEST});
- return msg;
-}
-
-} // namespace
-
-CaptureRequestBuffer::CaptureRequestBuffer(int streamId, int bufferId,
- sp<Fence> fence)
- : mStreamId(streamId), mBufferId(bufferId), mFence(fence) {
-}
-
-int CaptureRequestBuffer::getStreamId() const {
- return mStreamId;
-}
-
-int CaptureRequestBuffer::getBufferId() const {
- return mBufferId;
-}
-
-sp<Fence> CaptureRequestBuffer::getFence() const {
- return mFence;
-}
-
-VirtualCameraRenderThread::VirtualCameraRenderThread(
- VirtualCameraSessionContext& sessionContext, const int mWidth,
- const int mHeight,
- std::shared_ptr<ICameraDeviceCallback> cameraDeviceCallback, bool testMode)
- : mCameraDeviceCallback(cameraDeviceCallback),
- mInputSurfaceWidth(mWidth),
- mInputSurfaceHeight(mHeight),
- mTestMode(testMode),
- mSessionContext(sessionContext) {
-}
-
-VirtualCameraRenderThread::~VirtualCameraRenderThread() {
- stop();
- if (mThread.joinable()) {
- mThread.join();
- }
-}
-
-ProcessCaptureRequestTask::ProcessCaptureRequestTask(
- int frameNumber, const std::vector<CaptureRequestBuffer>& requestBuffers)
- : mFrameNumber(frameNumber), mBuffers(requestBuffers) {
-}
-
-int ProcessCaptureRequestTask::getFrameNumber() const {
- return mFrameNumber;
-}
-
-const std::vector<CaptureRequestBuffer>& ProcessCaptureRequestTask::getBuffers()
- const {
- return mBuffers;
-}
-
-void VirtualCameraRenderThread::enqueueTask(
- std::unique_ptr<ProcessCaptureRequestTask> task) {
- std::lock_guard<std::mutex> lock(mLock);
- mQueue.emplace_back(std::move(task));
- mCondVar.notify_one();
-}
-
-void VirtualCameraRenderThread::flush() {
- std::lock_guard<std::mutex> lock(mLock);
- for (auto task = std::move(mQueue.front()); !mQueue.empty();
- mQueue.pop_front()) {
- flushCaptureRequest(*task);
- }
-}
-
-void VirtualCameraRenderThread::start() {
- mThread = std::thread(&VirtualCameraRenderThread::threadLoop, this);
-}
-
-void VirtualCameraRenderThread::stop() {
- {
- std::lock_guard<std::mutex> lock(mLock);
- mPendingExit = true;
- mCondVar.notify_one();
- }
-}
-
-sp<Surface> VirtualCameraRenderThread::getInputSurface() {
- return mInputSurfacePromise.get_future().get();
-}
-
-std::unique_ptr<ProcessCaptureRequestTask>
-VirtualCameraRenderThread::dequeueTask() {
- std::unique_lock<std::mutex> lock(mLock);
- // Clang's thread safety analysis doesn't perform alias analysis,
- // so it doesn't support moveable std::unique_lock.
- //
- // Lock assertion below is basically explicit declaration that
- // the lock is held in this scope, which is true, since it's only
- // released during waiting inside mCondVar.wait calls.
- ScopedLockAssertion lockAssertion(mLock);
-
- mCondVar.wait(lock, [this]() REQUIRES(mLock) {
- return mPendingExit || !mQueue.empty();
- });
- if (mPendingExit) {
- return nullptr;
- }
- std::unique_ptr<ProcessCaptureRequestTask> task = std::move(mQueue.front());
- mQueue.pop_front();
- return task;
-}
-
-void VirtualCameraRenderThread::threadLoop() {
- ALOGV("Render thread starting");
-
- mEglDisplayContext = std::make_unique<EglDisplayContext>();
- mEglTextureProgram = std::make_unique<EglTextureProgram>();
- mEglSurfaceTexture = std::make_unique<EglSurfaceTexture>(mInputSurfaceWidth,
- mInputSurfaceHeight);
- mInputSurfacePromise.set_value(mEglSurfaceTexture->getSurface());
-
- while (std::unique_ptr<ProcessCaptureRequestTask> task = dequeueTask()) {
- processCaptureRequest(*task);
- }
-
- ALOGV("Render thread exiting");
-}
-
-void VirtualCameraRenderThread::processCaptureRequest(
- const ProcessCaptureRequestTask& request) {
- const std::chrono::nanoseconds timestamp =
- std::chrono::duration_cast<std::chrono::nanoseconds>(
- std::chrono::steady_clock::now().time_since_epoch());
-
- CaptureResult captureResult;
- captureResult.fmqResultSize = 0;
- captureResult.frameNumber = request.getFrameNumber();
- captureResult.partialResult = 1;
- captureResult.inputBuffer.streamId = -1;
- captureResult.physicalCameraMetadata.resize(0);
- captureResult.result = createCaptureResultMetadata(timestamp);
-
- const std::vector<CaptureRequestBuffer>& buffers = request.getBuffers();
- captureResult.outputBuffers.resize(buffers.size());
-
- if (mTestMode) {
- // In test mode let's just render something to the Surface ourselves.
- renderTestPatternYCbCr420(mEglSurfaceTexture->getSurface(),
- request.getFrameNumber());
- }
-
- mEglSurfaceTexture->updateTexture();
-
- for (int i = 0; i < buffers.size(); ++i) {
- const CaptureRequestBuffer& reqBuffer = buffers[i];
- StreamBuffer& resBuffer = captureResult.outputBuffers[i];
- resBuffer.streamId = reqBuffer.getStreamId();
- resBuffer.bufferId = reqBuffer.getBufferId();
- resBuffer.status = BufferStatus::OK;
-
- const std::optional<Stream> streamConfig =
- mSessionContext.getStreamConfig(reqBuffer.getStreamId());
-
- if (!streamConfig.has_value()) {
- resBuffer.status = BufferStatus::ERROR;
- continue;
- }
-
- auto status = streamConfig->format == PixelFormat::BLOB
- ? renderIntoBlobStreamBuffer(
- reqBuffer.getStreamId(), reqBuffer.getBufferId(),
- streamConfig->bufferSize, reqBuffer.getFence())
- : renderIntoImageStreamBuffer(reqBuffer.getStreamId(),
- reqBuffer.getBufferId(),
- reqBuffer.getFence());
- if (!status.isOk()) {
- resBuffer.status = BufferStatus::ERROR;
- }
- }
-
- std::vector<NotifyMsg> notifyMsg{
- createShutterNotifyMsg(request.getFrameNumber(), timestamp)};
- for (const StreamBuffer& resBuffer : captureResult.outputBuffers) {
- if (resBuffer.status != BufferStatus::OK) {
- notifyMsg.push_back(createBufferErrorNotifyMsg(request.getFrameNumber(),
- resBuffer.streamId));
- }
- }
-
- auto status = mCameraDeviceCallback->notify(notifyMsg);
- if (!status.isOk()) {
- ALOGE("%s: notify call failed: %s", __func__,
- status.getDescription().c_str());
- return;
- }
-
- std::vector<::aidl::android::hardware::camera::device::CaptureResult>
- captureResults(1);
- captureResults[0] = std::move(captureResult);
-
- status = mCameraDeviceCallback->processCaptureResult(captureResults);
- if (!status.isOk()) {
- ALOGE("%s: processCaptureResult call failed: %s", __func__,
- status.getDescription().c_str());
- return;
- }
-
- ALOGD("%s: Successfully called processCaptureResult", __func__);
-}
-
-void VirtualCameraRenderThread::flushCaptureRequest(
- const ProcessCaptureRequestTask& request) {
- const std::chrono::nanoseconds timestamp =
- std::chrono::duration_cast<std::chrono::nanoseconds>(
- std::chrono::steady_clock::now().time_since_epoch());
-
- CaptureResult captureResult;
- captureResult.fmqResultSize = 0;
- captureResult.frameNumber = request.getFrameNumber();
- captureResult.inputBuffer.streamId = -1;
- captureResult.result = createCaptureResultMetadata(timestamp);
-
- const std::vector<CaptureRequestBuffer>& buffers = request.getBuffers();
- captureResult.outputBuffers.resize(buffers.size());
-
- for (int i = 0; i < buffers.size(); ++i) {
- const CaptureRequestBuffer& reqBuffer = buffers[i];
- StreamBuffer& resBuffer = captureResult.outputBuffers[i];
- resBuffer.streamId = reqBuffer.getStreamId();
- resBuffer.bufferId = reqBuffer.getBufferId();
- resBuffer.status = BufferStatus::ERROR;
- sp<Fence> fence = reqBuffer.getFence();
- if (fence != nullptr && fence->isValid()) {
- resBuffer.releaseFence.fds.emplace_back(fence->dup());
- }
- }
-
- auto status = mCameraDeviceCallback->notify(
- {createRequestErrorNotifyMsg(request.getFrameNumber())});
- if (!status.isOk()) {
- ALOGE("%s: notify call failed: %s", __func__,
- status.getDescription().c_str());
- return;
- }
-
- std::vector<::aidl::android::hardware::camera::device::CaptureResult>
- captureResults(1);
- captureResults[0] = std::move(captureResult);
-
- status = mCameraDeviceCallback->processCaptureResult(captureResults);
- if (!status.isOk()) {
- ALOGE("%s: processCaptureResult call failed: %s", __func__,
- status.getDescription().c_str());
- }
-}
-
-ndk::ScopedAStatus VirtualCameraRenderThread::renderIntoBlobStreamBuffer(
- const int streamId, const int bufferId, const size_t bufferSize,
- sp<Fence> fence) {
- ALOGV("%s", __func__);
- sp<GraphicBuffer> gBuffer = mEglSurfaceTexture->getCurrentBuffer();
- std::shared_ptr<AHardwareBuffer> hwBuffer =
- mSessionContext.fetchHardwareBuffer(streamId, bufferId);
-
- AHardwareBuffer_Planes planes_info;
-
- int32_t rawFence = fence != nullptr ? fence->get() : -1;
- int result = AHardwareBuffer_lockPlanes(hwBuffer.get(),
- AHARDWAREBUFFER_USAGE_CPU_READ_RARELY,
- rawFence, nullptr, &planes_info);
- if (result != OK) {
- ALOGE("%s: Failed to lock planes for BLOB buffer: %d", __func__, result);
- return cameraStatus(Status::INTERNAL_ERROR);
- }
-
- android_ycbcr ycbcr;
- status_t status =
- gBuffer->lockYCbCr(AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN, &ycbcr);
- ALOGV("Locked buffers");
- if (status != NO_ERROR) {
- AHardwareBuffer_unlock(hwBuffer.get(), nullptr);
- ALOGE("%s: Failed to lock graphic buffer: %d", __func__, status);
- return cameraStatus(Status::INTERNAL_ERROR);
- }
-
- bool success = compressJpeg(gBuffer->getWidth(), gBuffer->getHeight(), ycbcr,
- bufferSize, planes_info.planes[0].data);
-
- status_t res = gBuffer->unlock();
- if (res != NO_ERROR) {
- ALOGE("Failed to unlock graphic buffer: %d", res);
- }
- AHardwareBuffer_unlock(hwBuffer.get(), nullptr);
- ALOGV("Unlocked buffers");
- return success ? ndk::ScopedAStatus::ok()
- : cameraStatus(Status::INTERNAL_ERROR);
-}
-
-ndk::ScopedAStatus VirtualCameraRenderThread::renderIntoImageStreamBuffer(
- int streamId, int bufferId, sp<Fence> fence) {
- ALOGV("%s", __func__);
-
- const std::chrono::nanoseconds before =
- std::chrono::duration_cast<std::chrono::nanoseconds>(
- std::chrono::steady_clock::now().time_since_epoch());
-
- // Render test pattern using EGL.
- std::shared_ptr<EglFrameBuffer> framebuffer =
- mSessionContext.fetchOrCreateEglFramebuffer(
- mEglDisplayContext->getEglDisplay(), streamId, bufferId);
- if (framebuffer == nullptr) {
- ALOGE(
- "%s: Failed to get EGL framebuffer corresponding to buffer id "
- "%d for streamId %d",
- __func__, bufferId, streamId);
- return cameraStatus(Status::ILLEGAL_ARGUMENT);
- }
-
- // Wait for fence to clear.
- if (fence != nullptr && fence->isValid()) {
- status_t ret = fence->wait(kAcquireFenceTimeout.count());
- if (ret != 0) {
- ALOGE(
- "Timeout while waiting for the acquire fence for buffer %d"
- " for streamId %d",
- bufferId, streamId);
- return cameraStatus(Status::INTERNAL_ERROR);
- }
- }
-
- mEglDisplayContext->makeCurrent();
- framebuffer->beforeDraw();
-
- mEglTextureProgram->draw(mEglSurfaceTexture->updateTexture());
- framebuffer->afterDraw();
-
- const std::chrono::nanoseconds after =
- std::chrono::duration_cast<std::chrono::nanoseconds>(
- std::chrono::steady_clock::now().time_since_epoch());
-
- ALOGV("Rendering to buffer %d, stream %d took %lld ns", bufferId, streamId,
- after.count() - before.count());
-
- return ndk::ScopedAStatus::ok();
-}
-
-} // namespace virtualcamera
-} // namespace companion
-} // namespace android
diff --git a/devices/VirtualCamera/VirtualCameraRenderThread.h b/devices/VirtualCamera/VirtualCameraRenderThread.h
deleted file mode 100644
index 30de7c2..0000000
--- a/devices/VirtualCamera/VirtualCameraRenderThread.h
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source 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 ANDROID_COMPANION_VIRTUALCAMERA_VIRTUALCAMERARENDERTHREAD_H
-#define ANDROID_COMPANION_VIRTUALCAMERA_VIRTUALCAMERARENDERTHREAD_H
-
-#include <deque>
-#include <future>
-#include <memory>
-#include <thread>
-
-#include "VirtualCameraSessionContext.h"
-#include "aidl/android/hardware/camera/device/ICameraDeviceCallback.h"
-#include "util/EglDisplayContext.h"
-#include "util/EglProgram.h"
-#include "util/EglSurfaceTexture.h"
-
-namespace android {
-namespace companion {
-namespace virtualcamera {
-
-// Represents single output buffer of capture request.
-class CaptureRequestBuffer {
- public:
- CaptureRequestBuffer(int streamId, int bufferId, sp<Fence> fence = nullptr);
-
- int getStreamId() const;
- int getBufferId() const;
- sp<Fence> getFence() const;
-
- private:
- const int mStreamId;
- const int mBufferId;
- const sp<Fence> mFence;
-};
-
-// Represents single capture request to fill set of buffers.
-class ProcessCaptureRequestTask {
- public:
- ProcessCaptureRequestTask(
- int frameNumber, const std::vector<CaptureRequestBuffer>& requestBuffers);
-
- // Returns frame number corresponding to the request.
- int getFrameNumber() const;
-
- // Get reference to vector describing output buffers corresponding
- // to this request.
- //
- // Note that the vector is owned by the ProcessCaptureRequestTask instance,
- // so it cannot be access outside of its lifetime.
- const std::vector<CaptureRequestBuffer>& getBuffers() const;
-
- private:
- const int mFrameNumber;
- const std::vector<CaptureRequestBuffer> mBuffers;
-};
-
-// Wraps dedicated rendering thread and rendering business with corresponding
-// input surface.
-class VirtualCameraRenderThread {
- public:
- // Create VirtualCameraRenderThread instance:
- // * sessionContext - VirtualCameraSessionContext reference for shared access
- // to mapped buffers.
- // * inputWidth - requested width of input surface ("virtual camera sensor")
- // * inputHeight - requested height of input surface ("virtual camera sensor")
- // * cameraDeviceCallback - callback for corresponding camera instance
- // * testMode - when set to true, test pattern is rendered to input surface
- // before each capture request is processed to simulate client input.
- VirtualCameraRenderThread(
- VirtualCameraSessionContext& sessionContext, int inputWidth,
- int inputHeight,
- std::shared_ptr<
- ::aidl::android::hardware::camera::device::ICameraDeviceCallback>
- cameraDeviceCallback,
- bool testMode = false);
-
- ~VirtualCameraRenderThread();
-
- // Start rendering thread.
- void start();
- // Stop rendering thread.
- void stop();
-
- // Equeue capture task for processing on render thread.
- void enqueueTask(std::unique_ptr<ProcessCaptureRequestTask> task)
- EXCLUDES(mLock);
-
- // Flush all in-flight requests.
- void flush() EXCLUDES(mLock);
-
- // Returns input surface corresponding to "virtual camera sensor".
- sp<Surface> getInputSurface();
-
- private:
- std::unique_ptr<ProcessCaptureRequestTask> dequeueTask() EXCLUDES(mLock);
-
- // Rendering thread entry point.
- void threadLoop();
-
- // Process single capture request task (always called on render thread).
- void processCaptureRequest(const ProcessCaptureRequestTask& captureRequestTask);
-
- // Flush single capture request task returning the error status immediately.
- void flushCaptureRequest(const ProcessCaptureRequestTask& captureRequestTask);
-
- // TODO(b/301023410) - Refactor the actual rendering logic off this class for
- // easier testability.
-
- // Render current image to the BLOB buffer.
- // If fence is specified, this function will block until the fence is cleared
- // before writing to the buffer.
- // Always called on render thread.
- ndk::ScopedAStatus renderIntoBlobStreamBuffer(const int streamId,
- const int bufferId,
- const size_t bufferSize,
- sp<Fence> fence = nullptr);
-
- // Render current image to the YCbCr buffer.
- // If fence is specified, this function will block until the fence is cleared
- // before writing to the buffer.
- // Always called on render thread.
- ndk::ScopedAStatus renderIntoImageStreamBuffer(int streamId, int bufferId,
- sp<Fence> fence = nullptr);
-
- // Camera callback
- const std::shared_ptr<
- ::aidl::android::hardware::camera::device::ICameraDeviceCallback>
- mCameraDeviceCallback;
-
- const int mInputSurfaceWidth;
- const int mInputSurfaceHeight;
- const int mTestMode;
-
- VirtualCameraSessionContext& mSessionContext;
-
- std::thread mThread;
-
- // Blocking queue implementation.
- std::mutex mLock;
- std::deque<std::unique_ptr<ProcessCaptureRequestTask>> mQueue GUARDED_BY(mLock);
- std::condition_variable mCondVar;
- volatile bool mPendingExit GUARDED_BY(mLock);
-
- // EGL helpers - constructed and accessed only from rendering thread.
- std::unique_ptr<EglDisplayContext> mEglDisplayContext;
- std::unique_ptr<EglTextureProgram> mEglTextureProgram;
- std::unique_ptr<EglSurfaceTexture> mEglSurfaceTexture;
-
- std::promise<sp<Surface>> mInputSurfacePromise;
-};
-
-} // namespace virtualcamera
-} // namespace companion
-} // namespace android
-
-#endif // ANDROID_COMPANION_VIRTUALCAMERA_VIRTUALCAMERARENDERTHREAD_H
diff --git a/devices/VirtualCamera/VirtualCameraService.cc b/devices/VirtualCamera/VirtualCameraService.cc
deleted file mode 100644
index 62dc08b..0000000
--- a/devices/VirtualCamera/VirtualCameraService.cc
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source 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
-#include "android/binder_status.h"
-#define LOG_TAG "VirtualCameraService"
-#include "VirtualCameraService.h"
-
-#include <cinttypes>
-#include <cstdint>
-#include <cstdio>
-#include <memory>
-#include <mutex>
-
-#include "VirtualCameraDevice.h"
-#include "VirtualCameraProvider.h"
-#include "android/binder_auto_utils.h"
-#include "android/binder_libbinder.h"
-#include "binder/Status.h"
-
-using ::android::binder::Status;
-
-namespace android {
-namespace companion {
-namespace virtualcamera {
-
-using ::aidl::android::companion::virtualcamera::VirtualCameraConfiguration;
-
-namespace {
-
-constexpr char kEnableTestCameraCmd[] = "enable_test_camera";
-constexpr char kDisableTestCameraCmd[] = "disable_test_camera";
-constexpr char kShellCmdHelp[] = R"(
-Available commands:
- * enable_test_camera
- * disable_test_camera
-)";
-
-} // namespace
-
-VirtualCameraService::VirtualCameraService(
- std::shared_ptr<VirtualCameraProvider> virtualCameraProvider)
- : mVirtualCameraProvider(virtualCameraProvider) {
-}
-
-ndk::ScopedAStatus VirtualCameraService::registerCamera(
- const ::ndk::SpAIBinder& token,
- const VirtualCameraConfiguration& configuration, bool* _aidl_return) {
- (void)configuration;
- if (_aidl_return == nullptr) {
- return ndk::ScopedAStatus::fromServiceSpecificError(
- Status::EX_ILLEGAL_ARGUMENT);
- }
- *_aidl_return = true;
-
- std::lock_guard lock(mLock);
- if (mTokenToCameraName.find(token) != mTokenToCameraName.end()) {
- ALOGE(
- "Attempt to register camera corresponding to already registered binder "
- "token: "
- "0x%" PRIxPTR,
- reinterpret_cast<uintptr_t>(token.get()));
- *_aidl_return = false;
- }
-
- // TODO(b/301023410) Validate configuration and pass it to the camera.
- std::shared_ptr<VirtualCameraDevice> camera =
- mVirtualCameraProvider->createCamera(configuration.virtualCameraCallback);
- if (camera == nullptr) {
- ALOGE("Failed to create camera for binder token 0x%" PRIxPTR,
- reinterpret_cast<uintptr_t>(token.get()));
- *_aidl_return = false;
- return ndk::ScopedAStatus::fromServiceSpecificError(
- Status::EX_SERVICE_SPECIFIC);
- }
-
- mTokenToCameraName[token] = camera->getCameraName();
- return ndk::ScopedAStatus::ok();
-}
-
-ndk::ScopedAStatus VirtualCameraService::unregisterCamera(
- const ::ndk::SpAIBinder& token) {
- std::lock_guard lock(mLock);
-
- auto it = mTokenToCameraName.find(token);
- if (it == mTokenToCameraName.end()) {
- ALOGE(
- "Attempt to unregister camera corresponding to unknown binder token: "
- "0x%" PRIxPTR,
- reinterpret_cast<uintptr_t>(token.get()));
- return ndk::ScopedAStatus::ok();
- }
-
- mVirtualCameraProvider->removeCamera(it->second);
-
- return ndk::ScopedAStatus::ok();
-}
-
-std::shared_ptr<VirtualCameraDevice> VirtualCameraService::getCamera(
- const ::ndk::SpAIBinder& token) {
- if (token == nullptr) {
- return nullptr;
- }
-
- std::lock_guard lock(mLock);
- auto it = mTokenToCameraName.find(token);
- if (it == mTokenToCameraName.end()) {
- return nullptr;
- }
-
- return mVirtualCameraProvider->getCamera(it->second);
-}
-
-binder_status_t VirtualCameraService::handleShellCommand(int in, int out,
- int err,
- const char** args,
- uint32_t numArgs) {
- if (numArgs <= 0) {
- dprintf(out, kShellCmdHelp);
- }
-
- if (args == nullptr || args[0] == nullptr) {
- return STATUS_BAD_VALUE;
- }
- const char* const cmd = args[0];
- if (strcmp(kEnableTestCameraCmd, cmd) == 0) {
- enableTestCameraCmd(in, err);
- } else if (strcmp(kDisableTestCameraCmd, cmd) == 0) {
- disableTestCameraCmd(in);
- } else {
- dprintf(out, kShellCmdHelp);
- }
-
- fsync(out);
- return STATUS_OK;
-}
-
-void VirtualCameraService::enableTestCameraCmd(const int out, const int err) {
- if (mTestCameraToken != nullptr) {
- dprintf(out, "Test camera is already enabled (%s).",
- getCamera(mTestCameraToken)->getCameraName().c_str());
- return;
- }
-
- sp<BBinder> token = sp<BBinder>::make();
- mTestCameraToken.set(AIBinder_fromPlatformBinder(token));
-
- bool ret;
- registerCamera(mTestCameraToken, VirtualCameraConfiguration(), &ret);
- if (ret) {
- dprintf(out, "Successfully registered test camera %s",
- getCamera(mTestCameraToken)->getCameraName().c_str());
- } else {
- dprintf(err, "Failed to create test camera");
- }
-}
-
-void VirtualCameraService::disableTestCameraCmd(const int out) {
- if (mTestCameraToken == nullptr) {
- dprintf(out, "Test camera is not registered.");
- }
- unregisterCamera(mTestCameraToken);
- mTestCameraToken.set(nullptr);
-}
-
-} // namespace virtualcamera
-} // namespace companion
-} // namespace android
diff --git a/devices/VirtualCamera/VirtualCameraService.h b/devices/VirtualCamera/VirtualCameraService.h
deleted file mode 100644
index cf68c1b..0000000
--- a/devices/VirtualCamera/VirtualCameraService.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source 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 ANDROID_COMPANION_VIRTUALCAMERA_VIRTUALCAMERASERVICE_H
-#define ANDROID_COMPANION_VIRTUALCAMERA_VIRTUALCAMERASERVICE_H
-
-#include <memory>
-#include <mutex>
-#include <unordered_map>
-
-#include "VirtualCameraDevice.h"
-#include "VirtualCameraProvider.h"
-#include "aidl/android/companion/virtualcamera/BnVirtualCameraService.h"
-
-namespace android {
-namespace companion {
-namespace virtualcamera {
-
-// Implementation of Virtual Camera Service for managing virtual camera devices.
-class VirtualCameraService
- : public aidl::android::companion::virtualcamera::BnVirtualCameraService {
- public:
- VirtualCameraService(
- std::shared_ptr<VirtualCameraProvider> virtualCameraProvider);
-
- // Register camera corresponding to the binder token.
- ndk::ScopedAStatus registerCamera(
- const ::ndk::SpAIBinder& token,
- const ::aidl::android::companion::virtualcamera::VirtualCameraConfiguration&
- configuration,
- bool* _aidl_return) override EXCLUDES(mLock);
-
- // Unregisters camera corresponding to the binder token.
- ndk::ScopedAStatus unregisterCamera(const ::ndk::SpAIBinder& token) override
- EXCLUDES(mLock);
-
- // Returns VirtualCameraDevice corresponding to binder token or nullptr if
- // there's no camera asociated with the token.
- std::shared_ptr<VirtualCameraDevice> getCamera(const ::ndk::SpAIBinder& token)
- EXCLUDES(mLock);
-
- // Handle cmd shell commands `adb shell cmd virtual_camera_service` [args].
- binder_status_t handleShellCommand(int in, int out, int err, const char** args,
- uint32_t numArgs) override;
-
- private:
- // Create and enable test camera instance if there's none.
- void enableTestCameraCmd(int out, int err);
- // Disable and destroy test camera instance if there's one.
- void disableTestCameraCmd(int out);
-
- std::shared_ptr<VirtualCameraProvider> mVirtualCameraProvider;
-
- std::mutex mLock;
- struct BinderTokenHash {
- std::size_t operator()(const ::ndk::SpAIBinder& key) const {
- return std::hash<void*>{}(reinterpret_cast<void*>(key.get()));
- }
- };
- // Map Binder tokens to names of cameras managed by camera provider.
- std::unordered_map<::ndk::SpAIBinder, std::string, BinderTokenHash>
- mTokenToCameraName GUARDED_BY(mLock);
-
- // Local binder token for test camera instance, or nullptr if there's none.
- ::ndk::SpAIBinder mTestCameraToken;
-};
-
-} // namespace virtualcamera
-} // namespace companion
-} // namespace android
-
-#endif // ANDROID_COMPANION_VIRTUALCAMERA_VIRTUALCAMERASERVICE_H
diff --git a/devices/VirtualCamera/VirtualCameraSession.cc b/devices/VirtualCamera/VirtualCameraSession.cc
deleted file mode 100644
index 55678b7..0000000
--- a/devices/VirtualCamera/VirtualCameraSession.cc
+++ /dev/null
@@ -1,436 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source 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 "VirtualCameraSession"
-#include "VirtualCameraSession.h"
-
-#include <atomic>
-#include <chrono>
-#include <cstddef>
-#include <cstdint>
-#include <cstring>
-#include <map>
-#include <memory>
-#include <mutex>
-#include <optional>
-#include <tuple>
-#include <unordered_set>
-#include <utility>
-#include <vector>
-
-#include "CameraMetadata.h"
-#include "EGL/egl.h"
-#include "VirtualCameraRenderThread.h"
-#include "VirtualCameraStream.h"
-#include "aidl/android/hardware/camera/common/Status.h"
-#include "aidl/android/hardware/camera/device/BufferCache.h"
-#include "aidl/android/hardware/camera/device/BufferStatus.h"
-#include "aidl/android/hardware/camera/device/CaptureRequest.h"
-#include "aidl/android/hardware/camera/device/HalStream.h"
-#include "aidl/android/hardware/camera/device/NotifyMsg.h"
-#include "aidl/android/hardware/camera/device/ShutterMsg.h"
-#include "aidl/android/hardware/camera/device/StreamBuffer.h"
-#include "aidl/android/hardware/camera/device/StreamConfiguration.h"
-#include "aidl/android/hardware/camera/device/StreamRotation.h"
-#include "aidl/android/hardware/graphics/common/BufferUsage.h"
-#include "aidl/android/hardware/graphics/common/PixelFormat.h"
-#include "android/hardware_buffer.h"
-#include "android/native_window_aidl.h"
-#include "fmq/AidlMessageQueue.h"
-#include "system/camera_metadata.h"
-#include "ui/GraphicBuffer.h"
-#include "util/EglDisplayContext.h"
-#include "util/EglFramebuffer.h"
-#include "util/EglProgram.h"
-#include "util/JpegUtil.h"
-#include "util/MetadataBuilder.h"
-#include "util/TestPatternHelper.h"
-#include "util/Util.h"
-
-namespace android {
-namespace companion {
-namespace virtualcamera {
-
-using ::aidl::android::companion::virtualcamera::Format;
-using ::aidl::android::companion::virtualcamera::IVirtualCameraCallback;
-using ::aidl::android::hardware::camera::common::Status;
-using ::aidl::android::hardware::camera::device::BufferCache;
-using ::aidl::android::hardware::camera::device::CameraMetadata;
-using ::aidl::android::hardware::camera::device::CameraOfflineSessionInfo;
-using ::aidl::android::hardware::camera::device::CaptureRequest;
-using ::aidl::android::hardware::camera::device::HalStream;
-using ::aidl::android::hardware::camera::device::ICameraDeviceCallback;
-using ::aidl::android::hardware::camera::device::ICameraOfflineSession;
-using ::aidl::android::hardware::camera::device::RequestTemplate;
-using ::aidl::android::hardware::camera::device::Stream;
-using ::aidl::android::hardware::camera::device::StreamBuffer;
-using ::aidl::android::hardware::camera::device::StreamConfiguration;
-using ::aidl::android::hardware::camera::device::StreamRotation;
-using ::aidl::android::hardware::common::fmq::MQDescriptor;
-using ::aidl::android::hardware::common::fmq::SynchronizedReadWrite;
-using ::aidl::android::hardware::graphics::common::BufferUsage;
-using ::aidl::android::hardware::graphics::common::PixelFormat;
-using ::android::base::unique_fd;
-
-namespace {
-
-using metadata_ptr =
- std::unique_ptr<camera_metadata_t, void (*)(camera_metadata_t*)>;
-
-using namespace std::chrono_literals;
-
-// Size of request/result metadata fast message queue.
-// Setting to 0 to always disables FMQ.
-static constexpr size_t kMetadataMsgQueueSize = 0;
-
-// Maximum number of buffers to use per single stream.
-static constexpr size_t kMaxStreamBuffers = 2;
-
-CameraMetadata createDefaultRequestSettings(RequestTemplate type) {
- hardware::camera::common::V1_0::helper::CameraMetadata metadataHelper;
-
- camera_metadata_enum_android_control_capture_intent_t intent =
- ANDROID_CONTROL_CAPTURE_INTENT_PREVIEW;
- switch (type) {
- case RequestTemplate::PREVIEW:
- intent = ANDROID_CONTROL_CAPTURE_INTENT_PREVIEW;
- break;
- case RequestTemplate::STILL_CAPTURE:
- intent = ANDROID_CONTROL_CAPTURE_INTENT_STILL_CAPTURE;
- break;
- case RequestTemplate::VIDEO_RECORD:
- intent = ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_RECORD;
- break;
- case RequestTemplate::VIDEO_SNAPSHOT:
- intent = ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT;
- break;
- default:
- // Leave default.
- break;
- }
-
- auto metadata = MetadataBuilder().setControlCaptureIntent(intent).build();
- return (metadata != nullptr) ? std::move(*metadata) : CameraMetadata();
-}
-
-HalStream getHalStream(const Stream& stream) {
- HalStream halStream;
- halStream.id = stream.id;
- halStream.physicalCameraId = stream.physicalCameraId;
- halStream.maxBuffers = kMaxStreamBuffers;
-
- if (stream.format == PixelFormat::IMPLEMENTATION_DEFINED) {
- // If format is implementation defined we need it to override
- // it with actual format.
- // TODO(b/301023410) Override with the format based on the
- // camera configuration, once we support more formats.
- halStream.overrideFormat = PixelFormat::YCBCR_420_888;
- } else {
- halStream.overrideFormat = stream.format;
- }
- halStream.overrideDataSpace = stream.dataSpace;
-
- halStream.producerUsage = BufferUsage::GPU_RENDER_TARGET;
- halStream.supportOffline = false;
- return halStream;
-}
-
-} // namespace
-
-VirtualCameraSession::VirtualCameraSession(
- const std::string& cameraId,
- std::shared_ptr<ICameraDeviceCallback> cameraDeviceCallback,
- std::shared_ptr<IVirtualCameraCallback> virtualCameraClientCallback)
- : mCameraId(cameraId),
- mCameraDeviceCallback(cameraDeviceCallback),
- mVirtualCameraClientCallback(virtualCameraClientCallback) {
- mRequestMetadataQueue = std::make_unique<RequestMetadataQueue>(
- kMetadataMsgQueueSize, false /* non blocking */);
- if (!mRequestMetadataQueue->isValid()) {
- ALOGE("%s: invalid request fmq", __func__);
- }
-
- mResultMetadataQueue = std::make_shared<ResultMetadataQueue>(
- kMetadataMsgQueueSize, false /* non blocking */);
- if (!mResultMetadataQueue->isValid()) {
- ALOGE("%s: invalid result fmq", __func__);
- }
-}
-
-ndk::ScopedAStatus VirtualCameraSession::close() {
- ALOGV("%s", __func__);
-
- if (mVirtualCameraClientCallback != nullptr) {
- mVirtualCameraClientCallback->onStreamClosed(/*streamId=*/0);
- }
-
- mSessionContext.closeAllStreams();
- return ndk::ScopedAStatus::ok();
-}
-
-ndk::ScopedAStatus VirtualCameraSession::configureStreams(
- const StreamConfiguration& in_requestedConfiguration,
- std::vector<HalStream>* _aidl_return) {
- ALOGV("%s: requestedConfiguration: %s", __func__,
- in_requestedConfiguration.toString().c_str());
-
- if (_aidl_return == nullptr) {
- return cameraStatus(Status::ILLEGAL_ARGUMENT);
- }
-
- mSessionContext.removeStreamsNotInStreamConfiguration(
- in_requestedConfiguration);
-
- auto& streams = in_requestedConfiguration.streams;
- auto& halStreams = *_aidl_return;
- halStreams.clear();
- halStreams.resize(in_requestedConfiguration.streams.size());
-
- sp<Surface> inputSurface = nullptr;
- int inputWidth;
- int inputHeight;
-
- {
- std::lock_guard<std::mutex> lock(mLock);
- for (int i = 0; i < in_requestedConfiguration.streams.size(); ++i) {
- // TODO(b/301023410) remove hardcoded format checks, verify against configuration.
- if (streams[i].width != 640 || streams[i].height != 480 ||
- streams[i].rotation != StreamRotation::ROTATION_0 ||
- (streams[i].format != PixelFormat::IMPLEMENTATION_DEFINED &&
- streams[i].format != PixelFormat::YCBCR_420_888 &&
- streams[i].format != PixelFormat::BLOB)) {
- halStreams.clear();
- return cameraStatus(Status::ILLEGAL_ARGUMENT);
- }
- halStreams[i] = getHalStream(streams[i]);
- if (mSessionContext.initializeStream(streams[i])) {
- ALOGV("Configured new stream: %s", streams[i].toString().c_str());
- }
- }
-
- inputWidth = streams[0].width;
- inputHeight = streams[0].height;
- if (mRenderThread == nullptr) {
- // If there's no client callback, start camera in test mode.
- const bool testMode = mVirtualCameraClientCallback == nullptr;
- mRenderThread = std::make_unique<VirtualCameraRenderThread>(
- mSessionContext, inputWidth, inputHeight, mCameraDeviceCallback,
- testMode);
- mRenderThread->start();
- inputSurface = mRenderThread->getInputSurface();
- }
- }
-
- if (mVirtualCameraClientCallback != nullptr && inputSurface != nullptr) {
- // TODO(b/301023410) Pass streamId based on client input stream id once
- // support for multiple input streams is implemented. For now we always
- // create single texture.
- mVirtualCameraClientCallback->onStreamConfigured(
- /*streamId=*/0, aidl::android::view::Surface(inputSurface.get()),
- inputWidth, inputHeight, Format::YUV_420_888);
- }
-
- mFirstRequest.store(true);
- return ndk::ScopedAStatus::ok();
-}
-
-ndk::ScopedAStatus VirtualCameraSession::constructDefaultRequestSettings(
- RequestTemplate in_type, CameraMetadata* _aidl_return) {
- ALOGV("%s: type %d", __func__, static_cast<int32_t>(in_type));
-
- switch (in_type) {
- case RequestTemplate::PREVIEW:
- case RequestTemplate::STILL_CAPTURE:
- case RequestTemplate::VIDEO_RECORD: {
- *_aidl_return = createDefaultRequestSettings(in_type);
- return ndk::ScopedAStatus::ok();
- }
- case RequestTemplate::VIDEO_SNAPSHOT:
- case RequestTemplate::MANUAL:
- case RequestTemplate::ZERO_SHUTTER_LAG:
- // Don't support VIDEO_SNAPSHOT, MANUAL, ZSL templates
- return ndk::ScopedAStatus::fromServiceSpecificError(
- static_cast<int32_t>(Status::ILLEGAL_ARGUMENT));
- ;
- default:
- ALOGE("%s: unknown request template type %d", __FUNCTION__,
- static_cast<int>(in_type));
- return ndk::ScopedAStatus::fromServiceSpecificError(
- static_cast<int32_t>(Status::ILLEGAL_ARGUMENT));
- ;
- }
-}
-
-ndk::ScopedAStatus VirtualCameraSession::flush() {
- ALOGV("%s", __func__);
- std::lock_guard<std::mutex> lock(mLock);
- mRenderThread->flush();
- return ndk::ScopedAStatus::ok();
-}
-
-ndk::ScopedAStatus VirtualCameraSession::getCaptureRequestMetadataQueue(
- MQDescriptor<int8_t, SynchronizedReadWrite>* _aidl_return) {
- ALOGV("%s", __func__);
- *_aidl_return = mRequestMetadataQueue->dupeDesc();
- return ndk::ScopedAStatus::ok();
-}
-
-ndk::ScopedAStatus VirtualCameraSession::getCaptureResultMetadataQueue(
- MQDescriptor<int8_t, SynchronizedReadWrite>* _aidl_return) {
- ALOGV("%s", __func__);
- *_aidl_return = mResultMetadataQueue->dupeDesc();
- return ndk::ScopedAStatus::ok();
-}
-
-ndk::ScopedAStatus VirtualCameraSession::isReconfigurationRequired(
- const CameraMetadata& in_oldSessionParams,
- const CameraMetadata& in_newSessionParams, bool* _aidl_return) {
- ALOGV("%s: oldSessionParams: %s newSessionParams: %s", __func__,
- in_newSessionParams.toString().c_str(),
- in_oldSessionParams.toString().c_str());
-
- if (_aidl_return == nullptr) {
- return ndk::ScopedAStatus::fromServiceSpecificError(
- static_cast<int32_t>(Status::ILLEGAL_ARGUMENT));
- }
-
- *_aidl_return = true;
- return ndk::ScopedAStatus::ok();
-}
-
-ndk::ScopedAStatus VirtualCameraSession::processCaptureRequest(
- const std::vector<CaptureRequest>& in_requests,
- const std::vector<BufferCache>& in_cachesToRemove, int32_t* _aidl_return) {
- ALOGV("%s", __func__);
-
- if (!in_cachesToRemove.empty()) {
- mSessionContext.removeBufferCaches(in_cachesToRemove);
- }
-
- for (const auto& captureRequest : in_requests) {
- auto status = processCaptureRequest(captureRequest);
- if (!status.isOk()) {
- return status;
- }
- }
- *_aidl_return = in_requests.size();
- return ndk::ScopedAStatus::ok();
-}
-
-ndk::ScopedAStatus VirtualCameraSession::signalStreamFlush(
- const std::vector<int32_t>& in_streamIds, int32_t in_streamConfigCounter) {
- ALOGV("%s", __func__);
-
- (void)in_streamIds;
- (void)in_streamConfigCounter;
- return ndk::ScopedAStatus::ok();
-}
-
-ndk::ScopedAStatus VirtualCameraSession::switchToOffline(
- const std::vector<int32_t>& in_streamsToKeep,
- CameraOfflineSessionInfo* out_offlineSessionInfo,
- std::shared_ptr<ICameraOfflineSession>* _aidl_return) {
- ALOGV("%s", __func__);
-
- (void)in_streamsToKeep;
- (void)out_offlineSessionInfo;
-
- if (_aidl_return == nullptr) {
- return ndk::ScopedAStatus::fromServiceSpecificError(
- static_cast<int32_t>(Status::ILLEGAL_ARGUMENT));
- }
-
- *_aidl_return = nullptr;
- return cameraStatus(Status::OPERATION_NOT_SUPPORTED);
-}
-
-ndk::ScopedAStatus VirtualCameraSession::repeatingRequestEnd(
- int32_t in_frameNumber, const std::vector<int32_t>& in_streamIds) {
- ALOGV("%s", __func__);
- (void)in_frameNumber;
- (void)in_streamIds;
- return ndk::ScopedAStatus::ok();
-}
-
-std::set<int> VirtualCameraSession::getStreamIds() const {
- return mSessionContext.getStreamIds();
-}
-
-ndk::ScopedAStatus VirtualCameraSession::processCaptureRequest(
- const CaptureRequest& request) {
- ALOGD("%s: request: %s", __func__, request.toString().c_str());
-
- if (mFirstRequest.exchange(false) && request.settings.metadata.empty()) {
- return cameraStatus(Status::ILLEGAL_ARGUMENT);
- }
-
- std::shared_ptr<ICameraDeviceCallback> cameraCallback = nullptr;
- {
- std::lock_guard<std::mutex> lock(mLock);
- cameraCallback = mCameraDeviceCallback;
- }
-
- if (cameraCallback == nullptr) {
- ALOGE(
- "%s: processCaptureRequest called, but there's no camera callback "
- "configured",
- __func__);
- return cameraStatus(Status::INTERNAL_ERROR);
- }
-
- if (!mSessionContext.importBuffersFromCaptureRequest(request)) {
- ALOGE("Failed to import buffers from capture request.");
- return cameraStatus(Status::INTERNAL_ERROR);
- }
-
- std::vector<CaptureRequestBuffer> taskBuffers;
- taskBuffers.reserve(request.outputBuffers.size());
- for (const StreamBuffer& streamBuffer : request.outputBuffers) {
- taskBuffers.emplace_back(streamBuffer.streamId, streamBuffer.bufferId,
- importFence(streamBuffer.acquireFence));
- }
-
- {
- std::lock_guard<std::mutex> lock(mLock);
- if (mRenderThread == nullptr) {
- ALOGE(
- "%s: processCaptureRequest (frameNumber %d)called before configure "
- "(render thread not initialized)",
- __func__, request.frameNumber);
- return cameraStatus(Status::INTERNAL_ERROR);
- }
- mRenderThread->enqueueTask(std::make_unique<ProcessCaptureRequestTask>(
- request.frameNumber, taskBuffers));
- }
-
- if (mVirtualCameraClientCallback != nullptr) {
- auto status = mVirtualCameraClientCallback->onProcessCaptureRequest(
- /*streamId=*/0, request.frameNumber);
- if (!status.isOk()) {
- ALOGE(
- "Failed to invoke onProcessCaptureRequest client callback for frame "
- "%d",
- request.frameNumber);
- }
- }
-
- return ndk::ScopedAStatus::ok();
-}
-
-} // namespace virtualcamera
-} // namespace companion
-} // namespace android
diff --git a/devices/VirtualCamera/VirtualCameraSession.h b/devices/VirtualCamera/VirtualCameraSession.h
deleted file mode 100644
index 440720e..0000000
--- a/devices/VirtualCamera/VirtualCameraSession.h
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source 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 ANDROID_COMPANION_VIRTUALCAMERA_VIRTUALCAMERASESSION_H
-#define ANDROID_COMPANION_VIRTUALCAMERA_VIRTUALCAMERASESSION_H
-
-#include <memory>
-#include <set>
-
-#include "VirtualCameraRenderThread.h"
-#include "VirtualCameraSessionContext.h"
-#include "aidl/android/companion/virtualcamera/IVirtualCameraCallback.h"
-#include "aidl/android/hardware/camera/device/BnCameraDeviceSession.h"
-#include "aidl/android/hardware/camera/device/ICameraDeviceCallback.h"
-#include "utils/Mutex.h"
-
-namespace android {
-
-template <typename T, typename U>
-struct AidlMessageQueue;
-namespace companion {
-namespace virtualcamera {
-
-// Implementation of ICameraDeviceSession AIDL interface to allow camera
-// framework to read image data from open virtual camera device. This class
-// encapsulates possibly several image streams for the same session.
-class VirtualCameraSession
- : public ::aidl::android::hardware::camera::device::BnCameraDeviceSession {
- public:
- // Construct new virtual camera session.
- // When virtualCameraClientCallback is null, the input surface will be filled
- // with test pattern.
- VirtualCameraSession(
- const std::string& cameraId,
- std::shared_ptr<
- ::aidl::android::hardware::camera::device::ICameraDeviceCallback>
- cameraDeviceCallback,
- std::shared_ptr<
- ::aidl::android::companion::virtualcamera::IVirtualCameraCallback>
- virtualCameraClientCallback = nullptr);
-
- virtual ~VirtualCameraSession() override = default;
-
- ndk::ScopedAStatus close() override;
-
- ndk::ScopedAStatus configureStreams(
- const ::aidl::android::hardware::camera::device::StreamConfiguration&
- in_requestedConfiguration,
- std::vector<::aidl::android::hardware::camera::device::HalStream>*
- _aidl_return) override EXCLUDES(mLock);
-
- ndk::ScopedAStatus constructDefaultRequestSettings(
- ::aidl::android::hardware::camera::device::RequestTemplate in_type,
- ::aidl::android::hardware::camera::device::CameraMetadata* _aidl_return)
- override;
-
- ndk::ScopedAStatus flush() override EXCLUDES(mLock);
-
- ndk::ScopedAStatus getCaptureRequestMetadataQueue(
- ::aidl::android::hardware::common::fmq::MQDescriptor<
- int8_t, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>*
- _aidl_return) override;
-
- ndk::ScopedAStatus getCaptureResultMetadataQueue(
- ::aidl::android::hardware::common::fmq::MQDescriptor<
- int8_t, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>*
- _aidl_return) override;
-
- ndk::ScopedAStatus isReconfigurationRequired(
- const ::aidl::android::hardware::camera::device::CameraMetadata&
- in_oldSessionParams,
- const ::aidl::android::hardware::camera::device::CameraMetadata&
- in_newSessionParams,
- bool* _aidl_return) override;
-
- ndk::ScopedAStatus processCaptureRequest(
- const std::vector<::aidl::android::hardware::camera::device::CaptureRequest>&
- in_requests,
- const std::vector<::aidl::android::hardware::camera::device::BufferCache>&
- in_cachesToRemove,
- int32_t* _aidl_return) override;
-
- ndk::ScopedAStatus signalStreamFlush(const std::vector<int32_t>& in_streamIds,
- int32_t in_streamConfigCounter) override;
-
- ndk::ScopedAStatus switchToOffline(
- const std::vector<int32_t>& in_streamsToKeep,
- ::aidl::android::hardware::camera::device::CameraOfflineSessionInfo*
- out_offlineSessionInfo,
- std::shared_ptr<
- ::aidl::android::hardware::camera::device::ICameraOfflineSession>*
- _aidl_return) override;
-
- ndk::ScopedAStatus repeatingRequestEnd(
- int32_t in_frameNumber, const std::vector<int32_t>& in_streamIds) override;
-
- std::set<int> getStreamIds() const EXCLUDES(mLock);
-
- private:
- ndk::ScopedAStatus processCaptureRequest(
- const ::aidl::android::hardware::camera::device::CaptureRequest& request)
- EXCLUDES(mLock);
-
- const std::string mCameraId;
-
- mutable std::mutex mLock;
-
- std::shared_ptr<::aidl::android::hardware::camera::device::ICameraDeviceCallback>
- mCameraDeviceCallback GUARDED_BY(mLock);
-
- const std::shared_ptr<
- ::aidl::android::companion::virtualcamera::IVirtualCameraCallback>
- mVirtualCameraClientCallback;
-
- VirtualCameraSessionContext mSessionContext;
-
- using RequestMetadataQueue = AidlMessageQueue<
- int8_t, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>;
- std::unique_ptr<RequestMetadataQueue> mRequestMetadataQueue;
-
- using ResultMetadataQueue = AidlMessageQueue<
- int8_t, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>;
- std::shared_ptr<ResultMetadataQueue> mResultMetadataQueue;
-
- std::atomic_bool mFirstRequest{true};
-
- std::unique_ptr<VirtualCameraRenderThread> mRenderThread GUARDED_BY(mLock);
-};
-
-} // namespace virtualcamera
-} // namespace companion
-} // namespace android
-
-#endif // ANDROID_SERVICES_VIRTUAL_CAMERA_VIRTUALCAMERASESSION_H
diff --git a/devices/VirtualCamera/VirtualCameraSessionContext.cc b/devices/VirtualCamera/VirtualCameraSessionContext.cc
deleted file mode 100644
index 284ad05..0000000
--- a/devices/VirtualCamera/VirtualCameraSessionContext.cc
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source 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 "VirtualCameraSessionContext.h"
-
-#include <memory>
-#include <mutex>
-#include <unordered_set>
-
-#include "VirtualCameraStream.h"
-#include "aidl/android/hardware/camera/device/StreamConfiguration.h"
-
-namespace android {
-namespace companion {
-namespace virtualcamera {
-
-using ::aidl::android::hardware::camera::device::BufferCache;
-using ::aidl::android::hardware::camera::device::Stream;
-using ::aidl::android::hardware::camera::device::StreamBuffer;
-using ::aidl::android::hardware::camera::device::StreamConfiguration;
-
-bool VirtualCameraSessionContext::initializeStream(
- const ::aidl::android::hardware::camera::device::Stream& stream) {
- std::lock_guard<std::mutex> lock(mLock);
-
- auto s = std::make_unique<VirtualCameraStream>(stream);
-
- const auto& [_, newlyInserted] = mStreams.emplace(
- std::piecewise_construct, std::forward_as_tuple(stream.id),
- std::forward_as_tuple(std::move(s)));
- return newlyInserted;
-}
-
-void VirtualCameraSessionContext::closeAllStreams() {
- std::lock_guard<std::mutex> lock(mLock);
- mStreams.clear();
-}
-
-bool VirtualCameraSessionContext::importBuffersFromCaptureRequest(
- const ::aidl::android::hardware::camera::device::CaptureRequest&
- captureRequest) {
- std::lock_guard<std::mutex> lock(mLock);
-
- for (const StreamBuffer& buffer : captureRequest.outputBuffers) {
- auto it = mStreams.find(buffer.streamId);
- if (it == mStreams.end()) {
- ALOGE("%s: Cannot import buffer for unknown stream with id %d", __func__,
- buffer.streamId);
- return false;
- }
- VirtualCameraStream& stream = *it->second;
- if (stream.getHardwareBuffer(buffer.bufferId) != nullptr) {
- // This buffer is already imported.
- continue;
- }
-
- if (stream.importBuffer(buffer) == nullptr) {
- ALOGE("%s: Failed to import buffer %" PRId64 " for streamId %d", __func__,
- buffer.bufferId, buffer.streamId);
- return false;
- }
- }
-
- return true;
-}
-
-void VirtualCameraSessionContext::removeBufferCaches(
- const std::vector<BufferCache>& cachesToRemove) {
- std::lock_guard<std::mutex> lock(mLock);
- for (const auto& bufferCache : cachesToRemove) {
- auto it = mStreams.find(bufferCache.streamId);
- if (it == mStreams.end()) {
- ALOGE("%s: Ask to remove buffer %" PRId64 " from unknown stream %d",
- __func__, bufferCache.bufferId, bufferCache.streamId);
- continue;
- }
- if (it->second->removeBuffer(bufferCache.bufferId)) {
- ALOGD("%s: Successfully removed buffer %" PRId64
- " from cache of stream %d",
- __func__, bufferCache.bufferId, bufferCache.streamId);
- } else {
- ALOGE("%s: Failed to remove buffer %" PRId64 " from cache of stream %d",
- __func__, bufferCache.bufferId, bufferCache.streamId);
- }
- }
-}
-
-void VirtualCameraSessionContext::removeStreamsNotInStreamConfiguration(
- const StreamConfiguration& streamConfiguration) {
- std::unordered_set<int> newConfigurationStreamIds;
- for (const Stream& stream : streamConfiguration.streams) {
- newConfigurationStreamIds.insert(stream.id);
- }
-
- std::lock_guard<std::mutex> lock(mLock);
- for (auto it = mStreams.begin(); it != mStreams.end();) {
- if (newConfigurationStreamIds.find(it->first) ==
- newConfigurationStreamIds.end()) {
- ALOGV(
- "Disposing of stream %d, since it is not referenced by new "
- "configuration.",
- it->first);
- it = mStreams.erase(it);
- } else {
- ++it;
- }
- }
-}
-
-std::optional<Stream> VirtualCameraSessionContext::getStreamConfig(
- int streamId) const {
- std::lock_guard<std::mutex> lock(mLock);
- auto it = mStreams.find(streamId);
- if (it == mStreams.end()) {
- ALOGE("%s: StreamBuffer references buffer of unknown streamId %d", __func__,
- streamId);
- return std::optional<Stream>();
- }
- return {it->second->getStreamConfig()};
-}
-
-std::shared_ptr<AHardwareBuffer> VirtualCameraSessionContext::fetchHardwareBuffer(
- const int streamId, const int bufferId) const {
- std::lock_guard<std::mutex> lock(mLock);
- auto it = mStreams.find(streamId);
- if (it == mStreams.end()) {
- ALOGE("%s: StreamBuffer references buffer of unknown streamId %d", __func__,
- streamId);
- return nullptr;
- }
- return it->second->getHardwareBuffer(bufferId);
-}
-
-std::shared_ptr<EglFrameBuffer>
-VirtualCameraSessionContext::fetchOrCreateEglFramebuffer(
- const EGLDisplay eglDisplay, const int streamId, const int bufferId) {
- std::lock_guard<std::mutex> lock(mLock);
- auto it = mStreams.find(streamId);
- if (it == mStreams.end()) {
- ALOGE("%s: StreamBuffer references buffer of unknown streamId %d", __func__,
- streamId);
- return nullptr;
- }
- return it->second->getEglFrameBuffer(eglDisplay, bufferId);
-}
-
-std::set<int> VirtualCameraSessionContext::getStreamIds() const {
- std::set<int> result;
- std::lock_guard<std::mutex> lock(mLock);
- for (const auto& [streamId, _] : mStreams) {
- result.insert(streamId);
- }
- return result;
-}
-
-} // namespace virtualcamera
-} // namespace companion
-} // namespace android
diff --git a/devices/VirtualCamera/VirtualCameraSessionContext.h b/devices/VirtualCamera/VirtualCameraSessionContext.h
deleted file mode 100644
index e5cf5f4..0000000
--- a/devices/VirtualCamera/VirtualCameraSessionContext.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source 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 ANDROID_COMPANION_VIRTUALCAMERA_VIRTUALCAMERASESSIONCONTEXT_H
-#define ANDROID_COMPANION_VIRTUALCAMERA_VIRTUALCAMERASESSIONCONTEXT_H
-
-#include <map>
-#include <memory>
-#include <mutex>
-#include <set>
-
-#include "VirtualCameraStream.h"
-#include "aidl/android/hardware/camera/device/BufferCache.h"
-#include "aidl/android/hardware/camera/device/CaptureRequest.h"
-#include "aidl/android/hardware/camera/device/Stream.h"
-#include "aidl/android/hardware/camera/device/StreamConfiguration.h"
-
-namespace android {
-namespace companion {
-namespace virtualcamera {
-
-// Encapsulates set of streams belonging to the same camera session.
-class VirtualCameraSessionContext {
- public:
- // (Re)initialize the stream.
- //
- // Returns true if the stream is initialized for the first time.
- bool initializeStream(
- const ::aidl::android::hardware::camera::device::Stream& stream)
- EXCLUDES(mLock);
-
- // Close all streams and free all asociated buffers.
- void closeAllStreams() EXCLUDES(mLock);
-
- // Remove no longer needed buffers.
- void removeBufferCaches(
- const std::vector<::aidl::android::hardware::camera::device::BufferCache>&
- cachesToRemove) EXCLUDES(mLock);
-
- // Remove all streams not referenced by provided configuration.
- void removeStreamsNotInStreamConfiguration(
- const ::aidl::android::hardware::camera::device::StreamConfiguration&
- streamConfiguration) EXCLUDES(mLock);
-
- // Importored all not-yet imported buffers referenced by the capture request.
- bool importBuffersFromCaptureRequest(
- const ::aidl::android::hardware::camera::device::CaptureRequest&
- captureRequest) EXCLUDES(mLock);
-
- // Get stream configuration for provided stream id.
- // Returns nullopt in case there's no stream with provided stream id.
- std::optional<::aidl::android::hardware::camera::device::Stream>
- getStreamConfig(int streamId) const EXCLUDES(mLock);
-
- // Get hardware buffer for provided streamId & bufferId.
- // Returns nullptr in case there's no such buffer.
- std::shared_ptr<AHardwareBuffer> fetchHardwareBuffer(int streamId,
- int bufferId) const
- EXCLUDES(mLock);
-
- // Get EGL framebuffer for provided EGL display, streamId & buffer id.
- //
- // This will also lazily create EglFrameBuffer for the provided EGLDisplay
- // connection and will cache it (subsequent calls for same EGLDisplay and
- // buffer will return same instance of EglFrameBuffer).
- //
- // Returns nullptr in case there's no such buffer or it was not possible
- // to create EglFrameBuffer.
- std::shared_ptr<EglFrameBuffer> fetchOrCreateEglFramebuffer(
- const EGLDisplay eglDisplay, int streamId, int bufferId) EXCLUDES(mLock);
-
- // Returns set of all stream ids managed by this instance.
- std::set<int> getStreamIds() const EXCLUDES(mLock);
-
- private:
- mutable std::mutex mLock;
- // streamId -> VirtualCameraStream mapping.
- std::map<int, std::unique_ptr<VirtualCameraStream>> mStreams GUARDED_BY(mLock);
-};
-
-} // namespace virtualcamera
-} // namespace companion
-} // namespace android
-
-#endif // ANDROID_COMPANION_VIRTUALCAMERA_VIRTUALCAMERASESSIONCONTEXT_H
diff --git a/devices/VirtualCamera/VirtualCameraStream.cc b/devices/VirtualCamera/VirtualCameraStream.cc
deleted file mode 100644
index 03da171..0000000
--- a/devices/VirtualCamera/VirtualCameraStream.cc
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source 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 "VirtualCameraStream"
-#include "VirtualCameraStream.h"
-
-#include <cstdint>
-#include <memory>
-#include <mutex>
-#include <tuple>
-#include <utility>
-
-#include "EGL/egl.h"
-#include "aidl/android/hardware/camera/device/Stream.h"
-#include "aidl/android/hardware/camera/device/StreamBuffer.h"
-#include "aidl/android/hardware/graphics/common/PixelFormat.h"
-#include "aidlcommonsupport/NativeHandle.h"
-#include "android/hardware_buffer.h"
-#include "cutils/native_handle.h"
-#include "ui/GraphicBuffer.h"
-#include "ui/GraphicBufferMapper.h"
-
-namespace android {
-namespace companion {
-namespace virtualcamera {
-
-using ::aidl::android::hardware::camera::device::Stream;
-using ::aidl::android::hardware::camera::device::StreamBuffer;
-using ::aidl::android::hardware::common::NativeHandle;
-using ::aidl::android::hardware::graphics::common::PixelFormat;
-
-namespace {
-
-sp<GraphicBuffer> createBlobGraphicBuffer(GraphicBufferMapper& mapper,
- buffer_handle_t bufferHandle) {
- uint64_t allocationSize;
- uint64_t usage;
- uint64_t layerCount;
- if (mapper.getAllocationSize(bufferHandle, &allocationSize) != NO_ERROR ||
- mapper.getUsage(bufferHandle, &usage) != NO_ERROR ||
- mapper.getLayerCount(bufferHandle, &layerCount) != NO_ERROR) {
- ALOGE("Error fetching metadata for the imported BLOB buffer handle.");
- return nullptr;
- }
-
- return sp<GraphicBuffer>::make(
- bufferHandle, GraphicBuffer::HandleWrapMethod::TAKE_HANDLE,
- allocationSize, /*height=*/1, static_cast<int>(ui::PixelFormat::BLOB),
- layerCount, usage, 0);
-}
-
-sp<GraphicBuffer> createYCbCr420GraphicBuffer(GraphicBufferMapper& mapper,
- buffer_handle_t bufferHandle) {
- uint64_t width;
- uint64_t height;
- uint64_t usage;
- uint64_t layerCount;
- if (mapper.getWidth(bufferHandle, &width) != NO_ERROR ||
- mapper.getHeight(bufferHandle, &height) != NO_ERROR ||
- mapper.getUsage(bufferHandle, &usage) != NO_ERROR ||
- mapper.getLayerCount(bufferHandle, &layerCount) != NO_ERROR) {
- ALOGE("Error fetching metadata for the imported YCbCr420 buffer handle.");
- return nullptr;
- }
-
- return sp<GraphicBuffer>::make(
- bufferHandle, GraphicBuffer::HandleWrapMethod::TAKE_HANDLE, width, height,
- static_cast<int>(ui::PixelFormat::YCBCR_420_888), /*layers=*/1, usage,
- width);
-}
-
-std::shared_ptr<AHardwareBuffer> importBufferInternal(
- const NativeHandle& aidlHandle, const Stream& streamConfig) {
- if (aidlHandle.fds.empty()) {
- ALOGE("Empty handle - nothing to import");
- return nullptr;
- }
- std::unique_ptr<native_handle_t, int (*)(native_handle_t*)> nativeHandle(
- ::android::makeFromAidl(aidlHandle), native_handle_delete);
-
- GraphicBufferMapper& mapper = GraphicBufferMapper::get();
-
- buffer_handle_t bufferHandle;
- // Use importBufferNoValidate to rely on ground-truth metadata passed along
- // the buffer.
- int ret = mapper.importBufferNoValidate(nativeHandle.get(), &bufferHandle);
- if (ret != NO_ERROR) {
- ALOGE("Failed to import buffer handle: %d", ret);
- return nullptr;
- }
-
- sp<GraphicBuffer> buf =
- streamConfig.format == PixelFormat::BLOB
- ? createBlobGraphicBuffer(mapper, bufferHandle)
- : createYCbCr420GraphicBuffer(mapper, bufferHandle);
-
- if (buf->initCheck() != NO_ERROR) {
- ALOGE("Imported graphic buffer is not correcly initialized.");
- return nullptr;
- }
-
- AHardwareBuffer* rawPtr = buf->toAHardwareBuffer();
- AHardwareBuffer_acquire(rawPtr);
-
- return std::shared_ptr<AHardwareBuffer>(buf->toAHardwareBuffer(),
- AHardwareBuffer_release);
-}
-
-} // namespace
-
-VirtualCameraStream::VirtualCameraStream(const Stream& stream)
- : mStreamConfig(stream) {
-}
-
-std::shared_ptr<AHardwareBuffer> VirtualCameraStream::importBuffer(
- const ::aidl::android::hardware::camera::device::StreamBuffer& buffer) {
- auto hwBufferPtr = importBufferInternal(buffer.buffer, mStreamConfig);
- if (hwBufferPtr != nullptr) {
- std::lock_guard<std::mutex> lock(mLock);
- mBuffers.emplace(std::piecewise_construct,
- std::forward_as_tuple(buffer.bufferId),
- std::forward_as_tuple(hwBufferPtr));
- }
- return hwBufferPtr;
-}
-
-std::shared_ptr<AHardwareBuffer> VirtualCameraStream::getHardwareBuffer(
- const int bufferId) {
- std::lock_guard<std::mutex> lock(mLock);
- return getHardwareBufferLocked(bufferId);
-}
-
-std::shared_ptr<EglFrameBuffer> VirtualCameraStream::getEglFrameBuffer(
- const EGLDisplay eglDisplay, const int bufferId) {
- const FramebufferMapKey key(bufferId, eglDisplay);
-
- std::lock_guard<std::mutex> lock(mLock);
-
- auto it = mEglFramebuffers.find(key);
- if (it != mEglFramebuffers.end()) {
- return it->second;
- }
-
- std::shared_ptr<AHardwareBuffer> hwBufferPtr =
- getHardwareBufferLocked(bufferId);
- if (hwBufferPtr == nullptr) {
- return nullptr;
- }
- std::shared_ptr<EglFrameBuffer> framebufferPtr =
- std::make_shared<EglFrameBuffer>(eglDisplay, hwBufferPtr);
- mEglFramebuffers.emplace(std::piecewise_construct, std::forward_as_tuple(key),
- std::forward_as_tuple(framebufferPtr));
-
- return framebufferPtr;
-}
-
-std::shared_ptr<AHardwareBuffer> VirtualCameraStream::getHardwareBufferLocked(
- const int bufferId) {
- auto it = mBuffers.find(bufferId);
- return it != mBuffers.end() ? it->second : nullptr;
-}
-
-bool VirtualCameraStream::removeBuffer(int bufferId) {
- std::lock_guard<std::mutex> lock(mLock);
-
- return mBuffers.erase(bufferId) == 1;
-}
-
-Stream VirtualCameraStream::getStreamConfig() const {
- return mStreamConfig;
-}
-
-} // namespace virtualcamera
-} // namespace companion
-} // namespace android
diff --git a/devices/VirtualCamera/VirtualCameraStream.h b/devices/VirtualCamera/VirtualCameraStream.h
deleted file mode 100644
index d76d05c..0000000
--- a/devices/VirtualCamera/VirtualCameraStream.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source 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 ANDROID_COMPANION_VIRTUALCAMERA_VIRTUALCAMERASTREAM_H
-#define ANDROID_COMPANION_VIRTUALCAMERA_VIRTUALCAMERASTREAM_H
-
-#include <cstdint>
-#include <functional>
-#include <memory>
-#include <mutex>
-#include <tuple>
-#include <unordered_map>
-
-#include "EGL/egl.h"
-#include "aidl/android/hardware/camera/device/Stream.h"
-#include "aidl/android/hardware/camera/device/StreamBuffer.h"
-#include "android/hardware_buffer.h"
-#include "util/EglFramebuffer.h"
-#include "utils/Mutex.h"
-
-namespace android {
-namespace companion {
-namespace virtualcamera {
-
-// Encapsulates buffer management for the set of buffers belonging to the single
-// camera stream.
-class VirtualCameraStream {
- public:
- VirtualCameraStream(
- const ::aidl::android::hardware::camera::device::Stream& stream);
-
- std::shared_ptr<AHardwareBuffer> importBuffer(
- const ::aidl::android::hardware::camera::device::StreamBuffer& streamBuffer);
-
- // Get AHardwareBuffer instance corresponding to StreamBuffer from camera AIDL.
- // In case this is the first occurrence of the buffer, this will perform mapping
- // and stores hardware buffer in cache for further use.
- //
- // Returns nullptr in case buffer cannot be mapped or retrieved from the cache.
- std::shared_ptr<AHardwareBuffer> getHardwareBuffer(int bufferId)
- EXCLUDES(mLock);
-
- std::shared_ptr<EglFrameBuffer> getEglFrameBuffer(const EGLDisplay eglDisplay,
- int bufferId)
- EXCLUDES(mLock);
-
- // Un-maps the previously mapped buffer and removes it from the stream cache.
- // Returns true if removal is successful, false otherwise.
- bool removeBuffer(int bufferId) EXCLUDES(mLock);
-
- // Returns AIDL Stream instance containing configuration of this stream.
- ::aidl::android::hardware::camera::device::Stream getStreamConfig() const;
-
- private:
- std::shared_ptr<AHardwareBuffer> getHardwareBufferLocked(int bufferId)
- REQUIRES(mLock);
-
- const ::aidl::android::hardware::camera::device::Stream mStreamConfig;
- std::mutex mLock;
-
- // Cache for already mapped buffers, mapping bufferId -> AHardwareBuffer instance.
- std::unordered_map<int, std::shared_ptr<AHardwareBuffer>> mBuffers
- GUARDED_BY(mLock);
-
- using FramebufferMapKey = std::pair<int, EGLDisplay>;
- struct FramebufferMapKeyHash {
- std::size_t operator()(const FramebufferMapKey& key) const {
- return std::hash<int>{}(key.first) ^
- (std::hash<void*>{}(reinterpret_cast<void*>(key.second)) << 1);
- }
- };
- std::unordered_map<FramebufferMapKey, std::shared_ptr<EglFrameBuffer>,
- FramebufferMapKeyHash>
- mEglFramebuffers GUARDED_BY(mLock);
-};
-
-} // namespace virtualcamera
-} // namespace companion
-} // namespace android
-
-#endif // ANDROID_COMPANION_VIRTUALCAMERA_VIRTUALCAMERASTREAM_H
diff --git a/devices/VirtualCamera/aidl/Android.bp b/devices/VirtualCamera/aidl/Android.bp
deleted file mode 100644
index 9105b09..0000000
--- a/devices/VirtualCamera/aidl/Android.bp
+++ /dev/null
@@ -1,36 +0,0 @@
-package {
- // See: http://go/android-license-faq
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-aidl_interface {
- name: "virtual_camera_service_aidl",
- unstable: true,
- srcs: [
- "android/companion/virtualcamera/Format.aidl",
- "android/companion/virtualcamera/IVirtualCameraCallback.aidl",
- "android/companion/virtualcamera/IVirtualCameraService.aidl",
- "android/companion/virtualcamera/VirtualCameraConfiguration.aidl",
- "android/companion/virtualcamera/SupportedStreamConfiguration.aidl",
- ],
- local_include_dir: ".",
- include_dirs: [
- "frameworks/native/aidl/gui",
- ],
- backend: {
- cpp: {
- enabled: false,
- },
- ndk: {
- enabled: true,
- additional_shared_libraries: [
- "libnativewindow",
- ],
- min_sdk_version: "34",
- },
- java: {
- enabled: true,
- platform_apis: true,
- }
- },
-}
diff --git a/devices/VirtualCamera/aidl/android/companion/virtualcamera/Format.aidl b/devices/VirtualCamera/aidl/android/companion/virtualcamera/Format.aidl
deleted file mode 100644
index d9b90a6..0000000
--- a/devices/VirtualCamera/aidl/android/companion/virtualcamera/Format.aidl
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source 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.
- */
-
-package android.companion.virtualcamera;
-
-/**
- * Pixel format supported by a virtual camera stream.
- *
- * @hide
- */
-@Backing(type="int")
-enum Format {
- UNKNOWN = 0,
- YUV_420_888 = 0x23,
-}
diff --git a/devices/VirtualCamera/aidl/android/companion/virtualcamera/IVirtualCameraCallback.aidl b/devices/VirtualCamera/aidl/android/companion/virtualcamera/IVirtualCameraCallback.aidl
deleted file mode 100644
index cbe03e9..0000000
--- a/devices/VirtualCamera/aidl/android/companion/virtualcamera/IVirtualCameraCallback.aidl
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source 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.
- */
-
-package android.companion.virtualcamera;
-
-import android.companion.virtualcamera.Format;
-import android.view.Surface;
-
-/**
- * AIDL Interface to receive callbacks from virtual camera instance.
- * @hide
- */
-oneway interface IVirtualCameraCallback {
-
- /**
- * Called when there's new video stream. This callback is send after clients opens and
- * configures camera. Implementation should hold onto the surface until corresponding
- * terminateStream call is received.
- *
- * @param streamId - id of the video stream.
- * @param surface - Surface representing the virtual camera sensor.
- * @param width - width of the surface.
- * @param height - height of the surface.
- * @param pixelFormat - pixel format of the surface.
- */
- void onStreamConfigured(int streamId, in Surface surface, int width, int height, in Format pixelFormat);
-
- /**
- * Called when framework requests capture. This can be used by the client as a hint
- * to render another frame into input surface.
- *
- * @param streamId - id of the stream corresponding to the Surface for which next
- * frame is requested.
- * @param frameId - id of the requested frame.
- */
- void onProcessCaptureRequest(int streamId, int frameId);
-
- /**
- * Called when the corresponding stream is no longer in use. Implementation should dispose of
- * corresponding Surface upon receiving this call and no longer interact with it.
- *
- * @param streamId - id of the video stream to terminate.
- */
- void onStreamClosed(int streamId);
-}
diff --git a/devices/VirtualCamera/aidl/android/companion/virtualcamera/IVirtualCameraService.aidl b/devices/VirtualCamera/aidl/android/companion/virtualcamera/IVirtualCameraService.aidl
deleted file mode 100644
index af8324a..0000000
--- a/devices/VirtualCamera/aidl/android/companion/virtualcamera/IVirtualCameraService.aidl
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source 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.
- */
-
-package android.companion.virtualcamera;
-
-import android.companion.virtualcamera.VirtualCameraConfiguration;
-
-/**
- * AIDL Interface to communicate with the VirtualCamera HAL
- * @hide
- */
-interface IVirtualCameraService {
-
- /**
- * Registers a new camera with the virtual camera hal.
- * @return true if the camera was successfully registered
- */
- boolean registerCamera(in IBinder token, in VirtualCameraConfiguration configuration);
-
- /**
- * Unregisters the camera from the virtual camera hal. After this call the virtual camera won't
- * be visible to the camera framework anymore.
- */
- void unregisterCamera(in IBinder token);
-}
diff --git a/devices/VirtualCamera/aidl/android/companion/virtualcamera/SupportedStreamConfiguration.aidl b/devices/VirtualCamera/aidl/android/companion/virtualcamera/SupportedStreamConfiguration.aidl
deleted file mode 100644
index 7070cbd..0000000
--- a/devices/VirtualCamera/aidl/android/companion/virtualcamera/SupportedStreamConfiguration.aidl
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source 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.
- */
-package android.companion.virtualcamera;
-
-import android.companion.virtualcamera.Format;
-
-/**
- * Configuration supported by virtual camera owner.
- *
- * @hide
- */
-parcelable SupportedStreamConfiguration {
- int width;
- int height;
- Format pixelFormat = Format.UNKNOWN;
-}
diff --git a/devices/VirtualCamera/aidl/android/companion/virtualcamera/VirtualCameraConfiguration.aidl b/devices/VirtualCamera/aidl/android/companion/virtualcamera/VirtualCameraConfiguration.aidl
deleted file mode 100644
index c1a2f22..0000000
--- a/devices/VirtualCamera/aidl/android/companion/virtualcamera/VirtualCameraConfiguration.aidl
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source 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.
- */
-package android.companion.virtualcamera;
-
-import android.companion.virtualcamera.IVirtualCameraCallback;
-import android.companion.virtualcamera.SupportedStreamConfiguration;
-
-/**
- * Configuration of virtual camera instance.
- *
- * @hide
- */
-parcelable VirtualCameraConfiguration {
- SupportedStreamConfiguration[] supportedStreamConfigs;
- IVirtualCameraCallback virtualCameraCallback;
-}
diff --git a/devices/VirtualCamera/fuzzer/Android.bp b/devices/VirtualCamera/fuzzer/Android.bp
deleted file mode 100644
index 71e8f50..0000000
--- a/devices/VirtualCamera/fuzzer/Android.bp
+++ /dev/null
@@ -1,46 +0,0 @@
-/******************************************************************************
- *
- * Copyright (C) 2023 The Android Open Source 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.
- *
- *****************************************************************************/
- package {
- // See: http://go/android-license-faq
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-cc_fuzz {
- name: "virtual_camera_fuzzer",
- defaults: [
- "libvirtualcamera_defaults",
- "service_fuzzer_defaults",
- ],
- static_libs: [
- "libvirtualcamera",
- "libvirtualcamera_utils",
- ],
- srcs: [
- "virtual_camera_fuzzer.cc",
- ],
- fuzz_config: {
- cc: [
- "if-xr+fuzzer@google.com",
- ],
- componentid: 1171888,
- hotlists: [
- "5426614",
- ],
- description: "The fuzzers target the APIs of virtual_camera binary",
- },
-}
diff --git a/devices/VirtualCamera/fuzzer/virtual_camera_fuzzer.cc b/devices/VirtualCamera/fuzzer/virtual_camera_fuzzer.cc
deleted file mode 100644
index ebd5e73..0000000
--- a/devices/VirtualCamera/fuzzer/virtual_camera_fuzzer.cc
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source 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 <android-base/logging.h>
-#include <android/binder_interface_utils.h>
-#include <fuzzbinder/libbinder_ndk_driver.h>
-#include <fuzzer/FuzzedDataProvider.h>
-
-#include "VirtualCameraProvider.h"
-#include "VirtualCameraService.h"
-
-using android::fuzzService;
-using ::android::companion::virtualcamera::VirtualCameraProvider;
-using ::android::companion::virtualcamera::VirtualCameraService;
-using ndk::SharedRefBase;
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
- std::shared_ptr<VirtualCameraProvider> defaultProvider =
- SharedRefBase::make<VirtualCameraProvider>();
-
- fuzzService(defaultProvider->asBinder().get(), FuzzedDataProvider(data, size));
-
- const std::string serviceName =
- std::string(VirtualCameraProvider::descriptor) + "/virtual/0";
- auto binder = SharedRefBase::make<VirtualCameraService>(defaultProvider);
-
- fuzzService(binder->asBinder().get(), FuzzedDataProvider(data, size));
- return 0;
-}
diff --git a/devices/VirtualCamera/main.cc b/devices/VirtualCamera/main.cc
deleted file mode 100644
index b7e9c38..0000000
--- a/devices/VirtualCamera/main.cc
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source 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_TAG "VirtualCamera"
-
-#include <android/binder_stability.h>
-
-#include <cstddef>
-
-#include "VirtualCameraProvider.h"
-#include "VirtualCameraService.h"
-#include "android-base/logging.h"
-#include "android/binder_manager.h"
-#include "android/binder_process.h"
-#include "log/log.h"
-
-using ::android::companion::virtualcamera::VirtualCameraProvider;
-using ::android::companion::virtualcamera::VirtualCameraService;
-
-namespace {
-// Default recommended RPC thread count for camera provider implementations
-const int HWBINDER_THREAD_COUNT = 6;
-
-constexpr char kVirtualCameraServiceName[] = "virtual_camera";
-} // namespace
-
-int main() {
- ALOGI("CameraProvider: virtual webcam service is starting.");
-
- ABinderProcess_setThreadPoolMaxThreadCount(HWBINDER_THREAD_COUNT);
-
- std::shared_ptr<VirtualCameraProvider> defaultProvider =
- ndk::SharedRefBase::make<VirtualCameraProvider>();
- const std::string serviceName =
- std::string(VirtualCameraProvider::descriptor) + "/virtual/0";
-
- auto aidlBinder = defaultProvider->asBinder();
- AIBinder_forceDowngradeToLocalStability(aidlBinder.get());
- binder_exception_t ret =
- AServiceManager_addService(aidlBinder.get(), serviceName.c_str());
- LOG_ALWAYS_FATAL_IF(
- ret != EX_NONE,
- "Error while registering virtual camera provider service: %d", ret);
-
- std::shared_ptr<VirtualCameraService> virtualCameraService =
- ndk::SharedRefBase::make<VirtualCameraService>(defaultProvider);
- ret = AServiceManager_addService(virtualCameraService->asBinder().get(),
- kVirtualCameraServiceName);
- LOG_ALWAYS_FATAL_IF(ret != EX_NONE,
- "Error while registering virtual camera service: %d", ret);
-
- ABinderProcess_joinThreadPool();
- return EXIT_FAILURE; // should not reach
-}
diff --git a/devices/VirtualCamera/tests/Android.bp b/devices/VirtualCamera/tests/Android.bp
deleted file mode 100644
index f590454..0000000
--- a/devices/VirtualCamera/tests/Android.bp
+++ /dev/null
@@ -1,26 +0,0 @@
-package {
- // See: http://go/android-license-faq
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-cc_test {
- name: "virtual_camera_tests",
- defaults: [
- "libvirtualcamera_defaults",
- ],
- include_dirs: [
- "hardware/google/camera/devices/VirtualCamera",
- ],
- static_libs: [
- "libvirtualcamera",
- "libvirtualcamera_utils",
- "libgtest",
- "libgmock",
- ],
- srcs: ["EglUtilTest.cc",
- "VirtualCameraProviderTest.cc",
- "VirtualCameraRenderThreadTest.cc",
- "VirtualCameraServiceTest.cc",
- "VirtualCameraSessionTest.cc"],
- test_suites: ["device-tests"],
-}
diff --git a/devices/VirtualCamera/tests/EglUtilTest.cc b/devices/VirtualCamera/tests/EglUtilTest.cc
deleted file mode 100644
index 86fc50c..0000000
--- a/devices/VirtualCamera/tests/EglUtilTest.cc
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source 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 "gtest/gtest.h"
-#include "util/EglDisplayContext.h"
-#include "util/EglProgram.h"
-#include "util/EglUtil.h"
-
-namespace android {
-namespace companion {
-namespace virtualcamera {
-namespace {
-
-constexpr char kGlExtYuvTarget[] = "GL_EXT_YUV_target";
-
-TEST(EglDisplayContextTest, SuccessfulInitialization) {
- EglDisplayContext displayContext;
-
- EXPECT_TRUE(displayContext.isInitialized());
-}
-
-class EglProgramTest : public ::testing::Test {
- public:
- void SetUp() override {
- ASSERT_TRUE(mEglDisplayContext.isInitialized());
- ASSERT_TRUE(mEglDisplayContext.makeCurrent());
- }
-
- private:
- EglDisplayContext mEglDisplayContext;
-};
-
-TEST_F(EglProgramTest, EglTestPatternProgramSuccessfulInit) {
- EglTestPatternProgram eglTestPatternProgram;
-
- // Verify the shaders compiled and linked successfully.
- EXPECT_TRUE(eglTestPatternProgram.isInitialized());
-}
-
-TEST_F(EglProgramTest, EglTextureProgramSuccessfulInit) {
- if (!isGlExtensionSupported(kGlExtYuvTarget)) {
- GTEST_SKIP() << "Skipping test because of missing required GL extension "
- << kGlExtYuvTarget;
- }
-
- EglTextureProgram eglTextureProgram;
-
- // Verify the shaders compiled and linked successfully.
- EXPECT_TRUE(eglTextureProgram.isInitialized());
-}
-
-} // namespace
-} // namespace virtualcamera
-} // namespace companion
-} // namespace android
diff --git a/devices/VirtualCamera/tests/VirtualCameraProviderTest.cc b/devices/VirtualCamera/tests/VirtualCameraProviderTest.cc
deleted file mode 100644
index 03fc2c2..0000000
--- a/devices/VirtualCamera/tests/VirtualCameraProviderTest.cc
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source 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 <memory>
-
-#include "VirtualCameraProvider.h"
-#include "aidl/android/hardware/camera/common/CameraDeviceStatus.h"
-#include "aidl/android/hardware/camera/common/Status.h"
-#include "aidl/android/hardware/camera/common/TorchModeStatus.h"
-#include "aidl/android/hardware/camera/provider/BnCameraProviderCallback.h"
-#include "android/binder_auto_utils.h"
-#include "android/binder_interface_utils.h"
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-#include "util/Util.h"
-
-namespace android {
-namespace companion {
-namespace virtualcamera {
-namespace {
-
-using ::aidl::android::hardware::camera::common::CameraDeviceStatus;
-using ::aidl::android::hardware::camera::common::Status;
-using ::aidl::android::hardware::camera::common::TorchModeStatus;
-using ::aidl::android::hardware::camera::provider::BnCameraProviderCallback;
-using ::testing::_;
-using ::testing::ElementsAre;
-using ::testing::Eq;
-using ::testing::IsEmpty;
-using ::testing::IsNull;
-using ::testing::MatchesRegex;
-using ::testing::Not;
-using ::testing::Return;
-
-constexpr char kVirtualCameraNameRegex[] =
- "device@[0-9]+\\.[0-9]+/virtual/[0-9]+";
-
-class MockCameraProviderCallback : public BnCameraProviderCallback {
- public:
- MOCK_METHOD(ndk::ScopedAStatus, cameraDeviceStatusChange,
- (const std::string&, CameraDeviceStatus), (override));
- MOCK_METHOD(ndk::ScopedAStatus, torchModeStatusChange,
- (const std::string&, TorchModeStatus), (override));
- MOCK_METHOD(ndk::ScopedAStatus, physicalCameraDeviceStatusChange,
- (const std::string&, const std::string&, CameraDeviceStatus),
- (override));
-};
-
-class VirtualCameraProviderTest : public ::testing::Test {
- public:
- void SetUp() override {
- mCameraProvider = ndk::SharedRefBase::make<VirtualCameraProvider>();
- mMockCameraProviderCallback =
- ndk::SharedRefBase::make<MockCameraProviderCallback>();
- ON_CALL(*mMockCameraProviderCallback, cameraDeviceStatusChange)
- .WillByDefault([](const std::string&, CameraDeviceStatus) {
- return ndk::ScopedAStatus::ok();
- });
- }
-
- protected:
- std::shared_ptr<VirtualCameraProvider> mCameraProvider;
- std::shared_ptr<MockCameraProviderCallback> mMockCameraProviderCallback =
- ndk::SharedRefBase::make<MockCameraProviderCallback>();
-};
-
-TEST_F(VirtualCameraProviderTest, SetNullCameraCallbackFails) {
- // Attempting to set callback to nullptr should fail.
- EXPECT_FALSE(mCameraProvider->setCallback(nullptr).isOk());
-}
-
-TEST_F(VirtualCameraProviderTest, NoCamerasInitially) {
- std::vector<std::string> cameras;
-
- // Initially, the camera provider should return empty list
- // of cameras.
- ASSERT_TRUE(mCameraProvider->getCameraIdList(&cameras).isOk());
- EXPECT_THAT(cameras, IsEmpty());
-}
-
-TEST_F(VirtualCameraProviderTest, CreateCamera) {
- // When new camera is created, we expect
- // cameraDeviceStatusChange to be called exactly once with
- // PRESENT status.
- EXPECT_CALL(*mMockCameraProviderCallback,
- cameraDeviceStatusChange(_, CameraDeviceStatus::PRESENT))
- .WillOnce(Return(ndk::ScopedAStatus::ok()));
-
- ASSERT_TRUE(mCameraProvider->setCallback(mMockCameraProviderCallback).isOk());
- std::shared_ptr<VirtualCameraDevice> camera = mCameraProvider->createCamera();
- EXPECT_THAT(camera, Not(IsNull()));
- EXPECT_THAT(camera->getCameraName(), MatchesRegex(kVirtualCameraNameRegex));
-
- // Created camera should be in the list of cameras.
- std::vector<std::string> cameraIds;
- ASSERT_TRUE(mCameraProvider->getCameraIdList(&cameraIds).isOk());
- EXPECT_THAT(cameraIds, ElementsAre(camera->getCameraName()));
-}
-
-TEST_F(VirtualCameraProviderTest, CreateCameraBeforeCallbackIsSet) {
- // We expect cameraDeviceStatusChange to be invoked even when the
- // setCallback configures the callback after camera is already created.
- EXPECT_CALL(*mMockCameraProviderCallback,
- cameraDeviceStatusChange(_, CameraDeviceStatus::PRESENT))
- .WillOnce(Return(ndk::ScopedAStatus::ok()));
-
- std::shared_ptr<VirtualCameraDevice> camera = mCameraProvider->createCamera();
- ASSERT_TRUE(mCameraProvider->setCallback(mMockCameraProviderCallback).isOk());
-
- // Created camera should be in the list of cameras.
- std::vector<std::string> cameraIds;
- EXPECT_TRUE(mCameraProvider->getCameraIdList(&cameraIds).isOk());
- EXPECT_THAT(cameraIds, ElementsAre(camera->getCameraName()));
-}
-
-TEST_F(VirtualCameraProviderTest, RemoveCamera) {
- ASSERT_TRUE(mCameraProvider->setCallback(mMockCameraProviderCallback).isOk());
- std::shared_ptr<VirtualCameraDevice> camera = mCameraProvider->createCamera();
-
- EXPECT_CALL(*mMockCameraProviderCallback,
- cameraDeviceStatusChange(Eq(camera->getCameraName()),
- CameraDeviceStatus::NOT_PRESENT))
- .WillOnce(Return(ndk::ScopedAStatus::ok()));
- EXPECT_TRUE(mCameraProvider->removeCamera(camera->getCameraName()));
-
- // There are no cameras present after only camera is removed.
- std::vector<std::string> cameraIds;
- ASSERT_TRUE(mCameraProvider->getCameraIdList(&cameraIds).isOk());
- EXPECT_THAT(cameraIds, IsEmpty());
-}
-
-TEST_F(VirtualCameraProviderTest, RemoveNonExistingCamera) {
- ASSERT_TRUE(mCameraProvider->setCallback(mMockCameraProviderCallback).isOk());
- std::shared_ptr<VirtualCameraDevice> camera = mCameraProvider->createCamera();
-
- // Removing non-existing camera should fail.
- const std::string cameraName = "DefinitelyNoTCamera";
- EXPECT_FALSE(mCameraProvider->removeCamera(cameraName));
-
- // Camera should be still present in the camera list.
- std::vector<std::string> cameraIds;
- ASSERT_TRUE(mCameraProvider->getCameraIdList(&cameraIds).isOk());
- EXPECT_THAT(cameraIds, ElementsAre(camera->getCameraName()));
-}
-
-} // namespace
-} // namespace virtualcamera
-} // namespace companion
-} // namespace android
diff --git a/devices/VirtualCamera/tests/VirtualCameraRenderThreadTest.cc b/devices/VirtualCamera/tests/VirtualCameraRenderThreadTest.cc
deleted file mode 100644
index 2e40d16..0000000
--- a/devices/VirtualCamera/tests/VirtualCameraRenderThreadTest.cc
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source 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 <sys/cdefs.h>
-
-#include <memory>
-
-#include "VirtualCameraRenderThread.h"
-#include "VirtualCameraSessionContext.h"
-#include "aidl/android/hardware/camera/common/CameraDeviceStatus.h"
-#include "aidl/android/hardware/camera/common/TorchModeStatus.h"
-#include "aidl/android/hardware/camera/device/BnCameraDeviceCallback.h"
-#include "aidl/android/hardware/camera/device/BufferRequest.h"
-#include "aidl/android/hardware/camera/device/BufferRequestStatus.h"
-#include "aidl/android/hardware/camera/device/BufferStatus.h"
-#include "aidl/android/hardware/camera/device/CaptureResult.h"
-#include "aidl/android/hardware/camera/device/NotifyMsg.h"
-#include "aidl/android/hardware/camera/device/StreamBuffer.h"
-#include "aidl/android/hardware/camera/device/StreamBufferRet.h"
-#include "android/binder_auto_utils.h"
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-
-namespace android {
-namespace companion {
-namespace virtualcamera {
-namespace {
-
-using ::aidl::android::hardware::camera::common::CameraDeviceStatus;
-using ::aidl::android::hardware::camera::common::TorchModeStatus;
-using ::aidl::android::hardware::camera::device::BnCameraDeviceCallback;
-using ::aidl::android::hardware::camera::device::BufferRequest;
-using ::aidl::android::hardware::camera::device::BufferRequestStatus;
-using ::aidl::android::hardware::camera::device::BufferStatus;
-using ::aidl::android::hardware::camera::device::CaptureResult;
-using ::aidl::android::hardware::camera::device::ErrorMsg;
-using ::aidl::android::hardware::camera::device::NotifyMsg;
-using ::aidl::android::hardware::camera::device::StreamBuffer;
-using ::aidl::android::hardware::camera::device::StreamBufferRet;
-using ::testing::AllOf;
-using ::testing::ElementsAre;
-using ::testing::Eq;
-using ::testing::Field;
-using ::testing::Matcher;
-using ::testing::Property;
-using ::testing::Return;
-using ::testing::SizeIs;
-
-constexpr int kInputWidth = 640;
-constexpr int kInputHeight = 480;
-
-Matcher<StreamBuffer> IsStreamBufferWithStatus(const int streamId,
- const int bufferId,
- const BufferStatus status) {
- return AllOf(Field(&StreamBuffer::streamId, Eq(streamId)),
- Field(&StreamBuffer::bufferId, Eq(bufferId)),
- Field(&StreamBuffer::status, Eq(status)));
-}
-
-Matcher<NotifyMsg> IsRequestErrorNotifyMsg(const int frameId) {
- return AllOf(Property(&NotifyMsg::getTag, Eq(NotifyMsg::error)),
- Property(&NotifyMsg::get<NotifyMsg::error>,
- Field(&ErrorMsg::frameNumber, Eq(frameId))));
-}
-
-class MockCameraDeviceCallback : public BnCameraDeviceCallback {
- public:
- MOCK_METHOD(ndk::ScopedAStatus, notify, (const std::vector<NotifyMsg>&),
- (override));
- MOCK_METHOD(ndk::ScopedAStatus, processCaptureResult,
- (const std::vector<CaptureResult>&), (override));
- MOCK_METHOD(ndk::ScopedAStatus, requestStreamBuffers,
- (const std::vector<BufferRequest>&, std::vector<StreamBufferRet>*,
- BufferRequestStatus*),
- (override));
- MOCK_METHOD(ndk::ScopedAStatus, returnStreamBuffers,
- (const std::vector<StreamBuffer>&), (override));
-};
-
-class VirtualCameraRenderThreadTest : public ::testing::Test {
- public:
- void SetUp() override {
- mSessionContext = std::make_unique<VirtualCameraSessionContext>();
- mMockCameraDeviceCallback =
- ndk::SharedRefBase::make<MockCameraDeviceCallback>();
- mRenderThread = std::make_unique<VirtualCameraRenderThread>(
- *mSessionContext, kInputWidth, kInputHeight, mMockCameraDeviceCallback);
- }
-
- protected:
- std::unique_ptr<VirtualCameraSessionContext> mSessionContext;
- std::unique_ptr<VirtualCameraRenderThread> mRenderThread;
- std::shared_ptr<MockCameraDeviceCallback> mMockCameraDeviceCallback;
-};
-
-TEST_F(VirtualCameraRenderThreadTest, FlushReturnsErrorForInFlightRequests) {
- const int frameNumber = 42;
- const int firstStreamId = 1;
- const int firstStreamBufferId = 1234;
- const int secondStreamId = 7;
- const int secondStreamBufferId = 4321;
-
- // Notify should be called with the error set to corresponding frame.
- EXPECT_CALL(*mMockCameraDeviceCallback,
- notify(ElementsAre(IsRequestErrorNotifyMsg(frameNumber))))
- .WillOnce(Return(ndk::ScopedAStatus::ok()));
-
- // Process capture result should be called with all buffers in error state.
- EXPECT_CALL(
- *mMockCameraDeviceCallback,
- processCaptureResult(ElementsAre(AllOf(
- Field(&CaptureResult::frameNumber, frameNumber),
- Field(&CaptureResult::outputBuffers,
- testing::UnorderedElementsAre(
- IsStreamBufferWithStatus(firstStreamId, firstStreamBufferId,
- BufferStatus::ERROR),
- IsStreamBufferWithStatus(secondStreamId, secondStreamBufferId,
- BufferStatus::ERROR)))))))
- .WillOnce([]() { return ndk::ScopedAStatus::ok(); });
-
- mRenderThread->enqueueTask(std::make_unique<ProcessCaptureRequestTask>(
- frameNumber,
- std::vector<CaptureRequestBuffer>{
- CaptureRequestBuffer(firstStreamId, firstStreamBufferId),
- CaptureRequestBuffer(secondStreamId, secondStreamBufferId)}));
-
- mRenderThread->flush();
-}
-
-} // namespace
-} // namespace virtualcamera
-} // namespace companion
-} // namespace android
\ No newline at end of file
diff --git a/devices/VirtualCamera/tests/VirtualCameraServiceTest.cc b/devices/VirtualCamera/tests/VirtualCameraServiceTest.cc
deleted file mode 100644
index 4fd0b3b..0000000
--- a/devices/VirtualCamera/tests/VirtualCameraServiceTest.cc
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source 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 <cstdio>
-#include <memory>
-
-#include "VirtualCameraService.h"
-#include "aidl/android/companion/virtualcamera/BnVirtualCameraCallback.h"
-#include "aidl/android/companion/virtualcamera/VirtualCameraConfiguration.h"
-#include "aidl/android/hardware/camera/provider/BnCameraProviderCallback.h"
-#include "aidl/android/hardware/graphics/common/PixelFormat.h"
-#include "android/binder_auto_utils.h"
-#include "android/binder_interface_utils.h"
-#include "android/binder_libbinder.h"
-#include "android/binder_status.h"
-#include "binder/Binder.h"
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-#include "utils/Errors.h"
-
-namespace android {
-namespace companion {
-namespace virtualcamera {
-namespace {
-
-using ::aidl::android::companion::virtualcamera::BnVirtualCameraCallback;
-using ::aidl::android::companion::virtualcamera::VirtualCameraConfiguration;
-using ::aidl::android::hardware::camera::common::CameraDeviceStatus;
-using ::aidl::android::hardware::camera::common::TorchModeStatus;
-using ::aidl::android::hardware::camera::provider::BnCameraProviderCallback;
-using ::aidl::android::hardware::graphics::common::PixelFormat;
-using ::aidl::android::view::Surface;
-using ::testing::_;
-using ::testing::Eq;
-using ::testing::Ge;
-using ::testing::IsEmpty;
-using ::testing::IsNull;
-using ::testing::Not;
-using ::testing::SizeIs;
-
-const VirtualCameraConfiguration kEmptyVirtualCameraConfiguration;
-
-class MockCameraProviderCallback : public BnCameraProviderCallback {
- public:
- MOCK_METHOD(ndk::ScopedAStatus, cameraDeviceStatusChange,
- (const std::string&, CameraDeviceStatus), (override));
- MOCK_METHOD(ndk::ScopedAStatus, torchModeStatusChange,
- (const std::string&, TorchModeStatus), (override));
- MOCK_METHOD(ndk::ScopedAStatus, physicalCameraDeviceStatusChange,
- (const std::string&, const std::string&, CameraDeviceStatus),
- (override));
-};
-
-class VirtualCameraServiceTest : public ::testing::Test {
- public:
- void SetUp() override {
- mCameraProvider = ndk::SharedRefBase::make<VirtualCameraProvider>();
- mMockCameraProviderCallback =
- ndk::SharedRefBase::make<MockCameraProviderCallback>();
- ON_CALL(*mMockCameraProviderCallback, cameraDeviceStatusChange)
- .WillByDefault([](const std::string&, CameraDeviceStatus) {
- return ndk::ScopedAStatus::ok();
- });
- mCameraProvider->setCallback(mMockCameraProviderCallback);
- mCameraService =
- ndk::SharedRefBase::make<VirtualCameraService>(mCameraProvider);
-
- mDevNullFd = open("/dev/null", O_RDWR);
- ASSERT_THAT(mDevNullFd, Ge(0));
- }
-
- void createCamera() {
- mOwnerToken = sp<BBinder>::make();
- mNdkOwnerToken.set(AIBinder_fromPlatformBinder(mOwnerToken));
- bool aidlRet;
-
- ASSERT_TRUE(mCameraService
- ->registerCamera(mNdkOwnerToken,
- kEmptyVirtualCameraConfiguration, &aidlRet)
- .isOk());
- ASSERT_TRUE(aidlRet);
- }
-
- void TearDown() override {
- close(mDevNullFd);
- }
-
- void execute_shell_command(const std::string cmd) {
- std::array<const char*, 1> args{cmd.data()};
- ASSERT_THAT(
- mCameraService->handleShellCommand(mDevNullFd, mDevNullFd, mDevNullFd,
- args.data(), args.size()),
- Eq(NO_ERROR));
- }
-
- protected:
- std::shared_ptr<VirtualCameraService> mCameraService;
- std::shared_ptr<VirtualCameraProvider> mCameraProvider;
- std::shared_ptr<MockCameraProviderCallback> mMockCameraProviderCallback =
- ndk::SharedRefBase::make<MockCameraProviderCallback>();
-
- sp<BBinder> mOwnerToken;
- ndk::SpAIBinder mNdkOwnerToken;
-
- int mDevNullFd;
-};
-
-TEST_F(VirtualCameraServiceTest, RegisterCameraSucceeds) {
- sp<BBinder> token = sp<BBinder>::make();
- ndk::SpAIBinder ndkToken(AIBinder_fromPlatformBinder(token));
- bool aidlRet;
-
- ASSERT_TRUE(
- mCameraService
- ->registerCamera(ndkToken, kEmptyVirtualCameraConfiguration, &aidlRet)
- .isOk());
-
- EXPECT_TRUE(aidlRet);
-}
-
-TEST_F(VirtualCameraServiceTest, RegisterCameraTwiceSecondReturnsFalse) {
- createCamera();
- bool aidlRet;
-
- ASSERT_TRUE(mCameraService
- ->registerCamera(mNdkOwnerToken,
- kEmptyVirtualCameraConfiguration, &aidlRet)
- .isOk());
- EXPECT_FALSE(aidlRet);
-}
-
-TEST_F(VirtualCameraServiceTest, GetCamera) {
- createCamera();
-
- EXPECT_THAT(mCameraService->getCamera(mNdkOwnerToken), Not(IsNull()));
-
- sp<BBinder> otherToken = sp<BBinder>::make();
- EXPECT_THAT(mCameraService->getCamera(
- ndk::SpAIBinder(AIBinder_fromPlatformBinder(otherToken))),
- IsNull());
-}
-
-TEST_F(VirtualCameraServiceTest, UnregisterCamera) {
- createCamera();
-
- EXPECT_THAT(mCameraService->getCamera(mNdkOwnerToken), Not(IsNull()));
-
- mCameraService->unregisterCamera(mNdkOwnerToken);
-
- EXPECT_THAT(mCameraService->getCamera(mNdkOwnerToken), IsNull());
-}
-
-TEST_F(VirtualCameraServiceTest, UnregisterCameraWithUnknownToken) {
- createCamera();
-
- EXPECT_THAT(mCameraService->getCamera(mNdkOwnerToken), Not(IsNull()));
-
- auto otherToken = sp<BBinder>::make();
- ndk::SpAIBinder ndkOtherToken(AIBinder_fromPlatformBinder(otherToken));
- mCameraService->unregisterCamera(ndkOtherToken);
-
- EXPECT_THAT(mCameraService->getCamera(mNdkOwnerToken), Not(IsNull()));
-}
-
-TEST_F(VirtualCameraServiceTest, ShellCmdWithNullArgs) {
- EXPECT_EQ(mCameraService->handleShellCommand(
- /*in=*/mDevNullFd, /*out=*/mDevNullFd, /*err=*/mDevNullFd,
- /*args=*/nullptr, /*numArgs=*/1),
- STATUS_BAD_VALUE);
-
- std::array<const char*, 1> args{nullptr};
- EXPECT_EQ(mCameraService->handleShellCommand(
- /*in=*/mDevNullFd, /*out=*/mDevNullFd, /*err=*/mDevNullFd,
- args.data(), /*numArgs=*/1),
- STATUS_BAD_VALUE);
-}
-
-TEST_F(VirtualCameraServiceTest, TestCameraShellCmd) {
- execute_shell_command("enable_test_camera");
-
- std::vector<std::string> cameraIds;
- EXPECT_TRUE(mCameraProvider->getCameraIdList(&cameraIds).isOk());
- EXPECT_THAT(cameraIds, SizeIs(1));
-
- execute_shell_command("disable_test_camera");
- EXPECT_TRUE(mCameraProvider->getCameraIdList(&cameraIds).isOk());
- EXPECT_THAT(cameraIds, IsEmpty());
-}
-
-} // namespace
-} // namespace virtualcamera
-} // namespace companion
-} // namespace android
diff --git a/devices/VirtualCamera/tests/VirtualCameraSessionTest.cc b/devices/VirtualCamera/tests/VirtualCameraSessionTest.cc
deleted file mode 100644
index 5da080b..0000000
--- a/devices/VirtualCamera/tests/VirtualCameraSessionTest.cc
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source 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 <cstdint>
-#include <memory>
-
-#include "VirtualCameraSession.h"
-#include "aidl/android/companion/virtualcamera/BnVirtualCameraCallback.h"
-#include "aidl/android/companion/virtualcamera/IVirtualCameraCallback.h"
-#include "aidl/android/hardware/camera/device/BnCameraDeviceCallback.h"
-#include "aidl/android/hardware/camera/device/StreamConfiguration.h"
-#include "aidl/android/hardware/graphics/common/PixelFormat.h"
-#include "android/binder_auto_utils.h"
-#include "android/binder_interface_utils.h"
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-#include "util/MetadataBuilder.h"
-
-namespace android {
-namespace companion {
-namespace virtualcamera {
-namespace {
-
-constexpr int kWidth = 640;
-constexpr int kHeight = 480;
-constexpr int kStreamId = 0;
-const std::string kCameraName = "virtual_camera";
-
-using ::aidl::android::companion::virtualcamera::BnVirtualCameraCallback;
-using ::aidl::android::companion::virtualcamera::Format;
-using ::aidl::android::hardware::camera::device::BnCameraDeviceCallback;
-using ::aidl::android::hardware::camera::device::BufferRequest;
-using ::aidl::android::hardware::camera::device::BufferRequestStatus;
-using ::aidl::android::hardware::camera::device::CaptureRequest;
-using ::aidl::android::hardware::camera::device::CaptureResult;
-using ::aidl::android::hardware::camera::device::HalStream;
-using ::aidl::android::hardware::camera::device::NotifyMsg;
-using ::aidl::android::hardware::camera::device::Stream;
-using ::aidl::android::hardware::camera::device::StreamBuffer;
-using ::aidl::android::hardware::camera::device::StreamBufferRet;
-using ::aidl::android::hardware::camera::device::StreamConfiguration;
-using ::aidl::android::hardware::graphics::common::PixelFormat;
-using ::aidl::android::view::Surface;
-using ::testing::_;
-using ::testing::ElementsAre;
-using ::testing::Eq;
-using ::testing::Return;
-using ::testing::SizeIs;
-
-Stream createStream(int streamId, int width, int height, PixelFormat format) {
- Stream s;
- s.id = streamId;
- s.width = width;
- s.height = height;
- s.format = format;
- return s;
-}
-
-class MockCameraDeviceCallback : public BnCameraDeviceCallback {
- public:
- MOCK_METHOD(ndk::ScopedAStatus, notify, (const std::vector<NotifyMsg>&),
- (override));
- MOCK_METHOD(ndk::ScopedAStatus, processCaptureResult,
- (const std::vector<CaptureResult>&), (override));
- MOCK_METHOD(ndk::ScopedAStatus, requestStreamBuffers,
- (const std::vector<BufferRequest>&, std::vector<StreamBufferRet>*,
- BufferRequestStatus*),
- (override));
- MOCK_METHOD(ndk::ScopedAStatus, returnStreamBuffers,
- (const std::vector<StreamBuffer>&), (override));
-};
-
-class MockVirtualCameraCallback : public BnVirtualCameraCallback {
- public:
- MOCK_METHOD(ndk::ScopedAStatus, onStreamConfigured,
- (int, const Surface&, int32_t, int32_t, Format), (override));
- MOCK_METHOD(ndk::ScopedAStatus, onProcessCaptureRequest, (int, int),
- (override));
- MOCK_METHOD(ndk::ScopedAStatus, onStreamClosed, (int), (override));
-};
-
-class VirtualCameraSessionTest : public ::testing::Test {
- public:
- void SetUp() override {
- mMockCameraDeviceCallback =
- ndk::SharedRefBase::make<MockCameraDeviceCallback>();
- mMockVirtualCameraClientCallback =
- ndk::SharedRefBase::make<MockVirtualCameraCallback>();
- mVirtualCameraSession = ndk::SharedRefBase::make<VirtualCameraSession>(
- kCameraName, mMockCameraDeviceCallback,
- mMockVirtualCameraClientCallback);
-
- ON_CALL(*mMockVirtualCameraClientCallback, onStreamConfigured)
- .WillByDefault(ndk::ScopedAStatus::ok);
- ON_CALL(*mMockVirtualCameraClientCallback, onProcessCaptureRequest)
- .WillByDefault(ndk::ScopedAStatus::ok);
- }
-
- protected:
- std::shared_ptr<MockCameraDeviceCallback> mMockCameraDeviceCallback;
- std::shared_ptr<MockVirtualCameraCallback> mMockVirtualCameraClientCallback;
- std::shared_ptr<VirtualCameraSession> mVirtualCameraSession;
-};
-
-TEST_F(VirtualCameraSessionTest, ConfigureTriggersClientConfigureCallback) {
- PixelFormat format = PixelFormat::YCBCR_420_888;
- StreamConfiguration streamConfiguration;
- streamConfiguration.streams = {
- createStream(kStreamId, kWidth, kHeight, format)};
- std::vector<HalStream> halStreams;
- EXPECT_CALL(
- *mMockVirtualCameraClientCallback,
- onStreamConfigured(kStreamId, _, kWidth, kHeight, Format::YUV_420_888));
-
- ASSERT_TRUE(
- mVirtualCameraSession->configureStreams(streamConfiguration, &halStreams)
- .isOk());
-
- EXPECT_THAT(halStreams, SizeIs(streamConfiguration.streams.size()));
- EXPECT_THAT(mVirtualCameraSession->getStreamIds(), ElementsAre(0));
-}
-
-TEST_F(VirtualCameraSessionTest, SecondConfigureDropsUnreferencedStreams) {
- PixelFormat format = PixelFormat::YCBCR_420_888;
- StreamConfiguration streamConfiguration;
- std::vector<HalStream> halStreams;
-
- streamConfiguration.streams = {createStream(0, kWidth, kHeight, format),
- createStream(1, kWidth, kHeight, format),
- createStream(2, kWidth, kHeight, format)};
- ASSERT_TRUE(
- mVirtualCameraSession->configureStreams(streamConfiguration, &halStreams)
- .isOk());
-
- EXPECT_THAT(mVirtualCameraSession->getStreamIds(), ElementsAre(0, 1, 2));
-
- streamConfiguration.streams = {createStream(0, kWidth, kHeight, format),
- createStream(2, kWidth, kHeight, format),
- createStream(3, kWidth, kHeight, format)};
- ASSERT_TRUE(
- mVirtualCameraSession->configureStreams(streamConfiguration, &halStreams)
- .isOk());
-
- EXPECT_THAT(mVirtualCameraSession->getStreamIds(), ElementsAre(0, 2, 3));
-}
-
-TEST_F(VirtualCameraSessionTest, CloseTriggersClientTerminateCallback) {
- EXPECT_CALL(*mMockVirtualCameraClientCallback, onStreamClosed(kStreamId))
- .WillOnce(Return(ndk::ScopedAStatus::ok()));
-
- ASSERT_TRUE(mVirtualCameraSession->close().isOk());
-}
-
-TEST_F(VirtualCameraSessionTest, onProcessCaptureRequestTriggersClientCallback) {
- StreamConfiguration streamConfiguration;
- streamConfiguration.streams = {
- createStream(kStreamId, kWidth, kHeight, PixelFormat::YCBCR_420_888)};
- std::vector<CaptureRequest> requests(1);
- requests[0].frameNumber = 42;
- requests[0].settings = *(
- MetadataBuilder().setControlAfMode(ANDROID_CONTROL_AF_MODE_AUTO).build());
-
- std::vector<HalStream> halStreams;
- ASSERT_TRUE(
- mVirtualCameraSession->configureStreams(streamConfiguration, &halStreams)
- .isOk());
-
- EXPECT_CALL(*mMockVirtualCameraClientCallback,
- onProcessCaptureRequest(kStreamId, requests[0].frameNumber))
- .WillOnce(Return(ndk::ScopedAStatus::ok()));
- int32_t aidlReturn = 0;
- ASSERT_TRUE(mVirtualCameraSession
- ->processCaptureRequest(requests, /*in_cachesToRemove=*/{},
- &aidlReturn)
- .isOk());
- EXPECT_THAT(aidlReturn, Eq(requests.size()));
-}
-
-} // namespace
-} // namespace virtualcamera
-} // namespace companion
-} // namespace android
diff --git a/devices/VirtualCamera/util/EglDisplayContext.cc b/devices/VirtualCamera/util/EglDisplayContext.cc
deleted file mode 100644
index 6d343a2..0000000
--- a/devices/VirtualCamera/util/EglDisplayContext.cc
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source 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 "EglDisplayContext"
-#define EGL_EGLEXT_PROTOTYPES
-#define GL_GLEXT_PROTOTYPES
-
-#include "EglDisplayContext.h"
-
-#include "EGL/egl.h"
-#include "EglDisplayContext.h"
-#include "EglFramebuffer.h"
-#include "log/log.h"
-
-namespace android {
-namespace companion {
-namespace virtualcamera {
-
-EglDisplayContext::EglDisplayContext()
- : mEglDisplay(EGL_NO_DISPLAY),
- mEglContext(EGL_NO_CONTEXT),
- mEglConfig(nullptr) {
- EGLBoolean result;
-
- mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
- if (mEglDisplay == EGL_NO_DISPLAY) {
- ALOGE("eglGetDisplay failed: %#x", eglGetError());
- return;
- }
-
- EGLint majorVersion, minorVersion;
- result = eglInitialize(mEglDisplay, &majorVersion, &minorVersion);
- if (result != EGL_TRUE) {
- ALOGE("eglInitialize failed: %#x", eglGetError());
- return;
- }
- ALOGV("Initialized EGL v%d.%d", majorVersion, minorVersion);
-
- EGLint numConfigs = 0;
- EGLint configAttribs[] = {
- EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, EGL_RENDERABLE_TYPE,
- EGL_OPENGL_ES2_BIT, EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8,
- // no alpha
- EGL_NONE};
-
- result =
- eglChooseConfig(mEglDisplay, configAttribs, &mEglConfig, 1, &numConfigs);
- if (result != EGL_TRUE) {
- ALOGE("eglChooseConfig error: %#x", eglGetError());
- return;
- }
-
- EGLint contextAttribs[] = {EGL_CONTEXT_MAJOR_VERSION_KHR, 3, EGL_NONE};
- mEglContext =
- eglCreateContext(mEglDisplay, mEglConfig, EGL_NO_CONTEXT, contextAttribs);
- if (mEglContext == EGL_NO_CONTEXT) {
- ALOGE("eglCreateContext error: %#x", eglGetError());
- return;
- }
-
- if (!makeCurrent()) {
- ALOGE(
- "Failed to set newly initialized EGLContext and EGLDisplay connection "
- "as current.");
- } else {
- ALOGV("EGL successfully initialized.");
- }
-}
-
-EglDisplayContext::~EglDisplayContext() {
- if (mEglDisplay != EGL_NO_DISPLAY) {
- eglTerminate(mEglDisplay);
- }
- if (mEglContext != EGL_NO_CONTEXT) {
- eglDestroyContext(mEglDisplay, mEglContext);
- }
- eglReleaseThread();
-}
-
-EGLDisplay EglDisplayContext::getEglDisplay() const {
- return mEglDisplay;
-}
-
-bool EglDisplayContext::isInitialized() const {
- return mEglContext != EGL_NO_CONTEXT && mEglDisplay != EGL_NO_DISPLAY;
-}
-
-bool EglDisplayContext::makeCurrent() {
- if (!eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, mEglContext)) {
- ALOGE("eglMakeCurrent failed: %#x", eglGetError());
- return false;
- }
- return true;
-}
-
-} // namespace virtualcamera
-} // namespace companion
-} // namespace android
diff --git a/devices/VirtualCamera/util/EglDisplayContext.h b/devices/VirtualCamera/util/EglDisplayContext.h
deleted file mode 100644
index 402ca3c..0000000
--- a/devices/VirtualCamera/util/EglDisplayContext.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source 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 ANDROID_COMPANION_VIRTUALCAMERA_EGLDISPLAYCONTEXT_H
-#define ANDROID_COMPANION_VIRTUALCAMERA_EGLDISPLAYCONTEXT_H
-
-#include "EGL/egl.h"
-
-namespace android {
-namespace companion {
-namespace virtualcamera {
-
-// Encapsulated EGLDisplay & EGLContext.
-//
-// Upon construction, this object will create and configure new
-// EGLDisplay & EGLContext and will destroy them once it goes
-// out of scope.
-class EglDisplayContext {
- public:
- EglDisplayContext();
- ~EglDisplayContext();
-
- // Sets EGLDisplay & EGLContext for current thread.
- //
- // Returns true on success, false otherwise.
- bool makeCurrent();
-
- EGLDisplay getEglDisplay() const;
-
- // Returns true if this instance encapsulates successfully initialized
- // EGLDisplay & EGLContext.
- bool isInitialized() const;
-
- private:
- EGLDisplay mEglDisplay;
- EGLContext mEglContext;
- EGLConfig mEglConfig;
-};
-
-} // namespace virtualcamera
-} // namespace companion
-} // namespace android
-
-#endif // ANDROID_COMPANION_VIRTUALCAMERA_EGLDISPLAYCONTEXT_H
diff --git a/devices/VirtualCamera/util/EglFramebuffer.cc b/devices/VirtualCamera/util/EglFramebuffer.cc
deleted file mode 100644
index acf0122..0000000
--- a/devices/VirtualCamera/util/EglFramebuffer.cc
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source 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 "EglFramebuffer"
-#include "EglFramebuffer.h"
-
-#include "EGL/eglext.h"
-#include "EglUtil.h"
-#include "GLES/gl.h"
-#include "GLES2/gl2.h"
-#include "GLES2/gl2ext.h"
-#include "android/hardware_buffer.h"
-#include "log/log.h"
-
-namespace android {
-namespace companion {
-namespace virtualcamera {
-
-EglFrameBuffer::EglFrameBuffer(EGLDisplay display,
- std::shared_ptr<AHardwareBuffer> hwBuffer)
- : mHardwareBuffer(hwBuffer), mEglDisplay(display) {
- if (hwBuffer == nullptr) {
- ALOGE("Cannot construct EglFramebuffer from null hwBuffer");
- return;
- }
-
- AHardwareBuffer_Desc hwBufferDesc;
- AHardwareBuffer_describe(hwBuffer.get(), &hwBufferDesc);
- mWidth = hwBufferDesc.width;
- mHeight = hwBufferDesc.height;
-
- EGLClientBuffer clientBuffer = eglGetNativeClientBufferANDROID(hwBuffer.get());
- mEglImageKhr = eglCreateImageKHR(display, EGL_NO_CONTEXT,
- EGL_NATIVE_BUFFER_ANDROID, clientBuffer, 0);
- if (checkEglError("eglCreateImageKHR")) {
- return;
- }
-
- // Create texture backed by the hardware buffer.
- glGenTextures(1, &mTextureId);
- glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTextureId);
- glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES,
- (GLeglImageOES)mEglImageKhr);
- if (checkEglError("configure external texture")) {
- return;
- }
-
- // Create framebuffer backed by the texture.
- glGenFramebuffers(1, &mFramebufferId);
- glBindFramebuffer(GL_FRAMEBUFFER, mFramebufferId);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
- GL_TEXTURE_EXTERNAL_OES, mTextureId, 0);
- GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
- if (status != GL_FRAMEBUFFER_COMPLETE) {
- ALOGE("Failed to configure framebuffer for texture");
- return; // false;
- }
- if (checkEglError("glCheckFramebufferStatus")) {
- return; // false;
- }
-}
-
-EglFrameBuffer::~EglFrameBuffer() {
- if (mFramebufferId != 0) {
- glDeleteFramebuffers(1, &mFramebufferId);
- }
- if (mTextureId != 0) {
- glDeleteTextures(1, &mTextureId);
- }
- if (mEglImageKhr != EGL_NO_IMAGE_KHR) {
- eglDestroyImageKHR(mEglDisplay, mEglDisplay);
- }
-}
-
-bool EglFrameBuffer::beforeDraw() {
- glBindFramebuffer(GL_FRAMEBUFFER, mFramebufferId);
- if (checkEglError("glBindFramebuffer")) {
- return false;
- }
-
- glViewport(0, 0, mWidth, mHeight);
-
- return true;
-}
-
-bool EglFrameBuffer::afterDraw() {
- glFinish();
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
- glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
- return true;
-}
-
-int EglFrameBuffer::getWidth() const {
- return mWidth;
-}
-
-int EglFrameBuffer::getHeight() const {
- return mHeight;
-}
-
-} // namespace virtualcamera
-} // namespace companion
-} // namespace android
diff --git a/devices/VirtualCamera/util/EglFramebuffer.h b/devices/VirtualCamera/util/EglFramebuffer.h
deleted file mode 100644
index 35f85e2..0000000
--- a/devices/VirtualCamera/util/EglFramebuffer.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source 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 ANDROID_COMPANION_VIRTUALCAMERA_EGLFRAMEBUFFER_H
-#define ANDROID_COMPANION_VIRTUALCAMERA_EGLFRAMEBUFFER_H
-
-#define EGL_EGLEXT_PROTOTYPES
-#define GL_GLEXT_PROTOTYPES
-
-#include <memory>
-
-#include "EGL/egl.h"
-#include "EGL/eglext.h"
-#include "GLES/gl.h"
-
-namespace android {
-namespace companion {
-namespace virtualcamera {
-
-// Encapsulates EGL Framebuffer backed by AHardwareBuffer instance.
-//
-// Note that the framebuffer is tied to EGLDisplay connection.
-class EglFrameBuffer {
- public:
- EglFrameBuffer(EGLDisplay display, std::shared_ptr<AHardwareBuffer> hwBuffer);
- virtual ~EglFrameBuffer();
-
- // Prepare for rendering into the framebuffer.
- bool beforeDraw();
-
- // Finishes rendering into the framebuffer.
- bool afterDraw();
-
- // Return width of framebuffer (in pixels).
- int getWidth() const;
-
- // Return height of framebuffer (in pixels).
- int getHeight() const;
-
- private:
- // Keeping shared_ptr to hardware buffer instance here prevents it from being
- // freed while tied to EGL framebufer / EGL texture.
- std::shared_ptr<AHardwareBuffer> mHardwareBuffer;
- EGLDisplay mEglDisplay;
- EGLImageKHR mEglImageKhr{EGL_NO_IMAGE_KHR};
- GLuint mTextureId;
- GLuint mFramebufferId;
-
- int mWidth;
- int mHeight;
-};
-
-} // namespace virtualcamera
-} // namespace companion
-} // namespace android
-
-#endif // ANDROID_COMPANION_VIRTUALCAMERA_EGLFRAMEBUFFER_H
diff --git a/devices/VirtualCamera/util/EglProgram.cc b/devices/VirtualCamera/util/EglProgram.cc
deleted file mode 100644
index c468d39..0000000
--- a/devices/VirtualCamera/util/EglProgram.cc
+++ /dev/null
@@ -1,292 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source 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 "EglProgram"
-#include "EglProgram.h"
-
-#include <array>
-#include <complex>
-
-#include "EglUtil.h"
-#include "GLES/gl.h"
-#include "GLES2/gl2.h"
-#include "GLES2/gl2ext.h"
-#include "log/log.h"
-
-namespace android {
-namespace companion {
-namespace virtualcamera {
-
-namespace {
-
-constexpr char kGlExtYuvTarget[] = "GL_EXT_YUV_target";
-
-constexpr char kIdentityVertexShader[] = R"(
- attribute vec4 vPosition;
- void main() {
- gl_Position = vPosition;
- })";
-
-constexpr char kJuliaFractalFragmentShader[] = R"(
- precision mediump float;
- uniform vec2 uResolution;
- uniform vec2 uC;
- uniform vec2 uUV;
- const float kIter = 64.0;
-
- vec2 imSq(vec2 n){
- return vec2(pow(n.x,2.0)-pow(n.y,2.0), 2.0*n.x*n.y);
- }
-
- float julia(vec2 n, vec2 c) {
- vec2 z = n;
- for (float i=0.0;i<kIter; i+=1.0) {
- z = imSq(z) + c;
- if (length(z) > 2.0) return i/kIter;
- }
- return kIter;
- }
-
- void main() {
- vec2 uv = vec2(gl_FragCoord.x / uResolution.x - 0.5, gl_FragCoord.y / uResolution.y - 0.5);
- float juliaVal = julia(uv * 4.0, uC);
- gl_FragColor = vec4( juliaVal,uUV.x,uUV.y,0.0);
- })";
-
-constexpr char kExternalTextureVertexShader[] = R"(#version 300 es
- in vec4 aPosition;
- in vec2 aTextureCoord;
- out vec2 vTextureCoord;
- void main() {
- gl_Position = aPosition;
- vTextureCoord = aTextureCoord;
- })";
-
-constexpr char kExternalTextureFragmentShader[] = R"(#version 300 es
- #extension GL_OES_EGL_image_external_essl3 : require
- #extension GL_EXT_YUV_target : require
- precision mediump float;
- in vec2 vTextureCoord;
- out vec4 fragColor;
- uniform __samplerExternal2DY2YEXT uTexture;
- void main() {
- fragColor = texture(uTexture, vTextureCoord);
- })";
-
-constexpr int kCoordsPerVertex = 3;
-constexpr std::array<float, 12> kSquareCoords{-1.f, 1.0f, 0.0f, // top left
- -1.f, -1.f, 0.0f, // bottom left
- 1.0f, -1.f, 0.0f, // bottom right
- 1.0f, 1.0f, 0.0f}; // top right
-
-constexpr std::array<float, 8> kTextureCoords{0.0f, 1.0f, // top left
- 0.0f, 0.0f, // bottom left
- 1.0f, 0.0f, // bottom right
- 1.0f, 1.0f}; // top right
-
-constexpr std::array<uint8_t, 6> kDrawOrder{0, 1, 2, 0, 2, 3};
-
-GLuint compileShader(GLenum shaderType, const char* src) {
- GLuint shader = glCreateShader(shaderType);
- if (shader == 0) {
- ALOGE("glCreateShader(shaderType=%x) error: %#x",
- static_cast<unsigned int>(shaderType), glGetError());
- return 0;
- }
-
- glShaderSource(shader, 1, &src, NULL);
- glCompileShader(shader);
-
- GLint compiled = 0;
- glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
- if (!compiled) {
- ALOGE("Compile of shader type %d failed", shaderType);
- GLint infoLen = 0;
- glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
- if (infoLen) {
- char* buf = new char[infoLen];
- if (buf) {
- glGetShaderInfoLog(shader, infoLen, NULL, buf);
- ALOGE("Compile log: %s", buf);
- delete[] buf;
- }
- }
- glDeleteShader(shader);
- return 0;
- }
- return shader;
-}
-
-} // namespace
-
-EglProgram::~EglProgram() {
- if (mProgram) {
- glDeleteProgram(mProgram);
- }
-}
-
-bool EglProgram::initialize(const char* vertexShaderSrc,
- const char* fragmentShaderSrc) {
- GLuint vertexShaderId = compileShader(GL_VERTEX_SHADER, vertexShaderSrc);
- if (checkEglError("compileShader(vertex)")) {
- return false;
- }
- GLuint fragmentShaderId = compileShader(GL_FRAGMENT_SHADER, fragmentShaderSrc);
- if (checkEglError("compileShader(fragment)")) {
- return false;
- }
-
- GLuint programId = glCreateProgram();
-
- glAttachShader(programId, vertexShaderId);
- glAttachShader(programId, fragmentShaderId);
- glLinkProgram(programId);
-
- GLint linkStatus = GL_FALSE;
- glGetProgramiv(programId, GL_LINK_STATUS, &linkStatus);
- if (linkStatus != GL_TRUE) {
- ALOGE("glLinkProgram failed");
- GLint bufLength = 0;
- glGetProgramiv(programId, GL_INFO_LOG_LENGTH, &bufLength);
- if (bufLength) {
- char* buf = new char[bufLength];
- if (buf) {
- glGetProgramInfoLog(programId, bufLength, NULL, buf);
- ALOGE("Link log: %s", buf);
- delete[] buf;
- }
- }
- glDeleteProgram(programId);
- return false;
- }
-
- mProgram = programId;
-
- mIsInitialized = true;
- return mIsInitialized;
-}
-
-bool EglProgram::isInitialized() const {
- return mIsInitialized;
-}
-
-EglTestPatternProgram::EglTestPatternProgram() {
- if (initialize(kIdentityVertexShader, kJuliaFractalFragmentShader)) {
- ALOGV("Successfully initialized EGL shaders for test pattern program.");
- } else {
- ALOGE("Test pattern EGL shader program initialization failed.");
- }
-}
-
-bool EglTestPatternProgram::draw(int width, int height, int frameNumber) {
- glViewport(0, 0, static_cast<GLsizei>(width), static_cast<GLsizei>(height));
- checkEglError("glViewport");
-
- // Load compiled shader.
- glUseProgram(mProgram);
- checkEglError("glUseProgram");
-
- // Compute point in complex plane corresponding to fractal for this frame number.
- float time = float(frameNumber) / 120.0f;
- const std::complex<float> c(std::sin(time) * 0.78f, std::cos(time) * 0.78f);
-
- // Pass uniform values to the shader.
- int resolutionHandle = glGetUniformLocation(mProgram, "uResolution");
- checkEglError("glGetUniformLocation -> uResolution");
- glUniform2f(resolutionHandle, static_cast<float>(width),
- static_cast<float>(height));
- checkEglError("glUniform2f -> uResolution");
-
- // Pass "C" constant value determining the Julia set to the shader.
- int cHandle = glGetUniformLocation(mProgram, "uC");
- glUniform2f(cHandle, c.imag(), c.real());
-
- // Pass chroma value to the shader.
- int uvHandle = glGetUniformLocation(mProgram, "uUV");
- glUniform2f(uvHandle, (c.imag() + 1.f) / 2.f, (c.real() + 1.f) / 2.f);
-
- // Pass vertex array to draw.
- int positionHandle = glGetAttribLocation(mProgram, "vPosition");
- glEnableVertexAttribArray(positionHandle);
-
- // Prepare the triangle coordinate data.
- glVertexAttribPointer(positionHandle, kCoordsPerVertex, GL_FLOAT, false,
- kSquareCoords.size(), kSquareCoords.data());
-
- // Draw triangle strip forming a square filling the viewport.
- glDrawElements(GL_TRIANGLES, kDrawOrder.size(), GL_UNSIGNED_BYTE,
- kDrawOrder.data());
- if (checkEglError("glDrawElements")) {
- return false;
- }
-
- return true;
-}
-
-EglTextureProgram::EglTextureProgram() {
- if (!isGlExtensionSupported(kGlExtYuvTarget)) {
- ALOGE(
- "Cannot initialize external texture program due to missing "
- "GL_EXT_YUV_target extension");
- return;
- }
-
- if (initialize(kExternalTextureVertexShader, kExternalTextureFragmentShader)) {
- ALOGV("Successfully initialized EGL shaders for external texture program.");
- } else {
- ALOGE("External texture EGL shader program initialization failed.");
- }
-}
-
-bool EglTextureProgram::draw(GLuint textureId) {
- // Load compiled shader.
- glUseProgram(mProgram);
- if (checkEglError("glUseProgram")) {
- return false;
- }
-
- // Pass vertex array to the shader.
- int positionHandle = glGetAttribLocation(mProgram, "aPosition");
- glEnableVertexAttribArray(positionHandle);
- glVertexAttribPointer(positionHandle, kCoordsPerVertex, GL_FLOAT, false,
- kSquareCoords.size(), kSquareCoords.data());
-
- // Pass texture coordinates corresponding to vertex array to the shader.
- int textureCoordHandle = glGetAttribLocation(mProgram, "aTextureCoord");
- glEnableVertexAttribArray(textureCoordHandle);
- glVertexAttribPointer(textureCoordHandle, 2, GL_FLOAT, false,
- kTextureCoords.size(), kTextureCoords.data());
-
- // Configure texture for the shader.
- int textureHandle = glGetUniformLocation(mProgram, "uTexture");
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_EXTERNAL_OES, textureId);
- glUniform1i(textureHandle, 0);
-
- // Draw triangle strip forming a square filling the viewport.
- glDrawElements(GL_TRIANGLES, kDrawOrder.size(), GL_UNSIGNED_BYTE,
- kDrawOrder.data());
- if (checkEglError("glDrawElements")) {
- return false;
- }
-
- return true;
-}
-
-} // namespace virtualcamera
-} // namespace companion
-} // namespace android
diff --git a/devices/VirtualCamera/util/EglProgram.h b/devices/VirtualCamera/util/EglProgram.h
deleted file mode 100644
index 8e394e7..0000000
--- a/devices/VirtualCamera/util/EglProgram.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source 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 ANDROID_COMPANION_VIRTUALCAMERA_EGLPROGRAM_H
-#define ANDROID_COMPANION_VIRTUALCAMERA_EGLPROGRAM_H
-
-#include "GLES/gl.h"
-
-namespace android {
-namespace companion {
-namespace virtualcamera {
-
-// Base class for EGL Shader programs representation.
-class EglProgram {
- public:
- virtual ~EglProgram();
-
- // Returns whether the EGL Program was successfully compiled and linked.
- bool isInitialized() const;
-
- protected:
- // Compile & link program from the vertex & fragment shader source.
- bool initialize(const char* vertexShaderSrc, const char* fragmentShaderSrc);
- GLuint mProgram;
- // Whether the EGL Program was successfully compiled and linked.
- bool mIsInitialized = false;
-};
-
-// Shader program to draw Julia Set test pattern.
-class EglTestPatternProgram : public EglProgram {
- public:
- EglTestPatternProgram();
-
- bool draw(int width, int height, int frameNumber);
-};
-
-// Shader program to draw texture.
-//
-// Shader stretches the texture over the viewport (if the texture is not same
-// aspect ratio as viewport, it will be deformed).
-//
-// TODO(b/301023410) Add support for translation / cropping.
-class EglTextureProgram : public EglProgram {
- public:
- EglTextureProgram();
-
- bool draw(GLuint textureId);
-};
-
-} // namespace virtualcamera
-} // namespace companion
-} // namespace android
-
-#endif // ANDROID_COMPANION_VIRTUALCAMERA_EGLPROGRAM_H
diff --git a/devices/VirtualCamera/util/EglSurfaceTexture.cc b/devices/VirtualCamera/util/EglSurfaceTexture.cc
deleted file mode 100644
index ac92bc4..0000000
--- a/devices/VirtualCamera/util/EglSurfaceTexture.cc
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source 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
-#include <memory>
-#define LOG_TAG "EglSurfaceTexture"
-
-#include <cstdint>
-
-#include "EglSurfaceTexture.h"
-#include "EglUtil.h"
-#include "GLES/gl.h"
-#include "gui/BufferQueue.h"
-#include "gui/GLConsumer.h"
-#include "gui/IGraphicBufferProducer.h"
-#include "hardware/gralloc.h"
-
-namespace android {
-namespace companion {
-namespace virtualcamera {
-
-EglSurfaceTexture::EglSurfaceTexture(const uint32_t width, const uint32_t height)
- : mWidth(width), mHeight(height) {
- glGenTextures(1, &mTextureId);
- if (checkEglError("EglSurfaceTexture(): glGenTextures")) {
- ALOGE("Failed to generate texture");
- return;
- }
- BufferQueue::createBufferQueue(&mBufferProducer, &mBufferConsumer);
- mGlConsumer = sp<GLConsumer>::make(
- mBufferConsumer, mTextureId, GLConsumer::TEXTURE_EXTERNAL, false, false);
- mGlConsumer->setName(String8("VirtualCameraEglSurfaceTexture"));
- mGlConsumer->setDefaultBufferSize(mWidth, mHeight);
- mGlConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_TEXTURE);
- mGlConsumer->setDefaultBufferFormat(AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420);
-
- mSurface = sp<Surface>::make(mBufferProducer);
-}
-
-EglSurfaceTexture::~EglSurfaceTexture() {
- if (mTextureId != 0) {
- glDeleteTextures(1, &mTextureId);
- }
-}
-
-sp<Surface> EglSurfaceTexture::getSurface() {
- return mSurface;
-}
-
-sp<GraphicBuffer> EglSurfaceTexture::getCurrentBuffer() {
- return mGlConsumer->getCurrentBuffer();
-}
-
-GLuint EglSurfaceTexture::updateTexture() {
- mGlConsumer->updateTexImage();
- return mTextureId;
-}
-
-uint32_t EglSurfaceTexture::getWidth() const {
- return mWidth;
-}
-
-uint32_t EglSurfaceTexture::getHeight() const {
- return mHeight;
-}
-
-} // namespace virtualcamera
-} // namespace companion
-} // namespace android
diff --git a/devices/VirtualCamera/util/EglSurfaceTexture.h b/devices/VirtualCamera/util/EglSurfaceTexture.h
deleted file mode 100644
index 14dc7d6..0000000
--- a/devices/VirtualCamera/util/EglSurfaceTexture.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source 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 ANDROID_COMPANION_VIRTUALCAMERA_EGLSURFACETEXTURE_H
-#define ANDROID_COMPANION_VIRTUALCAMERA_EGLSURFACETEXTURE_H
-
-#include <cstdint>
-
-#include "GLES/gl.h"
-#include "gui/Surface.h"
-#include "utils/RefBase.h"
-
-namespace android {
-
-class IGraphicBufferProducer;
-class IGraphicBufferConsumer;
-class GLConsumer;
-
-namespace companion {
-namespace virtualcamera {
-
-// Encapsulates GLConsumer & Surface for rendering into EGL texture.
-class EglSurfaceTexture {
- public:
- // Create new EGL Texture with specified size.
- EglSurfaceTexture(uint32_t width, uint32_t height);
- ~EglSurfaceTexture();
-
- // Get Surface backing up the texture.
- sp<Surface> getSurface();
-
- // Get GraphicBuffer backing the current texture.
- sp<GraphicBuffer> getCurrentBuffer();
-
- // Get width of surface / texture.
- uint32_t getWidth() const;
-
- // Get height of surface / texture.
- uint32_t getHeight() const;
-
- // Update the texture with the most recent submitted buffer.
- // Most be called on thread with EGL context.
- //
- // Returns EGL texture id of the texture.
- GLuint updateTexture();
-
- private:
- sp<IGraphicBufferProducer> mBufferProducer;
- sp<IGraphicBufferConsumer> mBufferConsumer;
- sp<GLConsumer> mGlConsumer;
- sp<Surface> mSurface;
- GLuint mTextureId;
- const uint32_t mWidth;
- const uint32_t mHeight;
-};
-
-} // namespace virtualcamera
-} // namespace companion
-} // namespace android
-
-#endif // ANDROID_COMPANION_VIRTUALCAMERA_EGLSURFACETEXTURE_H
diff --git a/devices/VirtualCamera/util/EglUtil.cc b/devices/VirtualCamera/util/EglUtil.cc
deleted file mode 100644
index 481d8f0..0000000
--- a/devices/VirtualCamera/util/EglUtil.cc
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source 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 "EglUtil"
-#include "EglUtil.h"
-
-#include <cstring>
-
-#include "GLES/gl.h"
-#include "log/log.h"
-
-namespace android {
-namespace companion {
-namespace virtualcamera {
-
-bool checkEglError(const char* operation) {
- GLenum err = glGetError();
- if (err == GL_NO_ERROR) {
- return false;
- }
- ALOGE("%s failed: %d", operation, err);
- return true;
-}
-
-bool isGlExtensionSupported(const char* extension) {
- const char* extensions =
- reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS));
- if (extension == nullptr || extensions == nullptr) {
- return false;
- }
- return strstr(extensions, extension) != nullptr;
-}
-
-} // namespace virtualcamera
-} // namespace companion
-} // namespace android
diff --git a/devices/VirtualCamera/util/EglUtil.h b/devices/VirtualCamera/util/EglUtil.h
deleted file mode 100644
index 71640e3..0000000
--- a/devices/VirtualCamera/util/EglUtil.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source 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 ANDROID_COMPANION_VIRTUALCAMERA_EGLUTIL_H
-#define ANDROID_COMPANION_VIRTUALCAMERA_EGLUTIL_H
-
-namespace android {
-namespace companion {
-namespace virtualcamera {
-
-// Returns true if the EGL is in an error state and logs the error.
-bool checkEglError(const char* operation = "EGL operation");
-
-// Returns true if the GL extension is supported, false otherwise.
-bool isGlExtensionSupported(const char* extension);
-
-} // namespace virtualcamera
-} // namespace companion
-} // namespace android
-
-#endif // ANDROID_COMPANION_VIRTUALCAMERA_EGLUTIL_H
diff --git a/devices/VirtualCamera/util/JpegUtil.cc b/devices/VirtualCamera/util/JpegUtil.cc
deleted file mode 100644
index 6f10376..0000000
--- a/devices/VirtualCamera/util/JpegUtil.cc
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source 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 "JpegUtil"
-#include "JpegUtil.h"
-
-#include <cstddef>
-#include <cstdint>
-#include <memory>
-
-#include "android/hardware_buffer.h"
-#include "jpeglib.h"
-#include "log/log.h"
-#include "ui/GraphicBuffer.h"
-#include "ui/GraphicBufferMapper.h"
-#include "utils/Errors.h"
-
-namespace android {
-namespace companion {
-namespace virtualcamera {
-namespace {
-
-constexpr int kJpegQuality = 80;
-
-class LibJpegContext {
- public:
- LibJpegContext(int width, int height, const android_ycbcr& ycbcr,
- const size_t outBufferSize, void* outBuffer)
- : mYCbCr(ycbcr),
- mWidth(width),
- mHeight(height),
- mDstBufferSize(outBufferSize),
- mDstBuffer(outBuffer) {
- // Initialize error handling for libjpeg.
- // We call jpeg_std_error to initialize standard error
- // handling and then override:
- // * output_message not to print to stderr, but use ALOG instead.
- // * error_exit not to terminate the process, but failure flag instead.
- mCompressStruct.err = jpeg_std_error(&mErrorMgr);
- mCompressStruct.err->output_message = onOutputError;
- mCompressStruct.err->error_exit = onErrorExit;
- jpeg_create_compress(&mCompressStruct);
-
- // Configure input image parameters.
- mCompressStruct.image_width = width;
- mCompressStruct.image_height = height;
- mCompressStruct.input_components = 3;
- mCompressStruct.in_color_space = JCS_YCbCr;
- // We pass pointer to this instance as a client data so we can
- // access this object from the static callbacks invoked by
- // libjpeg.
- mCompressStruct.client_data = this;
-
- // Configure destination manager for libjpeg.
- mCompressStruct.dest = &mDestinationMgr;
- mDestinationMgr.init_destination = onInitDestination;
- mDestinationMgr.empty_output_buffer = onEmptyOutputBuffer;
- mDestinationMgr.term_destination = onTermDestination;
- mDestinationMgr.next_output_byte = reinterpret_cast<JOCTET*>(mDstBuffer);
- mDestinationMgr.free_in_buffer = mDstBufferSize;
-
- // Configure everything else based on input configuration above.
- jpeg_set_defaults(&mCompressStruct);
-
- // Set quality and colorspace.
- jpeg_set_quality(&mCompressStruct, kJpegQuality, 1);
- jpeg_set_colorspace(&mCompressStruct, JCS_YCbCr);
-
- // Configure RAW input mode - this let's libjpeg know we're providing raw,
- // subsampled YCbCr data.
- mCompressStruct.raw_data_in = 1;
- mCompressStruct.dct_method = JDCT_IFAST;
-
- // Configure sampling factors - this states that every 2 Y
- // samples share 1 Cb & 1 Cr component vertically & horizontally (YUV420).
- mCompressStruct.comp_info[0].h_samp_factor = 2;
- mCompressStruct.comp_info[0].v_samp_factor = 2;
- mCompressStruct.comp_info[1].h_samp_factor = 1;
- mCompressStruct.comp_info[1].v_samp_factor = 1;
- mCompressStruct.comp_info[2].h_samp_factor = 1;
- mCompressStruct.comp_info[2].v_samp_factor = 1;
- }
-
- bool compress() {
- // Prepare arrays of pointers to scanlines of each plane.
- std::vector<JSAMPROW> yLines(mHeight);
- std::vector<JSAMPROW> cbLines(mHeight / 2);
- std::vector<JSAMPROW> crLines(mHeight / 2);
-
- uint8_t* y = static_cast<uint8_t*>(mYCbCr.y);
- uint8_t* cb = static_cast<uint8_t*>(mYCbCr.cb);
- uint8_t* cr = static_cast<uint8_t*>(mYCbCr.cr);
-
- // Since UV samples might be interleaved (semiplanar) we need to copy
- // them to separate planes, since libjpeg doesn't directly
- // support processing semiplanar YUV.
- const int c_samples = (mWidth / 2) * (mHeight / 2);
- std::vector<uint8_t> cb_plane(c_samples);
- std::vector<uint8_t> cr_plane(c_samples);
-
- // TODO(b/301023410) - Use libyuv or ARM SIMD for "unzipping" the data.
- for (int i = 0; i < c_samples; ++i) {
- cb_plane[i] = *cb;
- cr_plane[i] = *cr;
- cb += mYCbCr.chroma_step;
- cr += mYCbCr.chroma_step;
- }
-
- // Collect pointers to individual scanline of each plane.
- for (int i = 0; i < mHeight; ++i) {
- yLines[i] = y + i * mYCbCr.ystride;
- }
- for (int i = 0; i < (mHeight / 2); ++i) {
- cbLines[i] = cb_plane.data() + i * (mWidth / 2);
- crLines[i] = cr_plane.data() + i * (mWidth / 2);
- }
-
- // Perform actual compression.
- jpeg_start_compress(&mCompressStruct, TRUE);
-
- while (mCompressStruct.next_scanline < mCompressStruct.image_height) {
- const uint32_t batchSize = DCTSIZE * 2;
- const uint32_t nl = mCompressStruct.next_scanline;
- JSAMPARRAY planes[3]{&yLines[nl], &cbLines[nl / 2], &crLines[nl / 2]};
-
- uint32_t done = jpeg_write_raw_data(&mCompressStruct, planes, batchSize);
-
- if (done != batchSize) {
- ALOGE("%s: compressed %u lines, expected %u (total %u/%u)",
- __FUNCTION__, done, batchSize, mCompressStruct.next_scanline,
- mCompressStruct.image_height);
- return false;
- }
- }
- jpeg_finish_compress(&mCompressStruct);
- return mSuccess;
- }
-
- private:
- void setSuccess(const boolean success) {
- mSuccess = success;
- }
-
- void initDestination() {
- mDestinationMgr.next_output_byte = reinterpret_cast<JOCTET*>(mDstBuffer);
- mDestinationMgr.free_in_buffer = mDstBufferSize;
- ALOGV("%s:%d jpeg start: %p [%zu]", __FUNCTION__, __LINE__, mDstBuffer,
- mDstBufferSize);
- }
-
- void termDestination() {
- mEncodedSize = mDstBufferSize - mDestinationMgr.free_in_buffer;
- ALOGV("%s:%d Done with jpeg: %zu", __FUNCTION__, __LINE__, mEncodedSize);
- }
-
- // === libjpeg callbacks below ===
-
- static void onOutputError(j_common_ptr cinfo) {
- char buffer[JMSG_LENGTH_MAX];
- (*cinfo->err->format_message)(cinfo, buffer);
- ALOGE("libjpeg error: %s", buffer);
- };
-
- static void onErrorExit(j_common_ptr cinfo) {
- static_cast<LibJpegContext*>(cinfo->client_data)->setSuccess(false);
- };
-
- static void onInitDestination(j_compress_ptr cinfo) {
- static_cast<LibJpegContext*>(cinfo->client_data)->initDestination();
- }
-
- static int onEmptyOutputBuffer(j_compress_ptr cinfo __unused) {
- ALOGV("%s:%d Out of buffer", __FUNCTION__, __LINE__);
- return 0;
- }
-
- static void onTermDestination(j_compress_ptr cinfo) {
- static_cast<LibJpegContext*>(cinfo->client_data)->termDestination();
- }
-
- jpeg_compress_struct mCompressStruct;
- jpeg_error_mgr mErrorMgr;
- jpeg_destination_mgr mDestinationMgr;
-
- // Layout of the input image.
- android_ycbcr mYCbCr;
-
- // Dimensions of the input image.
- int mWidth;
- int mHeight;
-
- // Destination buffer and it's capacity.
- size_t mDstBufferSize;
- void* mDstBuffer;
-
- // This will be set to size of encoded data
- // written to the outputBuffer when encoding finishes.
- size_t mEncodedSize;
- // Set to true/false based on whether the encoding
- // was successful.
- boolean mSuccess = true;
-};
-
-} // namespace
-
-// Returns true if the EGL is in an error state and logs the error.
-bool compressJpeg(int width, int height, const android_ycbcr& ycbcr,
- size_t outBufferSize, void* outBuffer) {
- return LibJpegContext(width, height, ycbcr, outBufferSize, outBuffer)
- .compress();
-}
-
-} // namespace virtualcamera
-} // namespace companion
-} // namespace android
diff --git a/devices/VirtualCamera/util/JpegUtil.h b/devices/VirtualCamera/util/JpegUtil.h
deleted file mode 100644
index 8bff008..0000000
--- a/devices/VirtualCamera/util/JpegUtil.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source 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 ANDROID_COMPANION_VIRTUALCAMERA_JPEGUTIL_H
-#define ANDROID_COMPANION_VIRTUALCAMERA_JPEGUTIL_H
-
-#include <memory>
-
-#include "android/hardware_buffer.h"
-#include "system/graphics.h"
-
-namespace android {
-namespace companion {
-namespace virtualcamera {
-
-// Jpeg-compress image into the output buffer.
-bool compressJpeg(int width, int height, const android_ycbcr& ycbcr,
- size_t outBufferSize, void* outBuffer);
-
-} // namespace virtualcamera
-} // namespace companion
-} // namespace android
-
-#endif // ANDROID_COMPANION_VIRTUALCAMERA_JPEGUTIL_H
diff --git a/devices/VirtualCamera/util/MetadataBuilder.cc b/devices/VirtualCamera/util/MetadataBuilder.cc
deleted file mode 100644
index fb06e31..0000000
--- a/devices/VirtualCamera/util/MetadataBuilder.cc
+++ /dev/null
@@ -1,325 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source 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 "MetadataBuilder"
-
-#include "MetadataBuilder.h"
-
-#include <algorithm>
-#include <cstdint>
-#include <iterator>
-#include <memory>
-#include <utility>
-#include <variant>
-#include <vector>
-
-#include "CameraMetadata.h"
-#include "aidl/android/hardware/camera/device/CameraMetadata.h"
-#include "log/log.h"
-#include "system/camera_metadata.h"
-#include "utils/Errors.h"
-
-namespace android {
-namespace companion {
-namespace virtualcamera {
-
-namespace {
-
-using ::android::hardware::camera::common::helper::CameraMetadata;
-
-template <typename To, typename From>
-std::vector<To> convertTo(const std::vector<From>& from) {
- std::vector<To> to;
- to.reserve(from.size());
- std::transform(from.begin(), from.end(), std::back_inserter(to),
- [](const From& x) { return static_cast<To>(x); });
- return to;
-}
-
-} // namespace
-
-MetadataBuilder& MetadataBuilder::setSupportedHardwareLevel(
- camera_metadata_enum_android_info_supported_hardware_level_t hwLevel) {
- mEntryMap[ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL] =
- std::vector<uint8_t>({static_cast<uint8_t>(hwLevel)});
- return *this;
-}
-
-MetadataBuilder& MetadataBuilder::setFlashAvailable(bool flashAvailable) {
- const uint8_t metadataVal = flashAvailable
- ? ANDROID_FLASH_INFO_AVAILABLE_TRUE
- : ANDROID_FLASH_INFO_AVAILABLE_FALSE;
- mEntryMap[ANDROID_FLASH_INFO_AVAILABLE] = std::vector<uint8_t>({metadataVal});
- return *this;
-}
-
-MetadataBuilder& MetadataBuilder::setLensFacing(
- camera_metadata_enum_android_lens_facing lensFacing) {
- mEntryMap[ANDROID_LENS_FACING] =
- std::vector<uint8_t>({static_cast<uint8_t>(lensFacing)});
- return *this;
-}
-
-MetadataBuilder& MetadataBuilder::setSensorOrientation(int32_t sensorOrientation) {
- mEntryMap[ANDROID_SENSOR_ORIENTATION] =
- std::vector<int32_t>({sensorOrientation});
- return *this;
-}
-
-MetadataBuilder& MetadataBuilder::setSensorTimestamp(
- std::chrono::nanoseconds timestamp) {
- mEntryMap[ANDROID_SENSOR_TIMESTAMP] =
- std::vector<int64_t>({timestamp.count()});
- return *this;
-}
-
-MetadataBuilder& MetadataBuilder::setAvailableFaceDetectModes(
- const std::vector<camera_metadata_enum_android_statistics_face_detect_mode_t>&
- faceDetectModes) {
- mEntryMap[ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES] =
- convertTo<uint8_t>(faceDetectModes);
- return *this;
-}
-
-MetadataBuilder& MetadataBuilder::setControlAfAvailableModes(
- const std::vector<camera_metadata_enum_android_control_af_mode_t>&
- availableModes) {
- mEntryMap[ANDROID_CONTROL_AF_AVAILABLE_MODES] =
- convertTo<uint8_t>(availableModes);
- return *this;
-}
-
-MetadataBuilder& MetadataBuilder::setControlAfMode(
- const camera_metadata_enum_android_control_af_mode_t mode) {
- mEntryMap[ANDROID_CONTROL_AF_MODE] =
- std::vector<uint8_t>({static_cast<uint8_t>(mode)});
- return *this;
-}
-
-MetadataBuilder& MetadataBuilder::setControlAeAvailableFpsRange(
- const int32_t minFps, const int32_t maxFps) {
- mEntryMap[ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES] =
- std::vector<int32_t>({minFps, maxFps});
- return *this;
-}
-
-MetadataBuilder& MetadataBuilder::setControlMaxRegions(int32_t maxAeRegions,
- int32_t maxAwbRegions,
- int32_t maxAfRegions) {
- mEntryMap[ANDROID_CONTROL_MAX_REGIONS] =
- std::vector<int32_t>({maxAeRegions, maxAwbRegions, maxAfRegions});
- return *this;
-}
-
-MetadataBuilder& MetadataBuilder::setControlAeRegions(
- const std::vector<ControlRegion>& aeRegions) {
- std::vector<int32_t> regions;
- regions.reserve(5 * aeRegions.size());
- for (const ControlRegion& region : aeRegions) {
- regions.push_back(region.x0);
- regions.push_back(region.y0);
- regions.push_back(region.x1);
- regions.push_back(region.y1);
- regions.push_back(region.weight);
- }
- mEntryMap[ANDROID_CONTROL_AE_REGIONS] = std::move(regions);
- return *this;
-}
-
-MetadataBuilder& MetadataBuilder::setControlAfRegions(
- const std::vector<ControlRegion>& afRegions) {
- std::vector<int32_t> regions;
- regions.reserve(5 * afRegions.size());
- for (const ControlRegion& region : afRegions) {
- regions.push_back(region.x0);
- regions.push_back(region.y0);
- regions.push_back(region.x1);
- regions.push_back(region.y1);
- regions.push_back(region.weight);
- }
- mEntryMap[ANDROID_CONTROL_AF_REGIONS] = std::move(regions);
- return *this;
-}
-
-MetadataBuilder& MetadataBuilder::setControlAwbRegions(
- const std::vector<ControlRegion>& awbRegions) {
- std::vector<int32_t> regions;
- regions.reserve(5 * awbRegions.size());
- for (const ControlRegion& region : awbRegions) {
- regions.push_back(region.x0);
- regions.push_back(region.y0);
- regions.push_back(region.x1);
- regions.push_back(region.y1);
- regions.push_back(region.weight);
- }
- mEntryMap[ANDROID_CONTROL_AWB_REGIONS] = std::move(regions);
- return *this;
-}
-
-MetadataBuilder& MetadataBuilder::setControlCaptureIntent(
- const camera_metadata_enum_android_control_capture_intent_t intent) {
- mEntryMap[ANDROID_CONTROL_CAPTURE_INTENT] =
- std::vector<uint8_t>({static_cast<uint8_t>(intent)});
- return *this;
-}
-
-MetadataBuilder& MetadataBuilder::setMaxJpegSize(const int32_t size) {
- mEntryMap[ANDROID_JPEG_MAX_SIZE] = std::vector<int32_t>({size});
- return *this;
-}
-
-MetadataBuilder& MetadataBuilder::setAvailableOutputStreamConfigurations(
- const std::vector<StreamConfiguration>& streamConfigurations) {
- std::vector<int32_t> metadataStreamConfigs;
- std::vector<int64_t> metadataMinFrameDurations;
- std::vector<int64_t> metadataStallDurations;
- metadataStreamConfigs.reserve(streamConfigurations.size());
- metadataMinFrameDurations.reserve(streamConfigurations.size());
- metadataStallDurations.reserve(streamConfigurations.size());
-
- for (const auto& config : streamConfigurations) {
- metadataStreamConfigs.push_back(config.format);
- metadataStreamConfigs.push_back(config.width);
- metadataStreamConfigs.push_back(config.height);
- metadataStreamConfigs.push_back(
- ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT);
-
- metadataMinFrameDurations.push_back(config.format);
- metadataMinFrameDurations.push_back(config.width);
- metadataMinFrameDurations.push_back(config.height);
- metadataMinFrameDurations.push_back(config.minFrameDuration.count());
-
- metadataStallDurations.push_back(config.format);
- metadataStallDurations.push_back(config.width);
- metadataStallDurations.push_back(config.height);
- metadataStallDurations.push_back(config.minStallDuration.count());
- }
-
- mEntryMap[ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS] =
- metadataStreamConfigs;
- mEntryMap[ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS] =
- metadataMinFrameDurations;
- mEntryMap[ANDROID_SCALER_AVAILABLE_STALL_DURATIONS] =
- metadataMinFrameDurations;
-
- return *this;
-}
-
-MetadataBuilder& MetadataBuilder::setAvailableMaxDigitalZoom(const float maxZoom) {
- mEntryMap[ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM] =
- std::vector<float>(maxZoom);
- return *this;
-}
-
-MetadataBuilder& MetadataBuilder::setSensorActiveArraySize(int x0, int y0,
- int x1, int y1) {
- mEntryMap[ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE] =
- std::vector<int32_t>({x0, y0, x1, y1});
- return *this;
-}
-
-MetadataBuilder& MetadataBuilder::setControlAeCompensationRange(int32_t min,
- int32_t max) {
- mEntryMap[ANDROID_CONTROL_AE_COMPENSATION_RANGE] =
- std::vector<int32_t>({min, max});
- return *this;
-}
-
-MetadataBuilder& MetadataBuilder::setControlAeCompensationStep(
- const camera_metadata_rational step) {
- mEntryMap[ANDROID_CONTROL_AE_COMPENSATION_STEP] =
- std::vector<camera_metadata_rational>({step});
- return *this;
-}
-
-MetadataBuilder& MetadataBuilder::setAvailableRequestKeys(
- const std::vector<int32_t>& keys) {
- mEntryMap[ANDROID_REQUEST_AVAILABLE_REQUEST_KEYS] = keys;
- return *this;
-}
-
-MetadataBuilder& MetadataBuilder::setAvailableResultKeys(
- const std::vector<int32_t>& keys) {
- mEntryMap[ANDROID_REQUEST_AVAILABLE_RESULT_KEYS] = keys;
- return *this;
-}
-
-MetadataBuilder& MetadataBuilder::setAvailableCapabilities(
- const std::vector<camera_metadata_enum_android_request_available_capabilities_t>&
- capabilities) {
- mEntryMap[ANDROID_REQUEST_AVAILABLE_CAPABILITIES] =
- convertTo<uint8_t>(capabilities);
- return *this;
-}
-
-MetadataBuilder& MetadataBuilder::setAvailableCharacteristicKeys(
- const std::vector<camera_metadata_tag_t>& keys) {
- mEntryMap[ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS] =
- convertTo<int32_t>(keys);
- return *this;
-}
-
-MetadataBuilder& MetadataBuilder::setAvailableCharacteristicKeys() {
- std::vector<camera_metadata_tag_t> availableKeys;
- availableKeys.reserve(mEntryMap.size());
- for (const auto& [key, _] : mEntryMap) {
- if (key != ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS) {
- availableKeys.push_back(key);
- }
- }
- setAvailableCharacteristicKeys(availableKeys);
- return *this;
-}
-
-std::unique_ptr<aidl::android::hardware::camera::device::CameraMetadata>
-MetadataBuilder::build() const {
- CameraMetadata metadataHelper;
- for (const auto& entry : mEntryMap) {
- status_t ret = std::visit(
- [&](auto&& arg) {
- return metadataHelper.update(entry.first, arg.data(), arg.size());
- },
- entry.second);
- if (ret != NO_ERROR) {
- ALOGE("Failed to update metadata with key %d - %s: %s", entry.first,
- get_camera_metadata_tag_name(entry.first),
- ::android::statusToString(ret).c_str());
- return nullptr;
- }
- }
-
- const camera_metadata_t* metadata = metadataHelper.getAndLock();
- if (metadata == nullptr) {
- ALOGE(
- "Failure when constructing metadata -> CameraMetadata helper returned "
- "nullptr");
- return nullptr;
- }
-
- auto aidlMetadata =
- std::make_unique<aidl::android::hardware::camera::device::CameraMetadata>();
- const uint8_t* data_ptr = reinterpret_cast<const uint8_t*>(metadata);
- aidlMetadata->metadata.assign(data_ptr,
- data_ptr + get_camera_metadata_size(metadata));
- metadataHelper.unlock(metadata);
-
- return aidlMetadata;
-}
-
-} // namespace virtualcamera
-} // namespace companion
-} // namespace android
diff --git a/devices/VirtualCamera/util/MetadataBuilder.h b/devices/VirtualCamera/util/MetadataBuilder.h
deleted file mode 100644
index 25c931c..0000000
--- a/devices/VirtualCamera/util/MetadataBuilder.h
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source 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 ANDROID_COMPANION_VIRTUALCAMERA_METADATABUILDER_H
-#define ANDROID_COMPANION_VIRTUALCAMERA_METADATABUILDER_H
-
-#include <chrono>
-#include <cstdint>
-#include <map>
-#include <memory>
-#include <variant>
-#include <vector>
-
-#include "aidl/android/hardware/camera/device/CameraMetadata.h"
-#include "system/camera_metadata.h"
-
-namespace android {
-namespace companion {
-namespace virtualcamera {
-
-// Convenience builder for the
-// aidl::android::hardware::camera::device::CameraMetadata.
-//
-// Calling the same builder setter multiple will overwrite the value.
-// This class is not thread-safe.
-class MetadataBuilder {
- public:
- struct StreamConfiguration {
- int32_t width = 0;
- int32_t height = 0;
- int32_t format = 0;
- // Minimal frame duration - corresponds to maximal FPS for given format.
- // See ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS in CameraMetadataTag.aidl.
- std::chrono::nanoseconds minFrameDuration{std::chrono::seconds(1) / 30};
- // Minimal stall duration.
- // See ANDROID_SCALER_AVAILABLE_STALL_DURATIONS in CameraMetadataTag.aidl.
- std::chrono::nanoseconds minStallDuration{0};
- };
-
- struct ControlRegion {
- int32_t x0 = 0;
- int32_t y0 = 0;
- int32_t x1 = 0;
- int32_t y1 = 0;
- int32_t weight = 0;
- };
-
- MetadataBuilder() = default;
- ~MetadataBuilder() = default;
-
- // See ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL in CameraMetadataTag.aidl.
- MetadataBuilder& setSupportedHardwareLevel(
- camera_metadata_enum_android_info_supported_hardware_level_t hwLevel);
-
- // Whether this camera device has a flash unit
- // See ANDROID_FLASH_INFO_AVAILABLE in CameraMetadataTag.aidl.
- MetadataBuilder& setFlashAvailable(bool flashAvailable);
-
- // See ANDROID_LENS_FACING in CameraMetadataTag.aidl.
- MetadataBuilder& setLensFacing(
- camera_metadata_enum_android_lens_facing lensFacing);
-
- // See ANDROID_SENSOR_ORIENTATION in CameraMetadataTag.aidl.
- MetadataBuilder& setSensorOrientation(int32_t sensorOrientation);
-
- // Time at start of exposure of first row of the image
- // sensor active array, in nanoseconds.
- //
- // See ANDROID_SENSOR_TIMESTAMP in CameraMetadataTag.aidl.
- MetadataBuilder& setSensorTimestamp(std::chrono::nanoseconds timestamp);
-
- // See ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE in CameraMetadataTag.aidl.
- MetadataBuilder& setSensorActiveArraySize(int x0, int y0, int x1, int y1);
-
- // See ANDROID_STATISTICS_FACE_DETECT_MODE in CameraMetadataTag.aidl.
- MetadataBuilder& setAvailableFaceDetectModes(
- const std::vector<camera_metadata_enum_android_statistics_face_detect_mode_t>&
- faceDetectMode);
-
- // Sets available stream configurations along with corresponding minimal frame
- // durations (corresponding to max fps) and stall durations.
- //
- // See ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
- // ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS and
- // ANDROID_SCALER_AVAILABLE_STALL_DURATIONS in CameraMetadataTag.aidl.
- MetadataBuilder& setAvailableOutputStreamConfigurations(
- const std::vector<StreamConfiguration>& streamConfigurations);
-
- // See ANDROID_CONTROL_AE_COMPENSATION_RANGE in CameraMetadataTag.aidl.
- MetadataBuilder& setControlAeCompensationRange(int32_t min, int32_t max);
-
- // See ANDROID_CONTROL_AE_COMPENSATION_STEP in CameraMetadataTag.aidl.
- MetadataBuilder& setControlAeCompensationStep(camera_metadata_rational step);
-
- // See ANDROID_CONTROL_AF_AVAILABLE_MODES in CameraMetadataTag.aidl.
- MetadataBuilder& setControlAfAvailableModes(
- const std::vector<camera_metadata_enum_android_control_af_mode_t>&
- availableModes);
-
- // See ANDROID_CONTROL_AF_MODE in CameraMetadataTag.aidl.
- MetadataBuilder& setControlAfMode(
- const camera_metadata_enum_android_control_af_mode_t mode);
-
- // See ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES in CameraMetadataTag.aidl.
- MetadataBuilder& setControlAeAvailableFpsRange(int32_t min, int32_t max);
-
- // See ANDROID_CONTROL_CAPTURE_INTENT in CameraMetadataTag.aidl.
- MetadataBuilder& setControlCaptureIntent(
- camera_metadata_enum_android_control_capture_intent_t intent);
-
- // See ANDROID_CONTROL_MAX_REGIONS in CameraMetadataTag.aidl.
- MetadataBuilder& setControlMaxRegions(int32_t maxAeRegions,
- int32_t maxAwbRegions,
- int32_t maxAfRegions);
-
- // See ANDROID_CONTROL_AE_REGIONS in CameraMetadataTag.aidl.
- MetadataBuilder& setControlAeRegions(
- const std::vector<ControlRegion>& aeRegions);
-
- // See ANDROID_CONTROL_AWB_REGIONS in CameraMetadataTag.aidl.
- MetadataBuilder& setControlAwbRegions(
- const std::vector<ControlRegion>& awbRegions);
-
- // See ANDROID_CONTROL_AF_REGIONS in CameraMetadataTag.aidl.
- MetadataBuilder& setControlAfRegions(
- const std::vector<ControlRegion>& afRegions);
-
- // The size of the compressed JPEG image, in bytes.
- //
- // See ANDROID_JPEG_SIZE in CameraMetadataTag.aidl.
- MetadataBuilder& setMaxJpegSize(int32_t size);
-
- // See ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM in CameraMetadataTag.aidl.
- MetadataBuilder& setAvailableMaxDigitalZoom(const float maxZoom);
-
- // A list of all keys that the camera device has available to use with
- // CaptureRequest.
- //
- // See ANDROID_REQUEST_AVAILABLE_REQUEST_KEYS in CameraMetadataTag.aidl.
- MetadataBuilder& setAvailableRequestKeys(const std::vector<int32_t>& keys);
-
- // A list of all keys that the camera device has available to use with
- // CaptureResult.
- //
- // See ANDROID_RESULT_AVAILABLE_REQUEST_KEYS in CameraMetadataTag.aidl.
- MetadataBuilder& setAvailableResultKeys(const std::vector<int32_t>& keys);
-
- // See ANDROID_REQUEST_AVAILABLE_CAPABILITIES in CameraMetadataTag.aidl.
- MetadataBuilder& setAvailableCapabilities(
- const std::vector<
- camera_metadata_enum_android_request_available_capabilities_t>&
- capabilities);
-
- // A list of all keys that the camera device has available to use.
- //
- // See ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS in CameraMetadataTag.aidl.
- MetadataBuilder& setAvailableCharacteristicKeys(
- const std::vector<camera_metadata_tag_t>& keys);
-
- // Extends metadata with ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS
- // containing all previously set tags.
- MetadataBuilder& setAvailableCharacteristicKeys();
-
- // Build CameraMetadata instance.
- //
- // Returns nullptr in case something went wrong.
- std::unique_ptr<::aidl::android::hardware::camera::device::CameraMetadata>
- build() const;
-
- private:
- // Maps metadata tags to vectors of values for the given tag.
- std::map<camera_metadata_tag_t,
- std::variant<std::vector<int64_t>, std::vector<int32_t>,
- std::vector<uint8_t>, std::vector<float>,
- std::vector<camera_metadata_rational_t>>>
- mEntryMap;
-};
-
-} // namespace virtualcamera
-} // namespace companion
-} // namespace android
-
-#endif // ANDROID_COMPANION_VIRTUALCAMERA_METADATABUILDER_H
diff --git a/devices/VirtualCamera/util/TestPatternHelper.cc b/devices/VirtualCamera/util/TestPatternHelper.cc
deleted file mode 100644
index a00a1b8..0000000
--- a/devices/VirtualCamera/util/TestPatternHelper.cc
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source 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 "TestPatternHelper"
-
-#include "TestPatternHelper.h"
-
-#include <complex>
-#include <cstdint>
-
-#include "log/log.h"
-#include "utils/Errors.h"
-
-namespace android {
-namespace companion {
-namespace virtualcamera {
-
-namespace {
-
-uint8_t julia(const std::complex<float> n, const std::complex<float> c) {
- std::complex<float> z = n;
- for (int i = 0; i < 64; i++) {
- z = z * z + c;
- if (std::abs(z) > 2.0) return i * 4;
- }
- return 0xff;
-}
-
-uint8_t pixelToFractal(const int x, const int y, const std::complex<float> c) {
- std::complex<float> n(float(x) / 640.0f - 0.5, float(y) / 480.0f - 0.5);
- return julia(n * 5.f, c);
-}
-
-void renderTestPatternYcbCr420(uint8_t* data_ptr, const int width,
- const int height, const int frameNumber) {
- float time = float(frameNumber) / 120.0f;
- const std::complex<float> c(std::sin(time), std::cos(time));
-
- uint8_t* y_data = data_ptr;
- uint8_t* uv_data = static_cast<uint8_t*>(y_data + width * height);
-
- for (int i = 0; i < width; ++i) {
- for (int j = 0; j < height; ++j) {
- y_data[j * width + i] = pixelToFractal(i, j, c * 0.78f);
- if ((i & 1) && (j & 1)) {
- uv_data[((j / 2) * (width / 2) + i / 2) * 2] =
- static_cast<uint8_t>((float(i) / float(width)) * 255.f);
- uv_data[((j / 2) * (width / 2) + i / 2) * 2 + 1] =
- static_cast<uint8_t>((float(j) / float(height)) * 255.f);
- }
- }
- }
-}
-
-} // namespace
-
-// This is just to see some meaningfull image in the buffer for testing, only
-// works with YcbCr420.
-void renderTestPatternYCbCr420(const std::shared_ptr<AHardwareBuffer> buffer,
- const int frameNumber, const int fence) {
- AHardwareBuffer_Planes planes_info;
-
- AHardwareBuffer_Desc hwBufferDesc;
- AHardwareBuffer_describe(buffer.get(), &hwBufferDesc);
-
- const int width = hwBufferDesc.width;
- const int height = hwBufferDesc.height;
-
- int result = AHardwareBuffer_lockPlanes(buffer.get(),
- AHARDWAREBUFFER_USAGE_CPU_READ_RARELY,
- fence, nullptr, &planes_info);
- if (result != OK) {
- ALOGE("%s: Failed to lock planes: %d", __func__, result);
- return;
- }
-
- renderTestPatternYcbCr420(
- reinterpret_cast<uint8_t*>(planes_info.planes[0].data), width, height,
- frameNumber);
-
- AHardwareBuffer_unlock(buffer.get(), nullptr);
-}
-
-void renderTestPatternYCbCr420(sp<Surface> surface, int frameNumber) {
- ANativeWindow_Buffer buffer;
- surface->lock(&buffer, nullptr);
-
- ALOGV("buffer: %dx%d stride %d, pixfmt %d", buffer.width, buffer.height,
- buffer.stride, buffer.format);
-
- renderTestPatternYcbCr420(reinterpret_cast<uint8_t*>(buffer.bits),
- buffer.width, buffer.height, frameNumber);
-
- surface->unlockAndPost();
-}
-
-} // namespace virtualcamera
-} // namespace companion
-} // namespace android
diff --git a/devices/VirtualCamera/util/TestPatternHelper.h b/devices/VirtualCamera/util/TestPatternHelper.h
deleted file mode 100644
index aca1cdd..0000000
--- a/devices/VirtualCamera/util/TestPatternHelper.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source 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 ANDROID_COMPANION_VIRTUALCAMERA_TESTPATTERNHELPER_H
-#define ANDROID_COMPANION_VIRTUALCAMERA_TESTPATTERNHELPER_H
-
-#include <memory>
-
-#include "android/hardware_buffer.h"
-#include "gui/Surface.h"
-
-namespace android {
-namespace companion {
-namespace virtualcamera {
-
-// Helper function filling hardware buffer with test pattern for debugging /
-// testing purposes.
-void renderTestPatternYCbCr420(std::shared_ptr<AHardwareBuffer> buffer,
- int frameNumber, int fence = -1);
-
-// Helper function for rendering test pattern into Surface.
-void renderTestPatternYCbCr420(sp<Surface> surface, int frameNumber);
-
-} // namespace virtualcamera
-} // namespace companion
-} // namespace android
-
-#endif // ANDROID_COMPANION_VIRTUALCAMERA_TESTPATTERNHELPER_H
diff --git a/devices/VirtualCamera/util/Util.cc b/devices/VirtualCamera/util/Util.cc
deleted file mode 100644
index 90f5916..0000000
--- a/devices/VirtualCamera/util/Util.cc
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source 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 "VirtualCameraUtil"
-#include "Util.h"
-
-#include <unistd.h>
-
-#include "log/log.h"
-
-namespace android {
-namespace companion {
-namespace virtualcamera {
-
-using ::aidl::android::hardware::common::NativeHandle;
-
-sp<Fence> importFence(const NativeHandle& aidlHandle) {
- if (aidlHandle.fds.size() != 1) {
- ALOGE(
- "%s: Cannot import fence from aidlHandle containing %d file "
- "descriptors.",
- __func__, static_cast<int>(aidlHandle.fds.size()));
- return sp<Fence>::make();
- }
-
- return sp<Fence>::make(::dup(aidlHandle.fds[0].get()));
-}
-
-} // namespace virtualcamera
-} // namespace companion
-} // namespace android
diff --git a/devices/VirtualCamera/util/Util.h b/devices/VirtualCamera/util/Util.h
deleted file mode 100644
index 1a0a458..0000000
--- a/devices/VirtualCamera/util/Util.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source 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 ANDROID_COMPANION_VIRTUALCAMERA_UTIL_H
-#define ANDROID_COMPANION_VIRTUALCAMERA_UTIL_H
-
-#include <cstdint>
-
-#include "aidl/android/hardware/camera/common/Status.h"
-#include "aidl/android/hardware/camera/device/StreamBuffer.h"
-#include "android/binder_auto_utils.h"
-#include "ui/Fence.h"
-
-namespace android {
-namespace companion {
-namespace virtualcamera {
-
-// Converts camera AIDL status to ndk::ScopedAStatus
-inline ndk::ScopedAStatus cameraStatus(
- const ::aidl::android::hardware::camera::common::Status status) {
- return ndk::ScopedAStatus::fromServiceSpecificError(
- static_cast<int32_t>(status));
-}
-
-// Import Fence from AIDL NativeHandle.
-//
-// If the handle can't be used to construct Fence (is empty or doesn't contain
-// only single fd) this function will return Fence instance in invalid state.
-sp<Fence> importFence(
- const ::aidl::android::hardware::common::NativeHandle& handle);
-
-} // namespace virtualcamera
-} // namespace companion
-} // namespace android
-
-#endif // ANDROID_COMPANION_VIRTUALCAMERA_UTIL_H
diff --git a/devices/VirtualCamera/virtual_camera.hal.rc b/devices/VirtualCamera/virtual_camera.hal.rc
deleted file mode 100644
index fd86965..0000000
--- a/devices/VirtualCamera/virtual_camera.hal.rc
+++ /dev/null
@@ -1,7 +0,0 @@
-service virtual_camera /system/bin/virtual_camera
- class core
- user system
- group system
- capabilities SYS_NICE
- rlimit rtprio 10 10
- task_profiles CameraServiceCapacity CameraServicePerformance