1 /*
2  * Copyright (c) 2021-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 "ability_process.h"
17 
18 #include <dlfcn.h>
19 
20 #include "accesstoken_kit.h"
21 #include "hilog_tag_wrapper.h"
22 #include "permission_list_state.h"
23 
24 using OHOS::Security::AccessToken::AccessTokenKit;
25 using OHOS::Security::AccessToken::PermissionListState;
26 using OHOS::Security::AccessToken::TypePermissionOper;
27 
28 namespace OHOS {
29 namespace AppExecFwk {
30 static void *g_handle = nullptr;
31 #ifdef SUPPORT_GRAPHICS
32 #ifdef APP_USE_ARM
33 constexpr char SHARED_LIBRARY_FEATURE_ABILITY[] = "/system/lib/module/ability/libfeatureability.z.so";
34 #elif defined(APP_USE_X86_64)
35 constexpr char SHARED_LIBRARY_FEATURE_ABILITY[] = "/system/lib64/module/ability/libfeatureability.z.so";
36 #else
37 constexpr char SHARED_LIBRARY_FEATURE_ABILITY[] = "/system/lib64/module/ability/libfeatureability.z.so";
38 #endif
39 #endif
40 constexpr char FUNC_CALL_ON_ABILITY_RESULT[] = "CallOnAbilityResult";
41 using NAPICallOnAbilityResult = void (*)(int requestCode, int resultCode, const Want &resultData, CallbackInfo cb);
42 constexpr char FUNC_CALL_ON_REQUEST_PERMISSIONS_FROM_USERRESULT[] = "CallOnRequestPermissionsFromUserResult";
43 using NAPICallOnRequestPermissionsFromUserResult = void (*)(int requestCode,
44     const std::vector<std::string> &permissions, const std::vector<int> &grantResults, CallbackInfo callbackInfo);
45 
46 std::shared_ptr<AbilityProcess> AbilityProcess::instance_ = nullptr;
47 std::map<Ability *, std::map<int, CallbackInfo>> AbilityProcess::abilityResultMap_;
48 std::mutex AbilityProcess::mutex_;
GetInstance()49 std::shared_ptr<AbilityProcess> AbilityProcess::GetInstance()
50 {
51     if (instance_ == nullptr) {
52         std::lock_guard<std::mutex> lock_l(mutex_);
53         if (instance_ == nullptr) {
54             instance_ = std::make_shared<AbilityProcess>();
55         }
56     }
57     return instance_;
58 }
59 
AbilityProcess()60 AbilityProcess::AbilityProcess()
61 {}
62 
~AbilityProcess()63 AbilityProcess::~AbilityProcess()
64 {}
65 
StartAbility(Ability * ability,CallAbilityParam param,CallbackInfo callback)66 ErrCode AbilityProcess::StartAbility(Ability *ability, CallAbilityParam param, CallbackInfo callback)
67 {
68     TAG_LOGD(AAFwkTag::ABILITY, "begin");
69     if (ability == nullptr) {
70         TAG_LOGE(AAFwkTag::ABILITY, "null ability");
71         return ERR_NULL_OBJECT;
72     }
73 #ifdef SUPPORT_GRAPHICS
74     // inherit split mode
75     auto windowMode = ability->GetCurrentWindowMode();
76     if (windowMode == AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_PRIMARY ||
77         windowMode == AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_SECONDARY) {
78         param.want.SetParam(Want::PARAM_RESV_WINDOW_MODE, windowMode);
79     }
80     TAG_LOGI(AAFwkTag::ABILITY, "window mode:%{public}d", windowMode);
81 #endif
82     ErrCode err = ERR_OK;
83     if (param.forResultOption == true) {
84         if (param.setting == nullptr) {
85             TAG_LOGI(AAFwkTag::ABILITY, "null param.setting");
86             param.want.SetParam(Want::PARAM_RESV_FOR_RESULT, true);
87             err = ability->StartAbilityForResult(param.want, param.requestCode);
88         } else {
89             TAG_LOGI(AAFwkTag::ABILITY, "param.setting");
90             err = ability->StartAbilityForResult(param.want, param.requestCode, *(param.setting));
91         }
92 
93         std::lock_guard<std::mutex> lock_l(mutex_);
94 
95         std::map<int, CallbackInfo> map;
96         auto it = abilityResultMap_.find(ability);
97         if (it == abilityResultMap_.end()) {
98             TAG_LOGI(AAFwkTag::ABILITY, "not in abilityResultMap_");
99         } else {
100             TAG_LOGI(AAFwkTag::ABILITY, "in abilityResultMap_");
101             map = it->second;
102         }
103         callback.errCode = err;
104         map[param.requestCode] = callback;
105         abilityResultMap_[ability] = map;
106     } else {
107         if (param.setting == nullptr) {
108             TAG_LOGI(AAFwkTag::ABILITY, "null param.settingcall");
109             err = ability->StartAbility(param.want);
110         } else {
111             TAG_LOGI(AAFwkTag::ABILITY, "param.settingcall");
112             err = ability->StartAbility(param.want, *(param.setting));
113         }
114     }
115     TAG_LOGD(AAFwkTag::ABILITY, "end");
116     return err;
117 }
118 
AddAbilityResultCallback(Ability * ability,CallAbilityParam & param,int32_t errCode,CallbackInfo & callback)119 void AbilityProcess::AddAbilityResultCallback(Ability *ability, CallAbilityParam &param, int32_t errCode,
120                                               CallbackInfo &callback)
121 {
122     std::lock_guard<std::mutex> lock(mutex_);
123 
124     std::map<int, CallbackInfo> map;
125     auto it = abilityResultMap_.find(ability);
126     if (it == abilityResultMap_.end()) {
127         TAG_LOGI(AAFwkTag::ABILITY, "not in abilityResultMap_");
128     } else {
129         TAG_LOGI(AAFwkTag::ABILITY, "in abilityResultMap_");
130         map = it->second;
131     }
132     callback.errCode = errCode;
133     map[param.requestCode] = callback;
134     abilityResultMap_[ability] = map;
135 }
136 
OnAbilityResult(Ability * ability,int requestCode,int resultCode,const Want & resultData)137 void AbilityProcess::OnAbilityResult(Ability *ability, int requestCode, int resultCode, const Want &resultData)
138 {
139     TAG_LOGD(AAFwkTag::ABILITY, "begin");
140 
141     std::lock_guard<std::mutex> lock_l(mutex_);
142 
143     auto it = abilityResultMap_.find(ability);
144     if (it == abilityResultMap_.end()) {
145         TAG_LOGE(AAFwkTag::ABILITY, "not in abilityResultMap");
146         return;
147     }
148     std::map<int, CallbackInfo> map = it->second;
149 
150     auto callback = map.find(requestCode);
151     if (callback == map.end()) {
152         TAG_LOGE(AAFwkTag::ABILITY, "%{public}d not in map", requestCode);
153         return;
154     }
155     CallbackInfo callbackInfo = callback->second;
156 #ifdef SUPPORT_GRAPHICS
157     // start open featureability lib
158     if (g_handle == nullptr) {
159         g_handle = dlopen(SHARED_LIBRARY_FEATURE_ABILITY, RTLD_LAZY);
160         if (g_handle == nullptr) {
161             TAG_LOGE(AAFwkTag::ABILITY, "dlopen failed %{public}s. %{public}s",
162                 SHARED_LIBRARY_FEATURE_ABILITY,
163                 dlerror());
164             return;
165         }
166     }
167 #endif
168     // get function
169     auto func = reinterpret_cast<NAPICallOnAbilityResult>(dlsym(g_handle, FUNC_CALL_ON_ABILITY_RESULT));
170     if (func == nullptr) {
171         TAG_LOGE(AAFwkTag::ABILITY, "dlsym failed %{public}s. %{public}s", FUNC_CALL_ON_ABILITY_RESULT, dlerror());
172         dlclose(g_handle);
173         g_handle = nullptr;
174         return;
175     }
176     func(requestCode, resultCode, resultData, callbackInfo);
177 
178     map.erase(requestCode);
179 
180     abilityResultMap_[ability] = map;
181     TAG_LOGD(AAFwkTag::ABILITY, "end");
182 }
183 
RequestPermissionsFromUser(Ability * ability,CallAbilityPermissionParam & param,CallbackInfo callbackInfo)184 void AbilityProcess::RequestPermissionsFromUser(
185     Ability *ability, CallAbilityPermissionParam &param, CallbackInfo callbackInfo)
186 {
187     TAG_LOGD(AAFwkTag::ABILITY, "begin");
188     if (ability == nullptr) {
189         TAG_LOGE(AAFwkTag::ABILITY, "null ability");
190         return;
191     }
192 
193     std::vector<PermissionListState> permList;
194     for (auto permission : param.permission_list) {
195         TAG_LOGD(AAFwkTag::ABILITY, "permission:%{public}s", permission.c_str());
196         PermissionListState permState;
197         permState.permissionName = permission;
198         permState.state = Security::AccessToken::SETTING_OPER;
199         permList.emplace_back(permState);
200     }
201     TAG_LOGD(AAFwkTag::ABILITY, "permList size:%{public}zu, permissions size:%{public}zu",
202         permList.size(), param.permission_list.size());
203 
204     Security::AccessToken::PermissionGrantInfo grantInfo;
205     auto ret = AccessTokenKit::GetSelfPermissionsState(permList, grantInfo);
206     if (permList.size() != param.permission_list.size()) {
207         TAG_LOGE(AAFwkTag::ABILITY, "permList size:%{public}zu", permList.size());
208         return;
209     }
210 
211     std::vector<int> permissionsState;
212     for (auto permState : permList) {
213         TAG_LOGD(AAFwkTag::ABILITY, "permissions:%{public}s. permissionsState:%{public}u",
214             permState.permissionName.c_str(), permState.state);
215         permissionsState.emplace_back(permState.state);
216     }
217     TAG_LOGD(AAFwkTag::ABILITY, "permissions size:%{public}zu. permissionsState size:%{public}zu",
218         param.permission_list.size(), permissionsState.size());
219 
220     auto requestCode = param.requestCode;
221     if (ret != TypePermissionOper::DYNAMIC_OPER) {
222         TAG_LOGD(AAFwkTag::ABILITY, "need not dynamic popup");
223         (void)CaullFunc(requestCode, param.permission_list, permissionsState, callbackInfo);
224         return;
225     }
226 
227     auto task = [self = GetInstance(), requestCode, callbackInfo]
228         (const std::vector<std::string> &permissions, const std::vector<int> &grantResults) mutable {
229         if (!self) {
230             TAG_LOGE(AAFwkTag::ABILITY, "null self");
231             return;
232         }
233         if (!self->CaullFunc(requestCode, permissions, grantResults, callbackInfo)) {
234             TAG_LOGE(AAFwkTag::ABILITY, "call function failed");
235             return;
236         }
237     };
238 
239     ability->RequestPermissionsFromUser(param.permission_list, permissionsState, std::move(task));
240 }
241 
CaullFunc(int requestCode,const std::vector<std::string> & permissions,const std::vector<int> & permissionsState,CallbackInfo & callbackInfo)242 bool AbilityProcess::CaullFunc(int requestCode, const std::vector<std::string> &permissions,
243     const std::vector<int> &permissionsState, CallbackInfo &callbackInfo)
244 {
245 #ifdef SUPPORT_GRAPHICS
246     // start open featureability lib
247     if (g_handle == nullptr) {
248         g_handle = dlopen(SHARED_LIBRARY_FEATURE_ABILITY, RTLD_LAZY);
249         if (g_handle == nullptr) {
250             TAG_LOGE(AAFwkTag::ABILITY, "dlopen failed %{public}s. %{public}s",
251                 SHARED_LIBRARY_FEATURE_ABILITY, dlerror());
252             return false;
253         }
254     }
255 #endif
256     // get function
257     auto func = reinterpret_cast<NAPICallOnRequestPermissionsFromUserResult>(
258         dlsym(g_handle, FUNC_CALL_ON_REQUEST_PERMISSIONS_FROM_USERRESULT));
259     if (func == nullptr) {
260         TAG_LOGE(AAFwkTag::ABILITY, "dlsym failed %{public}s. %{public}s",
261             FUNC_CALL_ON_REQUEST_PERMISSIONS_FROM_USERRESULT, dlerror());
262         dlclose(g_handle);
263         g_handle = nullptr;
264         return false;
265     }
266     func(requestCode, permissions, permissionsState, callbackInfo);
267     return true;
268 }
269 }  // namespace AppExecFwk
270 }  // namespace OHOS
271