blob: bc5eaf24c5e8cf336dcca8efeb769735115640ff [file] [log] [blame]
Yifan Hong85dd3ad2017-01-25 14:20:34 -08001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17
18#include <getopt.h>
19
20#include <map>
Yifan Hongf4bee842017-02-01 15:54:01 -080021#include <fstream>
Yifan Hong85dd3ad2017-01-25 14:20:34 -080022#include <iomanip>
23#include <iostream>
24#include <sstream>
Yifan Hongf4bee842017-02-01 15:54:01 -080025#include <regex>
Yifan Hong85dd3ad2017-01-25 14:20:34 -080026
Yifan Hongf4bee842017-02-01 15:54:01 -080027#include <android-base/parseint.h>
Yifan Hong85dd3ad2017-01-25 14:20:34 -080028#include <android/hidl/manager/1.0/IServiceManager.h>
29#include <hidl/ServiceManagement.h>
30
Yifan Hongf4bee842017-02-01 15:54:01 -080031template <typename A, typename B, typename C, typename D, typename E>
Yifan Hong85dd3ad2017-01-25 14:20:34 -080032void printColumn(std::stringstream &stream,
Yifan Hongf4bee842017-02-01 15:54:01 -080033 const A &a, const B &b, const C &c, const D &d, const E &e) {
Yifan Hong85dd3ad2017-01-25 14:20:34 -080034 using namespace ::std;
35 stream << left
36 << setw(70) << a << "\t"
37 << setw(20) << b << "\t"
38 << setw(10) << c << "\t"
39 << setw(5) << d << "\t"
Yifan Hongf4bee842017-02-01 15:54:01 -080040 << setw(0) << e
Yifan Hong85dd3ad2017-01-25 14:20:34 -080041 << endl;
42}
43
Yifan Hongf4bee842017-02-01 15:54:01 -080044std::string toHexString(uint64_t t) {
45 std::ostringstream os;
46 os << std::hex << std::setfill('0') << std::setw(16) << t;
47 return os.str();
48}
49
50::android::status_t getReferencedPids(
51 pid_t serverPid, std::map<uint64_t, std::string> *objects) {
52
53 std::ifstream ifs("/d/binder/proc/" + std::to_string(serverPid));
54 if (!ifs.is_open()) {
55 return ::android::PERMISSION_DENIED;
56 }
57
58 static const std::regex prefix("^\\s*node \\d+:\\s+u([0-9a-f]+)\\s+c([0-9a-f]+)\\s+");
59
60 std::string line;
61 std::smatch match;
62 while(getline(ifs, line)) {
63 if (!std::regex_search(line, match, prefix)) {
64 // the line doesn't start with the correct prefix
65 continue;
66 }
67 std::string ptrString = "0x" + match.str(2); // use number after c
68 uint64_t ptr;
69 if (!::android::base::ParseUint(ptrString.c_str(), &ptr)) {
70 // Should not reach here, but just be tolerant.
71 std::cerr << "Could not parse number " << ptrString << std::endl;
72 continue;
73 }
74 const std::string proc = " proc ";
75 auto pos = line.rfind(proc);
76 if (pos != std::string::npos) {
77 (*objects)[ptr] += line.substr(pos + proc.size());
78 }
79 }
80 return ::android::OK;
81}
82
83
Yifan Hong85dd3ad2017-01-25 14:20:34 -080084int dump() {
85 using namespace ::std;
86 using namespace ::android::hardware;
87 using namespace ::android::hidl::manager::V1_0;
88
89 std::map<std::string, ::android::sp<IServiceManager>> mapping = {
90 {"hwbinder", defaultServiceManager()},
91 {"passthrough", getPassthroughServiceManager()}
92 };
93
94 std::stringstream stream;
95
96 stream << "All services:" << endl;
97 stream << left;
Yifan Hongf4bee842017-02-01 15:54:01 -080098 printColumn(stream, "Interface", "Instance", "Transport", "Server", "Clients");
Yifan Hong85dd3ad2017-01-25 14:20:34 -080099
100 for (const auto &pair : mapping) {
101 const std::string &mode = pair.first;
102 const ::android::sp<IServiceManager> &manager = pair.second;
103
104 if (manager == nullptr) {
105 cerr << "Failed to get IServiceManager for " << mode << "!" << endl;
106 continue;
107 }
108
109 auto ret = manager->debugDump([&](const auto &registered) {
Yifan Hongf4bee842017-02-01 15:54:01 -0800110 // server pid, .ptr value of binder object, child pids
111 std::map<pid_t, std::map<uint64_t, std::string>> allPids;
112 for (const auto &info : registered) {
113 if (info.pid < 0) {
114 continue;
115 }
116 pid_t serverPid = info.pid;
117 allPids[serverPid].clear();
118 }
119 for (auto &pair : allPids) {
120 pid_t serverPid = pair.first;
121 if (getReferencedPids(serverPid, &allPids[serverPid]) != ::android::OK) {
122 std::cerr << "Warning: no information for PID " << serverPid
123 << ", are you root?" << std::endl;
124 }
125 }
Yifan Hong85dd3ad2017-01-25 14:20:34 -0800126 for (const auto &info : registered) {
127 printColumn(stream,
128 info.interfaceName,
129 info.instanceName.empty() ? "N/A" : info.instanceName,
130 mode,
Yifan Hongf4bee842017-02-01 15:54:01 -0800131 info.pid < 0 ? "N/A" : std::to_string(info.pid),
132 info.pid < 0 || info.ptr == 0 ? "" : allPids[info.pid][info.ptr]);
Yifan Hong85dd3ad2017-01-25 14:20:34 -0800133 }
134 });
135 if (!ret.isOk()) {
136 cerr << "Failed to list services for " << mode << ": "
137 << ret.description() << endl;
138 }
139 }
140 cout << stream.rdbuf();
141 return 0;
142}
143
144int usage() {
145 using namespace ::std;
146 cerr
147 << "usage: lshal" << endl
148 << " To dump all hals." << endl
149 << "or:" << endl
150 << " lshal [-h|--help]" << endl
151 << " -h, --help: show this help information." << endl;
152 return -1;
153}
154
155int main(int argc, char **argv) {
156 static struct option longOptions[] = {
157 {"help", no_argument, 0, 'h' },
158 { 0, 0, 0, 0 }
159 };
160
161 int optionIndex;
162 int c;
163 optind = 1;
164 for (;;) {
165 // using getopt_long in case we want to add other options in the future
166 c = getopt_long(argc, argv, "h", longOptions, &optionIndex);
167 if (c == -1) {
168 break;
169 }
170 switch (c) {
171 case 'h': // falls through
172 default: // see unrecognized options
173 return usage();
174 }
175 }
176 return dump();
177
178}