1/*
2 * Copyright (c) 2022-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 "free_install_manager.h"
17
18#include "ability_manager_service.h"
19#include "ability_util.h"
20#include "atomic_service_status_callback.h"
21#include "distributed_client.h"
22#include "hitrace_meter.h"
23#include "insight_intent_execute_manager.h"
24#include "insight_intent_utils.h"
25#include "permission_constants.h"
26#include "utils/app_mgr_util.h"
27#include "uri_utils.h"
28
29namespace OHOS {
30namespace AAFwk {
31const std::u16string DMS_FREE_INSTALL_CALLBACK_TOKEN = u"ohos.DistributedSchedule.IDmsFreeInstallCallback";
32const std::string DMS_MISSION_ID = "dmsMissionId";
33const std::string PARAM_FREEINSTALL_APPID = "ohos.freeinstall.params.callingAppId";
34const std::string PARAM_FREEINSTALL_BUNDLENAMES = "ohos.freeinstall.params.callingBundleNames";
35const std::string PARAM_FREEINSTALL_UID = "ohos.freeinstall.params.callingUid";
36constexpr uint32_t IDMS_CALLBACK_ON_FREE_INSTALL_DONE = 0;
37constexpr uint32_t UPDATE_ATOMOIC_SERVICE_TASK_TIMER = 24 * 60 * 60 * 1000; /* 24h */
38constexpr const char* KEY_IS_APP_RUNNING = "com.ohos.param.isAppRunning";
39
40FreeInstallManager::FreeInstallManager(const std::weak_ptr<AbilityManagerService> &server)
41    : server_(server)
42{
43}
44
45bool FreeInstallManager::IsTopAbility(const sptr<IRemoteObject> &callerToken)
46{
47    auto server = server_.lock();
48    CHECK_POINTER_AND_RETURN_LOG(server, false, "Get server failed!");
49    AppExecFwk::ElementName elementName = IN_PROCESS_CALL(server->GetTopAbility());
50    if (elementName.GetBundleName().empty() || elementName.GetAbilityName().empty()) {
51        TAG_LOGE(AAFwkTag::FREE_INSTALL, "GetBundleName or GetAbilityName empty");
52        return false;
53    }
54
55    auto caller = Token::GetAbilityRecordByToken(callerToken);
56    if (caller == nullptr) {
57        TAG_LOGE(AAFwkTag::FREE_INSTALL, "null caller");
58        return false;
59    }
60
61    auto type = caller->GetAbilityInfo().type;
62    if (type == AppExecFwk::AbilityType::SERVICE || type == AppExecFwk::AbilityType::EXTENSION) {
63        TAG_LOGE(AAFwkTag::FREE_INSTALL, "service or extension");
64        return true;
65    }
66
67    AppExecFwk::ElementName callerElementName = caller->GetElementName();
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        TAG_LOGI(AAFwkTag::FREE_INSTALL, "top ability");
75        return true;
76    }
77
78    return false;
79}
80
81int FreeInstallManager::StartFreeInstall(const Want &want, int32_t userId, int requestCode,
82    const sptr<IRemoteObject> &callerToken, bool isAsync, uint32_t specifyTokenId, bool isOpenAtomicServiceShortUrl,
83    std::shared_ptr<Want> originalWant)
84{
85    HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
86    if (!VerifyStartFreeInstallPermission(callerToken)) {
87        return NOT_TOP_ABILITY;
88    }
89    FreeInstallInfo info = BuildFreeInstallInfo(want, userId, requestCode, callerToken,
90        isAsync, specifyTokenId, isOpenAtomicServiceShortUrl, originalWant);
91    {
92        std::lock_guard<ffrt::mutex> lock(freeInstallListLock_);
93        freeInstallList_.push_back(info);
94    }
95    int32_t recordId = GetRecordIdByToken(callerToken);
96    sptr<AtomicServiceStatusCallback> callback = new AtomicServiceStatusCallback(weak_from_this(), isAsync, recordId);
97    auto bundleMgrHelper = AbilityUtil::GetBundleManagerHelper();
98    CHECK_POINTER_AND_RETURN(bundleMgrHelper, GET_ABILITY_SERVICE_FAILED);
99    AppExecFwk::AbilityInfo abilityInfo = {};
100    constexpr auto flag = AppExecFwk::AbilityInfoFlag::GET_ABILITY_INFO_WITH_APPLICATION;
101    info.want.SetParam(PARAM_FREEINSTALL_UID, IPCSkeleton::GetCallingUid());
102
103    int result = SetAppRunningState(info.want);
104    if (result != ERR_OK) {
105        TAG_LOGE(AAFwkTag::FREE_INSTALL, "setAppRunningState failed");
106        return result;
107    }
108
109    if (IN_PROCESS_CALL(bundleMgrHelper->QueryAbilityInfo(info.want, flag, info.userId, abilityInfo, callback))) {
110        TAG_LOGI(AAFwkTag::FREE_INSTALL, "app installed");
111    }
112    std::string callingAppId = info.want.GetStringParam(PARAM_FREEINSTALL_APPID);
113    std::vector<std::string> callingBundleNames = info.want.GetStringArrayParam(PARAM_FREEINSTALL_BUNDLENAMES);
114    if (callingAppId.empty() && callingBundleNames.empty()) {
115        TAG_LOGI(AAFwkTag::FREE_INSTALL, "callingAppId and callingBundleNames empty");
116    }
117    info.want.RemoveParam(PARAM_FREEINSTALL_APPID);
118    info.want.RemoveParam(PARAM_FREEINSTALL_BUNDLENAMES);
119
120    if (isAsync) {
121        return ERR_OK;
122    } else {
123        auto future = info.promise->get_future();
124        std::future_status status = future.wait_for(std::chrono::milliseconds(DELAY_LOCAL_FREE_INSTALL_TIMEOUT));
125        if (status == std::future_status::timeout) {
126            RemoveFreeInstallInfo(info.want.GetElement().GetBundleName(), info.want.GetElement().GetAbilityName(),
127                info.want.GetStringParam(Want::PARAM_RESV_START_TIME));
128            return FREE_INSTALL_TIMEOUT;
129        }
130        return future.get();
131    }
132}
133
134int FreeInstallManager::RemoteFreeInstall(const Want &want, int32_t userId, int requestCode,
135    const sptr<IRemoteObject> &callerToken)
136{
137    HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
138    bool isFromRemote = want.GetBoolParam(FROM_REMOTE_KEY, false);
139    auto isSaCall = AAFwk::PermissionVerification::GetInstance()->IsSACall();
140    if (!isSaCall && !isFromRemote && !IsTopAbility(callerToken)) {
141        return NOT_TOP_ABILITY;
142    }
143    FreeInstallInfo info = BuildFreeInstallInfo(want, userId, requestCode, callerToken, false);
144    {
145        std::lock_guard<ffrt::mutex> lock(freeInstallListLock_);
146        freeInstallList_.push_back(info);
147    }
148    int32_t recordId = GetRecordIdByToken(callerToken);
149    sptr<AtomicServiceStatusCallback> callback = new AtomicServiceStatusCallback(weak_from_this(), false, recordId);
150    int32_t callerUid = IPCSkeleton::GetCallingUid();
151    uint32_t accessToken = IPCSkeleton::GetCallingTokenID();
152    UriUtils::GetInstance().FilterUriWithPermissionDms(info.want, accessToken);
153    DistributedClient dmsClient;
154    auto result = dmsClient.StartRemoteFreeInstall(info.want, callerUid, info.requestCode, accessToken, callback);
155    if (result != ERR_NONE) {
156        return result;
157    }
158    auto remoteFuture = info.promise->get_future();
159    std::future_status remoteStatus = remoteFuture.wait_for(std::chrono::milliseconds(
160        DELAY_REMOTE_FREE_INSTALL_TIMEOUT));
161    if (remoteStatus == std::future_status::timeout) {
162        return FREE_INSTALL_TIMEOUT;
163    }
164    return remoteFuture.get();
165}
166
167FreeInstallInfo FreeInstallManager::BuildFreeInstallInfo(const Want &want, int32_t userId, int requestCode,
168    const sptr<IRemoteObject> &callerToken, bool isAsync, uint32_t specifyTokenId, bool isOpenAtomicServiceShortUrl,
169    std::shared_ptr<Want> originalWant)
170{
171    FreeInstallInfo info = {
172        .want = want,
173        .userId = userId,
174        .requestCode = requestCode,
175        .callerToken = callerToken,
176        .specifyTokenId = specifyTokenId,
177        .isOpenAtomicServiceShortUrl = isOpenAtomicServiceShortUrl,
178        .originalWant = originalWant
179    };
180    if (!isAsync) {
181        auto promise = std::make_shared<std::promise<int32_t>>();
182        info.promise = promise;
183    }
184    auto identity = IPCSkeleton::ResetCallingIdentity();
185    info.identity = identity;
186    IPCSkeleton::SetCallingIdentity(identity);
187    return info;
188}
189
190int FreeInstallManager::StartRemoteFreeInstall(const Want &want, int requestCode, int32_t validUserId,
191    const sptr<IRemoteObject> &callerToken)
192{
193    HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
194    if (!want.GetBoolParam(Want::PARAM_RESV_FOR_RESULT, false)) {
195        TAG_LOGI(AAFwkTag::FREE_INSTALL, "StartAbility freeInstall");
196        return RemoteFreeInstall(want, validUserId, requestCode, callerToken);
197    }
198    int32_t missionId = DelayedSingleton<AbilityManagerService>::GetInstance()->
199        GetMissionIdByAbilityToken(callerToken);
200    if (missionId < 0) {
201        return ERR_INVALID_VALUE;
202    }
203    Want* newWant = const_cast<Want*>(&want);
204    newWant->SetParam(DMS_MISSION_ID, missionId);
205    return RemoteFreeInstall(*newWant, validUserId, requestCode, callerToken);
206}
207
208int FreeInstallManager::NotifyDmsCallback(const Want &want, int resultCode)
209{
210    HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
211    std::lock_guard<ffrt::mutex> autoLock(distributedFreeInstallLock_);
212    if (dmsFreeInstallCbs_.empty()) {
213        TAG_LOGE(AAFwkTag::FREE_INSTALL, "null dms callback");
214        return ERR_INVALID_VALUE;
215    }
216
217    MessageParcel reply;
218    MessageOption option;
219
220    for (auto it = dmsFreeInstallCbs_.begin(); it != dmsFreeInstallCbs_.end();) {
221        std::string abilityName = (*it).want.GetElement().GetAbilityName();
222        if (want.GetElement().GetAbilityName().compare(abilityName) == 0) {
223            TAG_LOGI(AAFwkTag::FREE_INSTALL, "Handle DMS");
224            MessageParcel data;
225            if (!data.WriteInterfaceToken(DMS_FREE_INSTALL_CALLBACK_TOKEN)) {
226                TAG_LOGE(AAFwkTag::FREE_INSTALL, "write interface token failed");
227                return ERR_INVALID_VALUE;
228            }
229
230            if (!data.WriteInt32(resultCode)) {
231                TAG_LOGE(AAFwkTag::FREE_INSTALL, "write resultCode error");
232                return ERR_INVALID_VALUE;
233            }
234
235            if (!data.WriteParcelable(&((*it).want))) {
236                TAG_LOGE(AAFwkTag::FREE_INSTALL, "want write failed");
237                return INNER_ERR;
238            }
239
240            if (!data.WriteInt32((*it).requestCode)) {
241                TAG_LOGE(AAFwkTag::FREE_INSTALL, "write resultCode error");
242                return ERR_INVALID_VALUE;
243            }
244
245            (*it).dmsCallback->SendRequest(IDMS_CALLBACK_ON_FREE_INSTALL_DONE, data, reply, option);
246            it = dmsFreeInstallCbs_.erase(it);
247        } else {
248            it++;
249        }
250    }
251
252    return reply.ReadInt32();
253}
254
255void FreeInstallManager::NotifyFreeInstallResult(int32_t recordId, const Want &want, int resultCode, bool isAsync)
256{
257    HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
258    std::lock_guard<ffrt::mutex> lock(freeInstallListLock_);
259    if (freeInstallList_.empty()) {
260        TAG_LOGE(AAFwkTag::FREE_INSTALL, "null app callback");
261        return;
262    }
263
264    bool isFromRemote = want.GetBoolParam(FROM_REMOTE_KEY, false);
265    for (auto it = freeInstallList_.begin(); it != freeInstallList_.end();) {
266        FreeInstallInfo &freeInstallInfo = *it;
267        std::string bundleName = freeInstallInfo.want.GetElement().GetBundleName();
268        std::string abilityName = freeInstallInfo.want.GetElement().GetAbilityName();
269        std::string startTime = freeInstallInfo.want.GetStringParam(Want::PARAM_RESV_START_TIME);
270        std::string url = freeInstallInfo.want.GetUriString();
271        if (want.GetElement().GetBundleName().compare(bundleName) != 0 ||
272            want.GetElement().GetAbilityName().compare(abilityName) != 0 ||
273            want.GetStringParam(Want::PARAM_RESV_START_TIME).compare(startTime) != 0 ||
274            want.GetUriString().compare(url) != 0) {
275            it++;
276            continue;
277        }
278
279        if (!isAsync && freeInstallInfo.promise == nullptr) {
280            it++;
281            continue;
282        }
283        freeInstallInfo.isFreeInstallFinished = true;
284        freeInstallInfo.resultCode = resultCode;
285        HandleFreeInstallResult(recordId, freeInstallInfo, resultCode, isAsync);
286        it = freeInstallList_.erase(it);
287    }
288}
289
290void FreeInstallManager::HandleOnFreeInstallSuccess(int32_t recordId, FreeInstallInfo &freeInstallInfo, bool isAsync)
291{
292    TAG_LOGI(AAFwkTag::FREE_INSTALL, "install success");
293    freeInstallInfo.isInstalled = true;
294
295    if (isAsync) {
296        std::string startTime = freeInstallInfo.want.GetStringParam(Want::PARAM_RESV_START_TIME);
297        std::string bundleName = freeInstallInfo.want.GetElement().GetBundleName();
298        std::string abilityName = freeInstallInfo.want.GetElement().GetAbilityName();
299        if (freeInstallInfo.isPreStartMissionCalled) {
300            StartAbilityByPreInstall(recordId, freeInstallInfo, bundleName, abilityName, startTime);
301            return;
302        }
303        if (freeInstallInfo.isOpenAtomicServiceShortUrl) {
304            StartAbilityByConvertedWant(freeInstallInfo, startTime);
305            return;
306        }
307        StartAbilityByFreeInstall(freeInstallInfo, bundleName, abilityName, startTime);
308        return;
309    }
310    freeInstallInfo.promise->set_value(ERR_OK);
311}
312
313void FreeInstallManager::HandleOnFreeInstallFail(int32_t recordId, FreeInstallInfo &freeInstallInfo, int resultCode,
314    bool isAsync)
315{
316    TAG_LOGI(AAFwkTag::FREE_INSTALL, "install failed");
317    freeInstallInfo.isInstalled = false;
318
319    if (isAsync) {
320        if (freeInstallInfo.isPreStartMissionCalled &&
321            freeInstallInfo.want.HasParameter(KEY_SESSION_ID) &&
322            !freeInstallInfo.want.GetStringParam(KEY_SESSION_ID).empty() &&
323            freeInstallInfo.isStartUIAbilityBySCBCalled) {
324            DelayedSingleton<AbilityManagerService>::GetInstance()->NotifySCBToHandleAtomicServiceException(
325                freeInstallInfo.want.GetStringParam(KEY_SESSION_ID),
326                resultCode, "free install failed");
327        }
328        std::string startTime = freeInstallInfo.want.GetStringParam(Want::PARAM_RESV_START_TIME);
329        if (freeInstallInfo.isOpenAtomicServiceShortUrl
330            && resultCode != CONCURRENT_TASKS_WAITING_FOR_RETRY) {
331            StartAbilityByOriginalWant(freeInstallInfo, startTime);
332            return;
333        }
334
335        std::string bundleName = freeInstallInfo.want.GetElement().GetBundleName();
336        std::string abilityName = freeInstallInfo.want.GetElement().GetAbilityName();
337        DelayedSingleton<FreeInstallObserverManager>::GetInstance()->OnInstallFinished(
338            recordId, bundleName, abilityName, startTime, resultCode);
339        return;
340    }
341    freeInstallInfo.promise->set_value(resultCode);
342}
343
344void FreeInstallManager::HandleFreeInstallResult(int32_t recordId, FreeInstallInfo &freeInstallInfo, int resultCode,
345    bool isAsync)
346{
347    if (resultCode == ERR_OK) {
348        HandleOnFreeInstallSuccess(recordId, freeInstallInfo, isAsync);
349        return;
350    }
351    HandleOnFreeInstallFail(recordId, freeInstallInfo, resultCode, isAsync);
352}
353
354void FreeInstallManager::StartAbilityByFreeInstall(FreeInstallInfo &info, std::string &bundleName,
355    std::string &abilityName, std::string &startTime)
356{
357    info.want.SetFlags(info.want.GetFlags() ^ Want::FLAG_INSTALL_ON_DEMAND);
358    auto identity = IPCSkeleton::ResetCallingIdentity();
359    IPCSkeleton::SetCallingIdentity(info.identity);
360    int32_t result = ERR_OK;
361    if (info.want.GetElement().GetAbilityName().empty()) {
362        result = UpdateElementName(info.want, info.userId);
363    }
364    if (result == ERR_OK) {
365        result = DelayedSingleton<AbilityManagerService>::GetInstance()->StartAbilityByFreeInstall(info.want,
366            info.callerToken, info.userId, info.requestCode);
367    }
368    IPCSkeleton::SetCallingIdentity(identity);
369    int32_t recordId = GetRecordIdByToken(info.callerToken);
370    TAG_LOGI(AAFwkTag::FREE_INSTALL, "result: %{public}d", result);
371    DelayedSingleton<FreeInstallObserverManager>::GetInstance()->OnInstallFinished(
372        recordId, bundleName, abilityName, startTime, result);
373}
374
375void FreeInstallManager::StartAbilityByPreInstall(int32_t recordId, FreeInstallInfo &info, std::string &bundleName,
376    std::string &abilityName, std::string &startTime)
377{
378    info.want.SetFlags(info.want.GetFlags() ^ Want::FLAG_INSTALL_ON_DEMAND);
379    auto identity = IPCSkeleton::ResetCallingIdentity();
380    IPCSkeleton::SetCallingIdentity(info.identity);
381    int32_t result = ERR_OK;
382    if (info.want.GetElement().GetAbilityName().empty()) {
383        result = UpdateElementName(info.want, info.userId);
384    }
385    if (result == ERR_OK) {
386        result = DelayedSingleton<AbilityManagerService>::GetInstance()->StartUIAbilityByPreInstall(info);
387    }
388    if (result != ERR_OK && info.isStartUIAbilityBySCBCalled) {
389        DelayedSingleton<AbilityManagerService>::GetInstance()->NotifySCBToHandleAtomicServiceException(
390            info.want.GetStringParam(KEY_SESSION_ID),
391            result, "start ability failed");
392    }
393    IPCSkeleton::SetCallingIdentity(identity);
394    TAG_LOGI(AAFwkTag::FREE_INSTALL, "preInstall result: %{public}d", result);
395    DelayedSingleton<FreeInstallObserverManager>::GetInstance()->OnInstallFinished(
396        recordId, bundleName, abilityName, startTime, result);
397}
398
399void FreeInstallManager::StartAbilityByConvertedWant(FreeInstallInfo &info, const std::string &startTime)
400{
401    info.want.SetFlags(info.want.GetFlags() ^ Want::FLAG_INSTALL_ON_DEMAND);
402    auto identity = IPCSkeleton::ResetCallingIdentity();
403    IPCSkeleton::SetCallingIdentity(info.identity);
404    int32_t result = ERR_OK;
405    if (info.want.GetElement().GetAbilityName().empty()) {
406        result = UpdateElementName(info.want, info.userId);
407    }
408    if (result == ERR_OK) {
409        result = DelayedSingleton<AbilityManagerService>::GetInstance()->StartAbility(info.want,
410            info.callerToken, info.userId, info.requestCode);
411    }
412    IPCSkeleton::SetCallingIdentity(identity);
413    auto url = info.want.GetUriString();
414    int32_t recordId = GetRecordIdByToken(info.callerToken);
415    DelayedSingleton<FreeInstallObserverManager>::GetInstance()->OnInstallFinishedByUrl(recordId,
416        startTime, url, result);
417}
418
419void FreeInstallManager::StartAbilityByOriginalWant(FreeInstallInfo &info, const std::string &startTime)
420{
421    auto identity = IPCSkeleton::ResetCallingIdentity();
422    IPCSkeleton::SetCallingIdentity(info.identity);
423    int result = ERR_INVALID_VALUE;
424    if (info.originalWant) {
425        TAG_LOGI(AAFwkTag::FREE_INSTALL, "StartAbility by originalWant");
426        result = DelayedSingleton<AbilityManagerService>::GetInstance()->StartAbility(*(info.originalWant),
427            info.callerToken, info.userId, info.requestCode);
428    } else {
429        TAG_LOGE(AAFwkTag::FREE_INSTALL, "null original want");
430    }
431    IPCSkeleton::SetCallingIdentity(identity);
432    TAG_LOGI(AAFwkTag::FREE_INSTALL, "startAbility result: %{public}d", result);
433    auto url = info.want.GetUriString();
434    int32_t recordId = GetRecordIdByToken(info.callerToken);
435    DelayedSingleton<FreeInstallObserverManager>::GetInstance()->OnInstallFinishedByUrl(recordId,
436        startTime, url, result);
437}
438
439int32_t FreeInstallManager::UpdateElementName(Want &want, int32_t userId) const
440{
441    auto bundleMgrHelper = AbilityUtil::GetBundleManagerHelper();
442    CHECK_POINTER_AND_RETURN(bundleMgrHelper, ERR_INVALID_VALUE);
443    Want launchWant;
444    auto errCode = IN_PROCESS_CALL(bundleMgrHelper->GetLaunchWantForBundle(want.GetBundle(), launchWant, userId));
445    if (errCode != ERR_OK) {
446        return errCode;
447    }
448    want.SetElement(launchWant.GetElement());
449    return ERR_OK;
450}
451
452int FreeInstallManager::FreeInstallAbilityFromRemote(const Want &want, const sptr<IRemoteObject> &callback,
453    int32_t userId, int requestCode)
454{
455    if (callback == nullptr) {
456        TAG_LOGE(AAFwkTag::FREE_INSTALL, "null callback");
457        return ERR_INVALID_VALUE;
458    }
459
460    FreeInstallInfo info = {
461        .want = want,
462        .userId = userId,
463        .requestCode = requestCode,
464        .dmsCallback = callback
465    };
466
467    {
468        std::lock_guard<ffrt::mutex> autoLock(distributedFreeInstallLock_);
469        dmsFreeInstallCbs_.push_back(info);
470    }
471
472    auto result = StartFreeInstall(info.want, info.userId, info.requestCode, nullptr);
473    if (result != ERR_OK) {
474        TAG_LOGE(AAFwkTag::FREE_INSTALL, "StartFreeInstall code: %{public}d", result);
475        NotifyDmsCallback(info.want, result);
476    }
477    return result;
478}
479
480int FreeInstallManager::ConnectFreeInstall(const Want &want, int32_t userId,
481    const sptr<IRemoteObject> &callerToken, const std::string& localDeviceId)
482{
483    auto bundleMgrHelper = AbilityUtil::GetBundleManagerHelper();
484    CHECK_POINTER_AND_RETURN(bundleMgrHelper, GET_ABILITY_SERVICE_FAILED);
485    std::string wantDeviceId = want.GetElement().GetDeviceID();
486    if (!(localDeviceId == wantDeviceId || wantDeviceId.empty())) {
487        TAG_LOGE(AAFwkTag::FREE_INSTALL, "deviceID empty");
488        return INVALID_PARAMETERS_ERR;
489    }
490
491    auto isSaCall = AAFwk::PermissionVerification::GetInstance()->IsSACall();
492    if (!isSaCall) {
493        std::string wantAbilityName = want.GetElement().GetAbilityName();
494        std::string wantBundleName = want.GetElement().GetBundleName();
495        if (wantBundleName.empty() || wantAbilityName.empty()) {
496            TAG_LOGE(AAFwkTag::FREE_INSTALL, "wantBundleName or wantAbilityName empty.");
497            return INVALID_PARAMETERS_ERR;
498        }
499        int callerUid = IPCSkeleton::GetCallingUid();
500        std::string localBundleName;
501        auto res = IN_PROCESS_CALL(bundleMgrHelper->GetNameForUid(callerUid, localBundleName));
502        if (res != ERR_OK || localBundleName != wantBundleName) {
503            TAG_LOGE(AAFwkTag::FREE_INSTALL, "not local BundleName");
504            return INVALID_PARAMETERS_ERR;
505        }
506    }
507
508    AppExecFwk::AbilityInfo abilityInfo;
509    std::vector<AppExecFwk::ExtensionAbilityInfo> extensionInfos;
510    if (!IN_PROCESS_CALL(bundleMgrHelper->QueryAbilityInfo(
511        want, AppExecFwk::AbilityInfoFlag::GET_ABILITY_INFO_WITH_APPLICATION, userId, abilityInfo)) &&
512        !IN_PROCESS_CALL(bundleMgrHelper->QueryExtensionAbilityInfos(
513            want, AppExecFwk::AbilityInfoFlag::GET_ABILITY_INFO_WITH_APPLICATION, userId, extensionInfos))) {
514        TAG_LOGI(AAFwkTag::FREE_INSTALL, "try to StartFreeInstall");
515        int result = StartFreeInstall(want, userId, DEFAULT_INVAL_VALUE, callerToken);
516        if (result) {
517            TAG_LOGE(AAFwkTag::FREE_INSTALL, "startFreeInstall error");
518            return result;
519        }
520    }
521    return ERR_OK;
522}
523
524std::time_t FreeInstallManager::GetTimeStamp()
525{
526    std::chrono::time_point<std::chrono::system_clock, std::chrono::milliseconds> tp =
527        std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::system_clock::now());
528    std::time_t timestamp = tp.time_since_epoch().count();
529    return timestamp;
530}
531
532void FreeInstallManager::OnInstallFinished(int32_t recordId, int resultCode, const Want &want,
533    int32_t userId, bool isAsync)
534{
535    HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
536    TAG_LOGI(AAFwkTag::FREE_INSTALL, "resultCode: %{public}d", resultCode);
537
538    if (!InsightIntentExecuteParam::IsInsightIntentExecute(want)) {
539        NotifyDmsCallback(want, resultCode);
540        NotifyFreeInstallResult(recordId, want, resultCode, isAsync);
541    } else {
542        NotifyInsightIntentFreeInstallResult(want, resultCode);
543    }
544
545    PostUpgradeAtomicServiceTask(resultCode, want, userId);
546}
547
548void FreeInstallManager::PostUpgradeAtomicServiceTask(int resultCode, const Want &want, int32_t userId)
549{
550    TAG_LOGI(AAFwkTag::FREE_INSTALL, "called");
551    std::weak_ptr<FreeInstallManager> thisWptr(shared_from_this());
552    if (resultCode == ERR_OK) {
553        auto updateAtmoicServiceTask = [want, userId, thisWptr, &timeStampMap = timeStampMap_]() {
554            auto sptr = thisWptr.lock();
555            TAG_LOGD(AAFwkTag::FREE_INSTALL,
556                "bundleName: %{public}s, moduleName: %{public}s", want.GetElement().GetBundleName().c_str(),
557                want.GetElement().GetModuleName().c_str());
558            std::string nameKey = want.GetElement().GetBundleName() + want.GetElement().GetModuleName();
559            if (timeStampMap.find(nameKey) == timeStampMap.end() ||
560                sptr->GetTimeStamp() - timeStampMap[nameKey] > UPDATE_ATOMOIC_SERVICE_TASK_TIMER) {
561                auto bundleMgrHelper = AbilityUtil::GetBundleManagerHelper();
562                CHECK_POINTER(bundleMgrHelper);
563                bundleMgrHelper->UpgradeAtomicService(want, userId);
564                timeStampMap.emplace(nameKey, sptr->GetTimeStamp());
565            }
566        };
567
568        auto handler = DelayedSingleton<AbilityManagerService>::GetInstance()->GetTaskHandler();
569        CHECK_POINTER_LOG(handler, "Fail to get Ability task handler.");
570        handler->SubmitTask(updateAtmoicServiceTask, "UpdateAtmoicServiceTask");
571    }
572}
573
574void FreeInstallManager::OnRemoteInstallFinished(int32_t recordId, int resultCode, const Want &want, int32_t userId)
575{
576    TAG_LOGI(AAFwkTag::FREE_INSTALL, "finished resultCode:%{public}d", resultCode);
577    NotifyFreeInstallResult(recordId, want, resultCode);
578}
579
580int FreeInstallManager::AddFreeInstallObserver(const sptr<IRemoteObject> &callerToken,
581    const sptr<AbilityRuntime::IFreeInstallObserver> &observer)
582{
583    TAG_LOGI(AAFwkTag::FREE_INSTALL, "called");
584    auto abilityRecord = Token::GetAbilityRecordByToken(callerToken);
585    if (abilityRecord != nullptr) {
586        return DelayedSingleton<FreeInstallObserverManager>::GetInstance()->AddObserver(abilityRecord->GetRecordId(),
587            observer);
588    }
589    if (AAFwk::PermissionVerification::GetInstance()->IsSACall()) {
590        return DelayedSingleton<FreeInstallObserverManager>::GetInstance()->AddObserver(-1, observer);
591    }
592    return CHECK_PERMISSION_FAILED;
593}
594
595void FreeInstallManager::RemoveFreeInstallInfo(const std::string &bundleName, const std::string &abilityName,
596    const std::string &startTime)
597{
598    std::lock_guard<ffrt::mutex> lock(freeInstallListLock_);
599    for (auto it = freeInstallList_.begin(); it != freeInstallList_.end();) {
600        if ((*it).want.GetElement().GetBundleName() == bundleName &&
601            (*it).want.GetElement().GetAbilityName() == abilityName &&
602            (*it).want.GetStringParam(Want::PARAM_RESV_START_TIME) == startTime) {
603            it = freeInstallList_.erase(it);
604        } else {
605            it++;
606        }
607    }
608}
609
610int32_t FreeInstallManager::GetRecordIdByToken(const sptr<IRemoteObject> &callerToken)
611{
612    auto abilityRecord = Token::GetAbilityRecordByToken(callerToken);
613    int recordId = -1;
614    if (abilityRecord != nullptr) {
615        recordId = abilityRecord->GetRecordId();
616    }
617    return recordId;
618}
619
620bool FreeInstallManager::VerifyStartFreeInstallPermission(const sptr<IRemoteObject> &callerToken)
621{
622    auto isSaCall = AAFwk::PermissionVerification::GetInstance()->IsSACall();
623    if (isSaCall || IsTopAbility(callerToken)) {
624        return true;
625    }
626
627    if (AAFwk::PermissionVerification::GetInstance()->VerifyCallingPermission(
628        PermissionConstants::PERMISSION_START_ABILITIES_FROM_BACKGROUND)) {
629        return true;
630    }
631
632    return false;
633}
634
635int FreeInstallManager::SetAppRunningState(Want &want)
636{
637    auto appMgr = AppMgrUtil::GetAppMgr();
638    if (appMgr == nullptr) {
639        TAG_LOGE(AAFwkTag::FREE_INSTALL, "null appMgr");
640        return ERR_INVALID_VALUE;
641    }
642
643    bool isAppRunning = appMgr->GetAppRunningStateByBundleName(want.GetElement().GetBundleName());
644    TAG_LOGI(AAFwkTag::FREE_INSTALL, "isAppRunning:%{public}d", static_cast<int>(isAppRunning));
645    want.SetParam(KEY_IS_APP_RUNNING, isAppRunning);
646    return ERR_OK;
647}
648
649bool FreeInstallManager::GetFreeInstallTaskInfo(const std::string& bundleName, const std::string& abilityName,
650    const std::string& startTime, FreeInstallInfo& taskInfo)
651{
652    std::lock_guard<ffrt::mutex> lock(freeInstallListLock_);
653    for (auto it = freeInstallList_.begin(); it != freeInstallList_.end();) {
654        if ((*it).want.GetElement().GetBundleName() == bundleName &&
655            (*it).want.GetElement().GetAbilityName() == abilityName &&
656            (*it).want.GetStringParam(Want::PARAM_RESV_START_TIME) == startTime) {
657            taskInfo = *it;
658            return true;
659        }
660        it++;
661    }
662    return false;
663}
664
665bool FreeInstallManager::GetFreeInstallTaskInfo(const std::string& sessionId, FreeInstallInfo& taskInfo)
666{
667    std::lock_guard<ffrt::mutex> lock(freeInstallListLock_);
668    for (auto it = freeInstallList_.begin(); it != freeInstallList_.end();) {
669        if ((*it).want.GetStringParam(KEY_SESSION_ID) == sessionId) {
670            taskInfo = *it;
671            return true;
672        }
673        it++;
674    }
675    return false;
676}
677
678void FreeInstallManager::SetSCBCallStatus(const std::string& bundleName, const std::string& abilityName,
679    const std::string& startTime, bool scbCallStatus)
680{
681    std::lock_guard<ffrt::mutex> lock(freeInstallListLock_);
682    for (auto it = freeInstallList_.begin(); it != freeInstallList_.end();) {
683        if ((*it).want.GetElement().GetBundleName() == bundleName &&
684            (*it).want.GetElement().GetAbilityName() == abilityName &&
685            (*it).want.GetStringParam(Want::PARAM_RESV_START_TIME) == startTime) {
686            (*it).isStartUIAbilityBySCBCalled = scbCallStatus;
687            return;
688        }
689        it++;
690    }
691}
692
693void FreeInstallManager::SetPreStartMissionCallStatus(const std::string& bundleName, const std::string& abilityName,
694    const std::string& startTime, bool preStartMissionCallStatus)
695{
696    std::lock_guard<ffrt::mutex> lock(freeInstallListLock_);
697    for (auto it = freeInstallList_.begin(); it != freeInstallList_.end();) {
698        if ((*it).want.GetElement().GetBundleName() == bundleName &&
699            (*it).want.GetElement().GetAbilityName() == abilityName &&
700            (*it).want.GetStringParam(Want::PARAM_RESV_START_TIME) == startTime) {
701            (*it).isPreStartMissionCalled = preStartMissionCallStatus;
702            return;
703        }
704        it++;
705    }
706}
707
708void FreeInstallManager::SetFreeInstallTaskSessionId(const std::string& bundleName, const std::string& abilityName,
709    const std::string& startTime, const std::string& sessionId)
710{
711    std::lock_guard<ffrt::mutex> lock(freeInstallListLock_);
712    for (auto it = freeInstallList_.begin(); it != freeInstallList_.end();) {
713        if ((*it).want.GetElement().GetBundleName() == bundleName &&
714            (*it).want.GetElement().GetAbilityName() == abilityName &&
715            (*it).want.GetStringParam(Want::PARAM_RESV_START_TIME) == startTime) {
716            (*it).want.SetParam(KEY_SESSION_ID, sessionId);
717            return;
718        }
719        it++;
720    }
721}
722
723void FreeInstallManager::NotifyInsightIntentFreeInstallResult(const Want &want, int resultCode)
724{
725    HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
726    TAG_LOGI(AAFwkTag::FREE_INSTALL, "insight install result:%{public}d", resultCode);
727    if (resultCode != ERR_OK) {
728        RemoveFreeInstallInfo(want.GetElement().GetBundleName(), want.GetElement().GetAbilityName(),
729            want.GetStringParam(Want::PARAM_RESV_START_TIME));
730        NotifyInsightIntentExecuteDone(want, ERR_INVALID_VALUE);
731        return;
732    }
733
734    std::lock_guard<ffrt::mutex> lock(freeInstallListLock_);
735    if (freeInstallList_.empty()) {
736        TAG_LOGI(AAFwkTag::FREE_INSTALL, "list empty");
737        return;
738    }
739
740    for (auto it = freeInstallList_.begin(); it != freeInstallList_.end();) {
741        std::string bundleName = (*it).want.GetElement().GetBundleName();
742        std::string abilityName = (*it).want.GetElement().GetAbilityName();
743        std::string startTime = (*it).want.GetStringParam(Want::PARAM_RESV_START_TIME);
744        if (want.GetElement().GetBundleName().compare(bundleName) != 0 ||
745            want.GetElement().GetAbilityName().compare(abilityName) != 0 ||
746            want.GetStringParam(Want::PARAM_RESV_START_TIME).compare(startTime) != 0) {
747            it++;
748            continue;
749        }
750
751        auto moduleName = (*it).want.GetElement().GetModuleName();
752        auto insightIntentName = (*it).want.GetStringParam(AppExecFwk::INSIGHT_INTENT_EXECUTE_PARAM_NAME);
753        auto executeMode = static_cast<AppExecFwk::ExecuteMode>(
754            it->want.GetIntParam(AppExecFwk::INSIGHT_INTENT_EXECUTE_PARAM_MODE, 0));
755        std::string srcEntry;
756        auto ret = AbilityRuntime::InsightIntentUtils::GetSrcEntry(it->want.GetElement(), insightIntentName,
757            executeMode, srcEntry);
758        if (ret != ERR_OK || srcEntry.empty()) {
759            TAG_LOGE(AAFwkTag::FREE_INSTALL, "failed. bundleName: %{public}s, "
760                "moduleName: %{public}s, insightIntentName: %{public}s", bundleName.c_str(), moduleName.c_str(),
761                insightIntentName.c_str());
762            NotifyInsightIntentExecuteDone(want, ERR_INVALID_VALUE);
763        } else {
764            (*it).want.SetParam(AppExecFwk::INSIGHT_INTENT_SRC_ENTRY, srcEntry);
765            StartAbilityByFreeInstall(*it, bundleName, abilityName, startTime);
766        }
767
768        it = freeInstallList_.erase(it);
769    }
770}
771
772void FreeInstallManager::NotifyInsightIntentExecuteDone(const Want &want, int resultCode)
773{
774    InsightIntentExecuteParam executeParam;
775    InsightIntentExecuteParam::GenerateFromWant(want, executeParam);
776    AppExecFwk::InsightIntentExecuteResult result;
777    auto ret = DelayedSingleton<InsightIntentExecuteManager>::GetInstance()->ExecuteIntentDone(
778        executeParam.insightIntentId_, resultCode, result);
779    if (ret != ERR_OK) {
780        TAG_LOGE(AAFwkTag::FREE_INSTALL, "failed with %{public}d", ret);
781    }
782}
783}  // namespace AAFwk
784}  // namespace OHOS
785