1 /*
2  * Copyright (c) 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 
16 #include "el5_filekey_manager_client.h"
17 
18 #include "el5_filekey_manager_log.h"
19 #include "el5_filekey_manager_proxy.h"
20 #include "iservice_registry.h"
21 #include "refbase.h"
22 #include "system_ability_definition.h"
23 #include "sys_binder.h"
24 
25 namespace OHOS {
26 namespace Security {
27 namespace AccessToken {
28 namespace {
29 constexpr int32_t LOAD_SA_TIMEOUT_SECOND = 4;
30 constexpr int32_t LOAD_SA_RETRY_TIMES = 5;
31 static const int32_t SA_REQUEST_RETRY_TIMES = 1;
32 static const int32_t SENDREQ_FAIL_ERR = 32;
33 static const std::vector<int32_t> RETRY_CODE_LIST = { BR_DEAD_REPLY, BR_FAILED_REPLY, SENDREQ_FAIL_ERR };
34 }
El5FilekeyManagerClient()35 El5FilekeyManagerClient::El5FilekeyManagerClient() {}
36 
~El5FilekeyManagerClient()37 El5FilekeyManagerClient::~El5FilekeyManagerClient() {}
38 
GetInstance()39 El5FilekeyManagerClient &El5FilekeyManagerClient::GetInstance()
40 {
41     static El5FilekeyManagerClient instance;
42     return instance;
43 }
44 
AcquireAccess(DataLockType type)45 int32_t El5FilekeyManagerClient::AcquireAccess(DataLockType type)
46 {
47     std::function<int32_t(sptr<El5FilekeyManagerInterface> &)> func = [&](sptr<El5FilekeyManagerInterface> &proxy) {
48         return proxy->AcquireAccess(type);
49     };
50     return CallProxyWithRetry(func, __FUNCTION__);
51 }
52 
ReleaseAccess(DataLockType type)53 int32_t El5FilekeyManagerClient::ReleaseAccess(DataLockType type)
54 {
55     std::function<int32_t(sptr<El5FilekeyManagerInterface> &)> func = [&](sptr<El5FilekeyManagerInterface> &proxy) {
56         return proxy->ReleaseAccess(type);
57     };
58     return CallProxyWithRetry(func, __FUNCTION__);
59 }
60 
GenerateAppKey(uint32_t uid,const std::string & bundleName,std::string & keyId)61 int32_t El5FilekeyManagerClient::GenerateAppKey(uint32_t uid, const std::string &bundleName, std::string &keyId)
62 {
63     std::function<int32_t(sptr<El5FilekeyManagerInterface> &)> func = [&](sptr<El5FilekeyManagerInterface> &proxy) {
64         return proxy->GenerateAppKey(uid, bundleName, keyId);
65     };
66     return CallProxyWithRetry(func, __FUNCTION__);
67 }
68 
DeleteAppKey(const std::string & bundleName,int32_t userId)69 int32_t El5FilekeyManagerClient::DeleteAppKey(const std::string &bundleName, int32_t userId)
70 {
71     std::function<int32_t(sptr<El5FilekeyManagerInterface> &)> func = [&](sptr<El5FilekeyManagerInterface> &proxy) {
72         return proxy->DeleteAppKey(bundleName, userId);
73     };
74     return CallProxyWithRetry(func, __FUNCTION__);
75 }
76 
GetUserAppKey(int32_t userId,bool getAllFlag,std::vector<std::pair<int32_t,std::string>> & keyInfos)77 int32_t El5FilekeyManagerClient::GetUserAppKey(int32_t userId, bool getAllFlag,
78     std::vector<std::pair<int32_t, std::string>> &keyInfos)
79 {
80     std::function<int32_t(sptr<El5FilekeyManagerInterface> &)> func = [&](sptr<El5FilekeyManagerInterface> &proxy) {
81         return proxy->GetUserAppKey(userId, getAllFlag, keyInfos);
82     };
83     return CallProxyWithRetry(func, __FUNCTION__);
84 }
85 
ChangeUserAppkeysLoadInfo(int32_t userId,std::vector<std::pair<std::string,bool>> & loadInfos)86 int32_t El5FilekeyManagerClient::ChangeUserAppkeysLoadInfo(int32_t userId,
87     std::vector<std::pair<std::string, bool>> &loadInfos)
88 {
89     std::function<int32_t(sptr<El5FilekeyManagerInterface> &)> func = [&](sptr<El5FilekeyManagerInterface> &proxy) {
90         return proxy->ChangeUserAppkeysLoadInfo(userId, loadInfos);
91     };
92     return CallProxyWithRetry(func, __FUNCTION__);
93 }
94 
SetFilePathPolicy()95 int32_t El5FilekeyManagerClient::SetFilePathPolicy()
96 {
97     std::function<int32_t(sptr<El5FilekeyManagerInterface> &)> func = [&](sptr<El5FilekeyManagerInterface> &proxy) {
98         return proxy->SetFilePathPolicy();
99     };
100     return CallProxyWithRetry(func, __FUNCTION__);
101 }
102 
RegisterCallback(const sptr<El5FilekeyCallbackInterface> & callback)103 int32_t El5FilekeyManagerClient::RegisterCallback(const sptr<El5FilekeyCallbackInterface> &callback)
104 {
105     std::function<int32_t(sptr<El5FilekeyManagerInterface> &)> func = [&](sptr<El5FilekeyManagerInterface> &proxy) {
106         return proxy->RegisterCallback(callback);
107     };
108     return CallProxyWithRetry(func, __FUNCTION__);
109 }
110 
GetProxy()111 sptr<El5FilekeyManagerInterface> El5FilekeyManagerClient::GetProxy()
112 {
113     std::unique_lock<std::mutex> lock(proxyMutex_);
114     auto systemAbilityManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
115     if (systemAbilityManager == nullptr) {
116         LOG_ERROR("Get system ability manager failed.");
117         return nullptr;
118     }
119 
120     auto el5FilekeyService = systemAbilityManager->CheckSystemAbility(EL5_FILEKEY_MANAGER_SERVICE_ID);
121     if (el5FilekeyService != nullptr) {
122         LOG_INFO("get el5 filekey manager proxy success");
123         return iface_cast<El5FilekeyManagerInterface>(el5FilekeyService);
124     }
125 
126     for (int i = 0; i <= LOAD_SA_RETRY_TIMES; i++) {
127         auto el5FilekeyService =
128             systemAbilityManager->LoadSystemAbility(EL5_FILEKEY_MANAGER_SERVICE_ID, LOAD_SA_TIMEOUT_SECOND);
129         if (el5FilekeyService != nullptr) {
130             LOG_INFO("load el5 filekey manager success");
131             return iface_cast<El5FilekeyManagerInterface>(el5FilekeyService);
132         }
133         LOG_INFO("load el5 filekey manager failed, retry count:%{public}d", i);
134     }
135     LOG_ERROR("get el5 filekey manager proxy failed");
136     return nullptr;
137 }
138 
CallProxyWithRetry(const std::function<int32_t (sptr<El5FilekeyManagerInterface> &)> & func,const char * funcName)139 int32_t El5FilekeyManagerClient::CallProxyWithRetry(
140     const std::function<int32_t(sptr<El5FilekeyManagerInterface> &)> &func, const char *funcName)
141 {
142     LOG_INFO("call proxy with retry function:%s", funcName);
143     auto proxy = GetProxy();
144     if (proxy != nullptr) {
145         int32_t ret = func(proxy);
146         if (!IsRequestNeedRetry(ret)) {
147             return ret;
148         }
149         LOG_WARN("First try cal %{public}s failed ret:%{public}d. Begin retry", funcName, ret);
150     } else {
151         LOG_WARN("First try call %{public}s failed, proxy is NULL. Begin retry.", funcName);
152     }
153 
154     for (int32_t i = 0; i < SA_REQUEST_RETRY_TIMES; i++) {
155         proxy = GetProxy();
156         if (proxy == nullptr) {
157             LOG_WARN("Get proxy %{public}s failed, retry time = %{public}d.", funcName, i);
158             continue;
159         }
160         int32_t ret = func(proxy);
161         if (!IsRequestNeedRetry(ret)) {
162             return ret;
163         }
164         LOG_WARN("Call %{public}s failed, retry time = %{public}d, result = %{public}d", funcName, i, ret);
165     }
166     LOG_ERROR("Retry call service %{public}s error, tried %{public}d times.", funcName, SA_REQUEST_RETRY_TIMES);
167     return EFM_ERR_REMOTE_CONNECTION;
168 }
169 
IsRequestNeedRetry(int32_t ret)170 bool El5FilekeyManagerClient::IsRequestNeedRetry(int32_t ret)
171 {
172     auto it = std::find(RETRY_CODE_LIST.begin(), RETRY_CODE_LIST.end(), ret);
173     return it != RETRY_CODE_LIST.end();
174 }
175 } // namespace AccessToken
176 } // namespace Security
177 } // namespace OHOS
178