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_info.h"
30 #include "cutout_info.h"
31 #include "call_manager_client.h"
32 #include "system_ability_definition.h"
33 #include "iservice_registry.h"
34 #include "tee_file.h"
35 #ifdef SCENE_BOARD_ENABLE
36 #include "display_manager_lite.h"
37 #include "display_lite.h"
38 #else
39 #include "display_manager.h"
40 #include "display.h"
41 #endif
42
43 #ifdef LOG_TAG
44 #undef LOG_TAG
45 #endif
46 #define LOG_TAG "tee_tui_daemon"
47
48 using namespace std;
49 using namespace OHOS::PowerMgr;
50 using namespace OHOS::Rosen;
51 using namespace OHOS::Telephony;
52
53 TUIEvent *TUIEvent::tuiInstance = nullptr;
54
55 static const uint32_t NOTCH_SIZE_MAX = 200;
56 static const double INCH_CM_FACTOR = 2.54;
57 static const uint32_t TUI_POLL_CANCEL = 7;
58 static const uint32_t TUI_POLL_NOTCH = 24;
59 static const uint32_t TUI_POLL_FOLD = 26;
60 static const uint32_t TUI_NEED_ROTATE = 256;
61
62 static const uint8_t TTF_HASH_SIZE = 32;
63 static const uint8_t TTF_STRING_SIZE = 64;
64 static const uint8_t HEX_BASE = 16;
65 static const uint8_t ASCII_DIGIT_GAP = 10;
66 static uint8_t g_ttfHash[TTF_HASH_SIZE];
67
68 static char g_hashVal[TTF_STRING_SIZE + 1] = {0};
69 static uint32_t g_hashLen = 0;
70 static bool g_tuiSendHashSuccess = false;
71 static bool g_tuiDisplayListenerRegisted = false;
72 static bool g_tuiCallBackRegisted = false;
73 static const int32_t RETRY_TIMES = 20;
74 static const uint32_t RETRY_SLEEP_TIME = 2;
75 static std::unique_ptr<TUICallManagerCallback> mTUITelephonyCallBack_ = nullptr;
76 static std::shared_ptr<OHOS::Telephony::CallManagerClient> callManagerClientPtr = nullptr;
77
TUISaveTTFHash(void)78 static void TUISaveTTFHash(void)
79 {
80 #ifndef FONT_HASH_VAL
81 tlogi("tui font hash not defined\n");
82 #else
83 const char *hashStr = FONT_HASH_VAL;
84 if (hashStr == NULL) {
85 tloge("get hashstr error\n");
86 return;
87 }
88
89 g_hashLen = (uint32_t)strlen(hashStr);
90 if (g_hashLen != TTF_STRING_SIZE) {
91 tloge("ttf hash invalid\n");
92 g_hashLen = 0;
93 return;
94 }
95 if (memcpy_s(g_hashVal, TTF_STRING_SIZE, hashStr, g_hashLen) != EOK) {
96 tloge("copy hash string failed\n");
97 g_hashLen = 0;
98 return;
99 }
100 #endif
101 return;
102 }
103
Ascii2Digit(char a)104 static uint8_t Ascii2Digit(char a)
105 {
106 uint8_t hex = 0;
107
108 if ((a >= '0') && (a <= '9')) {
109 hex = a - '0';
110 } else if ((a >= 'a') && (a <= 'f')) {
111 hex = (a - 'a') + ASCII_DIGIT_GAP;
112 } else if ((a >= 'A') && (a <= 'F')) {
113 hex = (a - 'A') + ASCII_DIGIT_GAP;
114 }
115
116 return hex;
117 }
118
TUISendEventToTz(TuiParameter * tuiParam)119 static bool TUISendEventToTz(TuiParameter *tuiParam)
120 {
121 int32_t fd = tee_open(TC_NS_CLIENT_DEV_NAME, O_RDWR, 0);
122 if (fd < 0) {
123 tloge("open tzdriver fd failed\n");
124 return false;
125 }
126 tlogd("TUISendEventToTz get fd = %" PUBLIC "d\n", fd);
127
128 int32_t ret = ioctl(fd, (int)TC_NS_CLIENT_IOCTL_TUI_EVENT, tuiParam);
129 tee_close(&fd);
130 if (ret != 0) {
131 tloge("Failed to send tui event[%" PUBLIC "d] to tzdriver, ret is %" PUBLIC "d \n",
132 tuiParam->eventType, ret);
133 return false;
134 }
135 return true;
136 }
137
TUISendTTFHashToTeeos(void)138 static void TUISendTTFHashToTeeos(void)
139 {
140 uint32_t i, j;
141 TuiParameter tuiParam = {.eventType = TUI_POLL_NOTCH};
142
143 if (g_tuiSendHashSuccess) {
144 return;
145 }
146
147 if (g_hashLen != TTF_STRING_SIZE) {
148 tloge("tui font hash len invalid\n");
149 g_hashLen = 0;
150 return;
151 }
152 tlogd("tui font hash is : %" PUBLIC "s \n", g_hashVal);
153
154 for (i = 0, j = 0; g_hashLen > 0 && i < (g_hashLen - 1) && j < sizeof(g_ttfHash); j++) {
155 g_ttfHash[j] = Ascii2Digit(g_hashVal[i++]) * HEX_BASE;
156 g_ttfHash[j] += Ascii2Digit(g_hashVal[i++]);
157 }
158
159 int rc = memcpy_s(&tuiParam.value,
160 sizeof(tuiParam) - sizeof(tuiParam.eventType),
161 g_ttfHash, sizeof(g_ttfHash));
162 if (rc == EOK) {
163 if (TUISendEventToTz(&tuiParam)) {
164 g_tuiSendHashSuccess = true;
165 } else {
166 tloge("send notch msg failed\n");
167 }
168 } else {
169 tloge("memcpy tui font hash failed");
170 }
171 }
172
TUISetStatus(bool status)173 void TUIEvent::TUISetStatus(bool status)
174 {
175 mTUIStatus = status;
176 }
177
TUIGetStatus()178 bool TUIEvent::TUIGetStatus()
179 {
180 return mTUIStatus;
181 }
182
TUIGetFoldableStatus()183 bool TUIEvent::TUIGetFoldableStatus()
184 {
185 return mTUIFoldable;
186 }
187
TUIGetNotch(OHOS::sptr<CutoutInfo> cutoutInfo,uint32_t displayMode)188 static int TUIGetNotch(OHOS::sptr<CutoutInfo> cutoutInfo, uint32_t displayMode)
189 {
190 tlogi("tui get cutoutinfo--->boundingRects for notch\n");
191 std::vector<OHOS::Rosen::DMRect> boundingRects = cutoutInfo->GetBoundingRects();
192 if (boundingRects.empty()) {
193 tlogi("get boundingRects failed\n");
194 return 0;
195 }
196 for (uint32_t i = 0; i < boundingRects.size(); i++) {
197 tlogi("tui print boundingRects[%" PUBLIC "d] info: \
198 posX[%" PUBLIC "d], posY[%" PUBLIC "d], width[%" PUBLIC "d], height[%" PUBLIC "d] \n",
199 i, boundingRects[i].posX_, boundingRects[i].posY_,
200 boundingRects[i].width_, boundingRects[i].height_);
201 }
202 /* calc notch, here is px, double height of the hole */
203 int notch = boundingRects[0].height_ + boundingRects[0].height_;
204 if (notch < 0 || notch > NOTCH_SIZE_MAX) {
205 /* 200 is too large for notch, just use 0 */
206 return 0;
207 }
208 return notch;
209 }
210
TUIGetDisplayMode(uint32_t foldState)211 static uint32_t TUIGetDisplayMode(uint32_t foldState)
212 {
213 if (foldState == FOLD_STATE_EXPANDED) {
214 return DISPLAY_MODE_FULL;
215 }
216
217 #ifdef SCENE_BOARD_ENABLE
218 uint32_t displayMode = static_cast<uint32_t>(OHOS::Rosen::DisplayManagerLite::GetInstance().GetFoldDisplayMode());
219 #else
220 uint32_t displayMode = static_cast<uint32_t>(OHOS::Rosen::DisplayManager::GetInstance().GetFoldDisplayMode());
221 #endif
222 if (displayMode < DISPLAY_MODE_MAX) {
223 return displayMode;
224 }
225
226 return DISPLAY_MODE_UNKNOWN; /* default mode */
227 }
228
CheckSAStarted(int32_t targetSAId)229 bool CheckSAStarted(int32_t targetSAId)
230 {
231 OHOS::sptr<OHOS::ISystemAbilityManager> systemAbilityManager =
232 OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
233 if (!systemAbilityManager) {
234 tlogi("Failed to get system ability mgr\n");
235 return false;
236 }
237
238 OHOS::sptr<OHOS::IRemoteObject> remoteObject = systemAbilityManager->GetSystemAbility(targetSAId);
239 if (!remoteObject) {
240 tlogi("SA service [targetID = %" PUBLIC "d] is not exist\n", targetSAId);
241 return false;
242 }
243
244 tlogd("get SA service, targetID = %" PUBLIC "d\n", targetSAId);
245 return true;
246 }
247
IsDisplaySAReady()248 static bool IsDisplaySAReady()
249 {
250 int32_t retry = 0;
251 #ifdef SCENE_BOARD_ENABLE
252 while (!CheckSAStarted(OHOS::WINDOW_MANAGER_SERVICE_ID)) {
253 #else
254 while (!CheckSAStarted(OHOS::DISPLAY_MANAGER_SERVICE_SA_ID)) {
255 #endif
256 if (retry++ >= RETRY_TIMES) {
257 tlogi("can not get display service now\n");
258 return false;
259 }
260 sleep(RETRY_SLEEP_TIME);
261 }
262
263 return true;
264 }
265
266 bool TUIEvent::TUIGetPannelInfo()
267 {
268 if (!IsDisplaySAReady()) {
269 return false;
270 }
271
272 #ifdef SCENE_BOARD_ENABLE
273 auto display = OHOS::Rosen::DisplayManagerLite::GetInstance().GetDefaultDisplay();
274 #else
275 auto display = OHOS::Rosen::DisplayManager::GetInstance().GetDefaultDisplay();
276 #endif
277 if (display == nullptr) {
278 tloge("GetDefaultDisplay: failed!\n");
279 return false;
280 }
281
282 OHOS::sptr<DisplayInfo> displayInfo = display->GetDisplayInfo();
283 if (displayInfo != nullptr) {
284 tlogi("get xdpi %" PUBLIC "f, ydpi %" PUBLIC "f, displaystate %" PUBLIC "u, DPI %" PUBLIC "d \n",
285 displayInfo->GetXDpi(), displayInfo->GetYDpi(),
286 (uint32_t)displayInfo->GetDisplayState(), displayInfo->GetDpi());
287 } else {
288 tloge("get displayInfo failed\n");
289 return false;
290 }
291
292 TUIGetFoldable();
293
294 mTUIPanelInfo.width = display->GetWidth();
295 mTUIPanelInfo.height = display->GetHeight();
296
297 if (displayInfo->GetXDpi() != 0 && displayInfo->GetYDpi() != 0) {
298 mTUIPanelInfo.phyWidth = mTUIPanelInfo.width * INCH_CM_FACTOR / displayInfo->GetXDpi();
299 mTUIPanelInfo.phyHeight = mTUIPanelInfo.height * INCH_CM_FACTOR / displayInfo->GetYDpi();
300 }
301
302 OHOS::sptr<CutoutInfo> cutoutInfo = display->GetCutoutInfo();
303 if (cutoutInfo == nullptr) {
304 tloge("get cutoutinfo failed\n");
305 } else {
306 mTUIPanelInfo.notch = TUIGetNotch(cutoutInfo, mTUIPanelInfo.displayMode);
307 }
308
309 tlogi("tui panelinfo: w %" PUBLIC "d, h %" PUBLIC "d, fold %" PUBLIC "u, "
310 "displayMode %" PUBLIC "u, notch %" PUBLIC "u\n",
311 mTUIPanelInfo.width, mTUIPanelInfo.height, mTUIPanelInfo.foldState,
312 mTUIPanelInfo.displayMode, mTUIPanelInfo.notch);
313
314 return true;
315 }
316
317 void TUIEvent::TUIGetFoldable()
318 {
319 #ifdef SCENE_BOARD_ENABLE
320 mTUIFoldable = OHOS::Rosen::DisplayManagerLite::GetInstance().IsFoldable();
321 #else
322 mTUIFoldable = OHOS::Rosen::DisplayManager::GetInstance().IsFoldable();
323 #endif
324 tlogi("TuiDaemonInit mTUIFoldable %" PUBLIC "d\n", mTUIFoldable);
325 if (mTUIFoldable) {
326 tlogi("tui get fold state\n");
327 #ifdef SCENE_BOARD_ENABLE
328 mTUIPanelInfo.foldState = static_cast<uint32_t>(OHOS::Rosen::DisplayManagerLite::GetInstance().GetFoldStatus());
329 #else
330 mTUIPanelInfo.foldState = static_cast<uint32_t>(OHOS::Rosen::DisplayManager::GetInstance().GetFoldStatus());
331 #endif
332 if (mTUIPanelInfo.foldState >= FOLD_STATE_HALF_FOLDED) {
333 mTUIPanelInfo.foldState = FOLD_STATE_UNKNOWN; /* default state */
334 }
335 } else {
336 mTUIPanelInfo.foldState = FOLD_STATE_UNKNOWN;
337 }
338
339 mTUIPanelInfo.displayMode = TUIGetDisplayMode(mTUIPanelInfo.foldState);
340 if (mTUIPanelInfo.foldState == FOLD_STATE_EXPANDED) {
341 mTUIPanelInfo.foldState += TUI_NEED_ROTATE;
342 }
343
344 return;
345 }
346
347 void TUIEvent::TUIGetRunningLock()
348 {
349 if (mRunningLock_ == nullptr) {
350 auto &powerMgrClient = OHOS::PowerMgr::PowerMgrClient::GetInstance();
351 mRunningLock_ = powerMgrClient.CreateRunningLock("TuiDaemonRunningLock",
352 OHOS::PowerMgr::RunningLockType::RUNNINGLOCK_SCREEN);
353 }
354
355 if (mRunningLock_ != nullptr) {
356 mRunningLock_->Lock();
357 tlogi("TUI Get RunningLock\n");
358 }
359 return;
360 }
361
362 void TUIEvent::TUIReleaseRunningLock()
363 {
364 if (mRunningLock_ != nullptr) {
365 mRunningLock_->UnLock();
366 }
367
368 tlogi("TUI Release RunningLock\n");
369 return;
370 }
371
372 void TUIEvent::TuiEventInit()
373 {
374 mRunningLock_ = nullptr;
375
376 mTUIPanelInfo = { 0 };
377 mTUIStatus = false;
378 mTUIFoldable = false;
379
380 return;
381 }
382
383 bool TUIEvent::TUISendCmd(uint32_t tuiEvent)
384 {
385 TuiParameter tuiParam = {0};
386
387 if (tuiEvent == TUI_POLL_CANCEL) {
388 tuiParam.eventType = TUI_POLL_CANCEL;
389 tuiParam.value = 0;
390 } else {
391 (void)memcpy_s(&tuiParam, sizeof(tuiParam), &mTUIPanelInfo, sizeof(mTUIPanelInfo));
392 tuiParam.eventType = TUI_POLL_FOLD;
393 tuiParam.value = 0;
394 }
395
396 /* if not send hash success, try again */
397 TUISendTTFHashToTeeos();
398
399 if (TUISendEventToTz(&tuiParam) == false) {
400 tloge("tui send cmd failed\n");
401 return false;
402 }
403
404 return true;
405 }
406
407 void TUIEvent::TUIDealWithEvent(bool state)
408 {
409 if (state == false) {
410 /* not need send cmd to tzdriver */
411 TUIReleaseRunningLock();
412 TUISetStatus(false);
413 return;
414 }
415
416 TUIGetRunningLock();
417 TUIGetPannelInfo();
418 TUISetStatus(true);
419 TUISendCmd(TUI_POLL_FOLD);
420 }
421
422 void TUIDisplayListener::OnFoldStatusChanged(OHOS::Rosen::FoldStatus foldState)
423 {
424 if (foldState != OHOS::Rosen::FoldStatus::EXPAND && foldState != OHOS::Rosen::FoldStatus::FOLDED) {
425 tloge("foldState = %" PUBLIC "u invalid\n", static_cast<uint32_t>(foldState));
426 return;
427 }
428
429 /* if foldState changed, should:
430 * 1. get pannelinfo,
431 * 2. send infos to teeos,
432 * 3. cancel current running proc
433 */
434 auto tempTUIInstance = TUIEvent::GetInstance();
435 if (tempTUIInstance == nullptr) {
436 return;
437 }
438 tlogi("get TUIStatus is %" PUBLIC "x\n", tempTUIInstance->TUIGetStatus());
439 if (tempTUIInstance->TUIGetPannelInfo()) {
440 (void)tempTUIInstance->TUISendCmd(TUI_POLL_FOLD); /* EVENT TUI_POLL_FOLD */
441 }
442 if (tempTUIInstance->TUIGetStatus()) {
443 tlogi("foldState changed, need cancel TUI proc\n");
444 (void)tempTUIInstance->TUISendCmd(TUI_POLL_CANCEL); /* EVENT Exit */
445 }
446 }
447
448 int32_t TUICallManagerCallback::OnCallDetailsChange(const OHOS::Telephony::CallAttributeInfo &info)
449 {
450 tlogd("----------OnCallDetailsChange--------\n");
451 tlogd("callId: %" PUBLIC "x\n", info.callId);
452 tlogd("callType: %" PUBLIC "x\n", (int32_t)info.callType);
453 tlogd("callState: %" PUBLIC "x\n", (int32_t)info.callState);
454 tlogd("conferenceState: %" PUBLIC "x\n", (int32_t)info.conferenceState);
455 tlogd("accountNumber: %" PUBLIC "s\n", info.accountNumber);
456
457 if (info.callState == OHOS::Telephony::TelCallState::CALL_STATUS_INCOMING) {
458 auto tempTUIInstance = TUIEvent::GetInstance();
459 if (tempTUIInstance->TUIGetStatus()) {
460 tlogi("new call state CALL_STATUS_INCOMING, need send cmd to teeos to cancel TUI proc\n");
461 tempTUIInstance->TUISetStatus(false); /* change tuiStatus to false */
462 (void)tempTUIInstance->TUISendCmd(TUI_POLL_CANCEL); /* EVENT Exit */
463 }
464 tlogd("tui get new call state CALL_STATUS_INCOMING\n");
465 }
466 return 0;
467 }
468
469 void TUIDaemon::TuiRegisteCallBack()
470 {
471 if (g_tuiCallBackRegisted) {
472 return;
473 }
474
475 int32_t retry = 0;
476 while (CheckSAStarted(OHOS::TELEPHONY_CALL_MANAGER_SYS_ABILITY_ID) == false) {
477 sleep(RETRY_SLEEP_TIME);
478 retry++;
479 if (retry >= RETRY_TIMES) {
480 tlogi("can not get telephony service now\n");
481 return;
482 }
483 }
484
485 if (mTUITelephonyCallBack_ == nullptr) {
486 mTUITelephonyCallBack_ = std::make_unique<TUICallManagerCallback>();
487 if (mTUITelephonyCallBack_ == nullptr) {
488 tloge("init callback instance failed\n");
489 return;
490 }
491 }
492
493 if (callManagerClientPtr == nullptr) {
494 callManagerClientPtr = OHOS::DelayedSingleton<OHOS::Telephony::CallManagerClient>::GetInstance();
495 if (callManagerClientPtr == nullptr) {
496 tloge("get callManagerClientPtr failed\n");
497 return;
498 }
499 }
500
501 tlogi("callback get instance finish\n");
502 callManagerClientPtr->Init(OHOS::TELEPHONY_CALL_MANAGER_SYS_ABILITY_ID);
503 tlogi("callback init finish\n");
504 int32_t ret = callManagerClientPtr->RegisterCallBack(std::move(mTUITelephonyCallBack_));
505 if (ret != TEEC_SUCCESS) {
506 tloge("regist telephony callback failed ret = 0x%" PUBLIC "x\n", ret);
507 } else {
508 g_tuiCallBackRegisted = true;
509 tlogi("regist telephony callback done\n");
510 }
511 }
512
513 void TUIDaemon::TuiRegisteDisplayListener()
514 {
515 if (g_tuiDisplayListenerRegisted) {
516 return;
517 }
518
519 if (!IsDisplaySAReady()) {
520 return;
521 }
522
523 if (mTUIDisplayListener_ == nullptr) {
524 mTUIDisplayListener_ = new TUIDisplayListener();
525 if (mTUIDisplayListener_ == nullptr) {
526 tloge("create listener obj failed\n");
527 return;
528 }
529 }
530 #ifdef SCENE_BOARD_ENABLE
531 OHOS::Rosen::DisplayManagerLite &dmPtr = (OHOS::Rosen::DisplayManagerLite::GetInstance());
532 #else
533 OHOS::Rosen::DisplayManager &dmPtr = (OHOS::Rosen::DisplayManager::GetInstance());
534 #endif
535 int32_t result = (int32_t)dmPtr.RegisterFoldStatusListener(mTUIDisplayListener_);
536 if (result == TEEC_SUCCESS) {
537 g_tuiDisplayListenerRegisted = true;
538 tlogi("regist display listener done\n");
539 } else {
540 tloge("regist display listener failed\n");
541 }
542 }
543
544 void TUIDaemon::TuiDaemonInit(bool onlyConfigRes)
545 {
546 TUISaveTTFHash();
547 auto tuiEvent = TUIEvent::GetInstance();
548 tuiEvent->TuiEventInit();
549
550 if (!onlyConfigRes) {
551 TuiRegisteCallBack();
552 TuiRegisteDisplayListener();
553 }
554
555 tlogi("TUIDaemon init ok\n");
556 }
557
558 TUIDaemon::~TUIDaemon()
559 {
560 if (mTUIDisplayListener_ != nullptr) {
561 #ifdef SCENE_BOARD_ENABLE
562 OHOS::Rosen::DisplayManagerLite::GetInstance().UnregisterFoldStatusListener(mTUIDisplayListener_);
563 #else
564 OHOS::Rosen::DisplayManager::GetInstance().UnregisterFoldStatusListener(mTUIDisplayListener_);
565 #endif
566 mTUIDisplayListener_ = nullptr;
567 }
568
569 if (g_tuiCallBackRegisted) {
570 OHOS::DelayedSingleton<OHOS::Telephony::CallManagerClient>::GetInstance()->UnRegisterCallBack();
571 g_tuiCallBackRegisted = false;
572 }
573
574 tlogi("TUIDaemon released\n");
575 }
576