1 /*
2 * Copyright (C) 2023-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 * Description: common method for cast session
15 * Author: lijianzhao
16 * Create: 2022-01-19
17 */
18
19 #include "utils.h"
20
21 #include <cctype>
22 #include <openssl/bio.h>
23 #include <openssl/evp.h>
24 #include <openssl/buffer.h>
25 #include <sys/prctl.h>
26 #include <sys/time.h>
27
28 #include "wifi_device.h"
29 #include "ohos_account_kits.h"
30 #include "os_account_manager.h"
31 #include "os_account_constants.h"
32 #include "cast_engine_log.h"
33 #include "ipc_skeleton.h"
34 #include "token_setproc.h"
35 #include "power_mgr_client.h"
36
37 using namespace OHOS::PowerMgr;
38
39 namespace OHOS {
40 namespace CastEngine {
41 namespace CastEngineService {
42 DEFINE_CAST_ENGINE_LABEL("Cast-Utils");
43
44 const uint32_t BASE64_UNIT_ONE_PADDING = 1;
45 const uint32_t BASE64_UNIT_TWO_PADDING = 2;
46 const uint32_t BASE64_SRC_UNIT_SIZE = 3;
47 const uint32_t BASE64_DEST_UNIT_SIZE = 4;
48 constexpr static int32_t DEFAULT_OS_ACCOUNT_ID = 100;
49 std::atomic<bool> Utils::isEnablePowerForceTimingOut = false;
50
Base64Encode(const std::string & source,std::string & encoded)51 bool Utils::Base64Encode(const std::string &source, std::string &encoded)
52 {
53 BIO *bio = BIO_new(BIO_s_mem());
54 if (bio == nullptr) {
55 CLOGE("Base64Encode error: BIO_new failed");
56 return false;
57 }
58 BIO *b64 = BIO_new(BIO_f_base64());
59 if (b64 == nullptr) {
60 CLOGE("Base64Encode error: BIO_f_base64 failed");
61 BIO_free(bio);
62 return false;
63 }
64
65 BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
66 bio = BIO_push(b64, bio);
67 int result = BIO_write(b64, source.c_str(), source.length());
68 if (result <= 0) {
69 CLOGE("Base64Encode error: bio write fail.");
70 BIO_free_all(b64);
71 return false;
72 }
73 BIO_flush(b64);
74
75 BUF_MEM *bptr = nullptr;
76 bool ret = false;
77 BIO_get_mem_ptr(b64, &bptr);
78 if (bptr != nullptr) {
79 encoded = std::string(bptr->data, bptr->length);
80 ret = true;
81 }
82 BIO_free_all(b64);
83 return ret;
84 }
85
Base64Decode(const std::string & encoded,std::string & decoded)86 bool Utils::Base64Decode(const std::string &encoded, std::string &decoded)
87 {
88 if (encoded.length() % BASE64_DEST_UNIT_SIZE != 0 || encoded.length() == 0) {
89 return false;
90 }
91
92 uint32_t decodedLen = encoded.length() * BASE64_SRC_UNIT_SIZE / BASE64_DEST_UNIT_SIZE;
93 if (encoded.at(encoded.length() - BASE64_UNIT_ONE_PADDING) == '=') {
94 decodedLen--;
95 if (encoded.at(encoded.length() - BASE64_UNIT_TWO_PADDING) == '=') {
96 decodedLen--;
97 }
98 }
99
100 bool ret = false;
101 char* buffer = static_cast<char *>(malloc(decodedLen));
102 if (buffer == nullptr) {
103 return ret;
104 }
105
106 BIO *bio = BIO_new_mem_buf(encoded.c_str(), encoded.length());
107 if (bio == nullptr) {
108 free(buffer);
109 return ret;
110 }
111
112 BIO *b64 = BIO_new(BIO_f_base64());
113 if (b64 == nullptr) {
114 CLOGE("Base64Encode error: BIO_f_base64 failed");
115 free(buffer);
116 BIO_free(bio);
117 return false;
118 }
119
120 BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
121 bio = BIO_push(b64, bio);
122 if (BIO_read(b64, buffer, encoded.length()) == static_cast<int32_t>(decodedLen)) {
123 decoded = std::string(buffer, decodedLen);
124 ret = true;
125 }
126
127 free(buffer);
128 BIO_free_all(b64);
129 return ret;
130 }
131
SplitString(const std::string & src,std::vector<std::string> & dest,const std::string & seperator)132 void Utils::SplitString(const std::string &src, std::vector<std::string> &dest, const std::string &seperator)
133 {
134 std::string::size_type beginPos = 0;
135 std::string::size_type endPos = src.find(seperator);
136 while (endPos != std::string::npos) {
137 dest.push_back(src.substr(beginPos, endPos - beginPos));
138 beginPos = endPos + seperator.size();
139 endPos = src.find(seperator, beginPos);
140 }
141 if (beginPos != src.length()) {
142 dest.push_back(src.substr(beginPos));
143 }
144 }
145
Trim(std::string & str)146 std::string &Utils::Trim(std::string &str)
147 {
148 if (str.empty()) {
149 return str;
150 }
151 str.erase(0, str.find_first_not_of(" "));
152 str.erase(str.find_last_not_of(" ") + 1);
153 return str;
154 }
155
ToLower(std::string & str)156 std::string &Utils::ToLower(std::string &str)
157 {
158 std::locale loc;
159 for (std::string::size_type i = 0; i < str.length(); ++i) {
160 str[i] = std::tolower(str[i], loc);
161 }
162 return str;
163 }
164
StartWith(const std::string & mainStr,const std::string & subStr)165 bool Utils::StartWith(const std::string &mainStr, const std::string &subStr)
166 {
167 return mainStr.find(subStr) == 0;
168 }
169
IntToByteArray(int num,int length,uint8_t * output)170 int Utils::IntToByteArray(int num, int length, uint8_t *output)
171 {
172 for (int i = 0; i < length; i++) {
173 output[length - 1 - i] = static_cast<uint8_t>(
174 (static_cast<unsigned int>(num) >> static_cast<unsigned int>(BYTE_TO_BIT_OFFSET * i))) &
175 INT_TO_BYTE;
176 }
177 return length;
178 }
179
ByteArrayToInt(const uint8_t * input,unsigned int length)180 uint32_t Utils::ByteArrayToInt(const uint8_t *input, unsigned int length)
181 {
182 uint32_t output = 0;
183 if (length > BYTE_TO_BIT_OFFSET) {
184 return output;
185 }
186 for (unsigned int i = 0; i < length; i++) {
187 output |= (input[i] << (BYTE_TO_BIT_OFFSET * (length - 1 - i)));
188 }
189 return output;
190 }
191
StringToInt(const std::string & str,int base)192 int32_t Utils::StringToInt(const std::string &str, int base)
193 {
194 if (str.size() == 0) {
195 return 0;
196 }
197 char *nextPtr = nullptr;
198 long result = strtol(str.c_str(), &nextPtr, base);
199 if (errno == ERANGE || *nextPtr != '\0') {
200 return 0;
201 }
202 return static_cast<int32_t>(result);
203 }
204
ConvertIpv4Address(unsigned int addressIpv4)205 std::string Utils::ConvertIpv4Address(unsigned int addressIpv4)
206 {
207 std::string address;
208 if (addressIpv4 == 0) {
209 return address;
210 }
211 std::ostringstream stream;
212 stream<<((addressIpv4>>OHOS::Wifi::BITS_24) & 0xFF)<<"."<<((addressIpv4>>OHOS::Wifi::BITS_16) & 0xFF)<<"."
213 <<((addressIpv4>>OHOS::Wifi::BITS_8) & 0xFF)<<"."<<(addressIpv4 & 0xFF);
214 address = stream.str();
215 return address;
216 }
217
GetWifiIp()218 std::string Utils::GetWifiIp()
219 {
220 std::shared_ptr<OHOS::Wifi::WifiDevice> wifiDevice = OHOS::Wifi::WifiDevice::GetInstance(WIFI_DEVICE_ABILITY_ID);
221 if (wifiDevice == nullptr) {
222 return "";
223 }
224 OHOS::Wifi::IpInfo ipInfo;
225 ErrCode ret = wifiDevice->GetIpInfo(ipInfo);
226 if (ret != OHOS::Wifi::WIFI_OPT_SUCCESS) {
227 return "";
228 }
229 std::string strIp = Utils::ConvertIpv4Address(ipInfo.ipAddress);
230 return strIp;
231 }
232
IsArrayAllZero(const uint8_t * input,int length)233 bool Utils::IsArrayAllZero(const uint8_t *input, int length)
234 {
235 bool isAllZero = true;
236 for (int i = 0; i < length; i++) {
237 if (input[i] != 0) {
238 isAllZero = false;
239 break;
240 }
241 }
242 return isAllZero;
243 }
244
TimeMilliSecond()245 uint64_t Utils::TimeMilliSecond()
246 {
247 struct timeval curTime = {0, 0};
248 gettimeofday(&curTime, nullptr);
249 return static_cast<int64_t>(curTime.tv_sec) * USEC_1000 + curTime.tv_usec / USEC_1000;
250 }
251
Mask(const std::string & str)252 std::string Utils::Mask(const std::string &str)
253 {
254 if (str.empty() || str.length() <= MASK_MIN_LEN) {
255 return str;
256 } else if (str.length() < (MASK_PRINT_PREFIX_LEN + MASK_PRINT_POSTFIX_LEN)) {
257 return str.substr(0, MASK_MIN_LEN) + "***" + str.substr(str.length() - 1);
258 } else {
259 return str.substr(0, MASK_PRINT_PREFIX_LEN) + "***" + str.substr(str.length() - MASK_PRINT_POSTFIX_LEN);
260 }
261 }
262
DrmUuidToType(std::string drmUUID)263 DrmType Utils::DrmUuidToType(std::string drmUUID)
264 {
265 if (drmUUID == UUID_CHINADRM) {
266 return DrmType::CHINADRM;
267 } else if (drmUUID == UUID_WIDEVINE) {
268 return DrmType::WIDEVINE;
269 } else if (drmUUID == UUID_PLAYREADY) {
270 return DrmType::PLAYREADY;
271 }
272 return DrmType::DRM_BASE;
273 }
274
GetCurrentActiveAccountUserId()275 int32_t Utils::GetCurrentActiveAccountUserId()
276 {
277 std::vector<int> activatedOsAccountIds;
278 OHOS::ErrCode res = OHOS::AccountSA::OsAccountManager::QueryActiveOsAccountIds(activatedOsAccountIds);
279 if (res != OHOS::ERR_OK || activatedOsAccountIds.size() <= 0) {
280 CLOGE("QueryActiveOsAccountIds failed res:%{public}d", res);
281 return DEFAULT_OS_ACCOUNT_ID;
282 }
283
284 int osAccountId = activatedOsAccountIds[0];
285 if (osAccountId != DEFAULT_OS_ACCOUNT_ID) {
286 CLOGI("currentOsAccount:%{public}d", osAccountId);
287 }
288
289 return osAccountId;
290 }
291
GetOhosAccountId()292 std::string Utils::GetOhosAccountId()
293 {
294 AccountSA::OhosAccountInfo accountInfo;
295 OHOS::ErrCode res = AccountSA::OhosAccountKits::GetInstance().GetOhosAccountInfo(accountInfo);
296 if (res != OHOS::ERR_OK || accountInfo.uid_ == "") {
297 CLOGE("GetOhosAccountInfo failed res:%{public}d", res);
298 return "";
299 }
300
301 return accountInfo.uid_;
302 }
303
SetFirstTokenID()304 int Utils::SetFirstTokenID()
305 {
306 uint32_t tokenId = IPCSkeleton::GetCallingTokenID();
307 auto ret = SetFirstCallerTokenID(tokenId);
308 CLOGI("SetFirstCallerTokenID ret %{public}d tokenId %{public}d", ret, tokenId);
309 return ret;
310 }
311
EnablePowerForceTimingOut()312 void Utils::EnablePowerForceTimingOut()
313 {
314 CLOGI("in");
315 if (isEnablePowerForceTimingOut.load()) {
316 CLOGI("already enable");
317 return;
318 }
319
320 isEnablePowerForceTimingOut = true;
321 auto& powerMgrClient = PowerMgrClient::GetInstance();
322 // 强制使能超时灭屏
323 powerMgrClient.SetForceTimingOut(true);
324 // 超时锁屏,但有常亮锁时不锁屏(如华为视频播放视频时不锁屏),且不发送熄屏广播
325 powerMgrClient.LockScreenAfterTimingOut(true, true, false);
326 }
327
ResetPowerForceTimingOut()328 void Utils::ResetPowerForceTimingOut()
329 {
330 CLOGI("in");
331
332 if (!isEnablePowerForceTimingOut.load()) {
333 CLOGI("already reset");
334 return;
335 }
336 isEnablePowerForceTimingOut = false;
337 auto& powerMgrClient = PowerMgrClient::GetInstance();
338 // 不强制使能超时灭屏
339 powerMgrClient.SetForceTimingOut(false);
340 // 超时锁屏,不受常亮锁影响(如华为视频播放视频时也锁屏),恢复发送熄屏广播
341 powerMgrClient.LockScreenAfterTimingOut(true, false, true);
342 }
343
LightAndLockScreen()344 void Utils::LightAndLockScreen()
345 {
346 auto& powerMgrClient = PowerMgrClient::GetInstance();
347 // 结束投屏时,如果手机是熄屏状态,要亮屏并锁屏
348 bool isScreenOn = powerMgrClient.IsScreenOn();
349 CLOGI("isScreenOn: %{public}d", isScreenOn);
350 if (!isScreenOn) {
351 PowerErrors wakeupRet = powerMgrClient.WakeupDevice(WakeupDeviceType::WAKEUP_DEVICE_APPLICATION,
352 std::string("cast+ exit playing"));
353 PowerErrors suspendRet = powerMgrClient.SuspendDevice();
354 CLOGI("wakeupRet: %{public}d, suspendRet: %{public}d", wakeupRet, suspendRet);
355 }
356 }
357
SetThreadName(const std::string & name)358 void Utils::SetThreadName(const std::string &name)
359 {
360 if (name.size() == 0) {
361 return;
362 }
363
364 static std::atomic<unsigned int> suffix = 0;
365 std::string threadName = name + "-" + std::to_string(suffix++);
366 if (prctl(PR_SET_NAME, threadName.c_str()) < 0) {
367 CLOGE("prctl errno %d", errno);
368 }
369 }
370
371 } // namespace CastEngineService
372 } // namespace CastEngine
373 } // namespace OHOS
374