blob: 1c572e30a9cb1cc3dcadfe3843557a363e4e0d3f [file] [log] [blame]
/*
* Copyright (C) 2019 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_HidlCameraProvider"
//#define LOG_NDEBUG 0
#include <log/log.h>
#include <regex>
#include "camera_device.h"
#include "hidl_camera_device.h"
#include "hidl_camera_provider.h"
#include "hidl_utils.h"
namespace android {
namespace hardware {
namespace camera {
namespace provider {
namespace V2_7 {
namespace implementation {
namespace hidl_utils = ::android::hardware::camera::implementation::hidl_utils;
using ::android::google_camera_hal::CameraDevice;
using ::android::hardware::Void;
using ::android::hardware::camera::common::V1_0::CameraDeviceStatus;
using ::android::hardware::camera::common::V1_0::TorchModeStatus;
using ::android::hardware::camera::common::V1_0::VendorTagSection;
const std::string HidlCameraProvider::kProviderName = "internal";
// "device@<version>/internal/<id>"
const std::regex HidlCameraProvider::kDeviceNameRegex(
"device@([0-9]+\\.[0-9]+)/internal/(.+)");
android::sp<HidlCameraProvider> HidlCameraProvider::Create() {
android::sp<HidlCameraProvider> provider = new HidlCameraProvider();
status_t res = provider->Initialize();
if (res != OK) {
ALOGE("%s: Initializing HidlCameraProvider failed: %s(%d)", __FUNCTION__,
strerror(-res), res);
return nullptr;
}
return provider;
}
status_t HidlCameraProvider::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 hidl_camera_device_status;
status_t res = hidl_utils::ConvertToHidlCameraDeviceStatus(
new_status, &hidl_camera_device_status);
if (res != OK) {
ALOGE(
"%s: Converting to hidl camera device status failed: %s(%d)",
__FUNCTION__, strerror(-res), res);
return;
}
std::unique_lock<std::mutex> lock(callbacks_lock_);
callbacks_->cameraDeviceStatusChange(
"device@" +
device::V3_7::implementation::HidlCameraDevice::kDeviceVersion +
"/" + kProviderName + "/" + camera_id,
hidl_camera_device_status);
}),
.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 hidl_camera_device_status;
status_t res = hidl_utils::ConvertToHidlCameraDeviceStatus(
new_status, &hidl_camera_device_status);
if (res != OK) {
ALOGE(
"%s: Converting to hidl camera device status failed: %s(%d)",
__FUNCTION__, strerror(-res), res);
return;
}
std::unique_lock<std::mutex> lock(callbacks_lock_);
callbacks_2_6_->physicalCameraDeviceStatusChange(
"device@" +
device::V3_7::implementation::HidlCameraDevice::kDeviceVersion +
"/" + kProviderName + "/" + camera_id,
physical_camera_id, hidl_camera_device_status);
}),
.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 hidl_torch_status;
status_t res = hidl_utils::ConvertToHidlTorchModeStatus(
new_status, &hidl_torch_status);
if (res != OK) {
ALOGE("%s: Converting to hidl torch status failed: %s(%d)",
__FUNCTION__, strerror(-res), res);
return;
}
std::unique_lock<std::mutex> lock(callbacks_lock_);
callbacks_->torchModeStatusChange(
"device@" +
device::V3_7::implementation::HidlCameraDevice::kDeviceVersion +
"/" + kProviderName + "/" + camera_id,
hidl_torch_status);
}),
};
google_camera_provider_->SetCallback(&camera_provider_callback_);
// purge pending malloc pages after initialization
mallopt(M_PURGE, 0);
return OK;
}
Return<Status> HidlCameraProvider::setCallback(
const sp<ICameraProviderCallback>& callback) {
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("HidlCameraProvider::setCallback() first time ready count: %d ",
ready_count);
}
#endif
return Status::OK;
}
Return<void> HidlCameraProvider::getVendorTags(getVendorTags_cb _hidl_cb) {
hidl_vec<VendorTagSection> hidl_vendor_tag_sections;
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);
_hidl_cb(Status::INTERNAL_ERROR, hidl_vendor_tag_sections);
return Void();
}
res = hidl_utils::ConvertToHidlVendorTagSections(hal_vendor_tag_sections,
&hidl_vendor_tag_sections);
if (res != OK) {
ALOGE("%s: Converting to hidl vendor tags failed: %s(%d)", __FUNCTION__,
strerror(-res), res);
_hidl_cb(Status::INTERNAL_ERROR, hidl_vendor_tag_sections);
return Void();
}
_hidl_cb(Status::OK, hidl_vendor_tag_sections);
return Void();
}
Return<void> HidlCameraProvider::getCameraIdList(getCameraIdList_cb _hidl_cb) {
std::vector<uint32_t> camera_ids;
hidl_vec<hidl_string> hidl_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);
_hidl_cb(Status::INTERNAL_ERROR, hidl_camera_ids);
return Void();
}
hidl_camera_ids.resize(camera_ids.size());
for (uint32_t i = 0; i < hidl_camera_ids.size(); i++) {
// camera ID is in the form of "device@<major>.<minor>/<type>/<id>"
hidl_camera_ids[i] =
"device@" +
device::V3_7::implementation::HidlCameraDevice::kDeviceVersion + "/" +
kProviderName + "/" + std::to_string(camera_ids[i]);
}
_hidl_cb(Status::OK, hidl_camera_ids);
return Void();
}
Return<void> HidlCameraProvider::getConcurrentStreamingCameraIds(
getConcurrentStreamingCameraIds_cb _hidl_cb) {
hidl_vec<hidl_vec<hidl_string>> hidl_camera_id_combinations;
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);
_hidl_cb(Status::INTERNAL_ERROR, hidl_camera_id_combinations);
return Void();
}
hidl_camera_id_combinations.resize(camera_id_combinations.size());
int i = 0;
for (auto& combination : camera_id_combinations) {
hidl_vec<hidl_string> hidl_combination(combination.size());
int c = 0;
for (auto& camera_id : combination) {
hidl_combination[c] = std::to_string(camera_id);
c++;
}
hidl_camera_id_combinations[i] = hidl_combination;
i++;
}
_hidl_cb(Status::OK, hidl_camera_id_combinations);
return Void();
}
Return<void> HidlCameraProvider::isConcurrentStreamCombinationSupported(
const hidl_vec<provider::V2_6::CameraIdAndStreamCombination>& configs,
isConcurrentStreamCombinationSupported_cb _hidl_cb) {
hidl_vec<CameraIdAndStreamCombination> configs2_7;
configs2_7.resize(configs.size());
for (size_t i = 0; i < configs.size(); i++) {
configs2_7[i].cameraId = configs[i].cameraId;
hidl_utils::ConvertStreamConfigurationV34ToV37(
configs[i].streamConfiguration, &configs2_7[i].streamConfiguration);
}
return isConcurrentStreamCombinationSupported_2_7(configs2_7, _hidl_cb);
}
Return<void> HidlCameraProvider::isConcurrentStreamCombinationSupported_2_7(
const hidl_vec<CameraIdAndStreamCombination>& configs,
isConcurrentStreamCombinationSupported_cb _hidl_cb) {
std::vector<google_camera_hal::CameraIdAndStreamConfiguration>
devices_stream_configs(configs.size());
status_t res = OK;
size_t c = 0;
for (auto& config : configs) {
res = hidl_utils::ConverToHalStreamConfig(
config.streamConfiguration,
&devices_stream_configs[c].stream_configuration);
if (res != OK) {
ALOGE("%s: ConverToHalStreamConfig failed", __FUNCTION__);
_hidl_cb(Status::INTERNAL_ERROR, false);
return Void();
}
uint32_t camera_id = atoi(config.cameraId.c_str());
devices_stream_configs[c].camera_id = camera_id;
c++;
}
bool is_supported = false;
res = google_camera_provider_->IsConcurrentStreamCombinationSupported(
devices_stream_configs, &is_supported);
if (res != OK) {
ALOGE("%s: ConverToHalStreamConfig failed", __FUNCTION__);
_hidl_cb(Status::INTERNAL_ERROR, false);
return Void();
}
_hidl_cb(Status::OK, is_supported);
return Void();
}
Return<void> HidlCameraProvider::isSetTorchModeSupported(
isSetTorchModeSupported_cb _hidl_cb) {
bool is_supported = google_camera_provider_->IsSetTorchModeSupported();
_hidl_cb(Status::OK, is_supported);
return Void();
}
Return<void> HidlCameraProvider::getCameraDeviceInterface_V1_x(
const hidl_string& /*cameraDeviceName*/,
getCameraDeviceInterface_V1_x_cb _hidl_cb) {
_hidl_cb(Status::OPERATION_NOT_SUPPORTED, nullptr);
return Void();
}
bool HidlCameraProvider::ParseDeviceName(const hidl_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,
HidlCameraProvider::kDeviceNameRegex)) {
if (device_version != nullptr) {
*device_version = sm[1];
}
if (camera_id != nullptr) {
*camera_id = sm[2];
}
return true;
}
return false;
}
Return<void> HidlCameraProvider::getCameraDeviceInterface_V3_x(
const hidl_string& camera_device_name,
getCameraDeviceInterface_V3_x_cb _hidl_cb) {
std::unique_ptr<CameraDevice> google_camera_device;
// 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__);
_hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr);
return Void();
}
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);
_hidl_cb(hidl_utils::ConvertToHidlStatus(res), nullptr);
return Void();
}
auto hidl_camera_device =
device::V3_7::implementation::HidlCameraDevice::Create(
std::move(google_camera_device));
if (hidl_camera_device == nullptr) {
ALOGE("%s: Creating HidlCameraDevice failed", __FUNCTION__);
_hidl_cb(Status::INTERNAL_ERROR, nullptr);
return Void();
}
_hidl_cb(Status::OK, hidl_camera_device.release());
return Void();
}
Return<void> HidlCameraProvider::notifyDeviceStateChange(
hardware::hidl_bitfield<DeviceState> /*newState*/) {
return Void();
}
} // namespace implementation
} // namespace V2_7
} // namespace provider
} // namespace camera
} // namespace hardware
} // namespace android