1 /*
2  * Copyright (c) 2023 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 #include "dump_manager_client.h"
16 #include <iservice_registry.h>
17 #include <string_ex.h>
18 #include <unistd.h>
19 #include "common.h"
20 #include "hilog_wrapper.h"
21 #include "dump_errors.h"
22 #include "inner/dump_service_id.h"
23 #include "dump_on_demand_load.h"
24 namespace OHOS {
25 namespace HiviewDFX {
26 static constexpr int32_t SLEEP_DUR = 5 * 1000 * 1000;
27 static constexpr int32_t SLEEP_UNIT = 100 * 1000;
28 
DumpManagerClient()29 DumpManagerClient::DumpManagerClient()
30 {
31 }
32 
~DumpManagerClient()33 DumpManagerClient::~DumpManagerClient()
34 {
35     Reset();
36 }
37 
Request(std::vector<std::u16string> & args,int outfd)38 int32_t DumpManagerClient::Request(std::vector<std::u16string> &args, int outfd)
39 {
40     if ((args.size() < 1) || (outfd < 0)) {
41         DUMPER_HILOGE(MODULE_CLIENT, "args or outfd failed.");
42         return DumpStatus::DUMP_FAIL;
43     }
44     for (size_t i = 0; i < args.size(); i++) {
45         std::string trimArg = TrimStr(Str16ToStr8(args[i]));
46         if (strlen(trimArg.c_str()) < 1) {
47             DUMPER_HILOGE(MODULE_CLIENT, "trimArg empty.");
48             return DumpStatus::DUMP_FAIL;
49         }
50     }
51     if (Connect() != ERR_OK) {
52         DUMPER_HILOGE(MODULE_CLIENT, "Connect failed.");
53         return DumpStatus::DUMP_FAIL;
54     }
55     int32_t ret = proxy_->Request(args, outfd);
56     DUMPER_HILOGD(MODULE_CLIENT, "debug|ret=%{public}d", ret);
57     return ret;
58 }
59 
Connect()60 ErrCode DumpManagerClient::Connect()
61 {
62     std::lock_guard<std::mutex> lock(mutex_);
63     if (proxy_ != nullptr) {
64         DUMPER_HILOGD(MODULE_CLIENT, "proxy_ is not nullptr.");
65         return ERR_OK;
66     }
67     sptr<ISystemAbilityManager> sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
68     if (sam == nullptr) {
69         DUMPER_HILOGE(MODULE_CLIENT, "sam is nullptr.");
70         return ERROR_GET_SYSTEM_ABILITY_MANAGER;
71     }
72     sptr<IRemoteObject> remoteObject = sam->CheckSystemAbility(DFX_SYS_HIDUMPER_ABILITY_ID);
73     if (remoteObject == nullptr) {
74         ErrCode retStart = OnDemandStart(sam, remoteObject);
75         if (remoteObject == nullptr || retStart != ERR_OK) {
76             DUMPER_HILOGE(MODULE_CLIENT, "remoteObject is nullptr.");
77             return ERROR_GET_DUMPER_SERVICE;
78         }
79     }
80     deathRecipient_ = sptr<IRemoteObject::DeathRecipient>(new DumpManagerDeathRecipient());
81     if (deathRecipient_ == nullptr) {
82         DUMPER_HILOGE(MODULE_CLIENT, "deathRecipient_ is nullptr.");
83         return ERR_NO_MEMORY;
84     }
85     if ((remoteObject->IsProxyObject()) && (!remoteObject->AddDeathRecipient(deathRecipient_))) {
86         DUMPER_HILOGE(MODULE_CLIENT, "IsProxyObject failed.");
87         return ERROR_ADD_DEATH_RECIPIENT;
88     }
89     proxy_ = iface_cast<IDumpBroker>(remoteObject);
90     DUMPER_HILOGD(MODULE_CLIENT, "debug|connected");
91     return ERR_OK;
92 }
93 
IsConnected()94 bool DumpManagerClient::IsConnected()
95 {
96     return (proxy_ != nullptr);
97 }
98 
Reset()99 void DumpManagerClient::Reset()
100 {
101     std::lock_guard<std::mutex> lock(mutex_);
102     if (proxy_ == nullptr) {
103         return;
104     }
105     auto serviceRemote = proxy_->AsObject();
106     if (serviceRemote != nullptr) {
107         serviceRemote->RemoveDeathRecipient(deathRecipient_);
108         proxy_ = nullptr;
109         DUMPER_HILOGD(MODULE_CLIENT, "debug|disconnected");
110     }
111 }
112 
ResetProxy(const wptr<IRemoteObject> & remote)113 void DumpManagerClient::ResetProxy(const wptr<IRemoteObject>& remote)
114 {
115     std::lock_guard<std::mutex> lock(mutex_);
116     if (proxy_ == nullptr) {
117         return;
118     }
119     auto serviceRemote = proxy_->AsObject();
120     if ((serviceRemote != nullptr) && (serviceRemote == remote.promote())) {
121         serviceRemote->RemoveDeathRecipient(deathRecipient_);
122         proxy_ = nullptr;
123         DUMPER_HILOGD(MODULE_CLIENT, "debug|disconnected");
124     }
125 }
126 
OnRemoteDied(const wptr<IRemoteObject> & remote)127 void DumpManagerClient::DumpManagerDeathRecipient::OnRemoteDied(const wptr<IRemoteObject>& remote)
128 {
129     if (remote == nullptr) {
130         return;
131     }
132     DumpManagerClient::GetInstance().ResetProxy(remote);
133 }
134 
OnDemandStart(sptr<ISystemAbilityManager> sam,sptr<IRemoteObject> & remoteObject)135 ErrCode DumpManagerClient::OnDemandStart(sptr<ISystemAbilityManager> sam, sptr<IRemoteObject> &remoteObject)
136 {
137     sptr<OnDemandLoadCallback> loadCallback = new OnDemandLoadCallback();
138     int32_t result = sam->LoadSystemAbility(DFX_SYS_HIDUMPER_ABILITY_ID, loadCallback);
139     if (result != ERR_OK) {
140         DUMPER_HILOGE(MODULE_CLIENT, "systemAbilityId:%{public}d load failed, result code:%{public}d",
141             DFX_SYS_HIDUMPER_ABILITY_ID, result);
142         return ERROR_GET_DUMPER_SERVICE;
143     }
144 
145     int32_t loop = SLEEP_DUR / SLEEP_UNIT;
146     while (loop-- > 0) {
147         if (!loadCallback->CheckLoadSystemAbilityStatus()) {
148             usleep(SLEEP_UNIT);
149             continue;
150         }
151         remoteObject = sam->CheckSystemAbility(DFX_SYS_HIDUMPER_ABILITY_ID);
152         if (remoteObject != nullptr) {
153             return ERR_OK;
154         } else {
155             usleep(SLEEP_UNIT);
156         }
157     }
158 
159     DUMPER_HILOGD(MODULE_CLIENT, "debug|on demand start fail");
160     return ERROR_GET_DUMPER_SERVICE;
161 }
162 } // namespace HiviewDFX
163 } // namespace OHOS
164