• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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  */
15 #include "first_use_dialog.h"
16 
17 #include <fcntl.h>
18 #include <fstream>
19 #include <cstdlib>
20 #include <sys/stat.h>
21 #include <sys/statfs.h>
22 #include <sys/types.h>
23 #include <unistd.h>
24 #include "ability_manager_client.h"
25 #include "accesstoken_kit.h"
26 #include "bundle_mgr_client.h"
27 #include "display.h"
28 #include "display_info.h"
29 #include "display_manager.h"
30 #include "hisysevent.h"
31 #include "ipc_skeleton.h"
32 #include "sec_comp_dialog_callback_proxy.h"
33 #include "sec_comp_err.h"
34 #include "sec_comp_log.h"
35 #include "want_params_wrapper.h"
36 
37 namespace OHOS {
38 namespace Security {
39 namespace SecurityComponent {
40 namespace {
41 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, SECURITY_DOMAIN_SECURITY_COMPONENT, "FirstUseDialog"};
42 static const std::string SECURITY_COMPONENT_MANAGER = "security_component_manager";
43 static const std::string SEC_COMP_SRV_CFG_PATH = "/data/service/el1/public/security_component_service";
44 static const std::string FIRST_USE_RECORD_JSON = SEC_COMP_SRV_CFG_PATH + "/first_use_record.json";
45 static const std::string FIRST_USE_RECORD_TAG = "FirstUseRecord";
46 static const std::string TOKEN_ID_TAG = "TokenId";
47 static const std::string COMP_TYPE_TAG = "CompType";
48 static const char* DATA_FOLDER = "/data";
49 
50 const std::string GRANT_ABILITY_BUNDLE_NAME = "com.ohos.permissionmanager";
51 const std::string GRANT_ABILITY_ABILITY_NAME = "com.ohos.permissionmanager.SecurityExtAbility";
52 const std::string TYPE_KEY = "ohos.user.security.type";
53 const std::string TOKEN_KEY = "ohos.ability.params.token";
54 const std::string CALLBACK_KEY = "ohos.ability.params.callback";
55 const std::string WINDOW_ID_KEY = "ohos.ability.params.windowId";
56 const std::string CALLER_UID_KEY = "ohos.caller.uid";
57 const std::string DISPLAY_WIDTH = "ohos.display.width";
58 const std::string DISPLAY_HEIGHT = "ohos.display.height";
59 const std::string DISPLAY_TOP = "ohos.display.top";
60 const std::string DIALOG_OFFSET = "ohos.dialog.offset";
61 const std::string NOTIFY_TYPE = "ohos.ability.notify.type";
62 const std::string TOAST_POSITION = "ohos.toast.position";
63 const std::string TOAST_OFFSET = "ohos.toast.offset";
64 
65 constexpr int32_t DISPLAY_HALF_RATIO = 2;
66 constexpr uint32_t MAX_CFG_FILE_SIZE = 100 * 1024; // 100k
67 constexpr uint64_t LOCATION_BUTTON_FIRST_USE = 1 << 0;
68 constexpr uint64_t SAVE_BUTTON_FIRST_USE = 1 << 1;
69 constexpr int32_t ABOVE_BOTTOM_OFFSET = 80;
70 constexpr int32_t BELOW_TOP_OFFSET = 112;
71 static std::mutex g_instanceMutex;
72 static std::unordered_map<TipPosition, int32_t> tipPositionsMap = {{TipPosition::ABOVE_BOTTOM, ABOVE_BOTTOM_OFFSET},
73     {TipPosition::BELOW_TOP, BELOW_TOP_OFFSET}};
74 }
75 
ReportUserData(const std::string & filePath,const std::string & folderPath)76 bool ReportUserData(const std::string& filePath, const std::string& folderPath)
77 {
78     struct stat fileInfo;
79     if (stat(filePath.c_str(), &fileInfo) != 0) {
80         SC_LOG_ERROR(LABEL, "Failed to get file stat, path = %{public}s.", filePath.c_str());
81         return false;
82     }
83     int64_t fileSize = fileInfo.st_size;
84 
85     struct statfs statsInfo;
86     if (statfs(folderPath.c_str(), &statsInfo) != 0) {
87         SC_LOG_ERROR(LABEL, "Failed to get data remain size.");
88         return false;
89     }
90     uint64_t remainSize = static_cast<uint64_t>(statsInfo.f_bfree) * statsInfo.f_bsize;
91 
92     HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::FILEMANAGEMENT, "USER_DATA_SIZE",
93         HiviewDFX::HiSysEvent::EventType::STATISTIC, "COMPONENT_NAME", SECURITY_COMPONENT_MANAGER,
94         "PARTITION_NAME", folderPath, "REMAIN_PARTITION_SIZE", remainSize,
95         "FILE_OR_FOLDER_PATH", filePath, "FILE_OR_FOLDER_SIZE", fileSize);
96     return true;
97 }
98 
OnDialogClosed(int32_t result)99 void SecCompDialogSrvCallback::OnDialogClosed(int32_t result)
100 {
101     SC_LOG_INFO(LABEL, "Call dialog close callback scId_ %{public}d", scId_);
102     int32_t grantRes = FirstUseDialog::GetInstance().GrantDialogWaitEntity(scId_);
103     if (grantRes == SC_SERVICE_ERROR_COMPONENT_NOT_EXIST) {
104         SC_LOG_ERROR(LABEL, "Call dialog close callback scId_ %{public}d is not exist", scId_);
105         return;
106     }
107     if (!grantRes && !FirstUseDialog::GetInstance().SetFirstUseMap(sc_)) {
108         return;
109     }
110     auto callback = iface_cast<ISecCompDialogCallback>(dialogCallback_);
111     if (callback != nullptr) {
112         callback->OnDialogClosed(grantRes);
113     }
114 }
115 
GetInstance()116 FirstUseDialog& FirstUseDialog::GetInstance()
117 {
118     static FirstUseDialog* instance = nullptr;
119     if (instance == nullptr) {
120         std::lock_guard<std::mutex> lock(g_instanceMutex);
121         if (instance == nullptr) {
122             instance = new FirstUseDialog();
123         }
124     }
125     return *instance;
126 }
127 
IsCfgDirExist(void)128 bool FirstUseDialog::IsCfgDirExist(void)
129 {
130     struct stat fstat = {};
131     if (stat(SEC_COMP_SRV_CFG_PATH.c_str(), &fstat) != 0) {
132         SC_LOG_INFO(LABEL, "path %{public}s errno %{public}d.", SEC_COMP_SRV_CFG_PATH.c_str(), errno);
133         return false;
134     }
135 
136     if (!S_ISDIR(fstat.st_mode)) {
137         SC_LOG_ERROR(LABEL, "path %{public}s is not directory.", SEC_COMP_SRV_CFG_PATH.c_str());
138         return false;
139     }
140     return true;
141 }
142 
IsCfgFileExist(void)143 bool FirstUseDialog::IsCfgFileExist(void)
144 {
145     struct stat fstat = {};
146     if (stat(FIRST_USE_RECORD_JSON.c_str(), &fstat) != 0) {
147         SC_LOG_INFO(LABEL, "path %{public}s errno %{public}d.", FIRST_USE_RECORD_JSON.c_str(), errno);
148         return false;
149     }
150     return true;
151 }
152 
IsCfgFileValid(void)153 bool FirstUseDialog::IsCfgFileValid(void)
154 {
155     struct stat fstat = {};
156     if (stat(FIRST_USE_RECORD_JSON.c_str(), &fstat) != 0) {
157         SC_LOG_INFO(LABEL, "path %{public}s errno %{public}d.", FIRST_USE_RECORD_JSON.c_str(), errno);
158         return false;
159     }
160     if (fstat.st_size > MAX_CFG_FILE_SIZE) {
161         SC_LOG_INFO(LABEL, "path %{public}s size too large.", FIRST_USE_RECORD_JSON.c_str());
162         return false;
163     }
164     return true;
165 }
166 
ReadCfgContent(std::string & content)167 bool FirstUseDialog::ReadCfgContent(std::string& content)
168 {
169     std::stringstream buffer;
170     char* canonicalPath = realpath(FIRST_USE_RECORD_JSON.c_str(), nullptr);
171     if (canonicalPath == nullptr) {
172         SC_LOG_ERROR(LABEL, "Cannot get canonical path for %{public}s, errno %{public}d.",
173             FIRST_USE_RECORD_JSON.c_str(), errno);
174         return false;
175     }
176     std::ifstream i(canonicalPath);
177     if (!i.is_open()) {
178         SC_LOG_ERROR(LABEL, "cannot open file %{public}s, errno %{public}d.", canonicalPath, errno);
179         free(canonicalPath);
180         return false;
181     }
182     buffer << i.rdbuf();
183     content = buffer.str();
184     i.close();
185     free(canonicalPath);
186     return true;
187 }
188 
WriteCfgContent(const std::string & content)189 void FirstUseDialog::WriteCfgContent(const std::string& content)
190 {
191     char* canonicalPath = realpath(FIRST_USE_RECORD_JSON.c_str(), nullptr);
192     if (canonicalPath == nullptr) {
193         SC_LOG_ERROR(LABEL, "Cannot get canonical path for %{public}s, errno %{public}d.",
194             FIRST_USE_RECORD_JSON.c_str(), errno);
195         return;
196     }
197     std::ofstream out(canonicalPath);
198     if (!out.is_open()) {
199         SC_LOG_ERROR(LABEL, "cannot open file %{public}s, errno %{public}d.", canonicalPath, errno);
200         free(canonicalPath);
201         return;
202     }
203     out << content;
204     free(canonicalPath);
205     out.close();
206 }
207 
ParseRecord(nlohmann::json & jsonRes,AccessToken::AccessTokenID & id,uint64_t & type)208 bool FirstUseDialog::ParseRecord(nlohmann::json& jsonRes,
209     AccessToken::AccessTokenID& id, uint64_t& type)
210 {
211     if (jsonRes.find(TOKEN_ID_TAG) == jsonRes.end() ||
212         !jsonRes.at(TOKEN_ID_TAG).is_number()) {
213         SC_LOG_ERROR(LABEL, "parse TokenId failed.");
214         return false;
215     }
216     id = jsonRes.at(TOKEN_ID_TAG).get<uint32_t>();
217     if (id == AccessToken::INVALID_TOKENID) {
218         SC_LOG_ERROR(LABEL, "TokenId is invalid.");
219         return false;
220     }
221 
222     if (jsonRes.find(COMP_TYPE_TAG) == jsonRes.end() ||
223         !jsonRes.at(COMP_TYPE_TAG).is_number()) {
224         SC_LOG_ERROR(LABEL, "parse CompType failed.");
225         return false;
226     }
227     type = jsonRes.at(COMP_TYPE_TAG).get<uint64_t>();
228     return true;
229 }
230 
ParseRecords(nlohmann::json & jsonRes)231 void FirstUseDialog::ParseRecords(nlohmann::json& jsonRes)
232 {
233     std::unique_lock<std::mutex> lock(useMapMutex_);
234     if (jsonRes.find(FIRST_USE_RECORD_TAG) == jsonRes.end() ||
235         !jsonRes.at(FIRST_USE_RECORD_TAG).is_array()) {
236         SC_LOG_ERROR(LABEL, "parse tag failed.");
237         return;
238     }
239 
240     nlohmann::json recordListJson = jsonRes.at(FIRST_USE_RECORD_TAG);
241     for (auto& recordJson : recordListJson) {
242         AccessToken::AccessTokenID id;
243         uint64_t type;
244         if (!ParseRecord(recordJson, id, type)) {
245             SC_LOG_ERROR(LABEL, "parse record failed.");
246             continue;
247         }
248         firstUseMap_[id] = type;
249     }
250 }
251 
LoadFirstUseRecord(void)252 void FirstUseDialog::LoadFirstUseRecord(void)
253 {
254     if (!IsCfgFileValid()) {
255         SC_LOG_INFO(LABEL, "first use record is invalid.");
256         return;
257     }
258 
259     std::string content;
260     if (!ReadCfgContent(content)) {
261         return;
262     }
263 
264     nlohmann::json jsonRes = nlohmann::json::parse(content, nullptr, false);
265     if (jsonRes.is_discarded()) {
266         SC_LOG_ERROR(LABEL, "cfg info format is invalid");
267         return;
268     }
269 
270     ParseRecords(jsonRes);
271 }
272 
SaveFirstUseRecord(void)273 void FirstUseDialog::SaveFirstUseRecord(void)
274 {
275     SC_LOG_INFO(LABEL, "start save first_use_record json");
276     if (!IsCfgDirExist()) {
277         SC_LOG_ERROR(LABEL, "dir %{public}s is not exist, errno %{public}d",
278             SEC_COMP_SRV_CFG_PATH.c_str(), errno);
279         return;
280     }
281 
282     if (!IsCfgFileExist()) {
283         if (creat(FIRST_USE_RECORD_JSON.c_str(), S_IRUSR | S_IWUSR) == -1) {
284             SC_LOG_ERROR(LABEL, "create %{public}s failed, errno %{public}d",
285                 FIRST_USE_RECORD_JSON.c_str(), errno);
286             return;
287         }
288     }
289 
290     nlohmann::json jsonRes;
291     {
292         std::unique_lock<std::mutex> lock(useMapMutex_);
293         nlohmann::json recordsJson;
294         for (auto iter = firstUseMap_.begin(); iter != firstUseMap_.end(); ++iter) {
295             AccessToken::AccessTokenID id = iter->first;
296             AccessToken::HapTokenInfo info;
297             if (AccessToken::AccessTokenKit::GetHapTokenInfo(id, info) != AccessToken::RET_SUCCESS) {
298                 SC_LOG_INFO(LABEL, "token id %{public}d is not exist, do not update it.", id);
299                 continue;
300             }
301             nlohmann::json recordJson;
302             recordJson[TOKEN_ID_TAG] = id;
303             recordJson[COMP_TYPE_TAG] = iter->second;
304             recordsJson.emplace_back(recordJson);
305         }
306 
307         jsonRes[FIRST_USE_RECORD_TAG] = recordsJson;
308     }
309     if (!ReportUserData(FIRST_USE_RECORD_JSON, DATA_FOLDER)) {
310         SC_LOG_ERROR(LABEL, "report user data failed.");
311     }
312     WriteCfgContent(jsonRes.dump());
313 }
314 
RemoveDialogWaitEntitys(int32_t pid)315 void FirstUseDialog::RemoveDialogWaitEntitys(int32_t pid)
316 {
317     std::unique_lock<std::mutex> lock(useMapMutex_);
318     for (auto iter = dialogWaitMap_.begin(); iter != dialogWaitMap_.end();) {
319         std::shared_ptr<SecCompEntity> entity = iter->second;
320         if ((entity != nullptr) && (entity->pid_ == pid)) {
321             iter = dialogWaitMap_.erase(iter);
322         } else {
323             ++iter;
324         }
325     }
326 }
327 
GrantDialogWaitEntity(int32_t scId)328 int32_t FirstUseDialog::GrantDialogWaitEntity(int32_t scId)
329 {
330     std::unique_lock<std::mutex> lock(useMapMutex_);
331     auto it = dialogWaitMap_.find(scId);
332     if (it == dialogWaitMap_.end()) {
333         SC_LOG_ERROR(LABEL, "Grant dialog wait security component %{public}d is not exist", scId);
334         return SC_SERVICE_ERROR_COMPONENT_NOT_EXIST;
335     }
336 
337     std::shared_ptr<SecCompEntity> sc = it->second;
338     if (sc == nullptr) {
339         SC_LOG_ERROR(LABEL, "Grant dialog wait security component %{public}d is nullptr", scId);
340         return SC_SERVICE_ERROR_COMPONENT_NOT_EXIST;
341     }
342     int32_t res = sc->GrantTempPermission();
343     if (res != SC_OK) {
344         OHOS::AppExecFwk::BundleMgrClient bmsClient;
345         std::string bundleName = "";
346         bmsClient.GetNameForUid(sc->uid_, bundleName);
347         HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::SEC_COMPONENT, "TEMP_GRANT_FAILED",
348             HiviewDFX::HiSysEvent::EventType::FAULT, "CALLER_UID", sc->uid_, "CALLER_BUNDLE_NAME", bundleName,
349             "CALLER_PID", sc->pid_, "SC_ID", scId, "SC_TYPE", sc->GetType());
350     } else {
351         HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::SEC_COMPONENT, "TEMP_GRANT_SUCCESS",
352             HiviewDFX::HiSysEvent::EventType::BEHAVIOR, "CALLER_UID", sc->uid_,
353             "CALLER_PID", sc->pid_, "SC_ID", scId, "SC_TYPE", sc->GetType());
354     }
355     dialogWaitMap_.erase(scId);
356     return res;
357 }
358 
SetDisplayInfo(AAFwk::Want & want,const DisplayInfo & displayInfo)359 bool FirstUseDialog::SetDisplayInfo(AAFwk::Want& want, const DisplayInfo& displayInfo)
360 {
361     sptr<OHOS::Rosen::Display> display =
362         OHOS::Rosen::DisplayManager::GetInstance().GetDisplayById(displayInfo.displayId);
363     if (display == nullptr) {
364         SC_LOG_ERROR(LABEL, "Get display manager failed");
365         return false;
366     }
367 
368     auto info = display->GetDisplayInfo();
369     if (info == nullptr) {
370         SC_LOG_ERROR(LABEL, "Get display info failed");
371         return false;
372     }
373     /* crossAxisState is INVALID or NO_CROSS */
374     int32_t width = info->GetWidth();
375     int32_t height = info->GetHeight();
376     int32_t offset = 0;
377     /* crossAxisState is CROSS */
378     if (displayInfo.crossAxisState == CrossAxisState::STATE_CROSS) {
379         height = info->GetPhysicalHeight();
380         offset = static_cast<int32_t>(info->GetAvailableHeight()) / DISPLAY_HALF_RATIO;
381     }
382     SC_LOG_INFO(LABEL, "Display info width %{public}d height %{public}d, dialog offset %{public}d",
383         width, height, offset);
384 
385     want.SetParam(DISPLAY_WIDTH, width);
386     want.SetParam(DISPLAY_HEIGHT, height);
387     want.SetParam(DIALOG_OFFSET, offset);
388     return true;
389 }
390 
StartToastAbility(const std::shared_ptr<SecCompEntity> entity,const sptr<IRemoteObject> callerToken,const DisplayInfo & displayInfo)391 void FirstUseDialog::StartToastAbility(const std::shared_ptr<SecCompEntity> entity,
392     const sptr<IRemoteObject> callerToken, const DisplayInfo& displayInfo)
393 {
394     if (!entity->AllowToShowToast()) {
395         return;
396     }
397     bool needToShow = AccessToken::AccessTokenKit::IsToastShownNeeded(entity->pid_);
398     if (!needToShow) {
399         SC_LOG_INFO(LABEL, "Process pid=%{public}d needs not to show", entity->pid_);
400         return;
401     }
402     AAFwk::Want want;
403     want.SetElementName(GRANT_ABILITY_BUNDLE_NAME, GRANT_ABILITY_ABILITY_NAME);
404     want.SetParam(NOTIFY_TYPE, NotifyType::TOAST);
405     want.SetParam(TOAST_POSITION, entity->componentInfo_->tipPosition_);
406     int32_t toastOffset = ABOVE_BOTTOM_OFFSET;
407     if (tipPositionsMap.find(entity->componentInfo_->tipPosition_) != tipPositionsMap.end()) {
408         toastOffset = tipPositionsMap[entity->componentInfo_->tipPosition_];
409     }
410     want.SetParam(TOAST_OFFSET, toastOffset);
411     int32_t superFoldOffsetY = 0;
412     if (entity->IsInPCVirtualScreen(displayInfo.crossAxisState)) {
413         superFoldOffsetY = displayInfo.superFoldOffsetY;
414     }
415     want.SetParam(DISPLAY_TOP, superFoldOffsetY);
416     if (!SetDisplayInfo(want, displayInfo)) {
417         SC_LOG_ERROR(LABEL, "Set display info failed.");
418         return;
419     }
420 
421     int startRes = AAFwk::AbilityManagerClient::GetInstance()->StartExtensionAbility(want, callerToken);
422     SC_LOG_INFO(LABEL, "Start toast ability res %{public}d", startRes);
423 }
424 
StartDialogAbility(std::shared_ptr<SecCompEntity> entity,sptr<IRemoteObject> callerToken,sptr<IRemoteObject> dialogCallback,const DisplayInfo & displayInfo)425 void FirstUseDialog::StartDialogAbility(std::shared_ptr<SecCompEntity> entity, sptr<IRemoteObject> callerToken,
426     sptr<IRemoteObject> dialogCallback, const DisplayInfo& displayInfo)
427 {
428     int32_t typeNum;
429     SecCompType type = entity->GetType();
430     if (type == LOCATION_COMPONENT) {
431         typeNum = 0;
432     } else if (type == SAVE_COMPONENT) {
433         typeNum = 1;
434     } else {
435         SC_LOG_ERROR(LABEL, "Unknown type.");
436         return;
437     }
438     int32_t scId = entity->scId_;
439     SecCompDialogSrvCallback *call = new (std::nothrow)SecCompDialogSrvCallback(scId, entity, dialogCallback);
440     sptr<IRemoteObject> srvCallback = call;
441     if (srvCallback == nullptr) {
442         SC_LOG_ERROR(LABEL, "New SecCompDialogCallback fail");
443         return;
444     }
445     dialogWaitMap_[scId] = entity;
446     AAFwk::Want want;
447     want.SetElementName(GRANT_ABILITY_BUNDLE_NAME, GRANT_ABILITY_ABILITY_NAME);
448     want.SetParam(TYPE_KEY, typeNum);
449     want.SetParam(TOKEN_KEY, callerToken);
450     want.SetParam(CALLBACK_KEY, srvCallback);
451     want.SetParam(WINDOW_ID_KEY, displayInfo.windowId);
452     want.SetParam(NOTIFY_TYPE, NotifyType::DIALOG);
453     int32_t uid = IPCSkeleton::GetCallingUid();
454     want.SetParam(CALLER_UID_KEY, uid);
455     if (!SetDisplayInfo(want, displayInfo)) {
456         SC_LOG_ERROR(LABEL, "Set display info failed.");
457         return;
458     }
459 
460     int startRes = AAFwk::AbilityManagerClient::GetInstance()->StartExtensionAbility(want, callerToken);
461     SC_LOG_INFO(LABEL, "Start ability res %{public}d", startRes);
462     if (startRes != 0) {
463         dialogWaitMap_.erase(scId);
464     }
465 }
466 
SendSaveEventHandler(void)467 void FirstUseDialog::SendSaveEventHandler(void)
468 {
469     std::function<void()> delayed = ([this]() {
470         this->SaveFirstUseRecord();
471     });
472 
473     SC_LOG_INFO(LABEL, "Delay first_use_record json");
474     secHandler_->ProxyPostTask(delayed);
475 }
476 
SetFirstUseMap(std::shared_ptr<SecCompEntity> entity)477 bool FirstUseDialog::SetFirstUseMap(std::shared_ptr<SecCompEntity> entity)
478 {
479     uint64_t typeMask;
480     if (entity == nullptr) {
481         SC_LOG_ERROR(LABEL, "Entity is invalid.");
482         return false;
483     }
484 
485     SecCompType type = entity->GetType();
486     if (type == LOCATION_COMPONENT) {
487         SC_LOG_INFO(LABEL, "LocationButton need not notify dialog to user.");
488         return true;
489     }
490     if (type == SAVE_COMPONENT) {
491         typeMask = SAVE_BUTTON_FIRST_USE;
492     } else {
493         SC_LOG_INFO(LABEL, "This type need not notify dialog to user.");
494         return false;
495     }
496 
497     std::unique_lock<std::mutex> lock(useMapMutex_);
498     AccessToken::AccessTokenID tokenId = entity->tokenId_;
499     auto iter = firstUseMap_.find(tokenId);
500     if (iter == firstUseMap_.end()) {
501         firstUseMap_[tokenId] = typeMask;
502         SendSaveEventHandler();
503         return true;
504     }
505 
506     firstUseMap_[tokenId] |= typeMask;
507     SendSaveEventHandler();
508     return true;
509 }
510 
NotifyFirstUseDialog(std::shared_ptr<SecCompEntity> entity,sptr<IRemoteObject> callerToken,sptr<IRemoteObject> dialogCallback,const DisplayInfo & displayInfo)511 int32_t FirstUseDialog::NotifyFirstUseDialog(std::shared_ptr<SecCompEntity> entity, sptr<IRemoteObject> callerToken,
512     sptr<IRemoteObject> dialogCallback, const DisplayInfo& displayInfo)
513 {
514     if (entity == nullptr) {
515         SC_LOG_ERROR(LABEL, "Entity is invalid.");
516         return SC_SERVICE_ERROR_VALUE_INVALID;
517     }
518     if (secHandler_ == nullptr) {
519         SC_LOG_ERROR(LABEL, "event handler invalid.");
520         return SC_SERVICE_ERROR_VALUE_INVALID;
521     }
522     if (callerToken == nullptr) {
523         SC_LOG_INFO(LABEL, "callerToken is null, no need to notify dialog");
524         return SC_SERVICE_ERROR_VALUE_INVALID;
525     }
526 
527     if (dialogCallback == nullptr) {
528         SC_LOG_INFO(LABEL, "DialogCallback is null, no need to notify dialog");
529         return SC_SERVICE_ERROR_VALUE_INVALID;
530     }
531 
532     uint64_t typeMask;
533     SecCompType type = entity->GetType();
534     if (type == LOCATION_COMPONENT) {
535         typeMask = LOCATION_BUTTON_FIRST_USE;
536     } else if (type == SAVE_COMPONENT) {
537         typeMask = SAVE_BUTTON_FIRST_USE;
538     } else {
539         SC_LOG_INFO(LABEL, "this type need not notify dialog to user");
540         return SC_OK;
541     }
542 
543     std::unique_lock<std::mutex> lock(useMapMutex_);
544     AccessToken::AccessTokenID tokenId = entity->tokenId_;
545     auto iter = firstUseMap_.find(tokenId);
546     if (iter == firstUseMap_.end()) {
547         SC_LOG_INFO(LABEL, "has not use record, start dialog");
548         StartDialogAbility(entity, callerToken, dialogCallback, displayInfo);
549         return SC_SERVICE_ERROR_WAIT_FOR_DIALOG_CLOSE;
550     }
551 
552     uint64_t compTypes = firstUseMap_[tokenId];
553     if ((typeMask == SAVE_BUTTON_FIRST_USE) && ((compTypes & typeMask) == typeMask)) {
554         SC_LOG_INFO(LABEL, "no need notify dialog again.");
555         StartToastAbility(entity, callerToken, displayInfo);
556         return SC_OK;
557     }
558     StartDialogAbility(entity, callerToken, dialogCallback, displayInfo);
559     return SC_SERVICE_ERROR_WAIT_FOR_DIALOG_CLOSE;
560 }
561 
Init(std::shared_ptr<SecEventHandler> secHandler)562 void FirstUseDialog::Init(std::shared_ptr<SecEventHandler> secHandler)
563 {
564     SC_LOG_DEBUG(LABEL, "Init!!");
565     secHandler_ = secHandler;
566     LoadFirstUseRecord();
567 }
568 }  // namespace SecurityComponent
569 }  // namespace Security
570 }  // namespace OHOS
571