1*38e8c45fSAndroid Build Coastguard Worker /*
2*38e8c45fSAndroid Build Coastguard Worker * Copyright (C) 2017 The Android Open Source Project
3*38e8c45fSAndroid Build Coastguard Worker *
4*38e8c45fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*38e8c45fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*38e8c45fSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*38e8c45fSAndroid Build Coastguard Worker *
8*38e8c45fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*38e8c45fSAndroid Build Coastguard Worker *
10*38e8c45fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*38e8c45fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*38e8c45fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*38e8c45fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*38e8c45fSAndroid Build Coastguard Worker * limitations under the License.
15*38e8c45fSAndroid Build Coastguard Worker */
16*38e8c45fSAndroid Build Coastguard Worker
17*38e8c45fSAndroid Build Coastguard Worker #define LOG_TAG "lshal"
18*38e8c45fSAndroid Build Coastguard Worker #include <android-base/logging.h>
19*38e8c45fSAndroid Build Coastguard Worker
20*38e8c45fSAndroid Build Coastguard Worker #include "Lshal.h"
21*38e8c45fSAndroid Build Coastguard Worker
22*38e8c45fSAndroid Build Coastguard Worker #include <set>
23*38e8c45fSAndroid Build Coastguard Worker #include <string>
24*38e8c45fSAndroid Build Coastguard Worker
25*38e8c45fSAndroid Build Coastguard Worker #include <hidl/ServiceManagement.h>
26*38e8c45fSAndroid Build Coastguard Worker #include <hidl/HidlTransportUtils.h>
27*38e8c45fSAndroid Build Coastguard Worker
28*38e8c45fSAndroid Build Coastguard Worker #include "DebugCommand.h"
29*38e8c45fSAndroid Build Coastguard Worker #include "HelpCommand.h"
30*38e8c45fSAndroid Build Coastguard Worker #include "ListCommand.h"
31*38e8c45fSAndroid Build Coastguard Worker #include "WaitCommand.h"
32*38e8c45fSAndroid Build Coastguard Worker #include "PipeRelay.h"
33*38e8c45fSAndroid Build Coastguard Worker
34*38e8c45fSAndroid Build Coastguard Worker namespace android {
35*38e8c45fSAndroid Build Coastguard Worker namespace lshal {
36*38e8c45fSAndroid Build Coastguard Worker
37*38e8c45fSAndroid Build Coastguard Worker using ::android::hidl::manager::V1_0::IServiceManager;
38*38e8c45fSAndroid Build Coastguard Worker
Lshal()39*38e8c45fSAndroid Build Coastguard Worker Lshal::Lshal()
40*38e8c45fSAndroid Build Coastguard Worker : Lshal(std::cout, std::cerr, ::android::hardware::defaultServiceManager(),
41*38e8c45fSAndroid Build Coastguard Worker ::android::hardware::getPassthroughServiceManager()) {
42*38e8c45fSAndroid Build Coastguard Worker }
43*38e8c45fSAndroid Build Coastguard Worker
Lshal(std::ostream & out,std::ostream & err,sp<hidl::manager::V1_0::IServiceManager> serviceManager,sp<hidl::manager::V1_0::IServiceManager> passthroughManager)44*38e8c45fSAndroid Build Coastguard Worker Lshal::Lshal(std::ostream &out, std::ostream &err,
45*38e8c45fSAndroid Build Coastguard Worker sp<hidl::manager::V1_0::IServiceManager> serviceManager,
46*38e8c45fSAndroid Build Coastguard Worker sp<hidl::manager::V1_0::IServiceManager> passthroughManager)
47*38e8c45fSAndroid Build Coastguard Worker : mOut(out), mErr(err),
48*38e8c45fSAndroid Build Coastguard Worker mServiceManager(serviceManager),
49*38e8c45fSAndroid Build Coastguard Worker mPassthroughManager(passthroughManager) {
50*38e8c45fSAndroid Build Coastguard Worker
51*38e8c45fSAndroid Build Coastguard Worker mRegisteredCommands.push_back({std::make_unique<ListCommand>(*this)});
52*38e8c45fSAndroid Build Coastguard Worker mRegisteredCommands.push_back({std::make_unique<DebugCommand>(*this)});
53*38e8c45fSAndroid Build Coastguard Worker mRegisteredCommands.push_back({std::make_unique<HelpCommand>(*this)});
54*38e8c45fSAndroid Build Coastguard Worker mRegisteredCommands.push_back({std::make_unique<WaitCommand>(*this)});
55*38e8c45fSAndroid Build Coastguard Worker }
56*38e8c45fSAndroid Build Coastguard Worker
forEachCommand(const std::function<void (const Command * c)> & f) const57*38e8c45fSAndroid Build Coastguard Worker void Lshal::forEachCommand(const std::function<void(const Command* c)>& f) const {
58*38e8c45fSAndroid Build Coastguard Worker for (const auto& e : mRegisteredCommands) f(e.get());
59*38e8c45fSAndroid Build Coastguard Worker }
60*38e8c45fSAndroid Build Coastguard Worker
usage()61*38e8c45fSAndroid Build Coastguard Worker void Lshal::usage() {
62*38e8c45fSAndroid Build Coastguard Worker err() << "lshal: List and debug HIDL HALs." << std::endl
63*38e8c45fSAndroid Build Coastguard Worker << " (for AIDL HALs, see `dumpsys`)" << std::endl << std::endl
64*38e8c45fSAndroid Build Coastguard Worker << "commands:" << std::endl;
65*38e8c45fSAndroid Build Coastguard Worker
66*38e8c45fSAndroid Build Coastguard Worker size_t nameMaxLength = 0;
67*38e8c45fSAndroid Build Coastguard Worker forEachCommand([&](const Command* e) {
68*38e8c45fSAndroid Build Coastguard Worker nameMaxLength = std::max(nameMaxLength, e->getName().length());
69*38e8c45fSAndroid Build Coastguard Worker });
70*38e8c45fSAndroid Build Coastguard Worker bool first = true;
71*38e8c45fSAndroid Build Coastguard Worker forEachCommand([&](const Command* e) {
72*38e8c45fSAndroid Build Coastguard Worker if (!first) err() << std::endl;
73*38e8c45fSAndroid Build Coastguard Worker first = false;
74*38e8c45fSAndroid Build Coastguard Worker err() << " " << std::left << std::setw(nameMaxLength + 8) << e->getName()
75*38e8c45fSAndroid Build Coastguard Worker << e->getSimpleDescription();
76*38e8c45fSAndroid Build Coastguard Worker });
77*38e8c45fSAndroid Build Coastguard Worker err() << std::endl << "If no command is specified, `" << ListCommand::GetName()
78*38e8c45fSAndroid Build Coastguard Worker << "` is the default." << std::endl << std::endl;
79*38e8c45fSAndroid Build Coastguard Worker
80*38e8c45fSAndroid Build Coastguard Worker first = true;
81*38e8c45fSAndroid Build Coastguard Worker forEachCommand([&](const Command* e) {
82*38e8c45fSAndroid Build Coastguard Worker if (!first) err() << std::endl;
83*38e8c45fSAndroid Build Coastguard Worker first = false;
84*38e8c45fSAndroid Build Coastguard Worker e->usage();
85*38e8c45fSAndroid Build Coastguard Worker });
86*38e8c45fSAndroid Build Coastguard Worker }
87*38e8c45fSAndroid Build Coastguard Worker
88*38e8c45fSAndroid Build Coastguard Worker // A unique_ptr type using a custom deleter function.
89*38e8c45fSAndroid Build Coastguard Worker template<typename T>
90*38e8c45fSAndroid Build Coastguard Worker using deleted_unique_ptr = std::unique_ptr<T, std::function<void(T *)> >;
91*38e8c45fSAndroid Build Coastguard Worker
convert(const std::vector<std::string> & v)92*38e8c45fSAndroid Build Coastguard Worker static hardware::hidl_vec<hardware::hidl_string> convert(const std::vector<std::string> &v) {
93*38e8c45fSAndroid Build Coastguard Worker hardware::hidl_vec<hardware::hidl_string> hv;
94*38e8c45fSAndroid Build Coastguard Worker hv.resize(v.size());
95*38e8c45fSAndroid Build Coastguard Worker for (size_t i = 0; i < v.size(); ++i) {
96*38e8c45fSAndroid Build Coastguard Worker hv[i].setToExternal(v[i].c_str(), v[i].size());
97*38e8c45fSAndroid Build Coastguard Worker }
98*38e8c45fSAndroid Build Coastguard Worker return hv;
99*38e8c45fSAndroid Build Coastguard Worker }
100*38e8c45fSAndroid Build Coastguard Worker
emitDebugInfo(const std::string & interfaceName,const std::string & instanceName,const std::vector<std::string> & options,ParentDebugInfoLevel parentDebugInfoLevel,std::ostream & out,NullableOStream<std::ostream> err) const101*38e8c45fSAndroid Build Coastguard Worker Status Lshal::emitDebugInfo(
102*38e8c45fSAndroid Build Coastguard Worker const std::string &interfaceName,
103*38e8c45fSAndroid Build Coastguard Worker const std::string &instanceName,
104*38e8c45fSAndroid Build Coastguard Worker const std::vector<std::string> &options,
105*38e8c45fSAndroid Build Coastguard Worker ParentDebugInfoLevel parentDebugInfoLevel,
106*38e8c45fSAndroid Build Coastguard Worker std::ostream &out,
107*38e8c45fSAndroid Build Coastguard Worker NullableOStream<std::ostream> err) const {
108*38e8c45fSAndroid Build Coastguard Worker using android::hidl::base::V1_0::IBase;
109*38e8c45fSAndroid Build Coastguard Worker using android::hardware::details::getDescriptor;
110*38e8c45fSAndroid Build Coastguard Worker
111*38e8c45fSAndroid Build Coastguard Worker hardware::Return<sp<IBase>> retBase = serviceManager()->get(interfaceName, instanceName);
112*38e8c45fSAndroid Build Coastguard Worker
113*38e8c45fSAndroid Build Coastguard Worker if (!retBase.isOk()) {
114*38e8c45fSAndroid Build Coastguard Worker std::string msg = "Cannot get " + interfaceName + "/" + instanceName + ": "
115*38e8c45fSAndroid Build Coastguard Worker + retBase.description();
116*38e8c45fSAndroid Build Coastguard Worker err << msg << std::endl;
117*38e8c45fSAndroid Build Coastguard Worker LOG(ERROR) << msg;
118*38e8c45fSAndroid Build Coastguard Worker return TRANSACTION_ERROR;
119*38e8c45fSAndroid Build Coastguard Worker }
120*38e8c45fSAndroid Build Coastguard Worker
121*38e8c45fSAndroid Build Coastguard Worker sp<IBase> base = retBase;
122*38e8c45fSAndroid Build Coastguard Worker if (base == nullptr) {
123*38e8c45fSAndroid Build Coastguard Worker std::string msg = interfaceName + "/" + instanceName + " does not exist, or "
124*38e8c45fSAndroid Build Coastguard Worker + "no permission to connect.";
125*38e8c45fSAndroid Build Coastguard Worker err << msg << std::endl;
126*38e8c45fSAndroid Build Coastguard Worker LOG(ERROR) << msg;
127*38e8c45fSAndroid Build Coastguard Worker return NO_INTERFACE;
128*38e8c45fSAndroid Build Coastguard Worker }
129*38e8c45fSAndroid Build Coastguard Worker
130*38e8c45fSAndroid Build Coastguard Worker if (parentDebugInfoLevel != ParentDebugInfoLevel::FULL) {
131*38e8c45fSAndroid Build Coastguard Worker const std::string descriptor = getDescriptor(base.get());
132*38e8c45fSAndroid Build Coastguard Worker if (descriptor.empty()) {
133*38e8c45fSAndroid Build Coastguard Worker std::string msg = interfaceName + "/" + instanceName + " getDescriptor failed";
134*38e8c45fSAndroid Build Coastguard Worker err << msg << std::endl;
135*38e8c45fSAndroid Build Coastguard Worker LOG(ERROR) << msg;
136*38e8c45fSAndroid Build Coastguard Worker }
137*38e8c45fSAndroid Build Coastguard Worker if (descriptor != interfaceName) {
138*38e8c45fSAndroid Build Coastguard Worker if (parentDebugInfoLevel == ParentDebugInfoLevel::FQNAME_ONLY) {
139*38e8c45fSAndroid Build Coastguard Worker out << "[See " << descriptor << "/" << instanceName << "]";
140*38e8c45fSAndroid Build Coastguard Worker }
141*38e8c45fSAndroid Build Coastguard Worker return OK;
142*38e8c45fSAndroid Build Coastguard Worker }
143*38e8c45fSAndroid Build Coastguard Worker }
144*38e8c45fSAndroid Build Coastguard Worker
145*38e8c45fSAndroid Build Coastguard Worker auto relay = PipeRelay::create(out, err, interfaceName + "/" + instanceName);
146*38e8c45fSAndroid Build Coastguard Worker if (!relay.ok()) {
147*38e8c45fSAndroid Build Coastguard Worker err << "Unable to create PipeRelay: " << relay.error() << std::endl;
148*38e8c45fSAndroid Build Coastguard Worker LOG(ERROR) << "Unable to create PipeRelay: " << relay.error();
149*38e8c45fSAndroid Build Coastguard Worker return IO_ERROR;
150*38e8c45fSAndroid Build Coastguard Worker }
151*38e8c45fSAndroid Build Coastguard Worker
152*38e8c45fSAndroid Build Coastguard Worker deleted_unique_ptr<native_handle_t> fdHandle(
153*38e8c45fSAndroid Build Coastguard Worker native_handle_create(1 /* numFds */, 0 /* numInts */),
154*38e8c45fSAndroid Build Coastguard Worker native_handle_delete);
155*38e8c45fSAndroid Build Coastguard Worker
156*38e8c45fSAndroid Build Coastguard Worker fdHandle->data[0] = relay.value()->fd().get();
157*38e8c45fSAndroid Build Coastguard Worker
158*38e8c45fSAndroid Build Coastguard Worker hardware::Return<void> ret = base->debug(fdHandle.get(), convert(options));
159*38e8c45fSAndroid Build Coastguard Worker
160*38e8c45fSAndroid Build Coastguard Worker if (!ret.isOk()) {
161*38e8c45fSAndroid Build Coastguard Worker std::string msg = "debug() FAILED on " + interfaceName + "/" + instanceName + ": "
162*38e8c45fSAndroid Build Coastguard Worker + ret.description();
163*38e8c45fSAndroid Build Coastguard Worker err << msg << std::endl;
164*38e8c45fSAndroid Build Coastguard Worker LOG(ERROR) << msg;
165*38e8c45fSAndroid Build Coastguard Worker return TRANSACTION_ERROR;
166*38e8c45fSAndroid Build Coastguard Worker }
167*38e8c45fSAndroid Build Coastguard Worker return OK;
168*38e8c45fSAndroid Build Coastguard Worker }
169*38e8c45fSAndroid Build Coastguard Worker
parseArgs(const Arg & arg)170*38e8c45fSAndroid Build Coastguard Worker Status Lshal::parseArgs(const Arg &arg) {
171*38e8c45fSAndroid Build Coastguard Worker optind = 1;
172*38e8c45fSAndroid Build Coastguard Worker if (optind >= arg.argc) {
173*38e8c45fSAndroid Build Coastguard Worker // no options at all.
174*38e8c45fSAndroid Build Coastguard Worker return OK;
175*38e8c45fSAndroid Build Coastguard Worker }
176*38e8c45fSAndroid Build Coastguard Worker mCommand = arg.argv[optind];
177*38e8c45fSAndroid Build Coastguard Worker if (selectCommand(mCommand) != nullptr) {
178*38e8c45fSAndroid Build Coastguard Worker ++optind;
179*38e8c45fSAndroid Build Coastguard Worker return OK; // mCommand is set correctly
180*38e8c45fSAndroid Build Coastguard Worker }
181*38e8c45fSAndroid Build Coastguard Worker
182*38e8c45fSAndroid Build Coastguard Worker if (mCommand.size() > 0 && mCommand[0] == '-') {
183*38e8c45fSAndroid Build Coastguard Worker // first argument is an option, set command to "" (which is recognized as "list")
184*38e8c45fSAndroid Build Coastguard Worker mCommand.clear();
185*38e8c45fSAndroid Build Coastguard Worker return OK;
186*38e8c45fSAndroid Build Coastguard Worker }
187*38e8c45fSAndroid Build Coastguard Worker
188*38e8c45fSAndroid Build Coastguard Worker err() << arg.argv[0] << ": unrecognized option `" << arg.argv[optind] << "'" << std::endl;
189*38e8c45fSAndroid Build Coastguard Worker return USAGE;
190*38e8c45fSAndroid Build Coastguard Worker }
191*38e8c45fSAndroid Build Coastguard Worker
signalHandler(int sig)192*38e8c45fSAndroid Build Coastguard Worker void signalHandler(int sig) {
193*38e8c45fSAndroid Build Coastguard Worker if (sig == SIGINT) {
194*38e8c45fSAndroid Build Coastguard Worker int retVal;
195*38e8c45fSAndroid Build Coastguard Worker pthread_exit(&retVal);
196*38e8c45fSAndroid Build Coastguard Worker }
197*38e8c45fSAndroid Build Coastguard Worker }
198*38e8c45fSAndroid Build Coastguard Worker
selectCommand(const std::string & command) const199*38e8c45fSAndroid Build Coastguard Worker Command* Lshal::selectCommand(const std::string& command) const {
200*38e8c45fSAndroid Build Coastguard Worker if (command.empty()) {
201*38e8c45fSAndroid Build Coastguard Worker return selectCommand(ListCommand::GetName());
202*38e8c45fSAndroid Build Coastguard Worker }
203*38e8c45fSAndroid Build Coastguard Worker for (const auto& e : mRegisteredCommands) {
204*38e8c45fSAndroid Build Coastguard Worker if (e->getName() == command) {
205*38e8c45fSAndroid Build Coastguard Worker return e.get();
206*38e8c45fSAndroid Build Coastguard Worker }
207*38e8c45fSAndroid Build Coastguard Worker }
208*38e8c45fSAndroid Build Coastguard Worker return nullptr;
209*38e8c45fSAndroid Build Coastguard Worker }
210*38e8c45fSAndroid Build Coastguard Worker
main(const Arg & arg)211*38e8c45fSAndroid Build Coastguard Worker Status Lshal::main(const Arg &arg) {
212*38e8c45fSAndroid Build Coastguard Worker // Allow SIGINT to terminate all threads.
213*38e8c45fSAndroid Build Coastguard Worker signal(SIGINT, signalHandler);
214*38e8c45fSAndroid Build Coastguard Worker
215*38e8c45fSAndroid Build Coastguard Worker Status status = parseArgs(arg);
216*38e8c45fSAndroid Build Coastguard Worker if (status != OK) {
217*38e8c45fSAndroid Build Coastguard Worker usage();
218*38e8c45fSAndroid Build Coastguard Worker return status;
219*38e8c45fSAndroid Build Coastguard Worker }
220*38e8c45fSAndroid Build Coastguard Worker auto c = selectCommand(mCommand);
221*38e8c45fSAndroid Build Coastguard Worker if (c == nullptr) {
222*38e8c45fSAndroid Build Coastguard Worker // unknown command, print global usage
223*38e8c45fSAndroid Build Coastguard Worker usage();
224*38e8c45fSAndroid Build Coastguard Worker return USAGE;
225*38e8c45fSAndroid Build Coastguard Worker }
226*38e8c45fSAndroid Build Coastguard Worker status = c->main(arg);
227*38e8c45fSAndroid Build Coastguard Worker if (status == USAGE) {
228*38e8c45fSAndroid Build Coastguard Worker // bad options. Run `lshal help ${mCommand}` instead.
229*38e8c45fSAndroid Build Coastguard Worker // For example, `lshal --unknown-option` becomes `lshal help` (prints global help)
230*38e8c45fSAndroid Build Coastguard Worker // and `lshal list --unknown-option` becomes `lshal help list`
231*38e8c45fSAndroid Build Coastguard Worker auto&& help = selectCommand(HelpCommand::GetName());
232*38e8c45fSAndroid Build Coastguard Worker return static_cast<HelpCommand*>(help)->usageOfCommand(mCommand);
233*38e8c45fSAndroid Build Coastguard Worker }
234*38e8c45fSAndroid Build Coastguard Worker
235*38e8c45fSAndroid Build Coastguard Worker // After Lshal::main() finishes, caller may call _exit(), causing debug
236*38e8c45fSAndroid Build Coastguard Worker // information to prematurely ends. Hence flush().
237*38e8c45fSAndroid Build Coastguard Worker err().flush();
238*38e8c45fSAndroid Build Coastguard Worker out().flush();
239*38e8c45fSAndroid Build Coastguard Worker
240*38e8c45fSAndroid Build Coastguard Worker return status;
241*38e8c45fSAndroid Build Coastguard Worker }
242*38e8c45fSAndroid Build Coastguard Worker
err() const243*38e8c45fSAndroid Build Coastguard Worker NullableOStream<std::ostream> Lshal::err() const {
244*38e8c45fSAndroid Build Coastguard Worker return mErr;
245*38e8c45fSAndroid Build Coastguard Worker }
out() const246*38e8c45fSAndroid Build Coastguard Worker NullableOStream<std::ostream> Lshal::out() const {
247*38e8c45fSAndroid Build Coastguard Worker return mOut;
248*38e8c45fSAndroid Build Coastguard Worker }
249*38e8c45fSAndroid Build Coastguard Worker
serviceManager() const250*38e8c45fSAndroid Build Coastguard Worker const sp<IServiceManager> &Lshal::serviceManager() const {
251*38e8c45fSAndroid Build Coastguard Worker return mServiceManager;
252*38e8c45fSAndroid Build Coastguard Worker }
253*38e8c45fSAndroid Build Coastguard Worker
passthroughManager() const254*38e8c45fSAndroid Build Coastguard Worker const sp<IServiceManager> &Lshal::passthroughManager() const {
255*38e8c45fSAndroid Build Coastguard Worker return mPassthroughManager;
256*38e8c45fSAndroid Build Coastguard Worker }
257*38e8c45fSAndroid Build Coastguard Worker
setWaitTimeForTest(std::chrono::milliseconds ipcCallWait,std::chrono::milliseconds debugDumpWait)258*38e8c45fSAndroid Build Coastguard Worker void Lshal::setWaitTimeForTest(std::chrono::milliseconds ipcCallWait,
259*38e8c45fSAndroid Build Coastguard Worker std::chrono::milliseconds debugDumpWait) {
260*38e8c45fSAndroid Build Coastguard Worker mIpcCallWait = ipcCallWait;
261*38e8c45fSAndroid Build Coastguard Worker mDebugDumpWait = debugDumpWait;
262*38e8c45fSAndroid Build Coastguard Worker }
getIpcCallWait() const263*38e8c45fSAndroid Build Coastguard Worker std::chrono::milliseconds Lshal::getIpcCallWait() const {
264*38e8c45fSAndroid Build Coastguard Worker return mIpcCallWait;
265*38e8c45fSAndroid Build Coastguard Worker }
getDebugDumpWait() const266*38e8c45fSAndroid Build Coastguard Worker std::chrono::milliseconds Lshal::getDebugDumpWait() const {
267*38e8c45fSAndroid Build Coastguard Worker return mDebugDumpWait;
268*38e8c45fSAndroid Build Coastguard Worker }
269*38e8c45fSAndroid Build Coastguard Worker
270*38e8c45fSAndroid Build Coastguard Worker } // namespace lshal
271*38e8c45fSAndroid Build Coastguard Worker } // namespace android
272