1 /*
2  * Copyright (C) 2019 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 <android/frameworks/stats/1.0/IStats.h>
17 
18 #include <statslog.h>
19 #include <utils/StrongPointer.h>
20 
21 #include <getopt.h>
22 #include <iostream>
23 
24 using android::frameworks::stats::V1_0::BatteryCausedShutdown;
25 using android::frameworks::stats::V1_0::BatteryHealthSnapshotArgs;
26 using android::frameworks::stats::V1_0::ChargeCycles;
27 using android::frameworks::stats::V1_0::HardwareFailed;
28 using android::frameworks::stats::V1_0::IStats;
29 using android::frameworks::stats::V1_0::PhysicalDropDetected;
30 using android::frameworks::stats::V1_0::SlowIo;
31 using android::frameworks::stats::V1_0::SpeakerImpedance;
32 using android::frameworks::stats::V1_0::SpeechDspStat;
33 using android::frameworks::stats::V1_0::UsbPortOverheatEvent;
34 using android::frameworks::stats::V1_0::VendorAtom;
35 using Value = android::frameworks::stats::V1_0::VendorAtom::Value;
36 
expect_message(int32_t action)37 void expect_message(int32_t action) {
38     std::cout << "expect the following log in logcat:\n";
39     std::cout << "statsd.*(" << action << ")0x10000->\n";
40 }
41 
show_help()42 void show_help() {
43     std::cout << "Stats HAL client\n";
44     std::cout << " arguments:\n";
45     std::cout << " -h or --help - shows help information\n";
46     std::cout << " -S or --SpeakerImpedance\n";
47     std::cout << " -f or --HardwareFailed\n";
48     std::cout << " -p or --PhysicalDropDetected\n";
49     std::cout << " -y or --ChargeCycles\n";
50     std::cout << " -n or --BatteryHealthSnapshot\n";
51     std::cout << " -i or --SlowIo\n";
52     std::cout << " -s or --BatteryCausedShutdown\n";
53     std::cout << " -u or --UsbPortOverheatEvent\n";
54     std::cout << " -d or --SpeechDspStat\n";
55     std::cout << " -v or --VendorAtom\n";
56     std::cout << "Please enable statsd logging using 'cmd stats print-logs'";
57     std::cout << "\n\n you can use multiple arguments to trigger multiple events.\n";
58 }
59 
main(int argc,char * argv[])60 int main(int argc, char* argv[]) {
61     android::sp<IStats> client = IStats::tryGetService();
62     if (!client) {
63         std::cerr << "No Stats HAL";
64         return 1;
65     }
66 
67     static struct option opts[] = {
68         {"SpeakerImpedance", no_argument, 0, 'S'},
69         {"HardwareFailed", no_argument, 0, 'f'},
70         {"PhysicalDropDetected", no_argument, 0, 'p'},
71         {"ChargeCycles", no_argument, 0, 'y'},
72         {"BatteryHealthSnapshot", no_argument, 0, 'n'},
73         {"SlowIo", no_argument, 0, 'i'},
74         {"BatteryCausedShutdown", no_argument, 0, 's'},
75         {"UsbPortOverheatEvent", no_argument, 0, 'u'},
76         {"SpeechDspStat", no_argument, 0, 'd'},
77         {"VendorAtom", no_argument, 0, 'v'},
78         {"help", no_argument, 0, 'h'},
79     };
80 
81     int c;
82     int hal_calls = 0;
83     while ((c = getopt_long(argc, argv, "hSfpynisudv", opts, nullptr)) != -1) {
84         switch (c) {
85             case 'h': {
86                 show_help();
87                 break;
88             }
89             case 'S': {
90                 SpeakerImpedance left_obj = {.speakerLocation = 0,
91                                              .milliOhms = static_cast<int32_t>(1234 * 1000)};
92                 client->reportSpeakerImpedance(left_obj);
93                 expect_message(android::util::SPEAKER_IMPEDANCE_REPORTED);
94                 ++hal_calls;
95                 break;
96             }
97             case 'f': {
98                 HardwareFailed failed = {.hardwareType = HardwareFailed::HardwareType::CODEC,
99                                          .hardwareLocation = 0,
100                                          .errorCode = HardwareFailed::HardwareErrorCode::COMPLETE};
101                 client->reportHardwareFailed(failed);
102                 expect_message(android::util::HARDWARE_FAILED);
103                 ++hal_calls;
104                 break;
105             }
106             case 'p': {
107                 PhysicalDropDetected drop{
108                     .confidencePctg = 75, .accelPeak = 250, .freefallDuration = 1234};
109                 client->reportPhysicalDropDetected(drop);
110                 expect_message(android::util::PHYSICAL_DROP_DETECTED);
111                 ++hal_calls;
112                 break;
113             }
114             case 'y': {
115                 std::vector<int> charge_cycles = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
116                 ChargeCycles cycles;
117                 cycles.cycleBucket = charge_cycles;
118                 client->reportChargeCycles(cycles);
119                 expect_message(android::util::CHARGE_CYCLES_REPORTED);
120                 ++hal_calls;
121                 break;
122             }
123             case 'n': {
124                 BatteryHealthSnapshotArgs args{.temperatureDeciC = 3000,
125                                                .voltageMicroV = 1,
126                                                .currentMicroA = 2,
127                                                .openCircuitVoltageMicroV = 3,
128                                                .resistanceMicroOhm = 5,
129                                                .levelPercent = 101};
130                 client->reportBatteryHealthSnapshot(args);
131                 expect_message(android::util::BATTERY_HEALTH_SNAPSHOT);
132                 ++hal_calls;
133                 break;
134             }
135             case 'i': {
136                 SlowIo slowio = {.operation = SlowIo::IoOperation::READ, .count = 5};
137                 client->reportSlowIo(slowio);
138                 expect_message(android::util::SLOW_IO);
139                 ++hal_calls;
140                 break;
141             }
142             case 's': {
143                 BatteryCausedShutdown shutdown = {.voltageMicroV = 3};
144                 client->reportBatteryCausedShutdown(shutdown);
145                 expect_message(android::util::BATTERY_CAUSED_SHUTDOWN);
146                 ++hal_calls;
147                 break;
148             }
149             case 'u': {
150                 UsbPortOverheatEvent event = {.plugTemperatureDeciC = 210,
151                                               .maxTemperatureDeciC = 220,
152                                               .timeToOverheat = 1,
153                                               .timeToHysteresis = 2,
154                                               .timeToInactive = 3};
155                 client->reportUsbPortOverheatEvent(event);
156                 expect_message(android::util::USB_PORT_OVERHEAT_EVENT_REPORTED);
157                 ++hal_calls;
158                 break;
159             }
160             case 'd': {
161                 SpeechDspStat speech{.totalUptimeMillis = 1234,
162                                      .totalDowntimeMillis = 4321,
163                                      .totalCrashCount = 42,
164                                      .totalRecoverCount = 99};
165                 client->reportSpeechDspStat(speech);
166                 expect_message(android::util::SPEECH_DSP_STAT_REPORTED);
167                 ++hal_calls;
168                 break;
169             }
170             case 'v': {
171                 std::vector<Value> values;
172                 Value tmp;
173                 tmp.longValue(70000);
174                 values.push_back(tmp);
175                 tmp.intValue(7);
176                 values.push_back(tmp);
177                 tmp.floatValue(8.5);
178                 values.push_back(tmp);
179                 tmp.stringValue("test");
180                 values.push_back(tmp);
181                 tmp.intValue(3);
182                 values.push_back(tmp);
183                 VendorAtom atom = {
184                     .reverseDomainName = "", .atomId = 100001, .values = values};
185                 client->reportVendorAtom(atom);
186                 ++hal_calls;
187                 break;
188             }
189             default: {
190                 show_help();
191                 return 1;
192             }
193         }
194     }
195 
196     if (hal_calls > 0) {
197         std::cout << hal_calls << " HAL methods called.\n";
198         std::cout << "try: logcat | grep \"statsd.*0x1000\"\n";
199     }
200     return 0;
201 }
202