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