1 /*
2 * Copyright (C) 2023 Huawei Technologies Co., Ltd.
3 * Licensed under the Mulan PSL v2.
4 * You can use this software according to the terms and conditions of the Mulan PSL v2.
5 * You may obtain a copy of Mulan PSL v2 at:
6 * http://license.coscl.org.cn/MulanPSL2
7 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
8 * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
9 * PURPOSE.
10 * See the Mulan PSL v2 for more details.
11 */
12
13 #include "tui_event.h"
14 #include <cctype>
15 #include <cstdint>
16 #include <cstring>
17 #include <ctime>
18 #include <cstdio>
19 #include <memory>
20 #include <fcntl.h>
21 #include <unistd.h>
22 #include <securec.h>
23 #include <securectype.h>
24 #include <sys/ioctl.h>
25
26 #include "tee_log.h"
27 #include "tc_ns_client.h"
28 #include "power_mgr_client.h"
29 #include "display_manager.h"
30 #include "display.h"
31 #include "display_info.h"
32 #include "call_manager_client.h"
33 #include "system_ability_definition.h"
34 #include "iservice_registry.h"
35
36 #ifdef LOG_TAG
37 #undef LOG_TAG
38 #endif
39 #define LOG_TAG "tee_tui_daemon"
40
41 using namespace std;
42 using namespace OHOS::PowerMgr;
43 using namespace OHOS::Rosen;
44 using namespace OHOS::Telephony;
45
46 TUIEvent *TUIEvent::tuiInstance = nullptr;
47
48 static const double INCH_CM_FACTOR = 2.54;
49 static const uint32_t TUI_POLL_CANCEL = 7;
50 static const uint32_t TUI_POLL_NOTCH = 24;
51 static const uint32_t TUI_POLL_FOLD = 26;
52
53 static const uint8_t TTF_HASH_SIZE = 32;
54 static const uint8_t TTF_STRING_SIZE = 64;
55 static const uint8_t HEX_BASE = 16;
56 static const uint8_t ASCII_DIGIT_GAP = 10;
57 static uint8_t g_ttfHash[TTF_HASH_SIZE];
58
59 static char g_hashVal[TTF_STRING_SIZE + 1] = {0};
60 static uint32_t g_hashLen = 0;
61 static bool g_tuiSendHashSuccess = false;
62 static bool g_tuiDisplayListenerRegisted = false;
63 static bool g_tuiCallBackRegisted = false;
64 static const int32_t RETRY_TIMES = 20;
65 static const uint32_t RETRY_SLEEP_TIME = 2;
66 std::unique_ptr<TUICallManagerCallback> mTUITelephonyCallBack_ = nullptr;
67 std::shared_ptr<OHOS::Telephony::CallManagerClient> callManagerClientPtr = nullptr;
68
TUISaveTTFHash(void)69 static void TUISaveTTFHash(void)
70 {
71 #ifndef FONT_HASH_VAL
72 tlogi("tui font hash not defined\n");
73 #else
74 const char *hashStr = FONT_HASH_VAL;
75 if (hashStr == NULL) {
76 tloge("get hashstr error\n");
77 return;
78 }
79
80 g_hashLen = (uint32_t)strlen(hashStr);
81 if (g_hashLen != TTF_STRING_SIZE) {
82 tloge("ttf hash invalid\n");
83 g_hashLen = 0;
84 return;
85 }
86 if (memcpy_s(g_hashVal, TTF_STRING_SIZE, hashStr, g_hashLen) != EOK) {
87 tloge("copy hash string failed\n");
88 g_hashLen = 0;
89 return;
90 }
91 #endif
92 return;
93 }
94
Ascii2Digit(char a)95 static uint8_t Ascii2Digit(char a)
96 {
97 uint8_t hex = 0;
98
99 if ((a >= '0') && (a <= '9')) {
100 hex = a - '0';
101 } else if ((a >= 'a') && (a <= 'f')) {
102 hex = (a - 'a') + ASCII_DIGIT_GAP;
103 } else if ((a >= 'A') && (a <= 'F')) {
104 hex = (a - 'A') + ASCII_DIGIT_GAP;
105 }
106
107 return hex;
108 }
109
TUISendEventToTz(TuiParameter * tuiParam)110 static bool TUISendEventToTz(TuiParameter *tuiParam)
111 {
112 int32_t fd = open(TC_NS_CLIENT_DEV_NAME, O_RDWR);
113 if (fd < 0) {
114 tloge("open tzdriver fd failed\n");
115 return false;
116 }
117 tlogd("TUISendEventToTz get fd = %{public}d\n", fd);
118
119 int32_t ret = ioctl(fd, (int)TC_NS_CLIENT_IOCTL_TUI_EVENT, tuiParam);
120 (void)close(fd);
121 if (ret != 0) {
122 tloge("Failed to send tui event[%{public}d] to tzdriver, ret is %{public}d \n",
123 tuiParam->eventType, ret);
124 return false;
125 }
126 return true;
127 }
128
TUISendTTFHashToTeeos(void)129 static void TUISendTTFHashToTeeos(void)
130 {
131 uint32_t i, j;
132 TuiParameter tuiParam = {.eventType = TUI_POLL_NOTCH};
133
134 if (g_tuiSendHashSuccess) {
135 return;
136 }
137
138 if (g_hashLen != TTF_STRING_SIZE) {
139 tloge("tui font hash len invalid\n");
140 g_hashLen = 0;
141 return;
142 }
143 tlogd("tui font hash is : %{public}s \n", g_hashVal);
144
145 for (i = 0, j = 0; g_hashLen > 0 && i < (g_hashLen - 1) && j < sizeof(g_ttfHash); j++) {
146 g_ttfHash[j] = Ascii2Digit(g_hashVal[i++]) * HEX_BASE;
147 g_ttfHash[j] += Ascii2Digit(g_hashVal[i++]);
148 }
149
150 int rc = memcpy_s(&tuiParam.value,
151 sizeof(tuiParam) - sizeof(tuiParam.eventType),
152 g_ttfHash, sizeof(g_ttfHash));
153 if (rc == EOK) {
154 if (TUISendEventToTz(&tuiParam) == true) {
155 g_tuiSendHashSuccess = true;
156 } else {
157 tloge("send notch msg failed\n");
158 }
159 } else {
160 tloge("memcpy tui font hash failed");
161 }
162 }
163
TUISetStatus(bool status)164 void TUIEvent::TUISetStatus(bool status)
165 {
166 mTUIStatus = status;
167 }
168
TUIGetStatus()169 bool TUIEvent::TUIGetStatus()
170 {
171 return mTUIStatus;
172 }
173
TUIGetPannelInfo()174 int TUIEvent::TUIGetPannelInfo()
175 {
176 auto display = OHOS::Rosen::DisplayManager::GetInstance().GetDefaultDisplay();
177 if (display == nullptr) {
178 tloge("GetDefaultDisplay: failed!\n");
179 return -1;
180 }
181 tlogi("GetDefaultDisplay: w %{public}d, h %{public}d, fps %{public}u\n",
182 display->GetWidth(),
183 display->GetHeight(),
184 display->GetRefreshRate());
185
186 OHOS::sptr<DisplayInfo> displayInfo = display->GetDisplayInfo();
187 if (displayInfo != nullptr) {
188 float xDpi = displayInfo->GetXDpi();
189 float yDpi = displayInfo->GetYDpi();
190 uint32_t displayState = (uint32_t)displayInfo->GetDisplayState();
191 tlogi("get xdpi %{public}f, ydpi %{public}f, displaystate %{public}u \n", xDpi, yDpi, displayState);
192 } else {
193 tloge("get displayInfo failed\n");
194 return -1;
195 }
196
197 mTUIPanelInfo.foldState = 0; // FOLD_STATE_UNKNOWN
198 mTUIPanelInfo.displayState = (uint32_t)displayInfo->GetDisplayState();
199 mTUIPanelInfo.notch = 0;
200 mTUIPanelInfo.width = display->GetWidth();
201 mTUIPanelInfo.height = display->GetHeight();
202 if (displayInfo->GetXDpi() != 0 && displayInfo->GetYDpi() != 0) {
203 mTUIPanelInfo.phyWidth = mTUIPanelInfo.width * INCH_CM_FACTOR / displayInfo->GetXDpi();
204 mTUIPanelInfo.phyHeight = mTUIPanelInfo.height * INCH_CM_FACTOR / displayInfo->GetYDpi();
205 }
206
207 return 0;
208 }
209
TUIGetRunningLock()210 void TUIEvent::TUIGetRunningLock()
211 {
212 if (mRunningLock_ == nullptr) {
213 auto &powerMgrClient = OHOS::PowerMgr::PowerMgrClient::GetInstance();
214 mRunningLock_ = powerMgrClient.CreateRunningLock("TuiDaemonRunningLock",
215 OHOS::PowerMgr::RunningLockType::RUNNINGLOCK_SCREEN);
216 }
217
218 if (mRunningLock_ != nullptr) {
219 mRunningLock_->Lock();
220 tlogi("TUI Get RunningLock\n");
221 }
222 return;
223 }
224
TUIReleaseRunningLock()225 void TUIEvent::TUIReleaseRunningLock()
226 {
227 if (mRunningLock_ != nullptr) {
228 mRunningLock_->UnLock();
229 }
230
231 tlogi("TUI Release RunningLock\n");
232 return;
233 }
234
TuiEventInit()235 void TUIEvent::TuiEventInit()
236 {
237 auto &powerMgrClient = OHOS::PowerMgr::PowerMgrClient::GetInstance();
238 mRunningLock_ = powerMgrClient.CreateRunningLock("TuiDaemonRunningLock",
239 OHOS::PowerMgr::RunningLockType::RUNNINGLOCK_SCREEN);
240
241 mTUIPanelInfo = { 0 };
242 mTUIStatus = false;
243
244 TUISendTTFHashToTeeos();
245
246 return;
247 }
248
TUISendCmd(uint32_t tuiEvent)249 bool TUIEvent::TUISendCmd(uint32_t tuiEvent)
250 {
251 TuiParameter tuiParam = {0};
252
253 if (tuiEvent == TUI_POLL_CANCEL) {
254 tuiParam.eventType = TUI_POLL_CANCEL;
255 tuiParam.value = 0;
256 } else {
257 (void)memcpy_s(&tuiParam, sizeof(tuiParam), &mTUIPanelInfo, sizeof(mTUIPanelInfo));
258 tuiParam.eventType = TUI_POLL_FOLD;
259 tuiParam.value = 0;
260 }
261
262 /* if not send hash success, try again */
263 TUISendTTFHashToTeeos();
264
265 if (TUISendEventToTz(&tuiParam) == false) {
266 return -1;
267 }
268
269 return 0;
270 }
271
TUIDealWithEvent(bool state)272 int32_t TUIEvent::TUIDealWithEvent(bool state)
273 {
274 if (state == false) {
275 /* not need send cmd to tzdriver */
276 TUIReleaseRunningLock();
277 TUISetStatus(false);
278 return 0;
279 }
280
281 TUIGetRunningLock();
282 TUIGetPannelInfo();
283 TUISetStatus(true);
284 return TUISendCmd(TUI_POLL_FOLD);
285 }
286
OnChange(OHOS::Rosen::DisplayId dId)287 void TUIDisplayListener::OnChange(OHOS::Rosen::DisplayId dId)
288 {
289 auto tempTUIInstance = TUIEvent::GetInstance();
290 if (tempTUIInstance == nullptr) {
291 return;
292 }
293
294 if (dId < 0) {
295 tloge("displayId invalid\n");
296 return;
297 }
298
299 tlogi("get TUIStatus is %{public}x\n", tempTUIInstance->TUIGetStatus());
300 /* if pannelinfo changed, should:
301 * 1. get pannelinfo,
302 * 2. send infos to teeos,
303 * 3. cancel current running proc
304 */
305 tempTUIInstance->TUIGetPannelInfo();
306 tempTUIInstance->TUISendCmd(TUI_POLL_FOLD); /* EVENT TUI_POLL_FOLD */
307 if (tempTUIInstance->TUIGetStatus() == true) {
308 tlogi("display state changed, need cancel TUI proc\n");
309 /* DO NOT change tuiStatus to false, and do not know why */
310 tempTUIInstance->TUISendCmd(TUI_POLL_CANCEL); /* EVENT Exit */
311 }
312 }
313
OnCallDetailsChange(const OHOS::Telephony::CallAttributeInfo & info)314 int32_t TUICallManagerCallback::OnCallDetailsChange(const OHOS::Telephony::CallAttributeInfo &info)
315 {
316 tlogd("----------OnCallDetailsChange--------\n");
317 tlogd("callId: %{public}x\n", info.callId);
318 tlogd("callType: %{public}x\n", (int32_t)info.callType);
319 tlogd("callState: %{public}x\n", (int32_t)info.callState);
320 tlogd("conferenceState: %{public}x\n", (int32_t)info.conferenceState);
321 tlogd("accountNumber: %{public}s\n", info.accountNumber);
322
323 if (info.callState == OHOS::Telephony::TelCallState::CALL_STATUS_INCOMING) {
324 /* call is incoming */
325 auto tempTUIInstance = TUIEvent::GetInstance();
326 if (tempTUIInstance->TUIGetStatus() == true) {
327 tlogi("new call state CALL_STATUS_INCOMING, need send cmd to teeos to cancel TUI proc\n");
328 tempTUIInstance->TUISetStatus(false); /* change tuiStatus to false */
329 tempTUIInstance->TUISendCmd(TUI_POLL_CANCEL); /* EVENT Exit */
330 }
331 tlogd("tui get new call state CALL_STATUS_INCOMING\n");
332 }
333 return 0;
334 }
335
CheckSAStarted(int32_t targetSAId)336 bool TUIDaemon::CheckSAStarted(int32_t targetSAId)
337 {
338 OHOS::sptr<OHOS::ISystemAbilityManager> systemAbilityManager =
339 OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
340 if (!systemAbilityManager) {
341 tlogi("Failed to get system ability mgr\n");
342 return false;
343 }
344
345 OHOS::sptr<OHOS::IRemoteObject> remoteObject = systemAbilityManager->GetSystemAbility(targetSAId);
346 if (!remoteObject) {
347 tlogi("SA service [targetID = %{public}d] is not exist\n", targetSAId);
348 return false;
349 }
350
351 tlogd("get SA service, targetID = %{public}d\n", targetSAId);
352 return true;
353 }
354
TuiRegisteCallBack()355 void TUIDaemon::TuiRegisteCallBack()
356 {
357 if (g_tuiCallBackRegisted) {
358 return;
359 }
360
361 int32_t retry = 0;
362 while (CheckSAStarted(OHOS::TELEPHONY_CALL_MANAGER_SYS_ABILITY_ID) == false) {
363 sleep(RETRY_SLEEP_TIME);
364 retry++;
365 if (retry >= RETRY_TIMES) {
366 tlogi("can not get telephony service now\n");
367 return;
368 }
369 }
370
371 if (mTUITelephonyCallBack_ == nullptr) {
372 mTUITelephonyCallBack_ = std::make_unique<TUICallManagerCallback>();
373 if (mTUITelephonyCallBack_ == nullptr) {
374 tloge("init callback instance failed\n");
375 return;
376 }
377 }
378
379 if (callManagerClientPtr == nullptr) {
380 callManagerClientPtr = OHOS::DelayedSingleton<OHOS::Telephony::CallManagerClient>::GetInstance();
381 if (callManagerClientPtr == nullptr) {
382 tloge("get callManagerClientPtr failed\n");
383 return;
384 }
385 }
386
387 tlogi("callback get instance finish\n");
388 callManagerClientPtr->Init(OHOS::TELEPHONY_CALL_MANAGER_SYS_ABILITY_ID);
389 tlogi("callback init finish\n");
390 int32_t ret = callManagerClientPtr->RegisterCallBack(std::move(mTUITelephonyCallBack_));
391 if (ret != TEEC_SUCCESS) {
392 tloge("regist telephony callback failed ret = 0x%{public}x\n", ret);
393 callManagerClientPtr->UnInit();
394 } else {
395 g_tuiCallBackRegisted = true;
396 tlogi("regist telephony callback done\n");
397 }
398 }
399
TuiRegisteDisplayListener()400 void TUIDaemon::TuiRegisteDisplayListener()
401 {
402 if (g_tuiDisplayListenerRegisted) {
403 return;
404 }
405
406 int32_t retry = 0;
407 while (CheckSAStarted(OHOS::DISPLAY_MANAGER_SERVICE_SA_ID) == false) {
408 sleep(RETRY_SLEEP_TIME);
409 retry++;
410 if (retry >= RETRY_TIMES) {
411 tlogi("can not get display service now\n");
412 return;
413 }
414 }
415
416 if (mTUIDisplayListener_ == nullptr) {
417 mTUIDisplayListener_ = new TUIDisplayListener();
418 if (mTUIDisplayListener_ == nullptr) {
419 tloge("create listener obj failed\n");
420 return;
421 }
422 }
423
424 OHOS::Rosen::DisplayManager& dmPtr = (OHOS::Rosen::DisplayManager::GetInstance());
425 int32_t result = (int32_t)dmPtr.RegisterDisplayListener(mTUIDisplayListener_);
426 if (result == TEEC_SUCCESS) {
427 g_tuiDisplayListenerRegisted = true;
428 tlogi("regist display listener done\n");
429 } else {
430 tloge("regist display listener failed\n");
431 }
432 }
433
TuiDaemonInit()434 void TUIDaemon::TuiDaemonInit()
435 {
436 TUISaveTTFHash();
437 auto tuiEvent = TUIEvent::GetInstance();
438 tuiEvent->TuiEventInit();
439
440 TuiRegisteCallBack();
441 TuiRegisteDisplayListener();
442
443 tlogi("TUIDaemon init ok\n");
444 }
445
~TUIDaemon()446 TUIDaemon::~TUIDaemon()
447 {
448 if (mTUIDisplayListener_ != nullptr) {
449 OHOS::Rosen::DisplayManager::GetInstance().UnregisterDisplayListener(mTUIDisplayListener_);
450 mTUIDisplayListener_ = nullptr;
451 }
452
453 OHOS::DelayedSingleton<OHOS::Telephony::CallManagerClient>::GetInstance()->UnInit();
454
455 tlogi("TUIDaemon released\n");
456 }