1/*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15#include "intell_voice_util.h"
16#include <sys/stat.h>
17#include <memory>
18#include <malloc.h>
19#include <fcntl.h>
20#include <cstdio>
21#include <unistd.h>
22#include <cinttypes>
23#include <fstream>
24#include "string_util.h"
25#include "accesstoken_kit.h"
26#include "privacy_kit.h"
27#include "tokenid_kit.h"
28#include "ipc_skeleton.h"
29#include "privacy_error.h"
30#include "intell_voice_log.h"
31#include "intell_voice_info.h"
32
33#define LOG_TAG "IntellVoiceUtil"
34
35using namespace OHOS::IntellVoice;
36
37namespace OHOS {
38namespace IntellVoiceUtils {
39static constexpr uint32_t VERSION_OFFSET = 8;
40
41uint32_t IntellVoiceUtil::GetHdiVersionId(uint32_t majorVer, uint32_t minorVer)
42{
43    return ((majorVer << VERSION_OFFSET) | minorVer);
44}
45
46bool IntellVoiceUtil::DeinterleaveAudioData(const int16_t *buffer, uint32_t size, int32_t channelCnt,
47    std::vector<std::vector<uint8_t>> &audioData)
48{
49    if (channelCnt == 0) {
50        INTELL_VOICE_LOG_ERROR("channel cnt is zero");
51        return false;
52    }
53    uint32_t channelLen = size / channelCnt;
54    std::unique_ptr<int16_t[]> channelData = std::make_unique<int16_t[]>(channelLen);
55    if (channelData == nullptr) {
56        INTELL_VOICE_LOG_ERROR("channelData is nullptr");
57        return false;
58    }
59    for (int32_t i = 0; i < channelCnt; i++) {
60        for (uint32_t j = 0; j < channelLen; j++) {
61            channelData[j] = buffer[i + j * channelCnt];
62        }
63        std::vector<uint8_t> item(reinterpret_cast<uint8_t *>(channelData.get()),
64            reinterpret_cast<uint8_t *>(channelData.get()) + channelLen * sizeof(int16_t));
65        audioData.emplace_back(item);
66    }
67    return true;
68}
69
70bool IntellVoiceUtil::ReadFile(const std::string &filePath, std::shared_ptr<uint8_t> &buffer, uint32_t &size)
71{
72    std::ifstream file(filePath, std::ios::binary);
73    if (!file.good()) {
74        INTELL_VOICE_LOG_ERROR("open file failed");
75        return false;
76    }
77
78    file.seekg(0, file.end);
79    size = static_cast<uint32_t>(file.tellg());
80    if (size == 0) {
81        INTELL_VOICE_LOG_ERROR("file is empty");
82        return false;
83    }
84    buffer = std::shared_ptr<uint8_t>(new uint8_t[size], [](uint8_t *p) { delete[] p; });
85    if (buffer == nullptr) {
86        INTELL_VOICE_LOG_ERROR("failed to allocate buffer");
87        return false;
88    }
89
90    file.seekg(0, file.beg);
91    file.read(reinterpret_cast<char *>(buffer.get()), size);
92    file.close();
93    return true;
94}
95
96void IntellVoiceUtil::SplitStringToKVPair(const std::string &inputStr, std::map<std::string, std::string> &kvpairs)
97{
98    std::vector<std::string> paramsList;
99    StringUtil::Split(inputStr, ";", paramsList);
100    for (const auto &it : paramsList) {
101        std::string key;
102        std::string value;
103        if (StringUtil::SplitLineToPair(it, key, value)) {
104            kvpairs[key] = value;
105            INTELL_VOICE_LOG_INFO("key:%{public}s, value:%{public}s", key.c_str(), value.c_str());
106        }
107    }
108}
109
110bool IntellVoiceUtil::IsFileExist(const std::string &filePath)
111{
112    struct stat sb;
113    if (stat(filePath.c_str(), &sb) != 0) {
114        INTELL_VOICE_LOG_ERROR("get file status failed");
115        return false;
116    }
117
118    return true;
119}
120
121bool IntellVoiceUtil::VerifyClientPermission(const std::string &permissionName)
122{
123    Security::AccessToken::AccessTokenID clientTokenId = IPCSkeleton::GetCallingTokenID();
124    INTELL_VOICE_LOG_INFO("clientTokenId:%{public}d, permission name:%{public}s", clientTokenId,
125        permissionName.c_str());
126    int res = Security::AccessToken::AccessTokenKit::VerifyAccessToken(clientTokenId, permissionName);
127    if (res != Security::AccessToken::PermissionState::PERMISSION_GRANTED) {
128        INTELL_VOICE_LOG_ERROR("Permission denied");
129        return false;
130    }
131    return true;
132}
133
134bool IntellVoiceUtil::CheckIsSystemApp()
135{
136    uint64_t fullTokenId = IPCSkeleton::GetCallingFullTokenID();
137    if (Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(IPCSkeleton::GetCallingTokenID()) ==
138        Security::AccessToken::TOKEN_NATIVE) {
139        INTELL_VOICE_LOG_INFO("calling by native");
140        return true;
141    }
142
143    if (!Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(fullTokenId)) {
144        INTELL_VOICE_LOG_INFO("Not system app, permission reject tokenid: %{public}" PRIu64 "", fullTokenId);
145        return false;
146    }
147
148    INTELL_VOICE_LOG_INFO("System app, fullTokenId:%{public}" PRIu64 "", fullTokenId);
149    return true;
150}
151
152int32_t IntellVoiceUtil::VerifySystemPermission(const std::string &permissionName)
153{
154#ifdef INTELL_VOICE_BUILD_VARIANT_ROOT
155    if (IPCSkeleton::GetCallingUid() == 0) { // 0 for root uid
156        INTELL_VOICE_LOG_INFO("callingUid is root");
157        return INTELLIGENT_VOICE_SUCCESS;
158    }
159#endif
160
161    if (!CheckIsSystemApp()) {
162        return INTELLIGENT_VOICE_NOT_SYSTEM_APPLICATION;
163    }
164
165    if (!VerifyClientPermission(permissionName)) {
166        return INTELLIGENT_VOICE_PERMISSION_DENIED;
167    }
168
169    return INTELLIGENT_VOICE_SUCCESS;
170}
171
172bool IntellVoiceUtil::RecordPermissionPrivacy(const std::string &permissionName, uint32_t targetTokenId,
173    IntellVoicePermissionState state)
174{
175    INTELL_VOICE_LOG_INFO("permissionName:%{public}s, tokenId:%{public}u, state:%{public}d", permissionName.c_str(),
176        targetTokenId, state);
177    if (state == INTELL_VOICE_PERMISSION_START) {
178        auto ret = Security::AccessToken::PrivacyKit::StartUsingPermission(targetTokenId, permissionName);
179        if (ret != 0 && ret != Security::AccessToken::ERR_PERMISSION_ALREADY_START_USING) {
180            INTELL_VOICE_LOG_ERROR("StartUsingPermission for tokenId %{public}u, ret is %{public}d",
181                targetTokenId, ret);
182            return false;
183        }
184        ret = Security::AccessToken::PrivacyKit::AddPermissionUsedRecord(targetTokenId, permissionName, 1, 0);
185        if (ret != 0 && ret != Security::AccessToken::ERR_PERMISSION_ALREADY_START_USING) {
186            INTELL_VOICE_LOG_ERROR("AddPermissionUsedRecord for tokenId %{public}u! The PrivacyKit error code is "
187                "%{public}d", targetTokenId, ret);
188            return false;
189        }
190    } else if (state == INTELL_VOICE_PERMISSION_STOP) {
191        auto ret = Security::AccessToken::PrivacyKit::StopUsingPermission(targetTokenId, permissionName);
192        if (ret != 0) {
193            INTELL_VOICE_LOG_ERROR("StopUsingPermission for tokenId %{public}u, ret is %{public}d",
194                targetTokenId, ret);
195            return false;
196        }
197    } else {
198        INTELL_VOICE_LOG_WARN("invalid state");
199        return false;
200    }
201
202    return true;
203}
204}
205}
206