• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 #include <cinttypes>
18 #include <android/binder_manager.h>
19 #include <android-base/file.h>
20 #include <pixelstats/StatsHelper.h>
21 
22 #define LOG_TAG "pixelstats-vendor"
23 
24 #include <utils/Log.h>
25 
26 namespace android {
27 namespace hardware {
28 namespace google {
29 namespace pixel {
30 
31 using aidl::android::frameworks::stats::VendorAtom;
32 using aidl::android::frameworks::stats::VendorAtomValue;
33 using android::base::ReadFileToString;
34 
35 // Proto messages are 1-indexed and VendorAtom field numbers start at 2, so
36 // store everything in the values array at the index of the field number
37 // -2.
38 const int kVendorAtomOffset = 2;
39 
fileExists(const std::string & path)40 bool fileExists(const std::string &path) {
41     struct stat sb;
42 
43     return stat(path.c_str(), &sb) == 0;
44 }
45 
getStatsService()46 std::shared_ptr<IStats> getStatsService() {
47     const std::string instance = std::string() + IStats::descriptor + "/default";
48     static bool isStatsDeclared = false;
49     if (!isStatsDeclared) {
50         // It is good to cache the result - it would not be changed
51         isStatsDeclared = AServiceManager_isDeclared(instance.c_str());
52         if (!isStatsDeclared) {
53             ALOGE("Stats service is not registered.");
54             return nullptr;
55         }
56     }
57     return IStats::fromBinder(ndk::SpAIBinder(AServiceManager_waitForService(instance.c_str())));
58 }
59 
reportSpeakerImpedance(const std::shared_ptr<IStats> & stats_client,const PixelAtoms::VendorSpeakerImpedance & speakerImpedance)60 void reportSpeakerImpedance(const std::shared_ptr<IStats> &stats_client,
61                             const PixelAtoms::VendorSpeakerImpedance &speakerImpedance) {
62     // Load values array
63     std::vector<VendorAtomValue> values(2);
64     VendorAtomValue tmp;
65     tmp.set<VendorAtomValue::intValue>(speakerImpedance.speaker_location());
66     values[0] = tmp;
67     tmp.set<VendorAtomValue::intValue>(speakerImpedance.impedance());
68     values[1] = tmp;
69 
70     // Send vendor atom to IStats HAL
71     VendorAtom event = {.reverseDomainName = "",
72                         .atomId = PixelAtoms::Atom::kVendorSpeakerImpedance,
73                         .values = std::move(values)};
74     const ndk::ScopedAStatus ret = stats_client->reportVendorAtom(event);
75     if (!ret.isOk())
76         ALOGE("Unable to report VendorSpeakerImpedance to Stats service");
77 }
78 
reportSpeakerHealthStat(const std::shared_ptr<IStats> & stats_client,const PixelAtoms::VendorSpeakerStatsReported & speakerHealthStat)79 void reportSpeakerHealthStat(const std::shared_ptr<IStats> &stats_client,
80                              const PixelAtoms::VendorSpeakerStatsReported &speakerHealthStat) {
81     // Load values array
82     std::vector<VendorAtomValue> values(5);
83     VendorAtomValue tmp;
84     tmp.set<VendorAtomValue::intValue>(speakerHealthStat.speaker_location());
85     values[0] = tmp;
86     tmp.set<VendorAtomValue::intValue>(speakerHealthStat.impedance());
87     values[1] = tmp;
88     tmp.set<VendorAtomValue::intValue>(speakerHealthStat.max_temperature());
89     values[2] = tmp;
90     tmp.set<VendorAtomValue::intValue>(speakerHealthStat.excursion());
91     values[3] = tmp;
92     tmp.set<VendorAtomValue::intValue>(speakerHealthStat.heartbeat());
93     values[4] = tmp;
94 
95     // Send vendor atom to IStats HAL
96     VendorAtom event = {.reverseDomainName = "",
97                         .atomId = PixelAtoms::Atom::kVendorSpeakerStatsReported,
98                         .values = std::move(values)};
99     const ndk::ScopedAStatus ret = stats_client->reportVendorAtom(event);
100     if (!ret.isOk())
101         ALOGE("Unable to report VendorSpeakerStatsReported to Stats service");
102 }
103 
reportSlowIo(const std::shared_ptr<IStats> & stats_client,const PixelAtoms::VendorSlowIo & slowIo)104 void reportSlowIo(const std::shared_ptr<IStats> &stats_client,
105                   const PixelAtoms::VendorSlowIo &slowIo) {
106     // Load values array
107     std::vector<VendorAtomValue> values(2);
108     VendorAtomValue tmp;
109     tmp.set<VendorAtomValue::intValue>(slowIo.operation());
110     values[0] = tmp;
111     tmp.set<VendorAtomValue::intValue>(slowIo.count());
112     values[1] = tmp;
113 
114     // Send vendor atom to IStats HAL
115     VendorAtom event = {.reverseDomainName = "",
116                         .atomId = PixelAtoms::Atom::kVendorSlowIo,
117                         .values = std::move(values)};
118     const ndk::ScopedAStatus ret = stats_client->reportVendorAtom(event);
119     if (!ret.isOk())
120         ALOGE("Unable to report VendorSlowIo to Stats service");
121 }
122 
reportChargeCycles(const std::shared_ptr<IStats> & stats_client,const std::vector<int32_t> & chargeCycles)123 void reportChargeCycles(const std::shared_ptr<IStats> &stats_client,
124                         const std::vector<int32_t> &chargeCycles) {
125     // Load values array
126     const int32_t kChargeCyclesBucketsCount =
127             PixelAtoms::VendorChargeCycles::kCycleBucket10FieldNumber - kVendorAtomOffset + 1;
128     std::vector<VendorAtomValue> values(kChargeCyclesBucketsCount);
129     VendorAtomValue tmp;
130     for (int32_t bucketIdx = 0; bucketIdx < kChargeCyclesBucketsCount; ++bucketIdx) {
131         tmp.set<VendorAtomValue::intValue>(chargeCycles[bucketIdx]);
132         values[bucketIdx] = tmp;
133     }
134 
135     // Send vendor atom to IStats HAL
136     VendorAtom event = {.reverseDomainName = "",
137                         .atomId = PixelAtoms::Atom::kVendorChargeCycles,
138                         .values = std::move(values)};
139     const ndk::ScopedAStatus ret = stats_client->reportVendorAtom(event);
140     if (!ret.isOk())
141         ALOGE("Unable to report VendorChargeCycles to Stats service");
142 }
143 
reportHardwareFailed(const std::shared_ptr<IStats> & stats_client,const PixelAtoms::VendorHardwareFailed & failure)144 void reportHardwareFailed(const std::shared_ptr<IStats> &stats_client,
145                           const PixelAtoms::VendorHardwareFailed &failure) {
146     // Load values array
147     std::vector<VendorAtomValue> values(3);
148     VendorAtomValue tmp;
149     tmp.set<VendorAtomValue::intValue>(failure.hardware_type());
150     values[0] = tmp;
151     tmp.set<VendorAtomValue::intValue>(failure.hardware_location());
152     values[1] = tmp;
153     tmp.set<VendorAtomValue::intValue>(failure.failure_code());
154     values[2] = tmp;
155 
156     // Send vendor atom to IStats HAL
157     VendorAtom event = {.reverseDomainName = "",
158                         .atomId = PixelAtoms::Atom::kVendorHardwareFailed,
159                         .values = std::move(values)};
160     const ndk::ScopedAStatus ret = stats_client->reportVendorAtom(event);
161     if (!ret.isOk())
162         ALOGE("Unable to report VendorHardwareFailed to Stats service");
163 }
164 
reportSpeechDspStat(const std::shared_ptr<IStats> & stats_client,const PixelAtoms::VendorSpeechDspStat & dsp_stats)165 void reportSpeechDspStat(const std::shared_ptr<IStats> &stats_client,
166                          const PixelAtoms::VendorSpeechDspStat &dsp_stats) {
167     // Load values array
168     std::vector<VendorAtomValue> values(4);
169     VendorAtomValue tmp;
170     tmp.set<VendorAtomValue::intValue>(dsp_stats.total_uptime_millis());
171     values[0] = tmp;
172     tmp.set<VendorAtomValue::intValue>(dsp_stats.total_downtime_millis());
173     values[1] = tmp;
174     tmp.set<VendorAtomValue::intValue>(dsp_stats.total_crash_count());
175     values[2] = tmp;
176     tmp.set<VendorAtomValue::intValue>(dsp_stats.total_recover_count());
177     values[3] = tmp;
178 
179     // Send vendor atom to IStats HAL
180     VendorAtom event = {.reverseDomainName = "",
181                         .atomId = PixelAtoms::Atom::kVendorSpeechDspStat,
182                         .values = std::move(values)};
183     const ndk::ScopedAStatus ret = stats_client->reportVendorAtom(event);
184     if (!ret.isOk())
185         ALOGE("Unable to report VendorSpeechDspStat to Stats service");
186 }
187 
reportUsbPortOverheat(const std::shared_ptr<IStats> & stats_client,const PixelAtoms::VendorUsbPortOverheat & overheat_info)188 void reportUsbPortOverheat(const std::shared_ptr<IStats> &stats_client,
189                            const PixelAtoms::VendorUsbPortOverheat &overheat_info) {
190     // Load values array
191     std::vector<VendorAtomValue> values(5);
192     VendorAtomValue tmp;
193     tmp.set<VendorAtomValue::intValue>(overheat_info.plug_temperature_deci_c());
194     values[0] = tmp;
195     tmp.set<VendorAtomValue::intValue>(overheat_info.max_temperature_deci_c());
196     values[1] = tmp;
197     tmp.set<VendorAtomValue::intValue>(overheat_info.time_to_overheat_secs());
198     values[2] = tmp;
199     tmp.set<VendorAtomValue::intValue>(overheat_info.time_to_hysteresis_secs());
200     values[3] = tmp;
201     tmp.set<VendorAtomValue::intValue>(overheat_info.time_to_inactive_secs());
202     values[4] = tmp;
203 
204     // Send vendor atom to IStats HAL
205     VendorAtom event = {.reverseDomainName = "",
206                         .atomId = PixelAtoms::Atom::kVendorUsbPortOverheat,
207                         .values = std::move(values)};
208     const ndk::ScopedAStatus ret = stats_client->reportVendorAtom(event);
209     if (!ret.isOk())
210         ALOGE("Unable to report VendorUsbPortOverheat to Stats service");
211 }
212 
reportUsbDataSessionEvent(const std::shared_ptr<IStats> & stats_client,const PixelAtoms::VendorUsbDataSessionEvent & usb_data_event)213 void reportUsbDataSessionEvent(const std::shared_ptr<IStats> &stats_client,
214                                const PixelAtoms::VendorUsbDataSessionEvent &usb_data_event) {
215     // Load values array
216     std::vector<VendorAtomValue> values(4);
217     VendorAtomValue tmp;
218     tmp.set<VendorAtomValue::intValue>(usb_data_event.usb_role());
219     values[0] = tmp;
220     tmp.set<VendorAtomValue::repeatedIntValue>(std::vector<int32_t>(
221             usb_data_event.usb_states().begin(), usb_data_event.usb_states().end()));
222     values[1] = tmp;
223     tmp.set<VendorAtomValue::repeatedLongValue>(std::vector<int64_t>(
224             usb_data_event.elapsed_time_ms().begin(), usb_data_event.elapsed_time_ms().end()));
225     values[2] = tmp;
226     tmp.set<VendorAtomValue::longValue>(usb_data_event.duration_ms());
227     values[3] = tmp;
228 
229     // Send vendor atom to IStats HAL
230     VendorAtom event = {.reverseDomainName = "",
231                         .atomId = PixelAtoms::Atom::kVendorUsbDataSessionEvent,
232                         .values = std::move(values)};
233     const ndk::ScopedAStatus ret = stats_client->reportVendorAtom(event);
234     if (!ret.isOk())
235         ALOGE("Unable to report VendorUsbDataSessionEvent to Stats service");
236 }
237 
readLogbuffer(const std::string & buf_path,int num_fields,uint16_t code,enum ReportEventFormat format,unsigned int last_check_time,std::vector<std::vector<uint16_t>> & events)238 void readLogbuffer(const std::string &buf_path, int num_fields, uint16_t code,
239                    enum ReportEventFormat format, unsigned int last_check_time,
240                    std::vector<std::vector<uint16_t>> &events) {
241     char hex_str[16];
242 
243     snprintf(hex_str, sizeof(hex_str), "0x%X", code);
244 
245     return readLogbuffer(buf_path, num_fields, hex_str, format, last_check_time, events);
246 }
247 
readLogbuffer(const std::string & buf_path,int num_fields,const char * code,enum ReportEventFormat format,unsigned int last_check_time,std::vector<std::vector<uint16_t>> & events)248 void readLogbuffer(const std::string &buf_path, int num_fields, const char *code,
249                    enum ReportEventFormat format, unsigned int last_check_time,
250                    std::vector<std::vector<uint16_t>> &events) {
251     std::istringstream ss;
252     std::string file_contents, line;
253     int num, field_idx, pos, read;
254     unsigned int ts, reported = 0;
255     uint16_t addr, val;
256     char type[16];
257     std::vector<uint16_t> vect(num_fields);
258 
259     if (!ReadFileToString(buf_path, &file_contents)) {
260         ALOGE("Unable to read logbuffer path: %s - %s", buf_path.c_str(), strerror(errno));
261         return;
262     }
263 
264     ss.str(file_contents);
265     while (getline(ss, line)) {
266         num = sscanf(line.c_str(), "[%u.%*u] %15s%n", &ts, type, &pos);
267         if (num != 2 || strncmp(type, code, strlen(code)))
268             continue;
269 
270         if (ts <= last_check_time) {
271             reported++;
272             continue;
273         }
274 
275         for (field_idx = 0; field_idx < num_fields; field_idx++, pos += read) {
276             if (format == FormatAddrWithVal) {
277                 num = sscanf(&line.c_str()[pos], " %2" SCNx16 ":%4" SCNx16 "%n", &addr, &val,
278                              &read);
279                 if (num != 2 || (num_fields - field_idx < 2))
280                     break;
281                 vect[field_idx++] = addr;
282                 vect[field_idx] = val;
283             } else if (format == FormatIgnoreAddr) {
284                 num = sscanf(&line.c_str()[pos], " %*2" SCNx16 ":%4" SCNx16 "%n", &val, &read);
285                 if (num != 1)
286                     break;
287                 vect[field_idx] = val;
288             } else if (format == FormatNoAddr) {
289                  num = sscanf(&line.c_str()[pos], " %4" SCNx16 "%n", &val, &read);
290                 if (num != 1)
291                     break;
292                 vect[field_idx] = val;
293             } else {
294                 break;
295             }
296         }
297 
298         if (field_idx == num_fields)
299             events.push_back(vect);
300     }
301     if (events.size() > 0 || reported > 0)
302         ALOGD("%s: new:%zu, reported:%d", code, events.size(), reported);
303 
304     return;
305 }
306 
307 }  // namespace pixel
308 }  // namespace google
309 }  // namespace hardware
310 }  // namespace android
311