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 ¶m, 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 ¶m, 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