1 /*
2  * Copyright (C) 2017 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 #pragma once
18 
19 #include <getopt.h>
20 #include <stdint.h>
21 
22 #include <fstream>
23 #include <string>
24 #include <vector>
25 
26 #include <android-base/macros.h>
27 #include <android/hidl/manager/1.0/IServiceManager.h>
28 #include <hidl-util/FqInstance.h>
29 #include <vintf/HalManifest.h>
30 #include <vintf/VintfObject.h>
31 
32 #include "Command.h"
33 #include "NullableOStream.h"
34 #include "TableEntry.h"
35 #include "TextTable.h"
36 #include "utils.h"
37 
38 namespace android {
39 namespace lshal {
40 
41 class Lshal;
42 
43 struct PidInfo {
44     std::map<uint64_t, Pids> refPids; // pids that are referenced
45     uint32_t threadUsage; // number of threads in use
46     uint32_t threadCount; // number of threads total
47 };
48 
49 enum class HalType {
50     BINDERIZED_SERVICES = 0,
51     PASSTHROUGH_CLIENTS,
52     PASSTHROUGH_LIBRARIES,
53     VINTF_MANIFEST,
54     LAZY_HALS,
55 };
56 
57 class ListCommand : public Command {
58 public:
ListCommand(Lshal & lshal)59     explicit ListCommand(Lshal &lshal) : Command(lshal) {}
60     virtual ~ListCommand() = default;
61     Status main(const Arg &arg) override;
62     void usage() const override;
63     std::string getSimpleDescription() const override;
getName()64     std::string getName() const override { return GetName(); }
65 
66     static std::string GetName();
67 
68     struct RegisteredOption {
69         // short alternative, e.g. 'v'. If '\0', no short options is available.
70         char shortOption;
71         // long alternative, e.g. 'init-vintf'
72         std::string longOption;
73         // no_argument, required_argument or optional_argument
74         int hasArg;
75         // value written to 'flag' by getopt_long
76         int val;
77         // operation when the argument is present
78         std::function<Status(ListCommand* thiz, const char* arg)> op;
79         // help message
80         std::string help;
81 
82         const std::string& getHelpMessageForArgument() const;
83     };
84     // A list of acceptable command line options
85     // key: value returned by getopt_long
86     using RegisteredOptions = std::vector<RegisteredOption>;
87 
88     static std::string INIT_VINTF_NOTES;
89 
90 protected:
91     Status parseArgs(const Arg &arg);
92     // Retrieve first-hand information
93     Status fetch();
94     // Retrieve derived information base on existing table
95     virtual void postprocess();
96     Status dump();
97     void putEntry(HalType type, TableEntry &&entry);
98     Status fetchPassthrough(const sp<::android::hidl::manager::V1_0::IServiceManager> &manager);
99     Status fetchBinderized(const sp<::android::hidl::manager::V1_0::IServiceManager> &manager);
100     Status fetchAllLibraries(const sp<::android::hidl::manager::V1_0::IServiceManager> &manager);
101     Status fetchManifestHals();
102     Status fetchLazyHals();
103 
104     Status fetchBinderizedEntry(const sp<::android::hidl::manager::V1_0::IServiceManager> &manager,
105                                 TableEntry *entry);
106 
107     // Get relevant information for a PID by parsing files under
108     // /dev/binderfs/binder_logs or /d/binder.
109     // It is a virtual member function so that it can be mocked.
110     virtual bool getPidInfo(pid_t serverPid, PidInfo *info) const;
111     // Retrieve from mCachedPidInfos and call getPidInfo if necessary.
112     const PidInfo* getPidInfoCached(pid_t serverPid);
113 
114     void dumpTable(const NullableOStream<std::ostream>& out) const;
115     void dumpVintf(const NullableOStream<std::ostream>& out) const;
116     void addLine(TextTable *table, const std::string &interfaceName, const std::string &transport,
117                  const std::string &arch, const std::string &threadUsage, const std::string &server,
118                  const std::string &serverCmdline, const std::string &address,
119                  const std::string &clients, const std::string &clientCmdlines) const;
120     void addLine(TextTable *table, const TableEntry &entry);
121     // Read and return /proc/{pid}/cmdline.
122     virtual std::string parseCmdline(pid_t pid) const;
123     // Return /proc/{pid}/cmdline if it exists, else empty string.
124     const std::string& getCmdline(pid_t pid);
125     // Call getCmdline on all pid in pids. If it returns empty string, the process might
126     // have died, and the pid is removed from pids.
127     void removeDeadProcesses(Pids *pids);
128 
129     virtual Partition getPartition(pid_t pid);
130     Partition resolvePartition(Partition processPartition, const FqInstance &fqInstance) const;
131 
132     VintfInfo getVintfInfo(const std::string &fqInstanceName, vintf::TransportArch ta) const;
133     // Allow to mock these functions for testing.
134     virtual std::shared_ptr<const vintf::HalManifest> getDeviceManifest() const;
135     virtual std::shared_ptr<const vintf::CompatibilityMatrix> getDeviceMatrix() const;
136     virtual std::shared_ptr<const vintf::HalManifest> getFrameworkManifest() const;
137     virtual std::shared_ptr<const vintf::CompatibilityMatrix> getFrameworkMatrix() const;
138 
139     void forEachTable(const std::function<void(Table &)> &f);
140     void forEachTable(const std::function<void(const Table &)> &f) const;
141     Table* tableForType(HalType type);
142     const Table* tableForType(HalType type) const;
143 
144     NullableOStream<std::ostream> err() const;
145     NullableOStream<std::ostream> out() const;
146 
147     void registerAllOptions();
148 
149     // helper functions to dumpVintf.
150     bool addEntryWithInstance(const TableEntry &entry, vintf::HalManifest *manifest) const;
151     bool addEntryWithoutInstance(const TableEntry &entry, const vintf::HalManifest *manifest) const;
152 
153     // Helper function. Whether to fetch entries corresponding to a given HAL type.
154     bool shouldFetchHalType(const HalType &type) const;
155 
156     void initFetchTypes();
157 
158     // Helper functions ti add HALs that are listed in VINTF manifest to LAZY_HALS table.
159     bool hasHwbinderEntry(const TableEntry& entry) const;
160     bool hasPassthroughEntry(const TableEntry& entry) const;
161 
162     Table mServicesTable{};
163     Table mPassthroughRefTable{};
164     Table mImplementationsTable{};
165     Table mManifestHalsTable{};
166     Table mLazyHalsTable{};
167 
168     std::string mFileOutputPath;
169     TableEntryCompare mSortColumn = nullptr;
170 
171     bool mEmitDebugInfo = false;
172 
173     // If true, output in VINTF format. Output only entries from the specified partition.
174     bool mVintf = false;
175     Partition mVintfPartition = Partition::UNKNOWN;
176 
177     // If true, explanatory text are not emitted.
178     bool mNeat = false;
179 
180     // Type(s) of HAL associations to list.
181     std::vector<HalType> mListTypes{};
182     // Type(s) of HAL associations to fetch.
183     std::set<HalType> mFetchTypes{};
184 
185     // If an entry does not exist, need to ask /proc/{pid}/cmdline to get it.
186     // If an entry exist but is an empty string, process might have died.
187     // If an entry exist and not empty, it contains the cached content of /proc/{pid}/cmdline.
188     std::map<pid_t, std::string> mCmdlines;
189 
190     // Cache for getPidInfo.
191     std::map<pid_t, PidInfo> mCachedPidInfos;
192 
193     // Cache for getPartition.
194     std::map<pid_t, Partition> mPartitions;
195 
196     RegisteredOptions mOptions;
197     // All selected columns
198     std::vector<TableColumnType> mSelectedColumns;
199     // If true, emit cmdlines instead of PIDs
200     bool mEnableCmdlines = false;
201 
202 private:
203     DISALLOW_COPY_AND_ASSIGN(ListCommand);
204 };
205 
206 
207 }  // namespace lshal
208 }  // namespace android
209