100600bfbSopenharmony_ci/*
200600bfbSopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd.
300600bfbSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
400600bfbSopenharmony_ci * you may not use this file except in compliance with the License.
500600bfbSopenharmony_ci * You may obtain a copy of the License at
600600bfbSopenharmony_ci *
700600bfbSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
800600bfbSopenharmony_ci *
900600bfbSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
1000600bfbSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
1100600bfbSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1200600bfbSopenharmony_ci * See the License for the specific language governing permissions and
1300600bfbSopenharmony_ci * limitations under the License.
1400600bfbSopenharmony_ci */
1500600bfbSopenharmony_ci#include "dump_manager_client.h"
1600600bfbSopenharmony_ci#include <iservice_registry.h>
1700600bfbSopenharmony_ci#include <string_ex.h>
1800600bfbSopenharmony_ci#include <unistd.h>
1900600bfbSopenharmony_ci#include "common.h"
2000600bfbSopenharmony_ci#include "hilog_wrapper.h"
2100600bfbSopenharmony_ci#include "dump_errors.h"
2200600bfbSopenharmony_ci#include "inner/dump_service_id.h"
2300600bfbSopenharmony_ci#include "dump_on_demand_load.h"
2400600bfbSopenharmony_cinamespace OHOS {
2500600bfbSopenharmony_cinamespace HiviewDFX {
2600600bfbSopenharmony_cistatic constexpr int32_t SLEEP_DUR = 5 * 1000 * 1000;
2700600bfbSopenharmony_cistatic constexpr int32_t SLEEP_UNIT = 100 * 1000;
2800600bfbSopenharmony_ci
2900600bfbSopenharmony_ciDumpManagerClient::DumpManagerClient()
3000600bfbSopenharmony_ci{
3100600bfbSopenharmony_ci}
3200600bfbSopenharmony_ci
3300600bfbSopenharmony_ciDumpManagerClient::~DumpManagerClient()
3400600bfbSopenharmony_ci{
3500600bfbSopenharmony_ci    Reset();
3600600bfbSopenharmony_ci}
3700600bfbSopenharmony_ci
3800600bfbSopenharmony_ciint32_t DumpManagerClient::Request(std::vector<std::u16string> &args, int outfd)
3900600bfbSopenharmony_ci{
4000600bfbSopenharmony_ci    if ((args.size() < 1) || (outfd < 0)) {
4100600bfbSopenharmony_ci        DUMPER_HILOGE(MODULE_CLIENT, "args or outfd failed.");
4200600bfbSopenharmony_ci        return DumpStatus::DUMP_FAIL;
4300600bfbSopenharmony_ci    }
4400600bfbSopenharmony_ci    for (size_t i = 0; i < args.size(); i++) {
4500600bfbSopenharmony_ci        std::string trimArg = TrimStr(Str16ToStr8(args[i]));
4600600bfbSopenharmony_ci        if (strlen(trimArg.c_str()) < 1) {
4700600bfbSopenharmony_ci            DUMPER_HILOGE(MODULE_CLIENT, "trimArg empty.");
4800600bfbSopenharmony_ci            return DumpStatus::DUMP_FAIL;
4900600bfbSopenharmony_ci        }
5000600bfbSopenharmony_ci    }
5100600bfbSopenharmony_ci    if (Connect() != ERR_OK) {
5200600bfbSopenharmony_ci        DUMPER_HILOGE(MODULE_CLIENT, "Connect failed.");
5300600bfbSopenharmony_ci        return DumpStatus::DUMP_FAIL;
5400600bfbSopenharmony_ci    }
5500600bfbSopenharmony_ci    int32_t ret = proxy_->Request(args, outfd);
5600600bfbSopenharmony_ci    DUMPER_HILOGD(MODULE_CLIENT, "debug|ret=%{public}d", ret);
5700600bfbSopenharmony_ci    return ret;
5800600bfbSopenharmony_ci}
5900600bfbSopenharmony_ci
6000600bfbSopenharmony_ciErrCode DumpManagerClient::Connect()
6100600bfbSopenharmony_ci{
6200600bfbSopenharmony_ci    std::lock_guard<std::mutex> lock(mutex_);
6300600bfbSopenharmony_ci    if (proxy_ != nullptr) {
6400600bfbSopenharmony_ci        DUMPER_HILOGD(MODULE_CLIENT, "proxy_ is not nullptr.");
6500600bfbSopenharmony_ci        return ERR_OK;
6600600bfbSopenharmony_ci    }
6700600bfbSopenharmony_ci    sptr<ISystemAbilityManager> sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
6800600bfbSopenharmony_ci    if (sam == nullptr) {
6900600bfbSopenharmony_ci        DUMPER_HILOGE(MODULE_CLIENT, "sam is nullptr.");
7000600bfbSopenharmony_ci        return ERROR_GET_SYSTEM_ABILITY_MANAGER;
7100600bfbSopenharmony_ci    }
7200600bfbSopenharmony_ci    sptr<IRemoteObject> remoteObject = sam->CheckSystemAbility(DFX_SYS_HIDUMPER_ABILITY_ID);
7300600bfbSopenharmony_ci    if (remoteObject == nullptr) {
7400600bfbSopenharmony_ci        ErrCode retStart = OnDemandStart(sam, remoteObject);
7500600bfbSopenharmony_ci        if (remoteObject == nullptr || retStart != ERR_OK) {
7600600bfbSopenharmony_ci            DUMPER_HILOGE(MODULE_CLIENT, "remoteObject is nullptr.");
7700600bfbSopenharmony_ci            return ERROR_GET_DUMPER_SERVICE;
7800600bfbSopenharmony_ci        }
7900600bfbSopenharmony_ci    }
8000600bfbSopenharmony_ci    deathRecipient_ = sptr<IRemoteObject::DeathRecipient>(new DumpManagerDeathRecipient());
8100600bfbSopenharmony_ci    if (deathRecipient_ == nullptr) {
8200600bfbSopenharmony_ci        DUMPER_HILOGE(MODULE_CLIENT, "deathRecipient_ is nullptr.");
8300600bfbSopenharmony_ci        return ERR_NO_MEMORY;
8400600bfbSopenharmony_ci    }
8500600bfbSopenharmony_ci    if ((remoteObject->IsProxyObject()) && (!remoteObject->AddDeathRecipient(deathRecipient_))) {
8600600bfbSopenharmony_ci        DUMPER_HILOGE(MODULE_CLIENT, "IsProxyObject failed.");
8700600bfbSopenharmony_ci        return ERROR_ADD_DEATH_RECIPIENT;
8800600bfbSopenharmony_ci    }
8900600bfbSopenharmony_ci    proxy_ = iface_cast<IDumpBroker>(remoteObject);
9000600bfbSopenharmony_ci    DUMPER_HILOGD(MODULE_CLIENT, "debug|connected");
9100600bfbSopenharmony_ci    return ERR_OK;
9200600bfbSopenharmony_ci}
9300600bfbSopenharmony_ci
9400600bfbSopenharmony_cibool DumpManagerClient::IsConnected()
9500600bfbSopenharmony_ci{
9600600bfbSopenharmony_ci    return (proxy_ != nullptr);
9700600bfbSopenharmony_ci}
9800600bfbSopenharmony_ci
9900600bfbSopenharmony_civoid DumpManagerClient::Reset()
10000600bfbSopenharmony_ci{
10100600bfbSopenharmony_ci    std::lock_guard<std::mutex> lock(mutex_);
10200600bfbSopenharmony_ci    if (proxy_ == nullptr) {
10300600bfbSopenharmony_ci        return;
10400600bfbSopenharmony_ci    }
10500600bfbSopenharmony_ci    auto serviceRemote = proxy_->AsObject();
10600600bfbSopenharmony_ci    if (serviceRemote != nullptr) {
10700600bfbSopenharmony_ci        serviceRemote->RemoveDeathRecipient(deathRecipient_);
10800600bfbSopenharmony_ci        proxy_ = nullptr;
10900600bfbSopenharmony_ci        DUMPER_HILOGD(MODULE_CLIENT, "debug|disconnected");
11000600bfbSopenharmony_ci    }
11100600bfbSopenharmony_ci}
11200600bfbSopenharmony_ci
11300600bfbSopenharmony_civoid DumpManagerClient::ResetProxy(const wptr<IRemoteObject>& remote)
11400600bfbSopenharmony_ci{
11500600bfbSopenharmony_ci    std::lock_guard<std::mutex> lock(mutex_);
11600600bfbSopenharmony_ci    if (proxy_ == nullptr) {
11700600bfbSopenharmony_ci        return;
11800600bfbSopenharmony_ci    }
11900600bfbSopenharmony_ci    auto serviceRemote = proxy_->AsObject();
12000600bfbSopenharmony_ci    if ((serviceRemote != nullptr) && (serviceRemote == remote.promote())) {
12100600bfbSopenharmony_ci        serviceRemote->RemoveDeathRecipient(deathRecipient_);
12200600bfbSopenharmony_ci        proxy_ = nullptr;
12300600bfbSopenharmony_ci        DUMPER_HILOGD(MODULE_CLIENT, "debug|disconnected");
12400600bfbSopenharmony_ci    }
12500600bfbSopenharmony_ci}
12600600bfbSopenharmony_ci
12700600bfbSopenharmony_civoid DumpManagerClient::DumpManagerDeathRecipient::OnRemoteDied(const wptr<IRemoteObject>& remote)
12800600bfbSopenharmony_ci{
12900600bfbSopenharmony_ci    if (remote == nullptr) {
13000600bfbSopenharmony_ci        return;
13100600bfbSopenharmony_ci    }
13200600bfbSopenharmony_ci    DumpManagerClient::GetInstance().ResetProxy(remote);
13300600bfbSopenharmony_ci}
13400600bfbSopenharmony_ci
13500600bfbSopenharmony_ciErrCode DumpManagerClient::OnDemandStart(sptr<ISystemAbilityManager> sam, sptr<IRemoteObject> &remoteObject)
13600600bfbSopenharmony_ci{
13700600bfbSopenharmony_ci    sptr<OnDemandLoadCallback> loadCallback = new OnDemandLoadCallback();
13800600bfbSopenharmony_ci    int32_t result = sam->LoadSystemAbility(DFX_SYS_HIDUMPER_ABILITY_ID, loadCallback);
13900600bfbSopenharmony_ci    if (result != ERR_OK) {
14000600bfbSopenharmony_ci        DUMPER_HILOGE(MODULE_CLIENT, "systemAbilityId:%{public}d load failed, result code:%{public}d",
14100600bfbSopenharmony_ci            DFX_SYS_HIDUMPER_ABILITY_ID, result);
14200600bfbSopenharmony_ci        return ERROR_GET_DUMPER_SERVICE;
14300600bfbSopenharmony_ci    }
14400600bfbSopenharmony_ci
14500600bfbSopenharmony_ci    int32_t loop = SLEEP_DUR / SLEEP_UNIT;
14600600bfbSopenharmony_ci    while (loop-- > 0) {
14700600bfbSopenharmony_ci        if (!loadCallback->CheckLoadSystemAbilityStatus()) {
14800600bfbSopenharmony_ci            usleep(SLEEP_UNIT);
14900600bfbSopenharmony_ci            continue;
15000600bfbSopenharmony_ci        }
15100600bfbSopenharmony_ci        remoteObject = sam->CheckSystemAbility(DFX_SYS_HIDUMPER_ABILITY_ID);
15200600bfbSopenharmony_ci        if (remoteObject != nullptr) {
15300600bfbSopenharmony_ci            return ERR_OK;
15400600bfbSopenharmony_ci        } else {
15500600bfbSopenharmony_ci            usleep(SLEEP_UNIT);
15600600bfbSopenharmony_ci        }
15700600bfbSopenharmony_ci    }
15800600bfbSopenharmony_ci
15900600bfbSopenharmony_ci    DUMPER_HILOGD(MODULE_CLIENT, "debug|on demand start fail");
16000600bfbSopenharmony_ci    return ERROR_GET_DUMPER_SERVICE;
16100600bfbSopenharmony_ci}
16200600bfbSopenharmony_ci} // namespace HiviewDFX
16300600bfbSopenharmony_ci} // namespace OHOS
164