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 #ifndef FRAMEWORK_NATIVE_CMDS_LSHAL_LIST_COMMAND_H_
18 #define FRAMEWORK_NATIVE_CMDS_LSHAL_LIST_COMMAND_H_
19 
20 #include <getopt.h>
21 #include <stdint.h>
22 
23 #include <fstream>
24 #include <string>
25 #include <vector>
26 
27 #include <android-base/macros.h>
28 #include <android/hidl/manager/1.0/IServiceManager.h>
29 #include <hidl-util/FQName.h>
30 
31 #include "Command.h"
32 #include "NullableOStream.h"
33 #include "TableEntry.h"
34 #include "TextTable.h"
35 #include "utils.h"
36 
37 namespace android {
38 namespace lshal {
39 
40 class Lshal;
41 
42 struct PidInfo {
43     std::map<uint64_t, Pids> refPids; // pids that are referenced
44     uint32_t threadUsage; // number of threads in use
45     uint32_t threadCount; // number of threads total
46 };
47 
48 class ListCommand : public Command {
49 public:
ListCommand(Lshal & lshal)50     ListCommand(Lshal &lshal) : Command(lshal) {}
51     virtual ~ListCommand() = default;
52     Status main(const Arg &arg) override;
53     void usage() const override;
54     std::string getSimpleDescription() const override;
getName()55     std::string getName() const override { return GetName(); }
56 
57     static std::string GetName();
58 
59     struct RegisteredOption {
60         // short alternative, e.g. 'v'. If '\0', no short options is available.
61         char shortOption;
62         // long alternative, e.g. 'init-vintf'
63         std::string longOption;
64         // no_argument, required_argument or optional_argument
65         int hasArg;
66         // value written to 'flag' by getopt_long
67         int val;
68         // operation when the argument is present
69         std::function<Status(ListCommand* thiz, const char* arg)> op;
70         // help message
71         std::string help;
72 
73         const std::string& getHelpMessageForArgument() const;
74     };
75     // A list of acceptable command line options
76     // key: value returned by getopt_long
77     using RegisteredOptions = std::vector<RegisteredOption>;
78 
79     static std::string INIT_VINTF_NOTES;
80 
81 protected:
82     Status parseArgs(const Arg &arg);
83     Status fetch();
84     virtual void postprocess();
85     Status dump();
86     void putEntry(TableEntrySource source, TableEntry &&entry);
87     Status fetchPassthrough(const sp<::android::hidl::manager::V1_0::IServiceManager> &manager);
88     Status fetchBinderized(const sp<::android::hidl::manager::V1_0::IServiceManager> &manager);
89     Status fetchAllLibraries(const sp<::android::hidl::manager::V1_0::IServiceManager> &manager);
90 
91     Status fetchBinderizedEntry(const sp<::android::hidl::manager::V1_0::IServiceManager> &manager,
92                                 TableEntry *entry);
93 
94     // Get relevant information for a PID by parsing files under /d/binder.
95     // It is a virtual member function so that it can be mocked.
96     virtual bool getPidInfo(pid_t serverPid, PidInfo *info) const;
97     // Retrieve from mCachedPidInfos and call getPidInfo if necessary.
98     const PidInfo* getPidInfoCached(pid_t serverPid);
99 
100     void dumpTable(const NullableOStream<std::ostream>& out) const;
101     void dumpVintf(const NullableOStream<std::ostream>& out) const;
102     void addLine(TextTable *table, const std::string &interfaceName, const std::string &transport,
103                  const std::string &arch, const std::string &threadUsage, const std::string &server,
104                  const std::string &serverCmdline, const std::string &address,
105                  const std::string &clients, const std::string &clientCmdlines) const;
106     void addLine(TextTable *table, const TableEntry &entry);
107     // Read and return /proc/{pid}/cmdline.
108     virtual std::string parseCmdline(pid_t pid) const;
109     // Return /proc/{pid}/cmdline if it exists, else empty string.
110     const std::string& getCmdline(pid_t pid);
111     // Call getCmdline on all pid in pids. If it returns empty string, the process might
112     // have died, and the pid is removed from pids.
113     void removeDeadProcesses(Pids *pids);
114 
115     virtual Partition getPartition(pid_t pid);
116     Partition resolvePartition(Partition processPartition, const FQName& fqName) const;
117 
118     void forEachTable(const std::function<void(Table &)> &f);
119     void forEachTable(const std::function<void(const Table &)> &f) const;
120 
121     NullableOStream<std::ostream> err() const;
122     NullableOStream<std::ostream> out() const;
123 
124     void registerAllOptions();
125 
126     Table mServicesTable{};
127     Table mPassthroughRefTable{};
128     Table mImplementationsTable{};
129 
130     std::string mFileOutputPath;
131     TableEntryCompare mSortColumn = nullptr;
132 
133     bool mEmitDebugInfo = false;
134 
135     // If true, output in VINTF format. Output only entries from the specified partition.
136     bool mVintf = false;
137     Partition mVintfPartition = Partition::UNKNOWN;
138 
139     // If true, explanatory text are not emitted.
140     bool mNeat = false;
141 
142     // If an entry does not exist, need to ask /proc/{pid}/cmdline to get it.
143     // If an entry exist but is an empty string, process might have died.
144     // If an entry exist and not empty, it contains the cached content of /proc/{pid}/cmdline.
145     std::map<pid_t, std::string> mCmdlines;
146 
147     // Cache for getPidInfo.
148     std::map<pid_t, PidInfo> mCachedPidInfos;
149 
150     // Cache for getPartition.
151     std::map<pid_t, Partition> mPartitions;
152 
153     RegisteredOptions mOptions;
154     // All selected columns
155     std::vector<TableColumnType> mSelectedColumns;
156     // If true, emit cmdlines instead of PIDs
157     bool mEnableCmdlines = false;
158 
159 private:
160     DISALLOW_COPY_AND_ASSIGN(ListCommand);
161 };
162 
163 
164 }  // namespace lshal
165 }  // namespace android
166 
167 #endif  // FRAMEWORK_NATIVE_CMDS_LSHAL_LIST_COMMAND_H_
168