1 /*
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 #pragma once
18 
19 #include <stdint.h>
20 
21 #include <string>
22 #include <vector>
23 #include <iostream>
24 
25 #include <procpartition/procpartition.h>
26 #include <vintf/Arch.h>
27 #include <vintf/Transport.h>
28 
29 #include "TextTable.h"
30 
31 namespace android {
32 namespace lshal {
33 
34 using android::procpartition::Partition;
35 using Pids = std::vector<int32_t>;
36 
37 enum class TableColumnType : unsigned int {
38     INTERFACE_NAME,
39     TRANSPORT,
40     SERVER_PID,
41     SERVER_CMD,
42     SERVER_ADDR,
43     CLIENT_PIDS,
44     CLIENT_CMDS,
45     ARCH,
46     THREADS,
47     RELEASED,
48     HASH,
49     VINTF,
50     SERVICE_STATUS,
51 };
52 
53 enum : unsigned int {
54     VINTF_INFO_EMPTY = 0,
55     DEVICE_MANIFEST = 1 << 0,
56     DEVICE_MATRIX = 1 << 1,
57     FRAMEWORK_MANIFEST = 1 << 2,
58     FRAMEWORK_MATRIX = 1 << 3,
59 };
60 using VintfInfo = unsigned int;
61 
62 enum {
63     NO_PID = -1,
64     NO_PTR = 0
65 };
66 
67 enum class ServiceStatus {
68     UNKNOWN, // For passthrough
69     ALIVE,
70     NON_RESPONSIVE, // registered but not respond to calls
71     DECLARED, // in VINTF manifest
72 };
73 std::string to_string(ServiceStatus s);
74 
75 struct TableEntry {
76     std::string interfaceName{};
77     vintf::Transport transport{vintf::Transport::EMPTY};
78     int32_t serverPid{NO_PID};
79     uint32_t threadUsage{0};
80     uint32_t threadCount{0};
81     std::string serverCmdline{};
82     uint64_t serverObjectAddress{NO_PTR};
83     Pids clientPids{};
84     std::vector<std::string> clientCmdlines{};
85     vintf::Arch arch{vintf::Arch::ARCH_EMPTY};
86     // empty: unknown, all zeros: unreleased, otherwise: released
87     std::string hash{};
88     Partition partition{Partition::UNKNOWN};
89     VintfInfo vintfInfo{VINTF_INFO_EMPTY};
90     // true iff hwbinder and service started
91     ServiceStatus serviceStatus{ServiceStatus::UNKNOWN};
92 
sortByInterfaceNameTableEntry93     static bool sortByInterfaceName(const TableEntry &a, const TableEntry &b) {
94         return a.interfaceName < b.interfaceName;
95     };
sortByServerPidTableEntry96     static bool sortByServerPid(const TableEntry &a, const TableEntry &b) {
97         return a.serverPid < b.serverPid;
98     };
99 
getThreadUsageTableEntry100     std::string getThreadUsage() const {
101         if (threadCount == 0) {
102             return "N/A";
103         }
104 
105         return std::to_string(threadUsage) + "/" + std::to_string(threadCount);
106     }
107 
108     std::string isReleased() const;
109 
110     std::string getVintfInfo() const;
111 
112     std::string getField(TableColumnType type) const;
113 
114     bool operator==(const TableEntry& other) const;
115     std::string to_string() const;
116 };
117 
118 using SelectedColumns = std::vector<TableColumnType>;
119 
120 class Table {
121 public:
122     using Entries = std::vector<TableEntry>;
123 
begin()124     Entries::iterator begin() { return mEntries.begin(); }
begin()125     Entries::const_iterator begin() const { return mEntries.begin(); }
end()126     Entries::iterator end() { return mEntries.end(); }
end()127     Entries::const_iterator end() const { return mEntries.end(); }
size()128     size_t size() const { return mEntries.size(); }
129 
add(TableEntry && entry)130     void add(TableEntry&& entry) { mEntries.push_back(std::move(entry)); }
131 
setSelectedColumns(const SelectedColumns & s)132     void setSelectedColumns(const SelectedColumns& s) { mSelectedColumns = s; }
getSelectedColumns()133     const SelectedColumns& getSelectedColumns() const { return mSelectedColumns; }
134 
setDescription(std::string && d)135     void setDescription(std::string&& d) { mDescription = std::move(d); }
136 
137     // Write table content.
138     TextTable createTextTable(bool neat = true,
139         const std::function<std::string(const std::string&)>& emitDebugInfo = nullptr) const;
140 
141 private:
142     std::string mDescription;
143     Entries mEntries;
144     SelectedColumns mSelectedColumns;
145 };
146 
147 using TableEntryCompare = std::function<bool(const TableEntry &, const TableEntry &)>;
148 
149 class MergedTable {
150 public:
MergedTable(std::vector<const Table * > && tables)151     explicit MergedTable(std::vector<const Table*>&& tables) : mTables(std::move(tables)) {}
152     TextTable createTextTable();
153 private:
154     std::vector<const Table*> mTables;
155 };
156 
157 }  // namespace lshal
158 }  // namespace android
159