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 }