• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023-2024 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 "widget_context.h"
16 
17 #include <algorithm>
18 #include "bool_wrapper.h"
19 #include "double_wrapper.h"
20 #include "int_wrapper.h"
21 #include "refbase.h"
22 
23 #include "ability_connection.h"
24 #include "ability_connect_callback.h"
25 #include "accesstoken_kit.h"
26 #include "auth_widget_helper.h"
27 #include "context_helper.h"
28 #include "context_pool.h"
29 #include "context_death_recipient.h"
30 #include "hisysevent_adapter.h"
31 #include "iam_check.h"
32 #include "iam_logger.h"
33 #include "iam_para2str.h"
34 #include "iam_ptr.h"
35 #include "iam_time.h"
36 #include "parameters.h"
37 #include "relative_timer.h"
38 #include "schedule_node.h"
39 #include "schedule_node_callback.h"
40 #include "string_wrapper.h"
41 #include "system_ability_definition.h"
42 #include "want_params_wrapper.h"
43 #include "widget_schedule_node_impl.h"
44 #include "widget_context_callback_impl.h"
45 #include "widget_client.h"
46 #include <sys/stat.h>
47 #ifdef SCENE_BOARD_ENABLE
48 #include "display_manager_lite.h"
49 #else
50 #include "display_manager.h"
51 #endif
52 
53 #define LOG_TAG "USER_AUTH_SA"
54 
55 namespace OHOS {
56 namespace UserIam {
57 namespace UserAuth {
58 constexpr int32_t DEFAULT_VALUE = -1;
59 const std::string UI_EXTENSION_TYPE_SET = "sysDialog/userAuth";
60 const uint32_t SYSDIALOG_ZORDER_DEFAULT = 1;
61 const uint32_t SYSDIALOG_ZORDER_UPPER = 2;
62 const uint32_t ORIENTATION_LANDSCAPE = 1;
63 const uint32_t ORIENTATION_PORTRAIT_INVERTED = 2;
64 const uint32_t ORIENTATION_LANDSCAPE_INVERTED = 3;
65 const std::string TO_PORTRAIT = "90";
66 const std::string TO_INVERTED = "180";
67 const std::string TO_PORTRAIT_INVERTED = "270";
68 const std::string SUPPORT_FOLLOW_CALLER_UI = "const.useriam.authWidget.supportFollowCallerUi";
69 
WidgetContext(uint64_t contextId,const ContextFactory::AuthWidgetContextPara & para,std::shared_ptr<ContextCallback> callback,const sptr<IModalCallback> & modalCallback)70 WidgetContext::WidgetContext(uint64_t contextId, const ContextFactory::AuthWidgetContextPara &para,
71     std::shared_ptr<ContextCallback> callback, const sptr<IModalCallback> &modalCallback)
72     : contextId_(contextId), description_("UserAuthWidget"), callerCallback_(callback), hasStarted_(false),
73     latestError_(ResultCode::GENERAL_ERROR), para_(para), schedule_(nullptr), modalCallback_(modalCallback),
74     connection_(nullptr)
75 {
76     AddDeathRecipient(callerCallback_, contextId_);
77     if (!para.isBackgroundApplication) {
78         SubscribeAppState(callerCallback_, contextId_);
79     }
80     LoadConfigJsonBuffer(jsonBuf_);
81 }
82 
~WidgetContext()83 WidgetContext::~WidgetContext()
84 {
85     IAM_LOGD("release WidgetContext");
86     RemoveDeathRecipient(callerCallback_);
87     UnSubscribeAppState();
88 }
89 
Start()90 bool WidgetContext::Start()
91 {
92     IAM_LOGD("%{public}s start", description_.c_str());
93     std::lock_guard<std::recursive_mutex> lock(mutex_);
94     if (hasStarted_) {
95         IAM_LOGI("%{public}s context has started, cannot start again", description_.c_str());
96         return false;
97     }
98     hasStarted_ = true;
99     return OnStart();
100 }
101 
Stop()102 bool WidgetContext::Stop()
103 {
104     IAM_LOGI("%{public}s start", description_.c_str());
105     return OnStop();
106 }
107 
GetContextId() const108 uint64_t WidgetContext::GetContextId() const
109 {
110     return contextId_;
111 }
112 
GetContextType() const113 ContextType WidgetContext::GetContextType() const
114 {
115     return WIDGET_AUTH_CONTEXT;
116 }
117 
GetScheduleNode(uint64_t scheduleId) const118 std::shared_ptr<ScheduleNode> WidgetContext::GetScheduleNode(uint64_t scheduleId) const
119 {
120     return nullptr;
121 }
122 
GetTokenId() const123 uint32_t WidgetContext::GetTokenId() const
124 {
125     return para_.tokenId;
126 }
127 
GetUserId() const128 int32_t WidgetContext::GetUserId() const
129 {
130     return para_.userId;
131 }
132 
GetAuthType() const133 int32_t WidgetContext::GetAuthType() const
134 {
135     return INVALID_AUTH_TYPE;
136 }
137 
GetCallerName() const138 std::string WidgetContext::GetCallerName() const
139 {
140     return para_.callerName;
141 }
142 
GetLatestError() const143 int32_t WidgetContext::GetLatestError() const
144 {
145     return latestError_;
146 }
147 
SetLatestError(int32_t error)148 void WidgetContext::SetLatestError(int32_t error)
149 {
150     if (error != ResultCode::SUCCESS) {
151         latestError_ = error;
152     }
153 }
154 
BuildSchedule()155 bool WidgetContext::BuildSchedule()
156 {
157     schedule_ = Common::MakeShared<WidgetScheduleNodeImpl>();
158     IF_FALSE_LOGE_AND_RETURN_VAL(schedule_ != nullptr, false);
159     schedule_->SetCallback(shared_from_this());
160     return true;
161 }
162 
GetAuthContextCallback(AuthType authType,AuthTrustLevel authTrustLevel,sptr<IIamCallback> & iamCallback)163 std::shared_ptr<ContextCallback> WidgetContext::GetAuthContextCallback(AuthType authType,
164     AuthTrustLevel authTrustLevel, sptr<IIamCallback> &iamCallback)
165 {
166     auto widgetCallback = ContextCallback::NewInstance(iamCallback, TRACE_AUTH_USER_SECURITY);
167     if (widgetCallback == nullptr) {
168         IAM_LOGE("failed to construct context callback");
169         Attributes extraInfo;
170         iamCallback->OnResult(ResultCode::GENERAL_ERROR, extraInfo.Serialize());
171         return nullptr;
172     }
173     widgetCallback->SetTraceCallerName(para_.callerName);
174     widgetCallback->SetTraceCallerType(para_.callerType);
175     widgetCallback->SetTraceRequestContextId(contextId_);
176     widgetCallback->SetTraceAuthTrustLevel(authTrustLevel);
177     widgetCallback->SetTraceAuthType(authType);
178     return widgetCallback;
179 }
180 
BuildTask(const std::vector<uint8_t> & challenge,AuthType authType,AuthTrustLevel authTrustLevel,bool endAfterFirstFail,AuthIntent authIntent)181 std::shared_ptr<Context> WidgetContext::BuildTask(const std::vector<uint8_t> &challenge,
182     AuthType authType, AuthTrustLevel authTrustLevel, bool endAfterFirstFail, AuthIntent authIntent)
183 {
184     IF_FALSE_LOGE_AND_RETURN_VAL(callerCallback_ != nullptr, nullptr);
185     auto userId = para_.userId;
186     auto tokenId = WidgetClient::Instance().GetAuthTokenId();
187     IAM_LOGI("Real userId: %{public}d, Real tokenId: %{public}s", userId, GET_MASKED_STRING(tokenId).c_str());
188     sptr<IIamCallback> iamCallback(new (std::nothrow) WidgetContextCallbackImpl(weak_from_this(),
189         static_cast<int32_t>(authType)));
190     IF_FALSE_LOGE_AND_RETURN_VAL(iamCallback != nullptr, nullptr);
191     auto widgetCallback = GetAuthContextCallback(authType, authTrustLevel, iamCallback);
192     IF_FALSE_LOGE_AND_RETURN_VAL(widgetCallback != nullptr, nullptr);
193 
194     Authentication::AuthenticationPara para = {};
195     para.tokenId = tokenId;
196     para.userId = userId;
197     para.authType = authType;
198     para.atl = authTrustLevel;
199     para.challenge = challenge;
200     para.endAfterFirstFail = endAfterFirstFail;
201     para.callerName = para_.callerName;
202     para.callerType = para_.callerType;
203     para.sdkVersion = para_.sdkVersion;
204     para.authIntent = authIntent;
205     para.skipLockedBiometricAuth = para_.skipLockedBiometricAuth;
206     para.isOsAccountVerified = para_.isOsAccountVerified;
207     auto context = ContextFactory::CreateSimpleAuthContext(para, widgetCallback, true);
208     if (context == nullptr || !ContextPool::Instance().Insert(context)) {
209         IAM_LOGE("failed to insert context");
210         Attributes extraInfo;
211         widgetCallback->SetTraceAuthFinishReason("WidgetContext BuildTask insert context fail");
212         widgetCallback->OnResult(ResultCode::GENERAL_ERROR, extraInfo);
213         return nullptr;
214     }
215     widgetCallback->SetTraceAuthContextId(context->GetContextId());
216     widgetCallback->SetCleaner(ContextHelper::Cleaner(context));
217     std::lock_guard<std::recursive_mutex> lock(mutex_);
218     return context;
219 }
220 
OnStart()221 bool WidgetContext::OnStart()
222 {
223     IAM_LOGI("%{public}s start", description_.c_str());
224     if (!BuildSchedule()) {
225         IAM_LOGE("failed to create widget schedule");
226         return false;
227     }
228     IF_FALSE_LOGE_AND_RETURN_VAL(schedule_ != nullptr, false);
229     WidgetClient::Instance().SetWidgetParam(para_.widgetParam);
230     WidgetClient::Instance().SetAuthTypeList(para_.authTypeList);
231     WidgetClient::Instance().SetWidgetSchedule(GetContextId(), schedule_);
232     WidgetClient::Instance().SetChallenge(para_.challenge);
233     WidgetClient::Instance().SetCallingBundleName(GetCallingBundleName());
234     schedule_->StartSchedule();
235 
236     IAM_LOGI("WidgetContext start success.");
237     return true;
238 }
239 
OnResult(int32_t resultCode,const std::shared_ptr<Attributes> & scheduleResultAttr)240 void WidgetContext::OnResult(int32_t resultCode, const std::shared_ptr<Attributes> &scheduleResultAttr)
241 {
242     IAM_LOGI("%{public}s receive result code %{public}d", description_.c_str(), resultCode);
243 }
244 
OnStop()245 bool WidgetContext::OnStop()
246 {
247     // response app.cancel()
248     IAM_LOGI("%{public}s start", description_.c_str());
249     End(ResultCode::CANCELED);
250     return true;
251 }
252 
AuthResult(int32_t resultCode,int32_t authType,const Attributes & finalResult)253 void WidgetContext::AuthResult(int32_t resultCode, int32_t authType, const Attributes &finalResult)
254 {
255     IAM_LOGI("recv task result: %{public}d, authType: %{public}d", resultCode, authType);
256     std::lock_guard<std::recursive_mutex> lock(mutex_);
257     int32_t remainTimes = -1;
258     int32_t freezingTime = -1;
259     if (!finalResult.GetInt32Value(Attributes::ATTR_REMAIN_TIMES, remainTimes)) {
260         IAM_LOGI("get remainTimes failed.");
261     }
262     if (!finalResult.GetInt32Value(Attributes::ATTR_FREEZING_TIME, freezingTime)) {
263         IAM_LOGI("get freezingTime failed.");
264     }
265     AuthType authTypeTmp = static_cast<AuthType>(authType);
266     WidgetClient::Instance().ReportWidgetResult(resultCode, authTypeTmp, freezingTime, remainTimes,
267         para_.skipLockedBiometricAuth);
268     IF_FALSE_LOGE_AND_RETURN(callerCallback_ != nullptr);
269     callerCallback_->SetTraceAuthType(authTypeTmp);
270     IAM_LOGD("call schedule:");
271     ProcAuthResult(resultCode, authTypeTmp, freezingTime, finalResult);
272 }
273 
AuthTipInfo(int32_t tipType,int32_t authType,const Attributes & extraInfo)274 void WidgetContext::AuthTipInfo(int32_t tipType, int32_t authType, const Attributes &extraInfo)
275 {
276     IAM_LOGD("recv tip: %{public}d, authType: %{public}d", tipType, authType);
277     std::lock_guard<std::recursive_mutex> lock(mutex_);
278     std::vector<uint8_t> tipInfo;
279     bool getTipInfoRet = extraInfo.GetUint8ArrayValue(Attributes::ATTR_EXTRA_INFO, tipInfo);
280     IF_FALSE_LOGE_AND_RETURN(getTipInfoRet);
281     WidgetClient::Instance().ReportWidgetTip(tipType, static_cast<AuthType>(authType), tipInfo,
282         para_.skipLockedBiometricAuth);
283     ProcAuthTipInfo(tipType, static_cast<AuthType>(authType), tipInfo);
284 }
285 
286 // WidgetScheduleNodeCallback
LaunchWidget()287 bool WidgetContext::LaunchWidget()
288 {
289     IAM_LOGI("launch widget");
290     WidgetRotatePara widgetRotatePara;
291     widgetRotatePara.isReload = false;
292     widgetRotatePara.needRotate = 0;
293     if (!ConnectExtension(widgetRotatePara)) {
294         IAM_LOGE("failed to launch widget.");
295         return false;
296     }
297     return true;
298 }
299 
ExecuteAuthList(const std::set<AuthType> & authTypeList,bool endAfterFirstFail,AuthIntent authIntent)300 void WidgetContext::ExecuteAuthList(const std::set<AuthType> &authTypeList, bool endAfterFirstFail,
301     AuthIntent authIntent)
302 {
303     IAM_LOGI("execute auth list");
304     // create task, and start it
305     std::lock_guard<std::recursive_mutex> lock(mutex_);
306     for (auto &authType : authTypeList) {
307         auto task = BuildTask(para_.challenge, authType, para_.atl, endAfterFirstFail, authIntent);
308         if (task == nullptr) {
309             IAM_LOGE("failed to create task, authType: %{public}s", AuthType2Str(authType).c_str());
310             continue;
311         }
312         if (!task->Start()) {
313             IAM_LOGE("BeginAuthentication failed");
314             static const int32_t INVALID_VAL = -1;
315             WidgetClient::Instance().ReportWidgetResult(task->GetLatestError(), authType, INVALID_VAL, INVALID_VAL,
316                 para_.skipLockedBiometricAuth);
317             return;
318         }
319         if (authType == FACE) {
320             faceReload_ = 1;
321             IAM_LOGI("faceReload_: %{public}d", faceReload_);
322         }
323         TaskInfo taskInfo {
324             .authType = authType,
325             .task = task
326         };
327         runTaskInfoList_.push_back(taskInfo);
328     }
329 }
330 
EndAuthAsCancel()331 void WidgetContext::EndAuthAsCancel()
332 {
333     IAM_LOGI("end auth as cancel");
334     std::lock_guard<std::recursive_mutex> lock(mutex_);
335     if (latestError_ == COMPLEXITY_CHECK_FAILED) {
336         IAM_LOGE("complexity check failed");
337         return End(TRUST_LEVEL_NOT_SUPPORT);
338     }
339     // report CANCELED to App
340     End(ResultCode::CANCELED);
341 }
342 
EndAuthAsNaviPin()343 void WidgetContext::EndAuthAsNaviPin()
344 {
345     IAM_LOGI("end auth as navi pin");
346     std::lock_guard<std::recursive_mutex> lock(mutex_);
347     // report CANCELED_FROM_WIDGET to App
348     End(ResultCode::CANCELED_FROM_WIDGET);
349 }
350 
EndAuthAsWidgetParaInvalid()351 void WidgetContext::EndAuthAsWidgetParaInvalid()
352 {
353     IAM_LOGI("end auth as widget para invalid");
354     std::lock_guard<std::recursive_mutex> lock(mutex_);
355     End(ResultCode::INVALID_PARAMETERS);
356 }
357 
AuthWidgetReloadInit()358 void WidgetContext::AuthWidgetReloadInit()
359 {
360     IAM_LOGI("auth widget reload init");
361     std::lock_guard<std::recursive_mutex> lock(mutex_);
362     if (!DisconnectExtension()) {
363         IAM_LOGE("failed to release launch widget");
364     }
365 }
366 
AuthWidgetReload(uint32_t orientation,uint32_t needRotate,uint32_t alreadyLoad,AuthType & rotateAuthType)367 bool WidgetContext::AuthWidgetReload(uint32_t orientation, uint32_t needRotate, uint32_t alreadyLoad,
368     AuthType &rotateAuthType)
369 {
370     IAM_LOGI("auth widget reload");
371     std::lock_guard<std::recursive_mutex> lock(mutex_);
372     WidgetRotatePara widgetRotatePara;
373     widgetRotatePara.isReload = true;
374     widgetRotatePara.orientation = orientation;
375     widgetRotatePara.needRotate = needRotate;
376     widgetRotatePara.alreadyLoad = alreadyLoad;
377     widgetRotatePara.rotateAuthType = rotateAuthType;
378     if (alreadyLoad) {
379         widgetAlreadyLoad_ = 1;
380     }
381     if (!IsValidRotate(widgetRotatePara)) {
382         IAM_LOGE("check rotate failed");
383         return false;
384     }
385     if (!ConnectExtension(widgetRotatePara)) {
386         IAM_LOGE("failed to reload widget");
387         return false;
388     }
389     return true;
390 }
391 
IsValidRotate(const WidgetRotatePara & widgetRotatePara)392 bool WidgetContext::IsValidRotate(const WidgetRotatePara &widgetRotatePara)
393 {
394     IAM_LOGI("check rotate, needRotate: %{public}u, orientation: %{public}u", widgetRotatePara.needRotate,
395         widgetRotatePara.orientation);
396     if (widgetRotatePara.needRotate) {
397         IAM_LOGI("check rotate, widgetAlreadyLoad_: %{public}u", widgetAlreadyLoad_);
398         if (widgetRotatePara.orientation == ORIENTATION_PORTRAIT_INVERTED && !widgetAlreadyLoad_) {
399             IAM_LOGI("only support first");
400             return true;
401         }
402     }
403     return true;
404 }
405 
StopAuthList(const std::vector<AuthType> & authTypeList)406 void WidgetContext::StopAuthList(const std::vector<AuthType> &authTypeList)
407 {
408     IAM_LOGI("stop auth list");
409     std::lock_guard<std::recursive_mutex> lock(mutex_);
410     for (auto &authType : authTypeList) {
411         auto it = std::find_if(runTaskInfoList_.begin(),
412             runTaskInfoList_.end(), [authType] (const TaskInfo &taskInfo) {
413             return (taskInfo.authType == authType);
414         });
415         if (it != runTaskInfoList_.end()) {
416             if (it->task == nullptr) {
417                 IAM_LOGE("task is nullptr");
418                 return;
419             }
420             it->task->Stop();
421             runTaskInfoList_.erase(it);
422         }
423     }
424 }
425 
SuccessAuth(AuthType authType)426 void WidgetContext::SuccessAuth(AuthType authType)
427 {
428     IAM_LOGI("success auth. authType:%{public}d", static_cast<int32_t>(authType));
429     std::lock_guard<std::recursive_mutex> lock(mutex_);
430     // report success to App
431     if (latestError_ == ResultCode::COMPLEXITY_CHECK_FAILED) {
432         IAM_LOGE("complexity check failed");
433         End(TRUST_LEVEL_NOT_SUPPORT);
434         return;
435     }
436     End(ResultCode::SUCCESS);
437 }
438 
FailAuth(AuthType authType)439 void WidgetContext::FailAuth(AuthType authType)
440 {
441     IAM_LOGI("fail auth. authType:%{public}d", static_cast<int32_t>(authType));
442     std::lock_guard<std::recursive_mutex> lock(mutex_);
443     End(ResultCode::LOCKED);
444 }
445 
ConnectExtensionAbility(const AAFwk::Want & want,const std::string commandStr)446 int32_t WidgetContext::ConnectExtensionAbility(const AAFwk::Want &want, const std::string commandStr)
447 {
448     IAM_LOGD("ConnectExtensionAbility start");
449     if (connection_ != nullptr) {
450         IAM_LOGE("invalid connection_");
451         return ERR_INVALID_OPERATION;
452     }
453     connection_ = sptr<UIExtensionAbilityConnection>(new (std::nothrow) UIExtensionAbilityConnection(commandStr));
454     if (connection_ == nullptr) {
455         IAM_LOGE("new connection error.");
456         return ERR_NO_MEMORY;
457     }
458 
459     std::string identity = IPCSkeleton::ResetCallingIdentity();
460 #ifdef IAM_TEST_ENABLE
461     return SUCCESS;
462 #endif
463     auto ret = AAFwk::ExtensionManagerClient::GetInstance().ConnectServiceExtensionAbility(want, connection_, nullptr,
464         DEFAULT_VALUE);
465     IPCSkeleton::SetCallingIdentity(identity);
466     IAM_LOGI("ConnectExtensionAbility errCode=%{public}d", ret);
467     return ret;
468 }
469 
IsInFollowCallerList()470 bool WidgetContext::IsInFollowCallerList()
471 {
472     IAM_LOGI("enter");
473 #ifdef SCENE_BOARD_ENABLE
474     auto foldStatus = Rosen::DisplayManagerLite::GetInstance().GetFoldStatus();
475 #else
476     auto foldStatus = Rosen::DisplayManager::GetInstance().GetFoldStatus();
477 #endif
478     IAM_LOGI("FoldStatus is %{public}d.", foldStatus);
479     if (foldStatus != Rosen::FoldStatus::FOLDED) {
480         return false;
481     }
482 
483     std::string productName = OHOS::system::GetParameter("const.build.product", "");
484     IAM_LOGI("productName is %{public}s.", productName.c_str());
485 
486     std::vector<std::string> processName;
487     if (!GetFollowCallerList(jsonBuf_, processName)) {
488         IAM_LOGE("GetFollowCallerList error");
489         return false;
490     }
491     for (auto it = processName.begin(); it != processName.end(); ++it) {
492         if (productName + "-" == *it) {
493             return true;
494         }
495     }
496     return false;
497 }
498 
IsSupportFollowCallerUi()499 bool WidgetContext::IsSupportFollowCallerUi()
500 {
501     bool isSupportFollowCallerUi = OHOS::system::GetParameter(SUPPORT_FOLLOW_CALLER_UI, "false") == "true";
502     IAM_LOGI("is support follow caller UI: %{public}d", isSupportFollowCallerUi);
503     return isSupportFollowCallerUi || IsInFollowCallerList();
504 }
505 
SetSysDialogZOrder(WidgetCmdParameters & widgetCmdParameters)506 void WidgetContext::SetSysDialogZOrder(WidgetCmdParameters &widgetCmdParameters)
507 {
508     IAM_LOGI("enter");
509     std::vector<std::string> processName;
510     if (ContextAppStateObserverManager::GetInstance().IsScreenLocked()) {
511         IAM_LOGI("the screen is currently locked, set zOrder");
512         widgetCmdParameters.sysDialogZOrder = SYSDIALOG_ZORDER_UPPER;
513     }
514     if (!GetProcessName(jsonBuf_, processName)) {
515         IAM_LOGE("getProcessName error");
516         return;
517     }
518     for (auto it = processName.begin(); it != processName.end(); ++it) {
519         if ((para_.callerName == *it) && (para_.callerType == Security::AccessToken::TOKEN_NATIVE)) {
520             IAM_LOGI("is on shutdown screen, set zOrder");
521             widgetCmdParameters.useriamCmdData.callingProcessName = para_.callerName;
522             widgetCmdParameters.sysDialogZOrder = SYSDIALOG_ZORDER_UPPER;
523             break;
524         }
525     }
526 }
527 
ConnectExtension(const WidgetRotatePara & widgetRotatePara)528 bool WidgetContext::ConnectExtension(const WidgetRotatePara &widgetRotatePara)
529 {
530     IAM_LOGI("connect extension start");
531     std::lock_guard<std::recursive_mutex> lock(mutex_);
532     if (widgetRotatePara.isReload) {
533         for (auto &authType : para_.authTypeList) {
534             ContextFactory::AuthProfile profile;
535             if (!AuthWidgetHelper::GetUserAuthProfile(para_.userId, authType, profile)) {
536                 IAM_LOGE("get user authType:%{public}d profile failed", static_cast<int32_t>(authType));
537                 return false;
538             }
539             para_.authProfileMap[authType] = profile;
540         }
541     }
542 
543     if (IsSingleFaceOrFingerPrintAuth() && para_.skipLockedBiometricAuth &&
544         para_.authProfileMap[para_.authTypeList[0]].remainTimes == 0) {
545         Attributes attr;
546         callerCallback_->OnResult(ResultCode::LOCKED, attr);
547         UnSubscribeAppState();
548         return true;
549     }
550 
551     std::string commandData = BuildStartCommand(widgetRotatePara);
552     IAM_LOGI("start command: %{public}s", commandData.c_str());
553 
554     IAM_LOGI("has context: %{public}d", para_.widgetParam.hasContext);
555     if (para_.widgetParam.hasContext && IsSupportFollowCallerUi()) {
556         // As modal application
557         // No need do anything, caller death has process; only process timeout for widget.
558         useModalApplication_ = true;
559         if (modalCallback_ != nullptr) {
560             modalCallback_->SendCommand(contextId_, commandData);
561         }
562         return true;
563     }
564     // Default as modal system
565     AAFwk::Want want;
566     std::string bundleName = "com.ohos.systemui";
567     std::string abilityName = "com.ohos.systemui.dialog";
568     if (!GetSceneboardBundleName(jsonBuf_, bundleName)) {
569         IAM_LOGI("GetSceneboardBundleName error");
570     }
571     if (!GetSceneboardAbilityName(jsonBuf_, abilityName)) {
572         IAM_LOGI("GetSceneboardAbilityName error");
573     }
574     want.SetElementName(bundleName, abilityName);
575     auto ret = ConnectExtensionAbility(want, commandData);
576     if (ret != ERR_OK) {
577         UserIam::UserAuth::ReportSystemFault(Common::GetNowTimeString(), "userauthservice");
578         IAM_LOGE("ConnectExtensionAbility failed.");
579         return false;
580     }
581     return true;
582 }
583 
DisconnectExtension()584 bool WidgetContext::DisconnectExtension()
585 {
586     IAM_LOGI("has context: %{public}d", para_.widgetParam.hasContext);
587     std::lock_guard<std::recursive_mutex> lock(mutex_);
588     if ((para_.widgetParam.hasContext && IsSupportFollowCallerUi()) || useModalApplication_) {
589         // As modal application release.
590         if (schedule_ != nullptr) {
591             schedule_->StopSchedule();
592         }
593         if (modalCallback_ != nullptr) {
594             std::string cmdData = "";
595             modalCallback_->SendCommand(contextId_, cmdData);
596         }
597         return true;
598     }
599     // Default as modal system release.
600     if (connection_ == nullptr) {
601         IAM_LOGE("invalid connection handle");
602         return false;
603     }
604     if (schedule_ != nullptr) {
605         schedule_->StopSchedule();
606     }
607     connection_->ReleaseUIExtensionComponent();
608     ErrCode ret = AAFwk::ExtensionManagerClient::GetInstance().DisconnectAbility(connection_);
609     connection_ = nullptr;
610     if (ret != ERR_OK) {
611         IAM_LOGE("disconnect extension ability failed ret: %{public}d.", ret);
612         return false;
613     }
614     return true;
615 }
616 
End(const ResultCode & resultCode)617 void WidgetContext::End(const ResultCode &resultCode)
618 {
619     IAM_LOGI("in End, resultCode: %{public}d", static_cast<int32_t>(resultCode));
620     StopAllRunTask(resultCode);
621     IF_FALSE_LOGE_AND_RETURN(callerCallback_ != nullptr);
622     Attributes attr;
623     if (resultCode == ResultCode::SUCCESS || authResultInfo_.token.size() != 0) {
624         if (!attr.SetInt32Value(Attributes::ATTR_AUTH_TYPE, authResultInfo_.authType)) {
625             IAM_LOGE("set auth type failed.");
626             callerCallback_->SetTraceAuthFinishReason("WidgetContext End set authType fail");
627             callerCallback_->OnResult(ResultCode::GENERAL_ERROR, attr);
628             goto EXIT;
629         }
630         if (authResultInfo_.token.size() > 0) {
631             if (!attr.SetUint8ArrayValue(Attributes::ATTR_SIGNATURE, authResultInfo_.token)) {
632                 IAM_LOGE("set signature token failed.");
633                 callerCallback_->SetTraceAuthFinishReason("WidgetContext End set token fail");
634                 callerCallback_->OnResult(ResultCode::GENERAL_ERROR, attr);
635                 goto EXIT;
636             }
637         }
638         IAM_LOGI("in End, token size: %{public}zu.", authResultInfo_.token.size());
639         if (!attr.SetUint64Value(Attributes::ATTR_CREDENTIAL_DIGEST, authResultInfo_.credentialDigest)) {
640             IAM_LOGE("set credential digest failed.");
641             callerCallback_->SetTraceAuthFinishReason("WidgetContext End set credentialDigest fail");
642             callerCallback_->OnResult(ResultCode::GENERAL_ERROR, attr);
643             goto EXIT;
644         }
645         if (!attr.SetUint16Value(Attributes::ATTR_CREDENTIAL_COUNT, authResultInfo_.credentialCount)) {
646             IAM_LOGE("set credential count failed.");
647             callerCallback_->SetTraceAuthFinishReason("WidgetContext End set credentialCount fail");
648             callerCallback_->OnResult(ResultCode::GENERAL_ERROR, attr);
649             goto EXIT;
650         }
651     }
652     callerCallback_->SetTraceAuthFinishReason("WidgetContext End fail");
653     callerCallback_->OnResult(resultCode, attr);
654     if (connection_ == nullptr) {
655         IAM_LOGE("invalid connection handle");
656         goto EXIT;
657     }
658     connection_->setIsNormalEnd(true);
659 EXIT:
660     UnSubscribeAppState();
661 }
662 
StopAllRunTask(const ResultCode & resultCode)663 void WidgetContext::StopAllRunTask(const ResultCode &resultCode)
664 {
665     std::lock_guard<std::recursive_mutex> lock(mutex_);
666     for (auto &taskInfo : runTaskInfoList_) {
667         IAM_LOGD("stop task");
668         if (taskInfo.task == nullptr) {
669             IAM_LOGE("task is null");
670             continue;
671         }
672         taskInfo.task->Stop();
673     }
674     runTaskInfoList_.clear();
675     if (resultCode != ResultCode::SUCCESS) {
676         IAM_LOGI("Try to disconnect extension");
677         if (!DisconnectExtension()) {
678             IAM_LOGE("failed to release launch widget.");
679         }
680     }
681 }
682 
BuildStartPinSubType(WidgetCmdParameters & widgetCmdParameters)683 void WidgetContext::BuildStartPinSubType(WidgetCmdParameters &widgetCmdParameters)
684 {
685     auto it = para_.authProfileMap.find(AuthType::PIN);
686     if (it == para_.authProfileMap.end()) {
687         it = para_.authProfileMap.find(AuthType::PRIVATE_PIN);
688     }
689     if (it != para_.authProfileMap.end()) {
690         widgetCmdParameters.useriamCmdData.pinSubType = PinSubType2Str(static_cast<PinSubType>(it->second.pinSubType));
691     }
692 }
693 
BuildStartCommand(const WidgetRotatePara & widgetRotatePara)694 std::string WidgetContext::BuildStartCommand(const WidgetRotatePara &widgetRotatePara)
695 {
696     WidgetCmdParameters widgetCmdParameters;
697     widgetCmdParameters.uiExtensionType = UI_EXTENSION_TYPE_SET;
698     widgetCmdParameters.useriamCmdData.widgetContextId = GetContextId();
699     widgetCmdParameters.useriamCmdData.widgetContextIdStr = std::to_string(GetContextId());
700     widgetCmdParameters.useriamCmdData.title = para_.widgetParam.title;
701     widgetCmdParameters.useriamCmdData.windowModeType = WinModeType2Str(para_.widgetParam.windowMode);
702     widgetCmdParameters.useriamCmdData.navigationButtonText = para_.widgetParam.navigationButtonText;
703     BuildStartPinSubType(widgetCmdParameters);
704     widgetCmdParameters.sysDialogZOrder = SYSDIALOG_ZORDER_DEFAULT;
705     SetSysDialogZOrder(widgetCmdParameters);
706     std::vector<std::string> typeList;
707     for (auto &item : para_.authProfileMap) {
708         auto &at = item.first;
709         auto &profile = item.second;
710         typeList.push_back(AuthType2Str(at));
711         WidgetCommand::Cmd cmd {
712             .event = CMD_NOTIFY_AUTH_START,
713             .version = NOTICE_VERSION_STR,
714             .type = AuthType2Str(at)
715         };
716         if (at == AuthType::FINGERPRINT && !profile.sensorInfo.empty()) {
717             cmd.sensorInfo = profile.sensorInfo;
718         }
719         if (para_.isPinExpired) {
720             cmd.result = PIN_EXPIRED;
721         }
722         cmd.remainAttempts = profile.remainTimes;
723         cmd.lockoutDuration = profile.freezingTime;
724         WidgetCommand::ExtraInfo extraInfo {
725             .callingBundleName = GetCallingBundleName(),
726             .challenge = para_.challenge
727         };
728         cmd.extraInfo = extraInfo;
729         widgetCmdParameters.useriamCmdData.cmdList.push_back(cmd);
730     }
731     widgetCmdParameters.useriamCmdData.typeList = typeList;
732     widgetCmdParameters.useriamCmdData.callingAppID = para_.callingAppID;
733     widgetCmdParameters.useriamCmdData.userId = para_.userId;
734     widgetCmdParameters.useriamCmdData.skipLockedBiometricAuth = para_.skipLockedBiometricAuth;
735     ProcessRotatePara(widgetCmdParameters, widgetRotatePara);
736     nlohmann::json root = widgetCmdParameters;
737     std::string cmdData = root.dump();
738     return cmdData;
739 }
740 
ProcessRotatePara(WidgetCmdParameters & widgetCmdParameters,const WidgetRotatePara & widgetRotatePara)741 void WidgetContext::ProcessRotatePara(WidgetCmdParameters &widgetCmdParameters,
742     const WidgetRotatePara &widgetRotatePara)
743 {
744     if (widgetRotatePara.isReload) {
745         widgetCmdParameters.useriamCmdData.isReload = 1;
746         if (widgetRotatePara.rotateAuthType == FACE) {
747             widgetCmdParameters.useriamCmdData.isReload = faceReload_;
748         }
749         widgetCmdParameters.useriamCmdData.rotateAuthType = AuthType2Str(widgetRotatePara.rotateAuthType);
750     }
751     IAM_LOGI("needRotate: %{public}u, orientation: %{public}u", widgetRotatePara.needRotate,
752         widgetRotatePara.orientation);
753     if (widgetRotatePara.needRotate) {
754         if (widgetRotatePara.orientation == ORIENTATION_LANDSCAPE) {
755             widgetCmdParameters.uiExtNodeAngle = TO_PORTRAIT;
756         }
757         if (widgetRotatePara.orientation == ORIENTATION_PORTRAIT_INVERTED) {
758             widgetCmdParameters.uiExtNodeAngle = TO_INVERTED;
759         }
760         if (widgetRotatePara.orientation == ORIENTATION_LANDSCAPE_INVERTED) {
761             widgetCmdParameters.uiExtNodeAngle = TO_PORTRAIT_INVERTED;
762         }
763     }
764 }
765 
GetCallingBundleName()766 std::string WidgetContext::GetCallingBundleName()
767 {
768     if (para_.callerType == Security::AccessToken::TOKEN_HAP) {
769         return para_.callerName;
770     }
771     return "";
772 }
773 
IsSingleFaceOrFingerPrintAuth()774 bool WidgetContext::IsSingleFaceOrFingerPrintAuth()
775 {
776     if (!para_.widgetParam.navigationButtonText.empty()) {
777         return false;
778     }
779     if (para_.authTypeList.size() == 1 && (para_.authTypeList[0] == FACE || para_.authTypeList[0] == FINGERPRINT)) {
780         return true;
781     }
782     return false;
783 }
784 
IsNavigationAuth()785 bool WidgetContext::IsNavigationAuth()
786 {
787     if (para_.widgetParam.navigationButtonText.empty()) {
788         return false;
789     }
790     return true;
791 }
792 
SendAuthTipInfo(int32_t authType,int32_t tipCode)793 void WidgetContext::SendAuthTipInfo(int32_t authType, int32_t tipCode)
794 {
795     IAM_LOGI("authType:%{public}d, tipCode:%{public}d", authType, tipCode);
796     Attributes attr;
797     bool setTipInfoRet = attr.SetInt32Value(Attributes::ATTR_TIP_INFO, tipCode);
798     if (!setTipInfoRet) {
799         IAM_LOGE("set tipInfo fail");
800         return;
801     }
802 
803     IF_FALSE_LOGE_AND_RETURN(callerCallback_ != nullptr);
804 
805     callerCallback_->OnAcquireInfo(ALL_IN_ONE, authType, attr.Serialize());
806 }
807 
GetAuthTipCode(int32_t authResult,int32_t freezingTime)808 UserAuthTipCode WidgetContext::GetAuthTipCode(int32_t authResult, int32_t freezingTime)
809 {
810     UserAuthTipCode tipCode = TIP_CODE_FAIL;
811     if (authResult == ResultCode::TIMEOUT) {
812         tipCode = TIP_CODE_TIMEOUT;
813     } else if (authResult == ResultCode::LOCKED) {
814         if (freezingTime == INT32_MAX) {
815             tipCode = TIP_CODE_PERMANENTLY_LOCKED;
816         } else {
817             tipCode = TIP_CODE_TEMPORARILY_LOCKED;
818         }
819     } else if (freezingTime > 0) {
820         tipCode = TIP_CODE_COMPARE_FAIL_WITH_FROZEN;
821     } else {
822         tipCode = TIP_CODE_FAIL;
823     }
824     return tipCode;
825 }
826 
ProcAuthResult(int32_t resultCode,AuthType authType,int32_t freezingTime,const Attributes & finalResult)827 void WidgetContext::ProcAuthResult(int32_t resultCode, AuthType authType, int32_t freezingTime,
828     const Attributes &finalResult)
829 {
830     IAM_LOGI("recv task result: %{public}d, authType: %{public}d", resultCode, authType);
831     IF_FALSE_LOGE_AND_RETURN(schedule_ != nullptr);
832     if (resultCode == ResultCode::SUCCESS || resultCode == ResultCode::COMPLEXITY_CHECK_FAILED) {
833         finalResult.GetUint8ArrayValue(Attributes::ATTR_SIGNATURE, authResultInfo_.token);
834         finalResult.GetUint64Value(Attributes::ATTR_CREDENTIAL_DIGEST, authResultInfo_.credentialDigest);
835         finalResult.GetUint16Value(Attributes::ATTR_CREDENTIAL_COUNT, authResultInfo_.credentialCount);
836         authResultInfo_.authType = authType;
837         IAM_LOGD("widget token size: %{public}zu.", authResultInfo_.token.size());
838         if (resultCode != ResultCode::SUCCESS) {
839             SetLatestError(resultCode);
840         }
841         schedule_->SuccessAuth(authType);
842     } else {
843         SetLatestError(resultCode);
844         if (resultCode != ResultCode::CANCELED) {
845             SendAuthTipInfo(authType, GetAuthTipCode(resultCode, freezingTime));
846         }
847         if (para_.skipLockedBiometricAuth && freezingTime > 0) {
848             if (IsSingleFaceOrFingerPrintAuth()) {
849                 schedule_->FailAuth(authType);
850             } else if (IsNavigationAuth()) {
851                 schedule_->NaviPinAuth();
852             }
853         } else {
854             schedule_->StopAuthList({authType});
855         }
856     }
857 }
858 
ProcAuthTipInfo(int32_t tip,AuthType authType,const std::vector<uint8_t> & extraInfo)859 void WidgetContext::ProcAuthTipInfo(int32_t tip, AuthType authType, const std::vector<uint8_t> &extraInfo)
860 {
861     IAM_LOGI("authType:%{public}d, tip:%{public}d", authType, tip);
862     IF_FALSE_LOGE_AND_RETURN(schedule_ != nullptr);
863     IF_FALSE_LOGE_AND_RETURN(callerCallback_ != nullptr);
864     int32_t resultCode = ResultCode::GENERAL_ERROR;
865     int32_t freezingTime = -1;
866     int32_t ret = callerCallback_->ParseAuthTipInfo(tip, extraInfo, resultCode, freezingTime);
867     if (ret != ResultCode::SUCCESS) {
868         IAM_LOGE("ParseAuthTipInfo fail");
869         return;
870     }
871     if (resultCode == ResultCode::SUCCESS) {
872         return;
873     }
874     if (resultCode != ResultCode::CANCELED) {
875         SendAuthTipInfo(authType, GetAuthTipCode(resultCode, freezingTime));
876     }
877     if (para_.skipLockedBiometricAuth && freezingTime > 0) {
878         if (IsSingleFaceOrFingerPrintAuth()) {
879             schedule_->FailAuth(authType);
880         } else if (IsNavigationAuth()) {
881             schedule_->NaviPinAuth();
882         }
883     }
884 }
885 
ClearSchedule()886 void WidgetContext::ClearSchedule()
887 {
888     IAM_LOGI("start");
889     auto result = ContextPool::Instance().Delete(GetContextId());
890     IAM_LOGI("context ****%{public}hx deleted %{public}s", static_cast<uint16_t>(contextId_), result ? "succ" : "fail");
891 }
892 } // namespace UserAuth
893 } // namespace UserIam
894 } // namespace OHOS
895