1 /*
2 * Copyright (C) 2021 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 #include <aidl/android/frameworks/stats/IStats.h>
17 #include <android/binder_manager.h>
18 #include <getopt.h>
19 #include <statslog.h>
20
21 #include <iostream>
22
23 using namespace aidl::android::frameworks::stats;
24
expect_message(int32_t action)25 void expect_message(int32_t action) {
26 std::cout << "expect the following log in logcat:\n";
27 std::cout << "statsd.*(" << action << ")0x10000->\n";
28 }
29
show_help()30 void show_help() {
31 std::cout << "AIDL Stats HAL client\n";
32 std::cout << " arguments:\n";
33 std::cout << " -h or --help - shows help information\n";
34 std::cout << " -v or --VendorAtom - tests report reportVendorAtom API\n";
35 std::cout << "Please enable statsd logging using 'cmd stats print-logs'";
36 std::cout << "\n\n you can use multiple arguments to trigger multiple events.\n";
37 }
38
buildVendorAtom()39 VendorAtom buildVendorAtom() {
40 std::vector<VendorAtomValue> values;
41 VendorAtomValue tmp;
42 tmp.set<VendorAtomValue::longValue>(70000);
43 values.push_back(tmp);
44 tmp.set<VendorAtomValue::intValue>(7);
45 values.push_back(tmp);
46 tmp.set<VendorAtomValue::floatValue>(8.5);
47 values.push_back(tmp);
48 tmp.set<VendorAtomValue::stringValue>("test");
49 values.push_back(tmp);
50 tmp.set<VendorAtomValue::intValue>(3);
51 values.push_back(tmp);
52 tmp.set<VendorAtomValue::boolValue>(true);
53 values.push_back(tmp);
54 tmp.set<VendorAtomValue::boolValue>(false);
55 values.push_back(tmp);
56 std::vector<int> emptyRepeatedIntValue = {};
57 tmp.set<VendorAtomValue::repeatedIntValue>(emptyRepeatedIntValue);
58 values.push_back(tmp);
59 std::vector<int> repeatedIntValue = {3, 1, 2};
60 tmp.set<VendorAtomValue::repeatedIntValue>(repeatedIntValue);
61 values.push_back(tmp);
62 std::vector<int64_t> repeatedLongValue = {500000, 430000, 1000001};
63 tmp.set<VendorAtomValue::repeatedLongValue>(repeatedLongValue);
64 values.push_back(tmp);
65 std::vector<float> repeatedFloatValue = {1.5, 2.3, 7.9};
66 tmp.set<VendorAtomValue::repeatedFloatValue>(repeatedFloatValue);
67 values.push_back(tmp);
68 std::vector<std::optional<std::string>> repeatedStringValue = {"str1", "str2", "str3"};
69 tmp.set<VendorAtomValue::repeatedStringValue>(repeatedStringValue);
70 values.push_back(tmp);
71 std::vector<bool> repeatedBoolValue = {true, false, true};
72 tmp.set<VendorAtomValue::repeatedBoolValue>(repeatedBoolValue);
73 values.push_back(tmp);
74 std::vector<uint8_t> byteArrayValue = {21, 50, 3};
75 tmp.set<VendorAtomValue::byteArrayValue>(byteArrayValue);
76 values.push_back(tmp);
77
78 VendorAtom atom = {
79 .atomId = 104999,
80 .values = values,
81 };
82
83 return atom;
84 }
85
buildVendorAtomWithAnnotations()86 VendorAtom buildVendorAtomWithAnnotations() {
87 // example of atom level annotation for VendorAtom from buildVendorAtom() API
88 Annotation atomAnnotation{AnnotationId::TRUNCATE_TIMESTAMP, true};
89 std::vector<std::optional<Annotation>> atomAnnotations;
90 atomAnnotations.push_back(std::make_optional<Annotation>(atomAnnotation));
91
92 // values annotation
93 std::vector<std::optional<AnnotationSet>> valuesAnnotations;
94 {
95 AnnotationSet valueAnnotationSet;
96 valueAnnotationSet.valueIndex = 0;
97 valueAnnotationSet.annotations.push_back(Annotation{AnnotationId::PRIMARY_FIELD, true});
98 valuesAnnotations.push_back(std::make_optional<AnnotationSet>(valueAnnotationSet));
99 }
100 {
101 AnnotationSet valueAnnotationSet;
102 valueAnnotationSet.valueIndex = 1;
103 valueAnnotationSet.annotations.push_back(Annotation{AnnotationId::IS_UID, true});
104 valuesAnnotations.push_back(std::make_optional<AnnotationSet>(valueAnnotationSet));
105 }
106 {
107 AnnotationSet valueAnnotationSet;
108 valueAnnotationSet.valueIndex = 4;
109 valueAnnotationSet.annotations.push_back(Annotation{AnnotationId::EXCLUSIVE_STATE, true});
110 valueAnnotationSet.annotations.push_back(Annotation{AnnotationId::STATE_NESTED, true});
111 valueAnnotationSet.annotations.push_back(Annotation{AnnotationId::TRIGGER_STATE_RESET, 0});
112 valuesAnnotations.push_back(std::make_optional<AnnotationSet>(valueAnnotationSet));
113 }
114
115 VendorAtom atom = buildVendorAtom();
116 atom.atomAnnotations =
117 std::make_optional<std::vector<std::optional<Annotation>>>(atomAnnotations);
118 atom.valuesAnnotations =
119 std::make_optional<std::vector<std::optional<AnnotationSet>>>(valuesAnnotations);
120 return atom;
121 }
122
main(int argc,char * argv[])123 int main(int argc, char* argv[]) {
124 // get instance of the aidl version
125 const std::string instance = std::string() + IStats::descriptor + "/default";
126 std::shared_ptr<IStats> service =
127 IStats::fromBinder(ndk::SpAIBinder(AServiceManager_getService(instance.c_str())));
128 if (!service) {
129 std::cerr << "No Stats aidl HAL";
130 return 1;
131 }
132
133 std::cout << "Service instance obtained : " << instance << std::endl;
134
135 static struct option opts[] = {
136 {"VendorAtom", no_argument, 0, 'v'},
137 {"help", no_argument, 0, 'h'},
138 };
139
140 int c;
141 int hal_calls = 0;
142 int failed_calls = 0;
143 while ((c = getopt_long(argc, argv, "vh", opts, nullptr)) != -1) {
144 switch (c) {
145 case 'h': {
146 show_help();
147 break;
148 }
149 case 'v': {
150 // TODO: fill the vector and run through the vector
151 VendorAtom sampleAtom = buildVendorAtom();
152 ndk::ScopedAStatus ret = service->reportVendorAtom(sampleAtom);
153 if (!ret.isOk()) {
154 std::cerr << "reportVendorAtom failed: " << ret.getServiceSpecificError()
155 << ". Message: " << ret.getMessage() << std::endl;
156 ++failed_calls;
157 }
158 ++hal_calls;
159 VendorAtom sampleAtomWithAnnotations = buildVendorAtomWithAnnotations();
160 ret = service->reportVendorAtom(sampleAtomWithAnnotations);
161 if (!ret.isOk()) {
162 std::cerr << "reportVendorAtom failed: " << ret.getServiceSpecificError()
163 << ". Message: " << ret.getMessage() << std::endl;
164 ++failed_calls;
165 }
166 ++hal_calls;
167 break;
168 }
169 default: {
170 show_help();
171 return 1;
172 }
173 }
174 }
175
176 if (hal_calls > 0) {
177 std::cout << hal_calls << " HAL methods called.\n";
178 std::cout << "try: logcat | grep \"statsd.*0x1000\"\n";
179 }
180
181 return failed_calls;
182 }
183