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 
35 using namespace OHOS::IntellVoice;
36 
37 namespace OHOS {
38 namespace IntellVoiceUtils {
39 static constexpr uint32_t VERSION_OFFSET = 8;
40 
GetHdiVersionId(uint32_t majorVer, uint32_t minorVer)41 uint32_t IntellVoiceUtil::GetHdiVersionId(uint32_t majorVer, uint32_t minorVer)
42 {
43     return ((majorVer << VERSION_OFFSET) | minorVer);
44 }
45 
DeinterleaveAudioData(const int16_t *buffer, uint32_t size, int32_t channelCnt, std::vector<std::vector<uint8_t>> &audioData)46 bool 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 
ReadFile(const std::string &filePath, std::shared_ptr<uint8_t> &buffer, uint32_t &size)70 bool 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 
SplitStringToKVPair(const std::string &inputStr, std::map<std::string, std::string> &kvpairs)96 void 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 
IsFileExist(const std::string &filePath)110 bool 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 
VerifyClientPermission(const std::string &permissionName)121 bool 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 
CheckIsSystemApp()134 bool 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 
VerifySystemPermission(const std::string &permissionName)152 int32_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 
RecordPermissionPrivacy(const std::string &permissionName, uint32_t targetTokenId, IntellVoicePermissionState state)172 bool 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