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