* Copyright (c) 2026 Huawei Device Co., Ltd.
* 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 <cstring>
#include <cstdlib>
#include <unistd.h>
#include <iostream>
#include <string>
#include <vector>
#include <securec.h>
#include "distributedcameratest.h"
#include "dcamera_hdf_operate.h"
#include "distributed_hardware_log.h"
#include "v1_1/id_camera_provider.h"
#include "v1_1/dcamera_types.h"
#include "token_setproc.h"
#include "nativetoken_kit.h"
#include "v1_3/icamera_host.h"
#include "v1_0/icamera_host.h"
#include "v1_3/icamera_host.h"
#include "v1_0/icamera_host_callback.h"
#include "v1_0/icamera_device_callback.h"
#include "v1_3/icamera_device.h"
#include "accesstoken_kit.h"
#include "camera_metadata_info.h"
#include "metadata_utils.h"
#include "idevmgr_hdi.h"
namespace {
constexpr int32_t RET_OK = 0;
constexpr int32_t RET_ERR = -1;
constexpr uint8_t CONNECTION_TYPE_BUILTIN = 0;
constexpr uint8_t CONNECTION_TYPE_USB = 1;
constexpr uint8_t CONNECTION_TYPE_REMOTE = 2;
const int32_t CMD_QUIT = 0;
const int32_t CMD_FIND = 1;
const int32_t CMD_SELECT_CAMERA = 2;
const int32_t CMD_OPEN_CAMERA = 3;
const int32_t CMD_CLOSE_CAMERA = 4;
const int32_t CMD_INPUT_TOKENID = 5;
constexpr const char *DCAMERA_SERVICE = "distributed_camera_service";
enum DeviceStatus {
DEVICE_IDLE = 0,
DEVICE_OPEN = 1,
DEVICE_START = 2,
DEVICE_STOP = 3,
};
uint64_t g_inputTokenId = 0;
static DeviceStatus g_cameraStatus = DeviceStatus::DEVICE_IDLE;
static std::string g_serviceName = DCAMERA_SERVICE;
static std::vector<std::string> g_cameraIds;
static size_t g_selectCameraIndex = 0;
static OHOS::sptr<OHOS::HDI::Camera::V1_0::ICameraHost> g_cameraHost = nullptr;
static OHOS::sptr<OHOS::HDI::Camera::V1_3::ICameraHost> g_cameraHostV1_3 = nullptr;
static OHOS::sptr<OHOS::HDI::Camera::V1_3::ICameraDevice> g_cameraDevice = nullptr;
static const char *ConnectionTypeStr(uint8_t type)
{
switch (type) {
case CONNECTION_TYPE_REMOTE:
return "REMOTE(对端)";
case CONNECTION_TYPE_USB:
return "USB";
case CONNECTION_TYPE_BUILTIN:
default:
return "BUILTIN(本端)";
}
}
static uint8_t GetCameraConnectionType(const std::string &cameraId)
{
if (g_cameraHost == nullptr) {
return CONNECTION_TYPE_BUILTIN;
}
std::vector<uint8_t> abilityVec;
int32_t ret = g_cameraHost->GetCameraAbility(cameraId, abilityVec);
if (ret != OHOS::HDI::Camera::V1_0::NO_ERROR || abilityVec.empty()) {
return CONNECTION_TYPE_BUILTIN;
}
std::shared_ptr<OHOS::Camera::CameraMetadata> ability;
OHOS::Camera::MetadataUtils::ConvertVecToMetadata(abilityVec, ability);
if (ability == nullptr) {
return CONNECTION_TYPE_BUILTIN;
}
camera_metadata_item_t item;
ret = OHOS::Camera::FindCameraMetadataItem(ability->get(), OHOS_ABILITY_CAMERA_CONNECTION_TYPE, &item);
if (ret == CAM_META_SUCCESS && item.count > 0) {
return item.data.u8[0];
}
return CONNECTION_TYPE_BUILTIN;
}
class DemoCameraDeviceCallback : public OHOS::HDI::Camera::V1_0::ICameraDeviceCallback {
public:
DemoCameraDeviceCallback() = default;
~DemoCameraDeviceCallback() = default;
int32_t OnError(OHOS::HDI::Camera::V1_0::ErrorType type, int32_t errorCode) override
{
std::cout << "DeviceCallback OnError type:" << type << " code:" << errorCode << std::endl;
return OHOS::HDI::Camera::V1_0::NO_ERROR;
}
int32_t OnResult(uint64_t timestamp, const std::vector<uint8_t>& result) override
{
return OHOS::HDI::Camera::V1_0::NO_ERROR;
}
};
class DemoCameraHostCallback : public OHOS::HDI::Camera::V1_0::ICameraHostCallback {
public:
DemoCameraHostCallback() = default;
~DemoCameraHostCallback() = default;
int32_t OnCameraStatus(const std::string& cameraId, OHOS::HDI::Camera::V1_0::CameraStatus status) override
{
std::cout << "HostCallback OnCameraStatus id:" << cameraId << " status:" << static_cast<int32_t>(status)
<< std::endl;
return OHOS::HDI::Camera::V1_0::NO_ERROR;
}
int32_t OnFlashlightStatus(const std::string& cameraId, OHOS::HDI::Camera::V1_0::FlashlightStatus status) override
{
std::cout << "HostCallback OnFlashlightStatus id:" << cameraId
<< " status:" << static_cast<int32_t>(status) << std::endl;
return OHOS::HDI::Camera::V1_0::NO_ERROR;
}
int32_t OnCameraEvent(const std::string& cameraId, OHOS::HDI::Camera::V1_0::CameraEvent event) override
{
std::cout << "HostCallback OnCameraEvent id:" << cameraId << " event:" << static_cast<int32_t>(event)
<< std::endl;
return OHOS::HDI::Camera::V1_0::NO_ERROR;
}
};
static int32_t GetUserInput()
{
int32_t res = -1;
size_t count = 3;
std::cout << ">>";
int ret = scanf_s("%d", &res);
if (ret == -1) {
std::cout << "get input error" << std::endl;
}
while (std::cin.fail() && count > 0) {
std::cin.clear();
std::cin.ignore();
std::cout << "invalid input, not a number! Please retry with a number." << std::endl;
std::cout << ">>";
ret = scanf_s("%d", &res);
if (ret == -1) {
std::cout << "get input error" << std::endl;
}
count--;
}
return res;
}
static void InputTokenId()
{
std::cout << "Please input tokenId." << std::endl;
int ret = scanf_s("%llu", &g_inputTokenId);
if (ret != 1) {
std::cout << "get input error" << std::endl;
}
}
static void SetPermissions()
{
const char *perms[1];
perms[0] = "ohos.permission.CAMERA";
NativeTokenInfoParams infoInstance = {
.dcapsNum = 0,
.permsNum = 1,
.aclsNum = 0,
.dcaps = NULL,
.perms = perms,
.acls = NULL,
.processName = "camera_host_sample",
.aplStr = "system_basic",
};
uint64_t tokenId = GetAccessTokenId(&infoInstance);
SetSelfTokenID(tokenId);
OHOS::Security::AccessToken::AccessTokenKit::ReloadNativeTokenInfo();
}
static int32_t InitTestDemo()
{
std::cout << "**********************************************************************************" << std::endl;
std::cout << "Camera Host Sample (ICameraHost V1_3) v1.0" << std::endl;
std::cout << "**********************************************************************************" << std::endl;
std::cout << "Init camera host service, name: " << g_serviceName << std::endl;
g_cameraHost = OHOS::HDI::Camera::V1_0::ICameraHost::Get(g_serviceName.c_str(), false);
if (g_cameraHost == nullptr) {
std::cout << "Get ICameraHost failed, check camera_host service." << std::endl;
return RET_ERR;
}
std::cout << "Get V1_0 ICameraHost success." << std::endl;
uint32_t majorVer = 0;
uint32_t minorVer = 0;
g_cameraHost->GetVersion(majorVer, minorVer);
std::cout << "CameraHost version: " << majorVer << "." << minorVer << std::endl;
g_cameraHostV1_3 = OHOS::HDI::Camera::V1_3::ICameraHost::CastFrom(g_cameraHost);
if (g_cameraHostV1_3 == nullptr) {
std::cout << "Cast to V1_3 ICameraHost failed, host does not support V1_3." << std::endl;
} else {
std::cout << "Cast to V1_3 ICameraHost success." << std::endl;
}
OHOS::sptr<DemoCameraHostCallback> hostCallback = new DemoCameraHostCallback();
int32_t ret = g_cameraHost->SetCallback(hostCallback);
if (ret != OHOS::HDI::Camera::V1_0::NO_ERROR) {
std::cout << "SetCallback failed, ret: " << ret << std::endl;
} else {
std::cout << "SetCallback success." << std::endl;
}
ret = g_cameraHost->GetCameraIds(g_cameraIds);
if (ret != OHOS::HDI::Camera::V1_0::NO_ERROR) {
std::cout << "GetCameraIds failed, ret: " << ret << std::endl;
return RET_ERR;
}
std::cout << "GetCameraIds success, count: " << g_cameraIds.size() << std::endl;
for (const auto &id : g_cameraIds) {
std::cout << " cameraId: " << id << std::endl;
}
return RET_OK;
}
static void OpenCamera()
{
if (g_cameraStatus != DeviceStatus::DEVICE_IDLE) {
std::cout << "Camera device is already opened." << std::endl;
return;
}
if (g_cameraHostV1_3 == nullptr) {
std::cout << "V1_3 ICameraHost is null, cannot OpenCamera_V1_3." << std::endl;
return;
}
if (g_cameraIds.empty()) {
std::cout << "No camera id available, run find first." << std::endl;
return;
}
if (g_inputTokenId != 0) {
SetFirstCallerTokenID(g_inputTokenId);
}
std::string cameraId = g_cameraIds.front();
if (g_selectCameraIndex < g_cameraIds.size()) {
cameraId = g_cameraIds[g_selectCameraIndex];
}
uint8_t connType = GetCameraConnectionType(cameraId);
std::cout << "Opening cameraId: " << cameraId << " connectionType: " << ConnectionTypeStr(connType) << std::endl;
OHOS::sptr<OHOS::HDI::Camera::V1_0::ICameraDeviceCallback> callback = new DemoCameraDeviceCallback();
OHOS::sptr<OHOS::HDI::Camera::V1_3::ICameraDevice> device = nullptr;
int32_t ret = g_cameraHostV1_3->OpenCamera_V1_3(cameraId, callback, device);
if (ret != OHOS::HDI::Camera::V1_0::NO_ERROR || device == nullptr) {
std::cout << "OpenCamera_V1_3 failed, ret: " << ret << std::endl;
return;
}
g_cameraDevice = device;
g_cameraStatus = DeviceStatus::DEVICE_OPEN;
std::cout << "OpenCamera_V1_3 success, cameraId: " << cameraId << std::endl;
}
static void CloseCamera()
{
if (g_cameraStatus == DeviceStatus::DEVICE_IDLE) {
std::cout << "Camera device is not opened." << std::endl;
return;
}
if (g_cameraDevice != nullptr) {
g_cameraDevice->Close();
g_cameraDevice = nullptr;
}
g_cameraStatus = DeviceStatus::DEVICE_IDLE;
std::cout << "CloseCamera success." << std::endl;
}
static void FindCameraDevice()
{
if (g_cameraHost == nullptr) {
g_cameraHost = OHOS::HDI::Camera::V1_0::ICameraHost::Get(g_serviceName.c_str(), false);
if (g_cameraHost == nullptr) {
std::cout << "Camera host is null, check service." << std::endl;
return;
}
}
if (g_cameraHostV1_3 == nullptr) {
g_cameraHostV1_3 = OHOS::HDI::Camera::V1_3::ICameraHost::CastFrom(g_cameraHost);
}
int32_t ret = g_cameraHost->GetCameraIds(g_cameraIds);
if (ret != OHOS::HDI::Camera::V1_0::NO_ERROR) {
std::cout << "GetCameraIds failed, ret: " << ret << std::endl;
return;
}
std::cout << "Find camera device success, count: " << g_cameraIds.size() << std::endl;
for (size_t i = 0; i < g_cameraIds.size(); i++) {
uint8_t connType = GetCameraConnectionType(g_cameraIds[i]);
std::cout << " [" << i << "] cameraId: " << g_cameraIds[i]
<< " connectionType: " << ConnectionTypeStr(connType) << std::endl;
}
if (g_selectCameraIndex >= g_cameraIds.size()) {
g_selectCameraIndex = 0;
}
std::cout << "current select index: " << g_selectCameraIndex
<< " (use 14 to change)" << std::endl;
}
static void SelectCamera()
{
if (g_cameraIds.empty()) {
std::cout << "No camera id available, run find(9) first." << std::endl;
return;
}
std::cout << "Please input camera index (0-" << (g_cameraIds.size() - 1) << ")." << std::endl;
int32_t index = -1;
int ret = scanf_s("%d", &index);
if (ret == -1) {
std::cout << "get input error" << std::endl;
}
if (index < 0 || static_cast<size_t>(index) >= g_cameraIds.size()) {
std::cout << "invalid index: " << index << std::endl;
return;
}
g_selectCameraIndex = static_cast<size_t>(index);
uint8_t connType = GetCameraConnectionType(g_cameraIds[g_selectCameraIndex]);
std::cout << "selected [" << g_selectCameraIndex << "] " << g_cameraIds[g_selectCameraIndex]
<< " connectionType: " << ConnectionTypeStr(connType) << std::endl;
}
static void HandleCameraEvent(const int32_t cmd)
{
switch (cmd) {
case CMD_FIND:
FindCameraDevice();
break;
case CMD_OPEN_CAMERA:
OpenCamera();
break;
case CMD_CLOSE_CAMERA:
CloseCamera();
break;
case CMD_INPUT_TOKENID:
InputTokenId();
break;
case CMD_SELECT_CAMERA:
SelectCamera();
break;
default:
std::cout << "Unknown operation." << std::endl;
break;
}
}
static void PrintInteractiveUsage()
{
std::cout << std::endl << "=============== InteractiveRunTestSelect ================" << std::endl;
std::cout << "You can respond to instructions for corresponding option:" << std::endl;
std::cout << "\t enter 1 to find camera device. " << std::endl;
std::cout << "\t enter 2 to select camera index (find first). " << std::endl;
std::cout << "\t enter 3 to open camera (selected index). " << std::endl;
std::cout << "\t enter 4 to close camera. " << std::endl;
std::cout << "\t enter 5 to input tokenId. " << std::endl;
std::cout << "\t enter 0 to exit. " << std::endl;
std::cout << "hint: use service \"camera_service\"; the remote (对端) camera is the id whose "
<< "connectionType == REMOTE(对端)." << std::endl;
}
}
int main(int argc, char *argv[])
{
SetPermissions();
if (InitTestDemo() != RET_OK) {
std::cout << "InitTestDemo failed, retry find(9) after camera_host ready, or exit(0)." << std::endl;
}
bool quit = false;
while (!quit) {
PrintInteractiveUsage();
int32_t cmd = GetUserInput();
if (cmd == CMD_QUIT) {
CloseCamera();
quit = true;
} else {
HandleCameraEvent(cmd);
}
}
return 0;
}