blob: 7eac3f2f90334edb510d2785b976472618c16288 [file] [log] [blame]
/*
* Copyright (C) 2022 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 "GCH_AidlCameraProvider"
//#define LOG_NDEBUG 0
#include "aidl_camera_provider.h"
#include <log/log.h>
#include <regex>
#include "aidl_camera_device.h"
#include "aidl_utils.h"
#include "camera_device.h"
namespace android {
namespace hardware {
namespace camera {
namespace provider {
namespace implementation {
namespace aidl_utils = ::android::hardware::camera::implementation::aidl_utils;
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::common::VendorTagSection;
using ::android::google_camera_hal::CameraDevice;
const std::string AidlCameraProvider::kProviderName = "internal";
// "device@<version>/internal/<id>"
const std::regex AidlCameraProvider::kDeviceNameRegex(
"device@([0-9]+\\.[0-9]+)/internal/(.+)");
std::shared_ptr<AidlCameraProvider> AidlCameraProvider::Create() {
std::shared_ptr<AidlCameraProvider> provider =
ndk::SharedRefBase::make<AidlCameraProvider>();
status_t res = provider->Initialize();
if (res != OK) {
ALOGE("%s: Initializing AidlCameraProvider failed: %s(%d)", __FUNCTION__,
strerror(-res), res);
return nullptr;
}
return provider;
}
status_t AidlCameraProvider::Initialize() {
google_camera_provider_ = CameraProvider::Create();
if (google_camera_provider_ == nullptr) {
ALOGE("%s: Creating CameraProvider failed.", __FUNCTION__);
return NO_INIT;
}
camera_provider_callback_ = {
.camera_device_status_change = google_camera_hal::CameraDeviceStatusChangeFunc(
[this](std::string camera_id,
google_camera_hal::CameraDeviceStatus new_status) {
if (callbacks_ == nullptr) {
ALOGE("%s: callbacks_ is null", __FUNCTION__);
return;
}
CameraDeviceStatus aidl_camera_device_status;
status_t res = aidl_utils::ConvertToAidlCameraDeviceStatus(
new_status, &aidl_camera_device_status);
if (res != OK) {
ALOGE(
"%s: Converting to aidl camera device status failed: %s(%d)",
__FUNCTION__, strerror(-res), res);
return;
}
std::unique_lock<std::mutex> lock(callbacks_lock_);
auto aidl_res = callbacks_->cameraDeviceStatusChange(
"device@" +
device::implementation::AidlCameraDevice::kDeviceVersion +
"/" + kProviderName + "/" + camera_id,
aidl_camera_device_status);
if (!aidl_res.isOk()) {
ALOGE("%s: device status change transaction error: %s",
__FUNCTION__, aidl_res.getMessage());
return;
}
}),
.physical_camera_device_status_change =
google_camera_hal::PhysicalCameraDeviceStatusChangeFunc(
[this](std::string camera_id, std::string physical_camera_id,
google_camera_hal::CameraDeviceStatus new_status) {
if (callbacks_ == nullptr) {
ALOGE("%s: callbacks_ is null", __FUNCTION__);
return;
}
/*auto castResult =
provider::V2_6::ICameraProviderCallback::castFrom(callbacks_);
if (!castResult.isOk()) {
ALOGE("%s: callbacks_ cannot be casted to version 2.6",
__FUNCTION__);
return;
}
sp<provider::V2_6::ICameraProviderCallback> callbacks_2_6_ =
castResult;
if (callbacks_2_6_ == nullptr) {
ALOGE("%s: callbacks_2_6_ is null", __FUNCTION__);
return;
}*/
CameraDeviceStatus aidl_camera_device_status;
status_t res = aidl_utils::ConvertToAidlCameraDeviceStatus(
new_status, &aidl_camera_device_status);
if (res != OK) {
ALOGE(
"%s: Converting to aidl camera device status failed: "
"%s(%d)",
__FUNCTION__, strerror(-res), res);
return;
}
std::unique_lock<std::mutex> lock(callbacks_lock_);
auto aidl_res = callbacks_->physicalCameraDeviceStatusChange(
"device@" +
device::implementation::AidlCameraDevice::kDeviceVersion +
"/" + kProviderName + "/" + camera_id,
physical_camera_id, aidl_camera_device_status);
if (!aidl_res.isOk()) {
ALOGE(
"%s: physical camera status change transaction error: %s",
__FUNCTION__, aidl_res.getMessage());
return;
}
}),
.torch_mode_status_change = google_camera_hal::TorchModeStatusChangeFunc(
[this](std::string camera_id,
google_camera_hal::TorchModeStatus new_status) {
if (callbacks_ == nullptr) {
ALOGE("%s: callbacks_ is null", __FUNCTION__);
return;
}
TorchModeStatus aidl_torch_status;
status_t res = aidl_utils::ConvertToAidlTorchModeStatus(
new_status, &aidl_torch_status);
if (res != OK) {
ALOGE("%s: Converting to aidl torch status failed: %s(%d)",
__FUNCTION__, strerror(-res), res);
return;
}
std::unique_lock<std::mutex> lock(callbacks_lock_);
auto aidl_res = callbacks_->torchModeStatusChange(
"device@" +
device::implementation::AidlCameraDevice::kDeviceVersion +
"/" + kProviderName + "/" + camera_id,
aidl_torch_status);
if (!aidl_res.isOk()) {
ALOGE("%s: torch status change transaction error: %s",
__FUNCTION__, aidl_res.getMessage());
return;
}
}),
};
google_camera_provider_->SetCallback(&camera_provider_callback_);
// purge pending malloc pages after initialization
mallopt(M_PURGE, 0);
return OK;
}
ScopedAStatus AidlCameraProvider::setCallback(
const std::shared_ptr<ICameraProviderCallback>& callback) {
if (callback == nullptr) {
ALOGE("AidlCameraProvider::setCallback() called with nullptr");
return ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(Status::ILLEGAL_ARGUMENT));
}
bool first_time = false;
{
std::unique_lock<std::mutex> lock(callbacks_lock_);
first_time = callbacks_ == nullptr;
callbacks_ = callback;
}
google_camera_provider_->TriggerDeferredCallbacks();
#ifdef __ANDROID_APEX__
if (first_time) {
std::string ready_property_name = "vendor.camera.hal.ready.count";
int ready_count = property_get_int32(ready_property_name.c_str(), 0);
property_set(ready_property_name.c_str(),
std::to_string(++ready_count).c_str());
ALOGI("AidlCameraProvider::setCallback() first time ready count: %d ",
ready_count);
}
#endif
return ScopedAStatus::ok();
}
ScopedAStatus AidlCameraProvider::getVendorTags(
std::vector<VendorTagSection>* vts) {
if (vts == nullptr) {
return ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(Status::ILLEGAL_ARGUMENT));
}
vts->clear();
std::vector<google_camera_hal::VendorTagSection> hal_vendor_tag_sections;
status_t res =
google_camera_provider_->GetVendorTags(&hal_vendor_tag_sections);
if (res != OK) {
ALOGE("%s: Getting vendor tags failed: %s(%d)", __FUNCTION__,
strerror(-res), res);
return ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(Status::INTERNAL_ERROR));
}
res = aidl_utils::ConvertToAidlVendorTagSections(hal_vendor_tag_sections, vts);
if (res != OK) {
ALOGE("%s: Converting to aidl vendor tags failed: %s(%d)", __FUNCTION__,
strerror(-res), res);
return ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(Status::INTERNAL_ERROR));
}
return ScopedAStatus::ok();
}
ScopedAStatus AidlCameraProvider::getCameraIdList(
std::vector<std::string>* camera_ids_ret) {
if (camera_ids_ret == nullptr) {
return ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(Status::ILLEGAL_ARGUMENT));
}
camera_ids_ret->clear();
std::vector<uint32_t> camera_ids;
status_t res = google_camera_provider_->GetCameraIdList(&camera_ids);
if (res != OK) {
ALOGE("%s: Getting camera ID list failed: %s(%d)", __FUNCTION__,
strerror(-res), res);
return ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(Status::INTERNAL_ERROR));
}
camera_ids_ret->resize(camera_ids.size());
for (uint32_t i = 0; i < camera_ids_ret->size(); i++) {
// camera ID is in the form of "device@<major>.<minor>/<type>/<id>"
(*camera_ids_ret)[i] =
"device@" + device::implementation::AidlCameraDevice::kDeviceVersion +
"/" + kProviderName + "/" + std::to_string(camera_ids[i]);
}
return ScopedAStatus::ok();
}
ScopedAStatus AidlCameraProvider::getConcurrentCameraIds(
std::vector<ConcurrentCameraIdCombination>* aidl_camera_id_combinations) {
if (aidl_camera_id_combinations == nullptr) {
return ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(Status::ILLEGAL_ARGUMENT));
}
aidl_camera_id_combinations->clear();
std::vector<std::unordered_set<uint32_t>> camera_id_combinations;
status_t res = google_camera_provider_->GetConcurrentStreamingCameraIds(
&camera_id_combinations);
if (res != OK) {
ALOGE(
"%s: Getting the combinations of concurrent streaming camera ids "
"failed: %s(%d)",
__FUNCTION__, strerror(-res), res);
return ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(Status::INTERNAL_ERROR));
}
aidl_camera_id_combinations->resize(camera_id_combinations.size());
int i = 0;
for (auto& combination : camera_id_combinations) {
std::vector<std::string> aidl_combination(combination.size());
int c = 0;
for (auto& camera_id : combination) {
aidl_combination[c] = std::to_string(camera_id);
c++;
}
(*aidl_camera_id_combinations)[i].combination = aidl_combination;
i++;
}
return ScopedAStatus::ok();
}
ScopedAStatus AidlCameraProvider::isConcurrentStreamCombinationSupported(
const std::vector<CameraIdAndStreamCombination>& configs, bool* supported) {
*supported = false;
std::vector<google_camera_hal::CameraIdAndStreamConfiguration>
devices_stream_configs(configs.size());
status_t res = OK;
size_t c = 0;
for (auto& config : configs) {
res = aidl_utils::ConvertToHalStreamConfig(
config.streamConfiguration,
&devices_stream_configs[c].stream_configuration);
if (res != OK) {
ALOGE("%s: ConverToHalStreamConfig failed", __FUNCTION__);
return ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(Status::INTERNAL_ERROR));
}
uint32_t camera_id = atoi(config.cameraId.c_str());
devices_stream_configs[c].camera_id = camera_id;
c++;
}
res = google_camera_provider_->IsConcurrentStreamCombinationSupported(
devices_stream_configs, supported);
if (res != OK) {
ALOGE("%s: ConverToHalStreamConfig failed", __FUNCTION__);
return ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(Status::INTERNAL_ERROR));
}
return ScopedAStatus::ok();
}
bool AidlCameraProvider::ParseDeviceName(const std::string& device_name,
std::string* device_version,
std::string* camera_id) {
std::string device_name_std(device_name.c_str());
std::smatch sm;
if (std::regex_match(device_name_std, sm,
AidlCameraProvider::kDeviceNameRegex)) {
if (device_version != nullptr) {
*device_version = sm[1];
}
if (camera_id != nullptr) {
*camera_id = sm[2];
}
return true;
}
return false;
}
ScopedAStatus AidlCameraProvider::getCameraDeviceInterface(
const std::string& camera_device_name,
std::shared_ptr<ICameraDevice>* device) {
std::unique_ptr<CameraDevice> google_camera_device;
if (device == nullptr) {
ALOGE("%s: device is nullptr. ", __FUNCTION__);
return ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(Status::ILLEGAL_ARGUMENT));
}
// Parse camera_device_name.
std::string camera_id, device_version;
bool match = ParseDeviceName(camera_device_name, &device_version, &camera_id);
if (!match) {
ALOGE("%s: Device name parse fail. ", __FUNCTION__);
return ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(Status::ILLEGAL_ARGUMENT));
}
status_t res = google_camera_provider_->CreateCameraDevice(
atoi(camera_id.c_str()), &google_camera_device);
if (res != OK) {
ALOGE("%s: Creating CameraDevice failed: %s(%d)", __FUNCTION__,
strerror(-res), res);
return aidl_utils::ConvertToAidlReturn(res);
}
*device = device::implementation::AidlCameraDevice::Create(
std::move(google_camera_device));
if (*device == nullptr) {
ALOGE("%s: Creating AidlCameraDevice failed", __FUNCTION__);
return ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(Status::INTERNAL_ERROR));
}
return ScopedAStatus::ok();
}
ScopedAStatus AidlCameraProvider::notifyDeviceStateChange(int64_t new_state) {
google_camera_hal::DeviceState device_state =
google_camera_hal::DeviceState::kNormal;
::android::hardware::camera::implementation::aidl_utils::ConvertToHalDeviceState(
new_state, device_state);
google_camera_provider_->NotifyDeviceStateChange(device_state);
return ScopedAStatus::ok();
}
} // namespace implementation
} // namespace provider
} // namespace camera
} // namespace hardware
} // namespace android