b928e92f创建于 3月12日历史提交
/*
 * Copyright (c) 2024 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "on_demand_start_stop_sa.h"

#include "global.h"
#include "iservice_registry.h"
#include "system_ability_definition.h"

namespace OHOS {
namespace MiscServices {
// LCOV_EXCL_START
std::atomic<uint32_t> OnDemandStartStopSa::processingIpcCount_ { 0 };
sptr<IRemoteObject> OnDemandStartStopSa::LoadInputMethodSystemAbility()
{
    std::unique_lock<std::mutex> lock(loadSaMtx_, std::try_to_lock);
    if (!lock.owns_lock()) {
        IMSA_HILOGE("lock is used!");
        return nullptr;
    }
    auto systemAbilityManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
    if (systemAbilityManager == nullptr) {
        IMSA_HILOGE("get system ability manager fail!");
        return nullptr;
    }

    auto remoteObject = systemAbilityManager->CheckSystemAbility(INPUT_METHOD_SYSTEM_ABILITY_ID);
    if (remoteObject != nullptr) {
        return remoteObject;
    }

    auto currentTime = std::chrono::system_clock::now();
    if (lastLoadTime_.time_since_epoch().count() != 0 &&
        currentTime - lastLoadTime_ < std::chrono::seconds(RETRY_MAX_WAIT_TIME)) {
        IMSA_HILOGE("The method can be called only once within 6 seconds.");
        return nullptr;
    }

    auto sharedThis = shared_from_this();
    sptr<SaLoadCallback> callback = new (std::nothrow) SaLoadCallback(sharedThis);
    if (callback == nullptr) {
        IMSA_HILOGE("LoadCallback new fail!");
        return nullptr;
    }

    int32_t ret = systemAbilityManager->LoadSystemAbility(INPUT_METHOD_SYSTEM_ABILITY_ID, callback);
    if (ret != ERR_OK) {
        IMSA_HILOGE("load input method system ability fail, ret: %{public}d", ret);
        return nullptr;
    }

    loadSaCv_.wait_for(lock, std::chrono::seconds(LOAD_SA_MAX_WAIT_TIME), [&sharedThis]() {
        return sharedThis->remoteObj_ != nullptr;
    });
    lastLoadTime_ = currentTime;
    return remoteObj_;
}

void OnDemandStartStopSa::UnloadInputMethodSystemAbility()
{
    auto systemAbilityManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
    if (systemAbilityManager == nullptr) {
        IMSA_HILOGE("get system ability manager fail!");
        return;
    }

    int32_t ret = systemAbilityManager->UnloadSystemAbility(INPUT_METHOD_SYSTEM_ABILITY_ID);
    if (ret != ERR_OK) {
        IMSA_HILOGE("unload input method system ability fail, ret: %{public}d", ret);
        return;
    }
    IMSA_HILOGI("unload input method system ability success!");
}

void OnDemandStartStopSa::SaLoadCallback::OnLoadSystemAbilitySuccess(int32_t said, const sptr<IRemoteObject> &object)
{
    IMSA_HILOGI("load inputmethod sa success!");
    if (onDemandObj_ == nullptr) {
        IMSA_HILOGE("onDemandObj is null!");
        return;
    }
    std::unique_lock<std::mutex> lock(onDemandObj_->loadSaMtx_);
    onDemandObj_->remoteObj_ = object;
    onDemandObj_->loadSaCv_.notify_all();
}

void OnDemandStartStopSa::SaLoadCallback::OnLoadSystemAbilityFail(int32_t said)
{
    IMSA_HILOGE("load inputmethod sa fail!");
    if (onDemandObj_ == nullptr) {
        IMSA_HILOGE("onDemandObj is null!");
        return;
    }
    std::unique_lock<std::mutex> lock(onDemandObj_->loadSaMtx_);
    onDemandObj_->remoteObj_ = nullptr;
    onDemandObj_->loadSaCv_.notify_all();
}

sptr<IRemoteObject> OnDemandStartStopSa::GetInputMethodSystemAbility(bool ifRetry)
{
    sptr<ISystemAbilityManager> systemAbilityManager =
        SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
    if (systemAbilityManager == nullptr) {
        IMSA_HILOGE("system ability manager is nullptr!");
        return nullptr;
    }

    sptr<IRemoteObject> systemAbility = nullptr;
    if (!ifRetry) {
        systemAbility = systemAbilityManager->CheckSystemAbility(INPUT_METHOD_SYSTEM_ABILITY_ID);
        if (systemAbility == nullptr) {
            IMSA_HILOGE("check system ability is nullptr!");
            return nullptr;
        }
        return systemAbility;
    }

#ifdef IMF_ON_DEMAND_START_STOP_SA_ENABLE
    auto onDemandStartStopSa = std::make_shared<OnDemandStartStopSa>();
    systemAbility = onDemandStartStopSa->LoadInputMethodSystemAbility();
    if (systemAbility == nullptr) {
        IMSA_HILOGE("load system ability fail!");
        return nullptr;
    }
#else
    systemAbility = systemAbilityManager->GetSystemAbility(INPUT_METHOD_SYSTEM_ABILITY_ID);
    if (systemAbility == nullptr) {
        IMSA_HILOGE("get system ability is nullptr!");
        return nullptr;
    }
#endif
    return systemAbility;
}

void OnDemandStartStopSa::IncreaseProcessingIpcCnt()
{
    processingIpcCount_.fetch_add(1);
}
void OnDemandStartStopSa::DecreaseProcessingIpcCnt()
{
    processingIpcCount_.fetch_sub(1);
}
bool OnDemandStartStopSa::IsSaBusy()
{
    return processingIpcCount_.load() > 0;
}
// LCOV_EXCL_STOP
} // namespace MiscServices
} // namespace OHOS