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