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