• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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 #define LOG_TAG "pixelstats: DisplayStats"
18 
19 #include <aidl/android/frameworks/stats/IStats.h>
20 #include <android-base/file.h>
21 #include <android-base/parseint.h>
22 #include <android-base/properties.h>
23 #include <android-base/stringprintf.h>
24 #include <android-base/strings.h>
25 #include <android/binder_manager.h>
26 #include <hardware/google/pixel/pixelstats/pixelatoms.pb.h>
27 #include <pixelstats/DisplayStatsReporter.h>
28 #include <utils/Log.h>
29 
30 #include <cinttypes>
31 
32 namespace android {
33 namespace hardware {
34 namespace google {
35 namespace pixel {
36 
37 using aidl::android::frameworks::stats::IStats;
38 using aidl::android::frameworks::stats::VendorAtom;
39 using aidl::android::frameworks::stats::VendorAtomValue;
40 using android::base::ReadFileToString;
41 using android::hardware::google::pixel::PixelAtoms::DisplayPanelErrorStats;
42 
DisplayStatsReporter()43 DisplayStatsReporter::DisplayStatsReporter() {}
44 
readDisplayErrorCount(const std::string & path,int64_t * val)45 bool DisplayStatsReporter::readDisplayErrorCount(const std::string &path, int64_t *val) {
46     std::string file_contents;
47 
48     if (path.empty()) {
49         return false;
50     }
51 
52     if (!ReadFileToString(path.c_str(), &file_contents)) {
53         if (errno != ENOENT) {
54             ALOGD("readDisplayErrorCount Unable to read %s - %s", path.c_str(), strerror(errno));
55         }
56         return false;
57     } else {
58         file_contents = android::base::Trim(file_contents);
59         if (!android::base::ParseInt(file_contents, val)) {
60             return false;
61         }
62     }
63 
64     return true;
65 }
66 
verifyCount(int val,bool * report_stats)67 int DisplayStatsReporter::verifyCount(int val, bool *report_stats) {
68     if (val < 0) {
69         ALOGE("Invalid display stats value(%d)", val);
70         return -EINVAL;
71     } else {
72         *report_stats |= (val != 0);
73     }
74 
75     return 0;
76 }
77 
captureDisplayPanelErrorStats(const std::vector<std::string> & display_stats_paths,struct DisplayPanelErrorStats * pcur_data)78 bool DisplayStatsReporter::captureDisplayPanelErrorStats(
79         const std::vector<std::string> &display_stats_paths,
80         struct DisplayPanelErrorStats *pcur_data) {
81     bool report_stats = false;
82     std::string path;
83 
84     if (display_stats_paths.size() < kNumOfDisplayPanelErrorStats) {
85         ALOGE("Number of display stats paths (%zu) is less than expected (%d)",
86               display_stats_paths.size(), kNumOfDisplayPanelErrorStats);
87         return false;
88     }
89 
90     int64_t index = PixelAtoms::DisplayPanelErrorStats::kPrimaryErrorCountTeFieldNumber;
91     index = index - kVendorAtomOffset;
92     path = display_stats_paths[index];
93 
94     // Read primary panel error stats.
95     if (!readDisplayErrorCount(path, &(pcur_data->primary_error_count_te))) {
96         pcur_data->primary_error_count_te = prev_panel_data_.primary_error_count_te;
97     } else {
98         report_stats |=
99                 (pcur_data->primary_error_count_te > prev_panel_data_.primary_error_count_te);
100     }
101 
102     index = PixelAtoms::DisplayPanelErrorStats::kPrimaryErrorCountUnknownFieldNumber;
103     index = index - kVendorAtomOffset;
104     path = display_stats_paths[index];
105     if (!readDisplayErrorCount(path, &(pcur_data->primary_error_count_unknown))) {
106         pcur_data->primary_error_count_unknown = prev_panel_data_.primary_error_count_unknown;
107     } else {
108         report_stats |= (pcur_data->primary_error_count_unknown >
109                          prev_panel_data_.primary_error_count_unknown);
110     }
111 
112     // Read secondary panel error stats.
113     index = PixelAtoms::DisplayPanelErrorStats::kSecondaryErrorCountTeFieldNumber;
114     index = index - kVendorAtomOffset;
115     path = display_stats_paths[index];
116     if (!readDisplayErrorCount(path, &(pcur_data->secondary_error_count_te))) {
117         pcur_data->secondary_error_count_te = prev_panel_data_.secondary_error_count_te;
118     } else {
119         report_stats |=
120                 (pcur_data->secondary_error_count_te > prev_panel_data_.secondary_error_count_te);
121     }
122 
123     index = PixelAtoms::DisplayPanelErrorStats::kSecondaryErrorCountUnknownFieldNumber;
124     index = index - kVendorAtomOffset;
125     path = display_stats_paths[index];
126     if (!readDisplayErrorCount(path, &(pcur_data->secondary_error_count_unknown))) {
127         pcur_data->secondary_error_count_unknown = prev_panel_data_.secondary_error_count_unknown;
128     } else {
129         report_stats |= (pcur_data->secondary_error_count_unknown >
130                          prev_panel_data_.secondary_error_count_unknown);
131     }
132 
133     return report_stats;
134 }
135 
logDisplayPanelErrorStats(const std::shared_ptr<IStats> & stats_client,const std::vector<std::string> & display_stats_paths)136 void DisplayStatsReporter::logDisplayPanelErrorStats(
137         const std::shared_ptr<IStats> &stats_client,
138         const std::vector<std::string> &display_stats_paths) {
139     struct DisplayPanelErrorStats cur_data = prev_panel_data_;
140     bool report_stats = false;
141 
142     if (!captureDisplayPanelErrorStats(display_stats_paths, &cur_data)) {
143         prev_panel_data_ = cur_data;
144         return;
145     }
146 
147     VendorAtomValue tmp;
148     int64_t max_error_count = static_cast<int64_t>(INT32_MAX);
149     int error_count;
150     std::vector<VendorAtomValue> values(kNumOfDisplayPanelErrorStats);
151 
152     error_count = std::min<int64_t>(
153             cur_data.primary_error_count_te - prev_panel_data_.primary_error_count_te,
154             max_error_count);
155     if (verifyCount(error_count, &report_stats) < 0)
156         return;
157 
158     tmp.set<VendorAtomValue::intValue>(error_count);
159     int64_t index = PixelAtoms::DisplayPanelErrorStats::kPrimaryErrorCountTeFieldNumber;
160     index = index - kVendorAtomOffset;
161     values[index] = tmp;
162 
163     error_count = std::min<int64_t>(
164             cur_data.primary_error_count_unknown - prev_panel_data_.primary_error_count_unknown,
165             max_error_count);
166     if (verifyCount(error_count, &report_stats) < 0)
167         return;
168 
169     tmp.set<VendorAtomValue::intValue>(error_count);
170     index = PixelAtoms::DisplayPanelErrorStats::kPrimaryErrorCountUnknownFieldNumber;
171     index = index - kVendorAtomOffset;
172     values[index] = tmp;
173 
174     prev_panel_data_ = cur_data;
175 
176     if (!report_stats)
177         return;
178 
179     ALOGD("Report updated display panel metrics to stats service");
180     // Send vendor atom to IStats HAL
181     VendorAtom event = {.reverseDomainName = "",
182                         .atomId = PixelAtoms::Atom::kDisplayPanelErrorStats,
183                         .values = std::move(values)};
184     const ndk::ScopedAStatus ret = stats_client->reportVendorAtom(event);
185     if (!ret.isOk())
186         ALOGE("Unable to report display Display Panel stats to Stats service");
187 }
188 
captureDisplayPortErrorStats(const std::vector<std::string> & displayport_stats_paths,int64_t * pcur_data)189 bool DisplayStatsReporter::captureDisplayPortErrorStats(
190         const std::vector<std::string> &displayport_stats_paths, int64_t *pcur_data) {
191     int64_t path_index;
192     bool report_stats = false;
193     std::string path;
194 
195     if (displayport_stats_paths.size() < DISPLAY_PORT_ERROR_STATS_SIZE)
196         return false;
197 
198     for (int i = 0; i < DISPLAY_PORT_ERROR_STATS_SIZE; i++) {
199         path_index = display_port_error_path_index[i];
200         path_index = path_index - kVendorAtomOffset;
201         path = displayport_stats_paths[path_index];
202 
203         if (!readDisplayErrorCount(path, &(pcur_data[i]))) {
204             pcur_data[i] = prev_dp_data_[i];
205         } else {
206             report_stats |= (pcur_data[i] > prev_dp_data_[i]);
207         }
208     }
209 
210     return report_stats;
211 }
212 
logDisplayPortErrorStats(const std::shared_ptr<IStats> & stats_client,const std::vector<std::string> & displayport_stats_paths)213 void DisplayStatsReporter::logDisplayPortErrorStats(
214         const std::shared_ptr<IStats> &stats_client,
215         const std::vector<std::string> &displayport_stats_paths) {
216     int64_t cur_data[DISPLAY_PORT_ERROR_STATS_SIZE];
217     int64_t path_index;
218     bool report_stats = false;
219 
220     memcpy(cur_data, prev_dp_data_, sizeof(prev_dp_data_));
221     if (!captureDisplayPortErrorStats(displayport_stats_paths, &cur_data[0])) {
222         memcpy(prev_dp_data_, cur_data, sizeof(cur_data));
223         return;
224     }
225 
226     VendorAtomValue tmp;
227     int64_t max_error_count = static_cast<int64_t>(INT32_MAX);
228     int error_count;
229     std::vector<VendorAtomValue> values(DISPLAY_PORT_ERROR_STATS_SIZE);
230 
231     for (int i = 0; i < DISPLAY_PORT_ERROR_STATS_SIZE; i++) {
232         error_count = std::min<int64_t>(cur_data[i] - prev_dp_data_[i], max_error_count);
233         if (verifyCount(error_count, &report_stats) < 0)
234             return;
235 
236         tmp.set<VendorAtomValue::intValue>(error_count);
237         path_index = display_port_error_path_index[i];
238         path_index = path_index - kVendorAtomOffset;
239         values[path_index] = tmp;
240     }
241 
242     memcpy(prev_dp_data_, cur_data, sizeof(cur_data));
243 
244     if (!report_stats)
245         return;
246 
247     ALOGD("Report updated displayport metrics to stats service");
248     // Send vendor atom to IStats HAL
249     VendorAtom event = {.reverseDomainName = "",
250                         .atomId = PixelAtoms::Atom::kDisplayPortErrorStats,
251                         .values = std::move(values)};
252     const ndk::ScopedAStatus ret = stats_client->reportVendorAtom(event);
253     if (!ret.isOk())
254         ALOGE("Unable to report DisplayPort stats to Stats service");
255 }
256 
captureHDCPAuthTypeStats(const std::vector<std::string> & hdcp_stats_paths,int64_t * pcur_data)257 bool DisplayStatsReporter::captureHDCPAuthTypeStats(
258         const std::vector<std::string> &hdcp_stats_paths, int64_t *pcur_data) {
259     int64_t path_index;
260     bool report_stats = false;
261     std::string path;
262 
263     if (hdcp_stats_paths.size() < HDCP_AUTH_TYPE_STATS_SIZE)
264         return false;
265 
266     for (int i = 0; i < HDCP_AUTH_TYPE_STATS_SIZE; i++) {
267         path_index = hdcp_auth_type_path_index[i];
268         path_index = path_index - kVendorAtomOffset;
269         path = hdcp_stats_paths[path_index];
270 
271         if (!readDisplayErrorCount(path, &(pcur_data[i]))) {
272             pcur_data[i] = prev_hdcp_data_[i];
273         } else {
274             report_stats |= (pcur_data[i] > prev_hdcp_data_[i]);
275         }
276     }
277 
278     return report_stats;
279 }
280 
logHDCPAuthTypeStats(const std::shared_ptr<IStats> & stats_client,const std::vector<std::string> & hdcp_stats_paths)281 void DisplayStatsReporter::logHDCPAuthTypeStats(const std::shared_ptr<IStats> &stats_client,
282                                                 const std::vector<std::string> &hdcp_stats_paths) {
283     int64_t cur_data[HDCP_AUTH_TYPE_STATS_SIZE];
284     int64_t path_index;
285     bool report_stats = false;
286 
287     memcpy(cur_data, prev_hdcp_data_, sizeof(prev_hdcp_data_));
288     if (!captureHDCPAuthTypeStats(hdcp_stats_paths, &cur_data[0])) {
289         memcpy(prev_hdcp_data_, cur_data, sizeof(cur_data));
290         return;
291     }
292 
293     VendorAtomValue tmp;
294     int64_t max_error_count = static_cast<int64_t>(INT32_MAX);
295     int error_count;
296     std::vector<VendorAtomValue> values(HDCP_AUTH_TYPE_STATS_SIZE);
297 
298     for (int i = 0; i < HDCP_AUTH_TYPE_STATS_SIZE; i++) {
299         error_count = std::min<int64_t>(cur_data[i] - prev_hdcp_data_[i], max_error_count);
300         if (verifyCount(error_count, &report_stats) < 0)
301             return;
302 
303         tmp.set<VendorAtomValue::intValue>(error_count);
304         path_index = hdcp_auth_type_path_index[i];
305         path_index = path_index - kVendorAtomOffset;
306         values[path_index] = tmp;
307     }
308 
309     memcpy(prev_hdcp_data_, cur_data, sizeof(cur_data));
310 
311     if (!report_stats)
312         return;
313 
314     ALOGD("Report updated hdcp metrics to stats service");
315     // Send vendor atom to IStats HAL
316     VendorAtom event = {.reverseDomainName = "",
317                         .atomId = PixelAtoms::Atom::kHdcpAuthTypeStats,
318                         .values = std::move(values)};
319     const ndk::ScopedAStatus ret = stats_client->reportVendorAtom(event);
320     if (!ret.isOk())
321         ALOGE("Unable to report hdcp stats to Stats service");
322 }
logDisplayStats(const std::shared_ptr<IStats> & stats_client,const std::vector<std::string> & display_stats_paths,const display_stats_type stats_type)323 void DisplayStatsReporter::logDisplayStats(const std::shared_ptr<IStats> &stats_client,
324                                            const std::vector<std::string> &display_stats_paths,
325                                            const display_stats_type stats_type) {
326     switch (stats_type) {
327         case DISP_PANEL_STATE:
328             logDisplayPanelErrorStats(stats_client, display_stats_paths);
329             break;
330         case DISP_PORT_STATE:
331             logDisplayPortErrorStats(stats_client, display_stats_paths);
332             break;
333         case HDCP_STATE:
334             logHDCPAuthTypeStats(stats_client, display_stats_paths);
335             break;
336         default:
337             ALOGE("Unsupport display state type(%d)", stats_type);
338     }
339 }
340 
341 }  // namespace pixel
342 }  // namespace google
343 }  // namespace hardware
344 }  // namespace android
345