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 #include "ability_manager_client.h"
33 #include "history_info_mgr.h"
34
35 #define LOG_TAG "IntellVoiceUtil"
36
37 using namespace OHOS::IntellVoice;
38
39 namespace OHOS {
40 namespace IntellVoiceUtils {
41 static constexpr uint32_t VERSION_OFFSET = 8;
42
GetHdiVersionId(uint32_t majorVer,uint32_t minorVer)43 uint32_t IntellVoiceUtil::GetHdiVersionId(uint32_t majorVer, uint32_t minorVer)
44 {
45 return ((majorVer << VERSION_OFFSET) | minorVer);
46 }
47
DeinterleaveAudioData(const int16_t * buffer,uint32_t size,int32_t channelCnt,std::vector<std::vector<uint8_t>> & audioData)48 bool IntellVoiceUtil::DeinterleaveAudioData(const int16_t *buffer, uint32_t size, int32_t channelCnt,
49 std::vector<std::vector<uint8_t>> &audioData)
50 {
51 if (channelCnt == 0) {
52 INTELL_VOICE_LOG_ERROR("channel cnt is zero");
53 return false;
54 }
55 uint32_t channelLen = size / channelCnt;
56 std::unique_ptr<int16_t[]> channelData = std::make_unique<int16_t[]>(channelLen);
57 if (channelData == nullptr) {
58 INTELL_VOICE_LOG_ERROR("channelData is nullptr");
59 return false;
60 }
61 for (int32_t i = 0; i < channelCnt; i++) {
62 for (uint32_t j = 0; j < channelLen; j++) {
63 channelData[j] = buffer[i + j * channelCnt];
64 }
65 std::vector<uint8_t> item(reinterpret_cast<uint8_t *>(channelData.get()),
66 reinterpret_cast<uint8_t *>(channelData.get()) + channelLen * sizeof(int16_t));
67 audioData.emplace_back(item);
68 }
69 return true;
70 }
71
ReadFile(const std::string & filePath,std::shared_ptr<uint8_t> & buffer,uint32_t & size)72 bool IntellVoiceUtil::ReadFile(const std::string &filePath, std::shared_ptr<uint8_t> &buffer, uint32_t &size)
73 {
74 std::ifstream file(filePath, std::ios::binary);
75 if (!file.good()) {
76 INTELL_VOICE_LOG_ERROR("open file failed");
77 return false;
78 }
79
80 file.seekg(0, file.end);
81 size = static_cast<uint32_t>(file.tellg());
82 if (size == 0) {
83 INTELL_VOICE_LOG_ERROR("file is empty");
84 return false;
85 }
86 buffer = std::shared_ptr<uint8_t>(new uint8_t[size], [](uint8_t *p) { delete[] p; });
87 if (buffer == nullptr) {
88 INTELL_VOICE_LOG_ERROR("failed to allocate buffer");
89 return false;
90 }
91
92 file.seekg(0, file.beg);
93 file.read(reinterpret_cast<char *>(buffer.get()), size);
94 file.close();
95 return true;
96 }
97
SplitStringToKVPair(const std::string & inputStr,std::map<std::string,std::string> & kvpairs)98 void IntellVoiceUtil::SplitStringToKVPair(const std::string &inputStr, std::map<std::string, std::string> &kvpairs)
99 {
100 std::vector<std::string> paramsList;
101 StringUtil::Split(inputStr, ";", paramsList);
102 for (const auto &it : paramsList) {
103 std::string key;
104 std::string value;
105 if (StringUtil::SplitLineToPair(it, key, value)) {
106 kvpairs[key] = value;
107 INTELL_VOICE_LOG_INFO("key:%{public}s, value:%{public}s", key.c_str(), value.c_str());
108 }
109 }
110 }
111
IsFileExist(const std::string & filePath)112 bool IntellVoiceUtil::IsFileExist(const std::string &filePath)
113 {
114 struct stat sb;
115 if (stat(filePath.c_str(), &sb) != 0) {
116 INTELL_VOICE_LOG_ERROR("get file status failed");
117 return false;
118 }
119
120 return true;
121 }
122
VerifyClientPermission(const std::string & permissionName)123 bool IntellVoiceUtil::VerifyClientPermission(const std::string &permissionName)
124 {
125 Security::AccessToken::AccessTokenID clientTokenId = IPCSkeleton::GetCallingTokenID();
126 INTELL_VOICE_LOG_INFO("clientTokenId:%{public}d, permission name:%{public}s", clientTokenId,
127 permissionName.c_str());
128 int res = Security::AccessToken::AccessTokenKit::VerifyAccessToken(clientTokenId, permissionName);
129 if (res != Security::AccessToken::PermissionState::PERMISSION_GRANTED) {
130 INTELL_VOICE_LOG_ERROR("Permission denied");
131 return false;
132 }
133 return true;
134 }
135
CheckIsSystemApp()136 bool IntellVoiceUtil::CheckIsSystemApp()
137 {
138 uint64_t fullTokenId = IPCSkeleton::GetCallingFullTokenID();
139 if (Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(IPCSkeleton::GetCallingTokenID()) ==
140 Security::AccessToken::TOKEN_NATIVE) {
141 INTELL_VOICE_LOG_INFO("calling by native");
142 return true;
143 }
144
145 if (!Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(fullTokenId)) {
146 INTELL_VOICE_LOG_INFO("Not system app, permission reject tokenid: %{public}" PRIu64 "", fullTokenId);
147 return false;
148 }
149
150 INTELL_VOICE_LOG_INFO("System app, fullTokenId:%{public}" PRIu64 "", fullTokenId);
151 return true;
152 }
153
VerifySystemPermission(const std::string & permissionName)154 int32_t IntellVoiceUtil::VerifySystemPermission(const std::string &permissionName)
155 {
156 #ifdef INTELL_VOICE_BUILD_VARIANT_ROOT
157 if (IPCSkeleton::GetCallingUid() == 0) { // 0 for root uid
158 INTELL_VOICE_LOG_INFO("callingUid is root");
159 return INTELLIGENT_VOICE_SUCCESS;
160 }
161 #endif
162
163 if (!CheckIsSystemApp()) {
164 return INTELLIGENT_VOICE_NOT_SYSTEM_APPLICATION;
165 }
166
167 if (!VerifyClientPermission(permissionName)) {
168 return INTELLIGENT_VOICE_PERMISSION_DENIED;
169 }
170 return INTELLIGENT_VOICE_SUCCESS;
171 }
172
RecordPermissionPrivacy(const std::string & permissionName,uint32_t targetTokenId,IntellVoicePermissionState state)173 bool IntellVoiceUtil::RecordPermissionPrivacy(const std::string &permissionName, uint32_t targetTokenId,
174 IntellVoicePermissionState state)
175 {
176 INTELL_VOICE_LOG_INFO("permissionName:%{public}s, tokenId:%{public}u, state:%{public}d", permissionName.c_str(),
177 targetTokenId, state);
178 if (state == INTELL_VOICE_PERMISSION_START) {
179 auto ret = Security::AccessToken::PrivacyKit::StartUsingPermission(targetTokenId, permissionName);
180 if (ret != 0 && ret != Security::AccessToken::ERR_PERMISSION_ALREADY_START_USING) {
181 INTELL_VOICE_LOG_ERROR("StartUsingPermission for tokenId %{public}u, ret is %{public}d",
182 targetTokenId, ret);
183 return false;
184 }
185 ret = Security::AccessToken::PrivacyKit::AddPermissionUsedRecord(targetTokenId, permissionName, 1, 0);
186 if (ret != 0 && ret != Security::AccessToken::ERR_PERMISSION_ALREADY_START_USING) {
187 INTELL_VOICE_LOG_ERROR("AddPermissionUsedRecord for tokenId %{public}u! The PrivacyKit error code is "
188 "%{public}d", targetTokenId, ret);
189 return false;
190 }
191 } else if (state == INTELL_VOICE_PERMISSION_STOP) {
192 auto ret = Security::AccessToken::PrivacyKit::StopUsingPermission(targetTokenId, permissionName);
193 if (ret != 0) {
194 INTELL_VOICE_LOG_ERROR("StopUsingPermission for tokenId %{public}u, ret is %{public}d",
195 targetTokenId, ret);
196 return false;
197 }
198 } else {
199 INTELL_VOICE_LOG_WARN("invalid state");
200 return false;
201 }
202
203 return true;
204 }
205
StartAbility(const std::string & event)206 void IntellVoiceUtil::StartAbility(const std::string &event)
207 {
208 AAFwk::Want want;
209 HistoryInfoMgr &historyInfoMgr = HistoryInfoMgr::GetInstance();
210
211 std::string bundleName = historyInfoMgr.GetStringKVPair(KEY_WAKEUP_ENGINE_BUNDLE_NAME);
212 std::string abilityName = historyInfoMgr.GetStringKVPair(KEY_WAKEUP_ENGINE_ABILITY_NAME);
213 INTELL_VOICE_LOG_INFO("bundleName:%{public}s, abilityName:%{public}s", bundleName.c_str(), abilityName.c_str());
214 if (bundleName.empty() || abilityName.empty()) {
215 INTELL_VOICE_LOG_ERROR("bundle name is empty or ability name is empty");
216 return;
217 }
218 want.SetElementName(bundleName, abilityName);
219 want.SetParam("serviceName", std::string("intell_voice"));
220 want.SetParam("servicePid", getpid());
221 want.SetParam("eventType", event);
222 auto abilityManagerClient = AAFwk::AbilityManagerClient::GetInstance();
223 if (abilityManagerClient == nullptr) {
224 INTELL_VOICE_LOG_ERROR("abilityManagerClient is nullptr");
225 return;
226 }
227 abilityManagerClient->StartAbility(want);
228 }
229 }
230 }
231