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