15490a39dSopenharmony_ci/*
25490a39dSopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd.
35490a39dSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
45490a39dSopenharmony_ci * you may not use this file except in compliance with the License.
55490a39dSopenharmony_ci * You may obtain a copy of the License at
65490a39dSopenharmony_ci *
75490a39dSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
85490a39dSopenharmony_ci *
95490a39dSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
105490a39dSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
115490a39dSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
125490a39dSopenharmony_ci * See the License for the specific language governing permissions and
135490a39dSopenharmony_ci * limitations under the License.
145490a39dSopenharmony_ci */
155490a39dSopenharmony_ci#include "intell_voice_util.h"
165490a39dSopenharmony_ci#include <sys/stat.h>
175490a39dSopenharmony_ci#include <memory>
185490a39dSopenharmony_ci#include <malloc.h>
195490a39dSopenharmony_ci#include <fcntl.h>
205490a39dSopenharmony_ci#include <cstdio>
215490a39dSopenharmony_ci#include <unistd.h>
225490a39dSopenharmony_ci#include <cinttypes>
235490a39dSopenharmony_ci#include <fstream>
245490a39dSopenharmony_ci#include "string_util.h"
255490a39dSopenharmony_ci#include "accesstoken_kit.h"
265490a39dSopenharmony_ci#include "privacy_kit.h"
275490a39dSopenharmony_ci#include "tokenid_kit.h"
285490a39dSopenharmony_ci#include "ipc_skeleton.h"
295490a39dSopenharmony_ci#include "privacy_error.h"
305490a39dSopenharmony_ci#include "intell_voice_log.h"
315490a39dSopenharmony_ci#include "intell_voice_info.h"
325490a39dSopenharmony_ci
335490a39dSopenharmony_ci#define LOG_TAG "IntellVoiceUtil"
345490a39dSopenharmony_ci
355490a39dSopenharmony_ciusing namespace OHOS::IntellVoice;
365490a39dSopenharmony_ci
375490a39dSopenharmony_cinamespace OHOS {
385490a39dSopenharmony_cinamespace IntellVoiceUtils {
395490a39dSopenharmony_cistatic constexpr uint32_t VERSION_OFFSET = 8;
405490a39dSopenharmony_ci
415490a39dSopenharmony_ciuint32_t IntellVoiceUtil::GetHdiVersionId(uint32_t majorVer, uint32_t minorVer)
425490a39dSopenharmony_ci{
435490a39dSopenharmony_ci    return ((majorVer << VERSION_OFFSET) | minorVer);
445490a39dSopenharmony_ci}
455490a39dSopenharmony_ci
465490a39dSopenharmony_cibool IntellVoiceUtil::DeinterleaveAudioData(const int16_t *buffer, uint32_t size, int32_t channelCnt,
475490a39dSopenharmony_ci    std::vector<std::vector<uint8_t>> &audioData)
485490a39dSopenharmony_ci{
495490a39dSopenharmony_ci    if (channelCnt == 0) {
505490a39dSopenharmony_ci        INTELL_VOICE_LOG_ERROR("channel cnt is zero");
515490a39dSopenharmony_ci        return false;
525490a39dSopenharmony_ci    }
535490a39dSopenharmony_ci    uint32_t channelLen = size / channelCnt;
545490a39dSopenharmony_ci    std::unique_ptr<int16_t[]> channelData = std::make_unique<int16_t[]>(channelLen);
555490a39dSopenharmony_ci    if (channelData == nullptr) {
565490a39dSopenharmony_ci        INTELL_VOICE_LOG_ERROR("channelData is nullptr");
575490a39dSopenharmony_ci        return false;
585490a39dSopenharmony_ci    }
595490a39dSopenharmony_ci    for (int32_t i = 0; i < channelCnt; i++) {
605490a39dSopenharmony_ci        for (uint32_t j = 0; j < channelLen; j++) {
615490a39dSopenharmony_ci            channelData[j] = buffer[i + j * channelCnt];
625490a39dSopenharmony_ci        }
635490a39dSopenharmony_ci        std::vector<uint8_t> item(reinterpret_cast<uint8_t *>(channelData.get()),
645490a39dSopenharmony_ci            reinterpret_cast<uint8_t *>(channelData.get()) + channelLen * sizeof(int16_t));
655490a39dSopenharmony_ci        audioData.emplace_back(item);
665490a39dSopenharmony_ci    }
675490a39dSopenharmony_ci    return true;
685490a39dSopenharmony_ci}
695490a39dSopenharmony_ci
705490a39dSopenharmony_cibool IntellVoiceUtil::ReadFile(const std::string &filePath, std::shared_ptr<uint8_t> &buffer, uint32_t &size)
715490a39dSopenharmony_ci{
725490a39dSopenharmony_ci    std::ifstream file(filePath, std::ios::binary);
735490a39dSopenharmony_ci    if (!file.good()) {
745490a39dSopenharmony_ci        INTELL_VOICE_LOG_ERROR("open file failed");
755490a39dSopenharmony_ci        return false;
765490a39dSopenharmony_ci    }
775490a39dSopenharmony_ci
785490a39dSopenharmony_ci    file.seekg(0, file.end);
795490a39dSopenharmony_ci    size = static_cast<uint32_t>(file.tellg());
805490a39dSopenharmony_ci    if (size == 0) {
815490a39dSopenharmony_ci        INTELL_VOICE_LOG_ERROR("file is empty");
825490a39dSopenharmony_ci        return false;
835490a39dSopenharmony_ci    }
845490a39dSopenharmony_ci    buffer = std::shared_ptr<uint8_t>(new uint8_t[size], [](uint8_t *p) { delete[] p; });
855490a39dSopenharmony_ci    if (buffer == nullptr) {
865490a39dSopenharmony_ci        INTELL_VOICE_LOG_ERROR("failed to allocate buffer");
875490a39dSopenharmony_ci        return false;
885490a39dSopenharmony_ci    }
895490a39dSopenharmony_ci
905490a39dSopenharmony_ci    file.seekg(0, file.beg);
915490a39dSopenharmony_ci    file.read(reinterpret_cast<char *>(buffer.get()), size);
925490a39dSopenharmony_ci    file.close();
935490a39dSopenharmony_ci    return true;
945490a39dSopenharmony_ci}
955490a39dSopenharmony_ci
965490a39dSopenharmony_civoid IntellVoiceUtil::SplitStringToKVPair(const std::string &inputStr, std::map<std::string, std::string> &kvpairs)
975490a39dSopenharmony_ci{
985490a39dSopenharmony_ci    std::vector<std::string> paramsList;
995490a39dSopenharmony_ci    StringUtil::Split(inputStr, ";", paramsList);
1005490a39dSopenharmony_ci    for (const auto &it : paramsList) {
1015490a39dSopenharmony_ci        std::string key;
1025490a39dSopenharmony_ci        std::string value;
1035490a39dSopenharmony_ci        if (StringUtil::SplitLineToPair(it, key, value)) {
1045490a39dSopenharmony_ci            kvpairs[key] = value;
1055490a39dSopenharmony_ci            INTELL_VOICE_LOG_INFO("key:%{public}s, value:%{public}s", key.c_str(), value.c_str());
1065490a39dSopenharmony_ci        }
1075490a39dSopenharmony_ci    }
1085490a39dSopenharmony_ci}
1095490a39dSopenharmony_ci
1105490a39dSopenharmony_cibool IntellVoiceUtil::IsFileExist(const std::string &filePath)
1115490a39dSopenharmony_ci{
1125490a39dSopenharmony_ci    struct stat sb;
1135490a39dSopenharmony_ci    if (stat(filePath.c_str(), &sb) != 0) {
1145490a39dSopenharmony_ci        INTELL_VOICE_LOG_ERROR("get file status failed");
1155490a39dSopenharmony_ci        return false;
1165490a39dSopenharmony_ci    }
1175490a39dSopenharmony_ci
1185490a39dSopenharmony_ci    return true;
1195490a39dSopenharmony_ci}
1205490a39dSopenharmony_ci
1215490a39dSopenharmony_cibool IntellVoiceUtil::VerifyClientPermission(const std::string &permissionName)
1225490a39dSopenharmony_ci{
1235490a39dSopenharmony_ci    Security::AccessToken::AccessTokenID clientTokenId = IPCSkeleton::GetCallingTokenID();
1245490a39dSopenharmony_ci    INTELL_VOICE_LOG_INFO("clientTokenId:%{public}d, permission name:%{public}s", clientTokenId,
1255490a39dSopenharmony_ci        permissionName.c_str());
1265490a39dSopenharmony_ci    int res = Security::AccessToken::AccessTokenKit::VerifyAccessToken(clientTokenId, permissionName);
1275490a39dSopenharmony_ci    if (res != Security::AccessToken::PermissionState::PERMISSION_GRANTED) {
1285490a39dSopenharmony_ci        INTELL_VOICE_LOG_ERROR("Permission denied");
1295490a39dSopenharmony_ci        return false;
1305490a39dSopenharmony_ci    }
1315490a39dSopenharmony_ci    return true;
1325490a39dSopenharmony_ci}
1335490a39dSopenharmony_ci
1345490a39dSopenharmony_cibool IntellVoiceUtil::CheckIsSystemApp()
1355490a39dSopenharmony_ci{
1365490a39dSopenharmony_ci    uint64_t fullTokenId = IPCSkeleton::GetCallingFullTokenID();
1375490a39dSopenharmony_ci    if (Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(IPCSkeleton::GetCallingTokenID()) ==
1385490a39dSopenharmony_ci        Security::AccessToken::TOKEN_NATIVE) {
1395490a39dSopenharmony_ci        INTELL_VOICE_LOG_INFO("calling by native");
1405490a39dSopenharmony_ci        return true;
1415490a39dSopenharmony_ci    }
1425490a39dSopenharmony_ci
1435490a39dSopenharmony_ci    if (!Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(fullTokenId)) {
1445490a39dSopenharmony_ci        INTELL_VOICE_LOG_INFO("Not system app, permission reject tokenid: %{public}" PRIu64 "", fullTokenId);
1455490a39dSopenharmony_ci        return false;
1465490a39dSopenharmony_ci    }
1475490a39dSopenharmony_ci
1485490a39dSopenharmony_ci    INTELL_VOICE_LOG_INFO("System app, fullTokenId:%{public}" PRIu64 "", fullTokenId);
1495490a39dSopenharmony_ci    return true;
1505490a39dSopenharmony_ci}
1515490a39dSopenharmony_ci
1525490a39dSopenharmony_ciint32_t IntellVoiceUtil::VerifySystemPermission(const std::string &permissionName)
1535490a39dSopenharmony_ci{
1545490a39dSopenharmony_ci#ifdef INTELL_VOICE_BUILD_VARIANT_ROOT
1555490a39dSopenharmony_ci    if (IPCSkeleton::GetCallingUid() == 0) { // 0 for root uid
1565490a39dSopenharmony_ci        INTELL_VOICE_LOG_INFO("callingUid is root");
1575490a39dSopenharmony_ci        return INTELLIGENT_VOICE_SUCCESS;
1585490a39dSopenharmony_ci    }
1595490a39dSopenharmony_ci#endif
1605490a39dSopenharmony_ci
1615490a39dSopenharmony_ci    if (!CheckIsSystemApp()) {
1625490a39dSopenharmony_ci        return INTELLIGENT_VOICE_NOT_SYSTEM_APPLICATION;
1635490a39dSopenharmony_ci    }
1645490a39dSopenharmony_ci
1655490a39dSopenharmony_ci    if (!VerifyClientPermission(permissionName)) {
1665490a39dSopenharmony_ci        return INTELLIGENT_VOICE_PERMISSION_DENIED;
1675490a39dSopenharmony_ci    }
1685490a39dSopenharmony_ci
1695490a39dSopenharmony_ci    return INTELLIGENT_VOICE_SUCCESS;
1705490a39dSopenharmony_ci}
1715490a39dSopenharmony_ci
1725490a39dSopenharmony_cibool IntellVoiceUtil::RecordPermissionPrivacy(const std::string &permissionName, uint32_t targetTokenId,
1735490a39dSopenharmony_ci    IntellVoicePermissionState state)
1745490a39dSopenharmony_ci{
1755490a39dSopenharmony_ci    INTELL_VOICE_LOG_INFO("permissionName:%{public}s, tokenId:%{public}u, state:%{public}d", permissionName.c_str(),
1765490a39dSopenharmony_ci        targetTokenId, state);
1775490a39dSopenharmony_ci    if (state == INTELL_VOICE_PERMISSION_START) {
1785490a39dSopenharmony_ci        auto ret = Security::AccessToken::PrivacyKit::StartUsingPermission(targetTokenId, permissionName);
1795490a39dSopenharmony_ci        if (ret != 0 && ret != Security::AccessToken::ERR_PERMISSION_ALREADY_START_USING) {
1805490a39dSopenharmony_ci            INTELL_VOICE_LOG_ERROR("StartUsingPermission for tokenId %{public}u, ret is %{public}d",
1815490a39dSopenharmony_ci                targetTokenId, ret);
1825490a39dSopenharmony_ci            return false;
1835490a39dSopenharmony_ci        }
1845490a39dSopenharmony_ci        ret = Security::AccessToken::PrivacyKit::AddPermissionUsedRecord(targetTokenId, permissionName, 1, 0);
1855490a39dSopenharmony_ci        if (ret != 0 && ret != Security::AccessToken::ERR_PERMISSION_ALREADY_START_USING) {
1865490a39dSopenharmony_ci            INTELL_VOICE_LOG_ERROR("AddPermissionUsedRecord for tokenId %{public}u! The PrivacyKit error code is "
1875490a39dSopenharmony_ci                "%{public}d", targetTokenId, ret);
1885490a39dSopenharmony_ci            return false;
1895490a39dSopenharmony_ci        }
1905490a39dSopenharmony_ci    } else if (state == INTELL_VOICE_PERMISSION_STOP) {
1915490a39dSopenharmony_ci        auto ret = Security::AccessToken::PrivacyKit::StopUsingPermission(targetTokenId, permissionName);
1925490a39dSopenharmony_ci        if (ret != 0) {
1935490a39dSopenharmony_ci            INTELL_VOICE_LOG_ERROR("StopUsingPermission for tokenId %{public}u, ret is %{public}d",
1945490a39dSopenharmony_ci                targetTokenId, ret);
1955490a39dSopenharmony_ci            return false;
1965490a39dSopenharmony_ci        }
1975490a39dSopenharmony_ci    } else {
1985490a39dSopenharmony_ci        INTELL_VOICE_LOG_WARN("invalid state");
1995490a39dSopenharmony_ci        return false;
2005490a39dSopenharmony_ci    }
2015490a39dSopenharmony_ci
2025490a39dSopenharmony_ci    return true;
2035490a39dSopenharmony_ci}
2045490a39dSopenharmony_ci}
2055490a39dSopenharmony_ci}
206