1 /*
2 * Copyright (c) 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 "free_install_manager.h"
17
18 #include <chrono>
19
20 #include "ability_info.h"
21 #include "ability_manager_errors.h"
22 #include "ability_manager_service.h"
23 #include "ability_util.h"
24 #include "atomic_service_status_callback.h"
25 #include "distributed_client.h"
26 #include "hilog_wrapper.h"
27 #include "in_process_call_wrapper.h"
28
29 namespace OHOS {
30 namespace AAFwk {
31 const std::u16string DMS_FREE_INSTALL_CALLBACK_TOKEN = u"ohos.DistributedSchedule.IDmsFreeInstallCallback";
32 const std::string DMS_MISSION_ID = "dmsMissionId";
33 const std::string PARAM_FREEINSTALL_APPID = "ohos.freeinstall.params.callingAppId";
34 const std::string PARAM_FREEINSTALL_BUNDLENAMES = "ohos.freeinstall.params.callingBundleNames";
35 const std::string PARAM_FREEINSTALL_UID = "ohos.freeinstall.params.callingUid";
36 constexpr uint32_t IDMS_CALLBACK_ON_FREE_INSTALL_DONE = 0;
37 constexpr uint32_t UPDATE_ATOMOIC_SERVICE_TASK_TIMER = 24 * 60 * 60 * 1000; /* 24h */
38
FreeInstallManager(const std::weak_ptr<AbilityManagerService> & server)39 FreeInstallManager::FreeInstallManager(const std::weak_ptr<AbilityManagerService> &server)
40 : server_(server)
41 {
42 }
43
IsTopAbility(const sptr<IRemoteObject> & callerToken)44 bool FreeInstallManager::IsTopAbility(const sptr<IRemoteObject> &callerToken)
45 {
46 HILOG_INFO("%{public}s", __func__);
47 auto server = server_.lock();
48 CHECK_POINTER_AND_RETURN_LOG(server, false, "Get server failed!");
49 AppExecFwk::ElementName elementName = server->GetTopAbility();
50 if (elementName.GetBundleName().empty() || elementName.GetAbilityName().empty()) {
51 HILOG_ERROR("GetBundleName or GetAbilityName empty!");
52 return false;
53 }
54
55 auto caller = Token::GetAbilityRecordByToken(callerToken);
56 if (caller == nullptr) {
57 HILOG_ERROR("Caller is null!");
58 return false;
59 }
60
61 auto type = caller->GetAbilityInfo().type;
62 if (type == AppExecFwk::AbilityType::SERVICE || type == AppExecFwk::AbilityType::EXTENSION) {
63 HILOG_INFO("The ability is service or extension ability.");
64 return true;
65 }
66
67 AppExecFwk::ElementName callerElementName = caller->GetWant().GetElement();
68 std::string callerBundleName = callerElementName.GetBundleName();
69 std::string callerAbilityName = callerElementName.GetAbilityName();
70 std::string callerModuleName = callerElementName.GetModuleName();
71 if (elementName.GetBundleName().compare(callerBundleName) == 0 &&
72 elementName.GetAbilityName().compare(callerAbilityName) == 0 &&
73 elementName.GetModuleName().compare(callerModuleName) == 0) {
74 HILOG_INFO("The ability is top ability.");
75 return true;
76 }
77
78 return false;
79 }
80
StartFreeInstall(const Want & want,int32_t userId,int requestCode,const sptr<IRemoteObject> & callerToken)81 int FreeInstallManager::StartFreeInstall(const Want &want, int32_t userId, int requestCode,
82 const sptr<IRemoteObject> &callerToken)
83 {
84 HILOG_INFO("StartFreeInstall called");
85 auto isSaCall = AAFwk::PermissionVerification::GetInstance()->IsSACall();
86 if (!isSaCall && !IsTopAbility(callerToken)) {
87 return NOT_TOP_ABILITY;
88 }
89 FreeInstallInfo info = BuildFreeInstallInfo(want, userId, requestCode, callerToken);
90 {
91 std::lock_guard<std::mutex> lock(freeInstallListLock_);
92 freeInstallList_.push_back(info);
93 }
94 sptr<AtomicServiceStatusCallback> callback = new AtomicServiceStatusCallback(weak_from_this(),
95 info.startInstallTime);
96 auto bms = AbilityUtil::GetBundleManager();
97 CHECK_POINTER_AND_RETURN(bms, GET_ABILITY_SERVICE_FAILED);
98 AppExecFwk::AbilityInfo abilityInfo = {};
99 constexpr auto flag = AppExecFwk::AbilityInfoFlag::GET_ABILITY_INFO_WITH_APPLICATION;
100 info.want.SetParam(PARAM_FREEINSTALL_UID, IPCSkeleton::GetCallingUid());
101 if (IN_PROCESS_CALL(bms->QueryAbilityInfo(info.want, flag, info.userId, abilityInfo, callback))) {
102 HILOG_INFO("The app has installed.");
103 }
104 std::string callingAppId = info.want.GetStringParam(PARAM_FREEINSTALL_APPID);
105 std::vector<std::string> callingBundleNames = info.want.GetStringArrayParam(PARAM_FREEINSTALL_BUNDLENAMES);
106 if (callingAppId.empty() && callingBundleNames.empty()) {
107 HILOG_INFO("callingAppId and callingBundleNames are empty");
108 }
109 info.want.RemoveParam(PARAM_FREEINSTALL_APPID);
110 info.want.RemoveParam(PARAM_FREEINSTALL_BUNDLENAMES);
111 auto future = info.promise->get_future();
112 std::future_status status = future.wait_for(std::chrono::milliseconds(DELAY_LOCAL_FREE_INSTALL_TIMEOUT));
113 if (status == std::future_status::timeout) {
114 info.isInstalled = true;
115 return FREE_INSTALL_TIMEOUT;
116 }
117 return future.get();
118 }
119
RemoteFreeInstall(const Want & want,int32_t userId,int requestCode,const sptr<IRemoteObject> & callerToken)120 int FreeInstallManager::RemoteFreeInstall(const Want &want, int32_t userId, int requestCode,
121 const sptr<IRemoteObject> &callerToken)
122 {
123 HILOG_INFO("RemoteFreeInstall called");
124 bool isFromRemote = want.GetBoolParam(FROM_REMOTE_KEY, false);
125 auto isSaCall = AAFwk::PermissionVerification::GetInstance()->IsSACall();
126 if (!isSaCall && !isFromRemote && !IsTopAbility(callerToken)) {
127 return NOT_TOP_ABILITY;
128 }
129 FreeInstallInfo info = BuildFreeInstallInfo(want, userId, requestCode, callerToken);
130 {
131 std::lock_guard<std::mutex> lock(freeInstallListLock_);
132 freeInstallList_.push_back(info);
133 }
134 sptr<AtomicServiceStatusCallback> callback = new AtomicServiceStatusCallback(weak_from_this(),
135 info.startInstallTime);
136 int32_t callerUid = IPCSkeleton::GetCallingUid();
137 uint32_t accessToken = IPCSkeleton::GetCallingTokenID();
138 DistributedClient dmsClient;
139 auto result = dmsClient.StartRemoteFreeInstall(info.want, callerUid, info.requestCode, accessToken, callback);
140 if (result != ERR_NONE) {
141 return result;
142 }
143 auto remoteFuture = info.promise->get_future();
144 std::future_status remoteStatus = remoteFuture.wait_for(std::chrono::milliseconds(
145 DELAY_REMOTE_FREE_INSTALL_TIMEOUT));
146 if (remoteStatus == std::future_status::timeout) {
147 return FREE_INSTALL_TIMEOUT;
148 }
149 return remoteFuture.get();
150 }
151
BuildFreeInstallInfo(const Want & want,int32_t userId,int requestCode,const sptr<IRemoteObject> & callerToken)152 FreeInstallInfo FreeInstallManager::BuildFreeInstallInfo(const Want &want, int32_t userId, int requestCode,
153 const sptr<IRemoteObject> &callerToken)
154 {
155 auto promise = std::make_shared<std::promise<int32_t>>();
156 FreeInstallInfo info = {
157 .want = want,
158 .userId = userId,
159 .requestCode = requestCode,
160 .startInstallTime = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::
161 system_clock::now().time_since_epoch()).count(),
162 .promise = promise,
163 .callerToken = callerToken
164 };
165 return info;
166 }
167
StartRemoteFreeInstall(const Want & want,int requestCode,int32_t validUserId,const sptr<IRemoteObject> & callerToken)168 int FreeInstallManager::StartRemoteFreeInstall(const Want &want, int requestCode, int32_t validUserId,
169 const sptr<IRemoteObject> &callerToken)
170 {
171 HILOG_INFO("%{public}s", __func__);
172 if (!want.GetBoolParam(Want::PARAM_RESV_FOR_RESULT, false)) {
173 HILOG_INFO("%{public}s: StartAbility freeInstall", __func__);
174 return RemoteFreeInstall(want, validUserId, requestCode, callerToken);
175 }
176 int32_t missionId = DelayedSingleton<AbilityManagerService>::GetInstance()->
177 GetMissionIdByAbilityToken(callerToken);
178 if (missionId < 0) {
179 return ERR_INVALID_VALUE;
180 }
181 Want* newWant = const_cast<Want*>(&want);
182 newWant->SetParam(DMS_MISSION_ID, missionId);
183 HILOG_INFO("%{public}s: StartAbilityForResult freeInstall", __func__);
184 return RemoteFreeInstall(*newWant, validUserId, requestCode, callerToken);
185 }
186
NotifyDmsCallback(const Want & want,int resultCode)187 int FreeInstallManager::NotifyDmsCallback(const Want &want, int resultCode)
188 {
189 std::lock_guard<std::mutex> autoLock(distributedFreeInstallLock_);
190 if (dmsFreeInstallCbs_.empty()) {
191 HILOG_ERROR("Has no dms callback.");
192 return ERR_INVALID_VALUE;
193 }
194
195 MessageParcel reply;
196 MessageOption option;
197
198 for (auto it = dmsFreeInstallCbs_.begin(); it != dmsFreeInstallCbs_.end();) {
199 std::string abilityName = (*it).want.GetElement().GetAbilityName();
200 if (want.GetElement().GetAbilityName().compare(abilityName) == 0) {
201 HILOG_INFO("Handle DMS.");
202 MessageParcel data;
203 if (!data.WriteInterfaceToken(DMS_FREE_INSTALL_CALLBACK_TOKEN)) {
204 HILOG_ERROR("Write interface token failed.");
205 return ERR_INVALID_VALUE;
206 }
207
208 if (!data.WriteInt32(resultCode)) {
209 HILOG_ERROR("Write resultCode error.");
210 return ERR_INVALID_VALUE;
211 }
212
213 if (!data.WriteParcelable(&((*it).want))) {
214 HILOG_ERROR("want write failed.");
215 return INNER_ERR;
216 }
217
218 if (!data.WriteInt32((*it).requestCode)) {
219 HILOG_ERROR("Write resultCode error.");
220 return ERR_INVALID_VALUE;
221 }
222
223 (*it).dmsCallback->SendRequest(IDMS_CALLBACK_ON_FREE_INSTALL_DONE, data, reply, option);
224 it = dmsFreeInstallCbs_.erase(it);
225 } else {
226 it++;
227 }
228 }
229
230 return reply.ReadInt32();
231 }
232
NotifyFreeInstallResult(const Want & want,int resultCode,int64_t startInstallTime)233 void FreeInstallManager::NotifyFreeInstallResult(const Want &want, int resultCode, int64_t startInstallTime)
234 {
235 std::lock_guard<std::mutex> lock(freeInstallListLock_);
236 if (freeInstallList_.empty()) {
237 HILOG_INFO("Has no app callback.");
238 return;
239 }
240
241 bool isFromRemote = want.GetBoolParam(FROM_REMOTE_KEY, false);
242 HILOG_INFO("isFromRemote = %{public}d", isFromRemote);
243 for (auto it = freeInstallList_.begin(); it != freeInstallList_.end();) {
244 std::string bundleName = (*it).want.GetElement().GetBundleName();
245 std::string abilityName = (*it).want.GetElement().GetAbilityName();
246 if (want.GetElement().GetBundleName().compare(bundleName) != 0 ||
247 want.GetElement().GetAbilityName().compare(abilityName) != 0 ||
248 (*it).startInstallTime != startInstallTime) {
249 it++;
250 continue;
251 }
252
253 if ((*it).isInstalled) {
254 it = freeInstallList_.erase(it);
255 continue;
256 }
257
258 if ((*it).promise == nullptr) {
259 it++;
260 continue;
261 }
262
263 if (resultCode == ERR_OK) {
264 HILOG_INFO("FreeInstall success.");
265 (*it).promise->set_value(resultCode);
266 (*it).isInstalled = true;
267 } else {
268 HILOG_INFO("FreeInstall failed.");
269 (*it).promise->set_value(resultCode);
270 }
271
272 it++;
273 }
274 }
275
FreeInstallAbilityFromRemote(const Want & want,const sptr<IRemoteObject> & callback,int32_t userId,int requestCode)276 int FreeInstallManager::FreeInstallAbilityFromRemote(const Want &want, const sptr<IRemoteObject> &callback,
277 int32_t userId, int requestCode)
278 {
279 HILOG_INFO("%{public}s", __func__);
280 if (callback == nullptr) {
281 HILOG_ERROR("FreeInstallAbilityFromRemote callback is nullptr.");
282 return ERR_INVALID_VALUE;
283 }
284
285 FreeInstallInfo info = {
286 .want = want,
287 .userId = userId,
288 .requestCode = requestCode,
289 .dmsCallback = callback
290 };
291
292 {
293 std::lock_guard<std::mutex> autoLock(distributedFreeInstallLock_);
294 dmsFreeInstallCbs_.push_back(info);
295 }
296
297 auto freeInstallTask = [manager = shared_from_this(), info]() {
298 auto result = manager->StartFreeInstall(info.want, info.userId, info.requestCode, nullptr);
299 if (result != ERR_OK) {
300 manager->NotifyDmsCallback(info.want, result);
301 }
302 };
303
304 std::shared_ptr<AbilityEventHandler> handler =
305 DelayedSingleton<AbilityManagerService>::GetInstance()->GetEventHandler();
306 CHECK_POINTER_AND_RETURN_LOG(handler, ERR_INVALID_VALUE, "Fail to get AbilityEventHandler.");
307
308 handler->PostTask(freeInstallTask, "FreeInstallAbilityFromRemote");
309 return ERR_OK;
310 }
311
ConnectFreeInstall(const Want & want,int32_t userId,const sptr<IRemoteObject> & callerToken,const std::string & localDeviceId)312 int FreeInstallManager::ConnectFreeInstall(const Want &want, int32_t userId,
313 const sptr<IRemoteObject> &callerToken, const std::string& localDeviceId)
314 {
315 auto bms = AbilityUtil::GetBundleManager();
316 CHECK_POINTER_AND_RETURN(bms, GET_ABILITY_SERVICE_FAILED);
317 std::string wantDeviceId = want.GetElement().GetDeviceID();
318 if (!(localDeviceId == wantDeviceId || wantDeviceId.empty())) {
319 HILOG_ERROR("AbilityManagerService::ConnectFreeInstall. wantDeviceId error");
320 return ERR_INVALID_VALUE;
321 }
322
323 auto isSaCall = AAFwk::PermissionVerification::GetInstance()->IsSACall();
324 if (!isSaCall) {
325 std::string wantAbilityName = want.GetElement().GetAbilityName();
326 std::string wantBundleName = want.GetElement().GetBundleName();
327 if (wantBundleName.empty() || wantAbilityName.empty()) {
328 HILOG_ERROR("AbilityManagerService::ConnectFreeInstall. wantBundleName or wantAbilityName is empty");
329 return ERR_INVALID_VALUE;
330 }
331 int callerUid = IPCSkeleton::GetCallingUid();
332 std::string localBundleName;
333 bms->GetBundleNameForUid(callerUid, localBundleName);
334 if (localBundleName != wantBundleName) {
335 HILOG_ERROR("AbilityManagerService::ConnectFreeInstall. wantBundleName is not local BundleName");
336 return ERR_INVALID_VALUE;
337 }
338 }
339
340 AppExecFwk::AbilityInfo abilityInfo;
341 std::vector<AppExecFwk::ExtensionAbilityInfo> extensionInfos;
342 if (!IN_PROCESS_CALL(bms->QueryAbilityInfo(
343 want, AppExecFwk::AbilityInfoFlag::GET_ABILITY_INFO_WITH_APPLICATION, userId, abilityInfo)) &&
344 !IN_PROCESS_CALL(bms->QueryExtensionAbilityInfos(
345 want, AppExecFwk::AbilityInfoFlag::GET_ABILITY_INFO_WITH_APPLICATION, userId, extensionInfos))) {
346 HILOG_INFO("AbilityManagerService::ConnectFreeInstall. try to StartFreeInstall");
347 int result = StartFreeInstall(want, userId, DEFAULT_INVAL_VALUE, callerToken);
348 if (result) {
349 HILOG_ERROR("AbilityManagerService::ConnectFreeInstall. StartFreeInstall error");
350 return result;
351 }
352 HILOG_INFO("AbilityManagerService::ConnectFreeInstall. StartFreeInstall success");
353 }
354 return ERR_OK;
355 }
356
GetTimeStamp()357 std::time_t FreeInstallManager::GetTimeStamp()
358 {
359 std::chrono::time_point<std::chrono::system_clock, std::chrono::milliseconds> tp =
360 std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::system_clock::now());
361 std::time_t timestamp = tp.time_since_epoch().count();
362 return timestamp;
363 }
364
OnInstallFinished(int resultCode,const Want & want,int32_t userId,int64_t startInstallTime)365 void FreeInstallManager::OnInstallFinished(int resultCode, const Want &want, int32_t userId, int64_t startInstallTime)
366 {
367 HILOG_INFO("%{public}s resultCode = %{public}d", __func__, resultCode);
368 NotifyDmsCallback(want, resultCode);
369 NotifyFreeInstallResult(want, resultCode, startInstallTime);
370
371 std::weak_ptr<FreeInstallManager> thisWptr(shared_from_this());
372 if (resultCode == ERR_OK) {
373 auto updateAtmoicServiceTask = [want, userId, thisWptr, &timeStampMap = timeStampMap_]() {
374 auto sptr = thisWptr.lock();
375 HILOG_DEBUG("bundleName: %{public}s, moduleName: %{public}s", want.GetElement().GetBundleName().c_str(),
376 want.GetElement().GetModuleName().c_str());
377 std::string nameKey = want.GetElement().GetBundleName() + want.GetElement().GetModuleName();
378 if (timeStampMap.find(nameKey) == timeStampMap.end() ||
379 sptr->GetTimeStamp() - timeStampMap[nameKey] > UPDATE_ATOMOIC_SERVICE_TASK_TIMER) {
380 auto bms = AbilityUtil::GetBundleManager();
381 CHECK_POINTER(bms);
382 bms->UpgradeAtomicService(want, userId);
383 timeStampMap.emplace(nameKey, sptr->GetTimeStamp());
384 }
385 };
386
387 std::shared_ptr<AbilityEventHandler> handler =
388 DelayedSingleton<AbilityManagerService>::GetInstance()->GetEventHandler();
389 CHECK_POINTER_LOG(handler, "Fail to get AbilityEventHandler.");
390 handler->PostTask(updateAtmoicServiceTask, "UpdateAtmoicServiceTask");
391 }
392 }
393
OnRemoteInstallFinished(int resultCode,const Want & want,int32_t userId,int64_t startInstallTime)394 void FreeInstallManager::OnRemoteInstallFinished(int resultCode, const Want &want, int32_t userId,
395 int64_t startInstallTime)
396 {
397 HILOG_INFO("%{public}s resultCode = %{public}d", __func__, resultCode);
398 NotifyFreeInstallResult(want, resultCode, startInstallTime);
399 }
400 } // namespace AAFwk
401 } // namespace OHOS
402