• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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