xref: /aosp_15_r20/frameworks/av/services/mediametrics/statsd_codec.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
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 
17 //#define LOG_NDEBUG 0
18 #define LOG_TAG "statsd_codec"
19 #include <utils/Log.h>
20 
21 #include <dirent.h>
22 #include <inttypes.h>
23 #include <pthread.h>
24 #include <pwd.h>
25 #include <stdint.h>
26 #include <string>
27 #include <string.h>
28 #include <sys/stat.h>
29 #include <sys/time.h>
30 #include <sys/types.h>
31 #include <unistd.h>
32 
33 #include <stats_media_metrics.h>
34 #include <stats_event.h>
35 
36 #include <audio_utils/StringUtils.h>
37 #include <frameworks/proto_logging/stats/message/mediametrics_message.pb.h>
38 #include <mediametricsservice/cleaner.h>
39 #include <mediametricsservice/iface_statsd.h>
40 #include <mediametricsservice/MediaMetricsService.h>
41 #include <mediametricsservice/StringUtils.h>
42 #include <mediametricsservice/ValidateId.h>
43 
44 namespace android {
45 
46 using stats::media_metrics::stats_write;
47 using stats::media_metrics::MEDIA_CODEC_RENDERED;
48 using stats::media_metrics::MEDIA_CODEC_RENDERED__CODEC__CODEC_UNKNOWN;
49 using stats::media_metrics::MEDIA_CODEC_RENDERED__RESOLUTION__RESOLUTION_INVALID;
50 using stats::media_metrics::MEDIA_CODEC_RENDERED__RESOLUTION__RESOLUTION_ZERO;
51 using stats::media_metrics::MEDIA_CODEC_RENDERED__CONTENT_FRAMERATE__FRAMERATE_UNKNOWN;
52 using stats::media_metrics::MEDIA_CODEC_RENDERED__CONTENT_FRAMERATE__FRAMERATE_UNDETERMINED;
53 using stats::media_metrics::MEDIA_CODEC_RENDERED__CONTENT_FRAMERATE__FRAMERATE_24_3_2_PULLDOWN;
54 using stats::media_metrics::MEDIA_CODEC_RENDERED__HDR_FORMAT__HDR_FORMAT_NONE;
55 using stats::media_metrics::MEDIA_CODEC_RENDERED__HDR_FORMAT__HDR_FORMAT_HLG;
56 using stats::media_metrics::MEDIA_CODEC_RENDERED__HDR_FORMAT__HDR_FORMAT_HDR10;
57 using stats::media_metrics::MEDIA_CODEC_RENDERED__HDR_FORMAT__HDR_FORMAT_HDR10_PLUS;
58 using stats::media_metrics::MEDIA_CODEC_RENDERED__HDR_FORMAT__HDR_FORMAT_DOLBY_VISION;
59 
60 static const int BITRATE_UNKNOWN =
61         stats::media_metrics::MEDIA_CODEC_RENDERED__BITRATE__BITRATE_UNKNOWN;
62 
63 static const std::pair<char const *, int> CODEC_LOOKUP[] = {
64     { "avc", stats::media_metrics::MEDIA_CODEC_RENDERED__CODEC__CODEC_AVC },
65     { "h264", stats::media_metrics::MEDIA_CODEC_RENDERED__CODEC__CODEC_AVC },
66     { "hevc", stats::media_metrics::MEDIA_CODEC_RENDERED__CODEC__CODEC_HEVC },
67     { "h265", stats::media_metrics::MEDIA_CODEC_RENDERED__CODEC__CODEC_HEVC },
68     { "vp8", stats::media_metrics::MEDIA_CODEC_RENDERED__CODEC__CODEC_VP8 },
69     { "vp9", stats::media_metrics::MEDIA_CODEC_RENDERED__CODEC__CODEC_VP9 },
70     { "av1", stats::media_metrics::MEDIA_CODEC_RENDERED__CODEC__CODEC_AV1 },
71     { "av01", stats::media_metrics::MEDIA_CODEC_RENDERED__CODEC__CODEC_AV1 },
72     { "dolby-vision", stats::media_metrics::MEDIA_CODEC_RENDERED__CODEC__CODEC_HEVC },
73 };
74 
75 static const int32_t RESOLUTION_LOOKUP[] = {
76     stats::media_metrics::MEDIA_CODEC_RENDERED__RESOLUTION__RESOLUTION_MAX_SIZE,
77     stats::media_metrics::MEDIA_CODEC_RENDERED__RESOLUTION__RESOLUTION_32K,
78     stats::media_metrics::MEDIA_CODEC_RENDERED__RESOLUTION__RESOLUTION_16K,
79     stats::media_metrics::MEDIA_CODEC_RENDERED__RESOLUTION__RESOLUTION_8K_UHD,
80     stats::media_metrics::MEDIA_CODEC_RENDERED__RESOLUTION__RESOLUTION_8K_UHD_ALMOST,
81     stats::media_metrics::MEDIA_CODEC_RENDERED__RESOLUTION__RESOLUTION_4K_UHD_ALMOST,
82     stats::media_metrics::MEDIA_CODEC_RENDERED__RESOLUTION__RESOLUTION_1440X2560,
83     stats::media_metrics::MEDIA_CODEC_RENDERED__RESOLUTION__RESOLUTION_1080X2400,
84     stats::media_metrics::MEDIA_CODEC_RENDERED__RESOLUTION__RESOLUTION_1080X2340,
85     stats::media_metrics::MEDIA_CODEC_RENDERED__RESOLUTION__RESOLUTION_1080P_FHD,
86     stats::media_metrics::MEDIA_CODEC_RENDERED__RESOLUTION__RESOLUTION_1080P_FHD_ALMOST,
87     stats::media_metrics::MEDIA_CODEC_RENDERED__RESOLUTION__RESOLUTION_720P_HD,
88     stats::media_metrics::MEDIA_CODEC_RENDERED__RESOLUTION__RESOLUTION_720P_HD_ALMOST,
89     stats::media_metrics::MEDIA_CODEC_RENDERED__RESOLUTION__RESOLUTION_576X1024,
90     stats::media_metrics::MEDIA_CODEC_RENDERED__RESOLUTION__RESOLUTION_540X960,
91     stats::media_metrics::MEDIA_CODEC_RENDERED__RESOLUTION__RESOLUTION_480X854,
92     stats::media_metrics::MEDIA_CODEC_RENDERED__RESOLUTION__RESOLUTION_480X640,
93     stats::media_metrics::MEDIA_CODEC_RENDERED__RESOLUTION__RESOLUTION_360X640,
94     stats::media_metrics::MEDIA_CODEC_RENDERED__RESOLUTION__RESOLUTION_352X640,
95     stats::media_metrics::MEDIA_CODEC_RENDERED__RESOLUTION__RESOLUTION_VERY_LOW,
96     stats::media_metrics::MEDIA_CODEC_RENDERED__RESOLUTION__RESOLUTION_SMALLEST,
97     stats::media_metrics::MEDIA_CODEC_RENDERED__RESOLUTION__RESOLUTION_ZERO,
98 };
99 
100 static const int32_t FRAMERATE_LOOKUP[] = {
101     stats::media_metrics::MEDIA_CODEC_RENDERED__CONTENT_FRAMERATE__FRAMERATE_24,
102     stats::media_metrics::MEDIA_CODEC_RENDERED__CONTENT_FRAMERATE__FRAMERATE_25,
103     stats::media_metrics::MEDIA_CODEC_RENDERED__CONTENT_FRAMERATE__FRAMERATE_30,
104     stats::media_metrics::MEDIA_CODEC_RENDERED__CONTENT_FRAMERATE__FRAMERATE_50,
105     stats::media_metrics::MEDIA_CODEC_RENDERED__CONTENT_FRAMERATE__FRAMERATE_60,
106     stats::media_metrics::MEDIA_CODEC_RENDERED__CONTENT_FRAMERATE__FRAMERATE_120,
107 };
108 
getMetricsCodecEnum(const std::string & mime,const std::string & componentName)109 static int32_t getMetricsCodecEnum(const std::string &mime, const std::string &componentName) {
110     for (const auto & codecStrAndEnum : CODEC_LOOKUP) {
111         if (strcasestr(mime.c_str(), codecStrAndEnum.first) != nullptr ||
112             strcasestr(componentName.c_str(), codecStrAndEnum.first) != nullptr) {
113             return codecStrAndEnum.second;
114         }
115     }
116     return MEDIA_CODEC_RENDERED__CODEC__CODEC_UNKNOWN;
117 }
118 
getMetricsResolutionEnum(int32_t width,int32_t height)119 static int32_t getMetricsResolutionEnum(int32_t width, int32_t height) {
120     if (width == 0 || height == 0) {
121         return MEDIA_CODEC_RENDERED__RESOLUTION__RESOLUTION_ZERO;
122     }
123     int64_t pixels = int64_t(width) * height / 1000;
124     if (width < 0 || height < 0 || pixels > RESOLUTION_LOOKUP[0]) {
125         return MEDIA_CODEC_RENDERED__RESOLUTION__RESOLUTION_INVALID;
126     }
127     for (int32_t resolutionEnum : RESOLUTION_LOOKUP) {
128         if (pixels > resolutionEnum) {
129             return resolutionEnum;
130         }
131     }
132     return MEDIA_CODEC_RENDERED__RESOLUTION__RESOLUTION_ZERO;
133 }
134 
getMetricsFramerateEnum(float inFramerate)135 static int32_t getMetricsFramerateEnum(float inFramerate) {
136     if (inFramerate == -1.0f) {
137         return MEDIA_CODEC_RENDERED__CONTENT_FRAMERATE__FRAMERATE_UNDETERMINED;
138     }
139     if (inFramerate == -2.0f) {
140         return MEDIA_CODEC_RENDERED__CONTENT_FRAMERATE__FRAMERATE_24_3_2_PULLDOWN;
141     }
142     int framerate = int(inFramerate * 100); // Table is in hundredths of frames per second
143     static const int framerateTolerance = 40; // Tolerance is 0.4 frames per second - table is 100s
144     for (int32_t framerateEnum : FRAMERATE_LOOKUP) {
145         if (abs(framerate - framerateEnum) < framerateTolerance) {
146             return framerateEnum;
147         }
148     }
149     return MEDIA_CODEC_RENDERED__CONTENT_FRAMERATE__FRAMERATE_UNKNOWN;
150 }
151 
getMetricsHdrFormatEnum(std::string & mime,std::string & componentName,int32_t configColorTransfer,int32_t parsedColorTransfer,int32_t hdr10StaticInfo,int32_t hdr10PlusInfo)152 static int32_t getMetricsHdrFormatEnum(std::string &mime, std::string &componentName,
153                                        int32_t configColorTransfer, int32_t parsedColorTransfer,
154                                        int32_t hdr10StaticInfo, int32_t hdr10PlusInfo) {
155     if (hdr10PlusInfo) {
156         return MEDIA_CODEC_RENDERED__HDR_FORMAT__HDR_FORMAT_HDR10_PLUS;
157     }
158     if (hdr10StaticInfo) {
159         return MEDIA_CODEC_RENDERED__HDR_FORMAT__HDR_FORMAT_HDR10;
160     }
161     // 7 = COLOR_TRANSFER_HLG in MediaCodecConstants.h
162     if (configColorTransfer == 7 || parsedColorTransfer == 7) {
163         return MEDIA_CODEC_RENDERED__HDR_FORMAT__HDR_FORMAT_HLG;
164     }
165     if (strcasestr(mime.c_str(), "dolby-vision") != nullptr ||
166         strcasestr(componentName.c_str(), "dvhe") != nullptr ||
167         strcasestr(componentName.c_str(), "dvav") != nullptr ||
168         strcasestr(componentName.c_str(), "dav1") != nullptr) {
169         return MEDIA_CODEC_RENDERED__HDR_FORMAT__HDR_FORMAT_DOLBY_VISION;
170     }
171     return MEDIA_CODEC_RENDERED__HDR_FORMAT__HDR_FORMAT_NONE;
172 }
173 
parseVector(const std::string & str,std::vector<int32_t> * vector)174 static void parseVector(const std::string &str, std::vector<int32_t> *vector) {
175     if (!audio_utils::stringutils::parseVector(str, vector)) {
176         ALOGE("failed to parse integer vector from '%s'", str.c_str());
177     }
178 }
179 
statsd_codec(const std::shared_ptr<const mediametrics::Item> & item,const std::shared_ptr<mediametrics::StatsdLog> & statsdLog)180 bool statsd_codec(const std::shared_ptr<const mediametrics::Item>& item,
181         const std::shared_ptr<mediametrics::StatsdLog>& statsdLog)
182 {
183     if (item == nullptr) return false;
184 
185     AStatsEvent* event = AStatsEvent_obtain();
186     AStatsEvent_setAtomId(event, stats::media_metrics::MEDIA_CODEC_REPORTED);
187 
188     const nsecs_t timestampNanos = MediaMetricsService::roundTime(item->getTimestamp());
189     AStatsEvent_writeInt64(event, timestampNanos);
190 
191     // packageName deprecated for calling_uid and statsd support as of U-QPR2
192     std::string packageName = "";
193     AStatsEvent_writeString(event, packageName.c_str());
194 
195     // packageVersion depreccated for calling_uid and statsd support as of U-QPR2
196     int64_t packageVersionCode = 0;
197     AStatsEvent_writeInt64(event, packageVersionCode);
198 
199     int64_t mediaApexVersion = 0;
200     AStatsEvent_writeInt64(event, mediaApexVersion);
201 
202     // the rest into our own proto
203     //
204     ::android::stats::mediametrics_message::CodecData metrics_proto;
205 
206     // flesh out the protobuf we'll hand off with our data
207     //
208     std::string codec;
209     if (item->getString("android.media.mediacodec.codec", &codec)) {
210         metrics_proto.set_codec(codec);
211     }
212     AStatsEvent_writeString(event, codec.c_str());
213 
214     std::string mime;
215     if (item->getString("android.media.mediacodec.mime", &mime)) {
216         metrics_proto.set_mime(mime);
217     }
218     AStatsEvent_writeString(event, mime.c_str());
219 
220     std::string mode;
221     if (item->getString("android.media.mediacodec.mode", &mode)) {
222         metrics_proto.set_mode(mode);
223     }
224     AStatsEvent_writeString(event, mode.c_str());
225 
226     int32_t isEncoder = -1;
227     if (item->getInt32("android.media.mediacodec.encoder", &isEncoder)) {
228         metrics_proto.set_encoder(isEncoder);
229     }
230     AStatsEvent_writeInt32(event, isEncoder);
231 
232     int32_t isSecure = -1;
233     if (item->getInt32("android.media.mediacodec.secure", &isSecure)) {
234         metrics_proto.set_secure(isSecure);
235     }
236     AStatsEvent_writeInt32(event, isSecure);
237 
238     int32_t isHardware = -1;
239     item->getInt32("android.media.mediacodec.hardware", &isHardware);
240     // not logged to MediaCodecReported or MediametricsCodecReported
241 
242     int32_t isTunneled = -1;
243     item->getInt32("android.media.mediacodec.tunneled", &isTunneled);
244     // not logged to MediaCodecReported or MediametricsCodecReported
245 
246     int32_t width = -1;
247     if (item->getInt32("android.media.mediacodec.width", &width)) {
248         metrics_proto.set_width(width);
249     }
250     AStatsEvent_writeInt32(event, width);
251 
252     int32_t height = -1;
253     if (item->getInt32("android.media.mediacodec.height", &height)) {
254         metrics_proto.set_height(height);
255     }
256     AStatsEvent_writeInt32(event, height);
257 
258     int32_t rotation = -1;
259     if (item->getInt32("android.media.mediacodec.rotation-degrees", &rotation)) {
260         metrics_proto.set_rotation(rotation);
261     }
262     AStatsEvent_writeInt32(event, rotation);
263 
264     int32_t crypto = -1;
265     if (item->getInt32("android.media.mediacodec.crypto", &crypto)) {
266         metrics_proto.set_crypto(crypto);
267     }
268     AStatsEvent_writeInt32(event, crypto);
269 
270     int32_t profile = -1;
271     if (item->getInt32("android.media.mediacodec.profile", &profile)) {
272         metrics_proto.set_profile(profile);
273     }
274     AStatsEvent_writeInt32(event, profile);
275 
276     int32_t level = -1;
277     if (item->getInt32("android.media.mediacodec.level", &level)) {
278         metrics_proto.set_level(level);
279     }
280     AStatsEvent_writeInt32(event, level);
281 
282 
283     int32_t maxWidth = -1;
284     if ( item->getInt32("android.media.mediacodec.maxwidth", &maxWidth)) {
285         metrics_proto.set_max_width(maxWidth);
286     }
287     AStatsEvent_writeInt32(event, maxWidth);
288 
289     int32_t maxHeight = -1;
290     if ( item->getInt32("android.media.mediacodec.maxheight", &maxHeight)) {
291         metrics_proto.set_max_height(maxHeight);
292     }
293     AStatsEvent_writeInt32(event, maxHeight);
294 
295     int32_t errorCode = -1;
296     if ( item->getInt32("android.media.mediacodec.errcode", &errorCode)) {
297         metrics_proto.set_error_code(errorCode);
298     }
299     AStatsEvent_writeInt32(event, errorCode);
300 
301     std::string errorState;
302     if ( item->getString("android.media.mediacodec.errstate", &errorState)) {
303         metrics_proto.set_error_state(errorState);
304     }
305     AStatsEvent_writeString(event, errorState.c_str());
306 
307     int64_t latencyMax = -1;
308     if (item->getInt64("android.media.mediacodec.latency.max", &latencyMax)) {
309         metrics_proto.set_latency_max(latencyMax);
310     }
311     AStatsEvent_writeInt64(event, latencyMax);
312 
313     int64_t latencyMin = -1;
314     if (item->getInt64("android.media.mediacodec.latency.min", &latencyMin)) {
315         metrics_proto.set_latency_min(latencyMin);
316     }
317     AStatsEvent_writeInt64(event, latencyMin);
318 
319     int64_t latencyAvg = -1;
320     if (item->getInt64("android.media.mediacodec.latency.avg", &latencyAvg)) {
321         metrics_proto.set_latency_avg(latencyAvg);
322     }
323     AStatsEvent_writeInt64(event, latencyAvg);
324 
325     int64_t latencyCount = -1;
326     if (item->getInt64("android.media.mediacodec.latency.n", &latencyCount)) {
327         metrics_proto.set_latency_count(latencyCount);
328     }
329     AStatsEvent_writeInt64(event, latencyCount);
330 
331     int64_t latencyUnknown = -1;
332     if (item->getInt64("android.media.mediacodec.latency.unknown", &latencyUnknown)) {
333         metrics_proto.set_latency_unknown(latencyUnknown);
334     }
335     AStatsEvent_writeInt64(event, latencyUnknown);
336 
337     int32_t queueSecureInputBufferError = -1;
338     if (item->getInt32("android.media.mediacodec.queueSecureInputBufferError",
339             &queueSecureInputBufferError)) {
340         metrics_proto.set_queue_secure_input_buffer_error(queueSecureInputBufferError);
341     }
342     AStatsEvent_writeInt32(event, queueSecureInputBufferError);
343 
344     int32_t queueInputBufferError = -1;
345     if (item->getInt32("android.media.mediacodec.queueInputBufferError", &queueInputBufferError)) {
346         metrics_proto.set_queue_input_buffer_error(queueInputBufferError);
347     }
348     AStatsEvent_writeInt32(event, queueInputBufferError);
349 
350     std::string bitrateMode;
351     if (item->getString("android.media.mediacodec.bitrate_mode", &bitrateMode)) {
352         metrics_proto.set_bitrate_mode(bitrateMode);
353     }
354     AStatsEvent_writeString(event, bitrateMode.c_str());
355 
356     int32_t bitrate = -1;
357     if (item->getInt32("android.media.mediacodec.bitrate", &bitrate)) {
358         metrics_proto.set_bitrate(bitrate);
359     }
360     AStatsEvent_writeInt32(event, bitrate);
361 
362     int64_t lifetimeMillis = -1;
363     if (item->getInt64("android.media.mediacodec.lifetimeMs", &lifetimeMillis)) {
364         lifetimeMillis = mediametrics::bucket_time_minutes(lifetimeMillis);
365         metrics_proto.set_lifetime_millis(lifetimeMillis);
366     }
367     AStatsEvent_writeInt64(event, lifetimeMillis);
368 
369     int64_t playbackDurationSec = -1;
370     item->getInt64("android.media.mediacodec.playback-duration-sec", &playbackDurationSec);
371     // DO NOT record  playback-duration in the metrics_proto - it should only
372     // exist in the flattened atom
373     AStatsEvent_writeInt64(event, playbackDurationSec);
374 
375     std::string sessionId;
376     if (item->getString("android.media.mediacodec.log-session-id", &sessionId)) {
377         sessionId = mediametrics::ValidateId::get()->validateId(sessionId);
378         metrics_proto.set_log_session_id(sessionId);
379     }
380     AStatsEvent_writeString(event, sessionId.c_str());
381 
382     int32_t channelCount = -1;
383     if (item->getInt32("android.media.mediacodec.channelCount", &channelCount)) {
384         metrics_proto.set_channel_count(channelCount);
385     }
386     AStatsEvent_writeInt32(event, channelCount);
387 
388     int32_t sampleRate = -1;
389     if (item->getInt32("android.media.mediacodec.sampleRate", &sampleRate)) {
390         metrics_proto.set_sample_rate(sampleRate);
391     }
392     AStatsEvent_writeInt32(event, sampleRate);
393 
394     // TODO PWG may want these fuzzed up a bit to obscure some precision
395     int64_t bytes = -1;
396     if (item->getInt64("android.media.mediacodec.vencode.bytes", &bytes)) {
397         metrics_proto.set_video_encode_bytes(bytes);
398     }
399     AStatsEvent_writeInt64(event, bytes);
400 
401     int64_t frames = -1;
402     if (item->getInt64("android.media.mediacodec.vencode.frames", &frames)) {
403         metrics_proto.set_video_encode_frames(frames);
404     }
405     AStatsEvent_writeInt64(event, frames);
406 
407     int64_t inputBytes = -1;
408     if (item->getInt64("android.media.mediacodec.video.input.bytes", &inputBytes)) {
409         metrics_proto.set_video_input_bytes(inputBytes);
410     }
411     AStatsEvent_writeInt64(event, inputBytes);
412 
413     int64_t inputFrames = -1;
414     if (item->getInt64("android.media.mediacodec.video.input.frames", &inputFrames)) {
415         metrics_proto.set_video_input_frames(inputFrames);
416     }
417     AStatsEvent_writeInt64(event, inputFrames);
418 
419     int64_t durationUs = -1;
420     if (item->getInt64("android.media.mediacodec.vencode.durationUs", &durationUs)) {
421         metrics_proto.set_video_encode_duration_us(durationUs);
422     }
423     AStatsEvent_writeInt64(event, durationUs);
424 
425     int32_t colorFormat = -1;
426     if (item->getInt32("android.media.mediacodec.color-format", &colorFormat)) {
427         metrics_proto.set_color_format(colorFormat);
428     }
429     AStatsEvent_writeInt32(event, colorFormat);
430 
431     double frameRate = -1.0;
432     if (item->getDouble("android.media.mediacodec.frame-rate", &frameRate)) {
433         metrics_proto.set_frame_rate(frameRate);
434     }
435     AStatsEvent_writeFloat(event, (float) frameRate);
436 
437     double captureRate = -1.0;
438     if (item->getDouble("android.media.mediacodec.capture-rate", &captureRate)) {
439         metrics_proto.set_capture_rate(captureRate);
440     }
441     AStatsEvent_writeFloat(event, (float) captureRate);
442 
443     double operatingRate = -1.0;
444     if (item->getDouble("android.media.mediacodec.operating-rate", &operatingRate)) {
445         metrics_proto.set_operating_rate(operatingRate);
446     }
447     AStatsEvent_writeFloat(event, (float) operatingRate);
448 
449     int32_t priority = -1;
450     if (item->getInt32("android.media.mediacodec.priority", &priority)) {
451         metrics_proto.set_priority(priority);
452     }
453     AStatsEvent_writeInt32(event, priority);
454 
455     int32_t qpIMin = -1;
456     if (item->getInt32("android.media.mediacodec.video-qp-i-min", &qpIMin)) {
457         metrics_proto.set_video_qp_i_min(qpIMin);
458     }
459     AStatsEvent_writeInt32(event, qpIMin);
460 
461     int32_t qpIMax = -1;
462     if (item->getInt32("android.media.mediacodec.video-qp-i-max", &qpIMax)) {
463         metrics_proto.set_video_qp_i_max(qpIMax);
464     }
465     AStatsEvent_writeInt32(event, qpIMax);
466 
467     int32_t qpPMin = -1;
468     if (item->getInt32("android.media.mediacodec.video-qp-p-min", &qpPMin)) {
469         metrics_proto.set_video_qp_p_min(qpPMin);
470     }
471     AStatsEvent_writeInt32(event, qpPMin);
472 
473     int32_t qpPMax = -1;
474     if (item->getInt32("android.media.mediacodec.video-qp-p-max", &qpPMax)) {
475         metrics_proto.set_video_qp_p_max(qpPMax);
476     }
477     AStatsEvent_writeInt32(event, qpPMax);
478 
479     int32_t qpBMin = -1;
480     if (item->getInt32("android.media.mediacodec.video-qp-b-min", &qpBMin)) {
481         metrics_proto.set_video_qp_b_min(qpBMin);
482     }
483     AStatsEvent_writeInt32(event, qpBMin);
484 
485     int32_t qpBMax = -1;
486     if (item->getInt32("android.media.mediacodec.video-qp-b-max", &qpBMax)) {
487         metrics_proto.set_video_qp_b_max(qpBMax);
488     }
489     AStatsEvent_writeInt32(event, qpBMax);
490 
491     int32_t originalBitrate = -1;
492     if (item->getInt32("android.media.mediacodec.original.bitrate", &originalBitrate)) {
493         metrics_proto.set_original_bitrate(originalBitrate);
494     }
495     AStatsEvent_writeInt32(event, originalBitrate);
496 
497     int32_t shapingEnhanced = -1;
498     if ( item->getInt32("android.media.mediacodec.shaped", &shapingEnhanced)) {
499         metrics_proto.set_shaping_enhanced(shapingEnhanced);
500     }
501     AStatsEvent_writeInt32(event, shapingEnhanced);
502 
503     int32_t qpIMinOri = -1;
504     if ( item->getInt32("android.media.mediacodec.original-video-qp-i-min", &qpIMinOri)) {
505         metrics_proto.set_original_video_qp_i_min(qpIMinOri);
506     }
507     AStatsEvent_writeInt32(event, qpIMinOri);
508 
509     int32_t qpIMaxOri = -1;
510     if ( item->getInt32("android.media.mediacodec.original-video-qp-i-max", &qpIMaxOri)) {
511         metrics_proto.set_original_video_qp_i_max(qpIMaxOri);
512     }
513     AStatsEvent_writeInt32(event, qpIMaxOri);
514 
515     int32_t qpPMinOri = -1;
516     if ( item->getInt32("android.media.mediacodec.original-video-qp-p-min", &qpPMinOri)) {
517         metrics_proto.set_original_video_qp_p_min(qpPMinOri);
518     }
519     AStatsEvent_writeInt32(event, qpPMinOri);
520 
521     int32_t qpPMaxOri = -1;
522     if ( item->getInt32("android.media.mediacodec.original-video-qp-p-max", &qpPMaxOri)) {
523         metrics_proto.set_original_video_qp_p_max(qpPMaxOri);
524     }
525     AStatsEvent_writeInt32(event, qpPMaxOri);
526 
527     int32_t qpBMinOri = -1;
528     if ( item->getInt32("android.media.mediacodec.original-video-qp-b-min", &qpBMinOri)) {
529         metrics_proto.set_original_video_qp_b_min(qpBMinOri);
530     }
531     AStatsEvent_writeInt32(event, qpBMinOri);
532 
533     int32_t qpBMaxOri = -1;
534     if ( item->getInt32("android.media.mediacodec.original-video-qp-b-max", &qpBMaxOri)) {
535         metrics_proto.set_original_video_qp_b_max(qpBMaxOri);
536     }
537     AStatsEvent_writeInt32(event, qpBMaxOri);
538 
539     int32_t configColorStandard = -1;
540     if (item->getInt32("android.media.mediacodec.config-color-standard", &configColorStandard)) {
541         metrics_proto.set_config_color_standard(configColorStandard);
542     }
543     AStatsEvent_writeInt32(event, configColorStandard);
544 
545     int32_t configColorRange = -1;
546     if (item->getInt32("android.media.mediacodec.config-color-range", &configColorRange)) {
547         metrics_proto.set_config_color_range(configColorRange);
548     }
549     AStatsEvent_writeInt32(event, configColorRange);
550 
551     int32_t configColorTransfer = -1;
552     if (item->getInt32("android.media.mediacodec.config-color-transfer", &configColorTransfer)) {
553         metrics_proto.set_config_color_transfer(configColorTransfer);
554     }
555     AStatsEvent_writeInt32(event, configColorTransfer);
556 
557     int32_t parsedColorStandard = -1;
558     if (item->getInt32("android.media.mediacodec.parsed-color-standard", &parsedColorStandard)) {
559         metrics_proto.set_parsed_color_standard(parsedColorStandard);
560     }
561     AStatsEvent_writeInt32(event, parsedColorStandard);
562 
563     int32_t parsedColorRange = -1;
564     if (item->getInt32("android.media.mediacodec.parsed-color-range", &parsedColorRange)) {
565         metrics_proto.set_parsed_color_range(parsedColorRange);
566     }
567     AStatsEvent_writeInt32(event, parsedColorRange);
568 
569     int32_t parsedColorTransfer = -1;
570     if (item->getInt32("android.media.mediacodec.parsed-color-transfer", &parsedColorTransfer)) {
571         metrics_proto.set_parsed_color_transfer(parsedColorTransfer);
572     }
573     AStatsEvent_writeInt32(event, parsedColorTransfer);
574 
575     int32_t hdrStaticInfo = -1;
576     if (item->getInt32("android.media.mediacodec.hdr-static-info", &hdrStaticInfo)) {
577         metrics_proto.set_hdr_static_info(hdrStaticInfo);
578     }
579     AStatsEvent_writeInt32(event, hdrStaticInfo);
580 
581     int32_t hdr10PlusInfo = -1;
582     if (item->getInt32("android.media.mediacodec.hdr10-plus-info", &hdr10PlusInfo)) {
583         metrics_proto.set_hdr10_plus_info(hdr10PlusInfo);
584     }
585     AStatsEvent_writeInt32(event, hdr10PlusInfo);
586 
587     int32_t hdrFormat = -1;
588     if (item->getInt32("android.media.mediacodec.hdr-format", &hdrFormat)) {
589         metrics_proto.set_hdr_format(hdrFormat);
590     }
591     AStatsEvent_writeInt32(event, hdrFormat);
592 
593     int64_t codecId = 0;
594     if (item->getInt64("android.media.mediacodec.id", &codecId)) {
595         metrics_proto.set_codec_id(codecId);
596     }
597     AStatsEvent_writeInt64(event, codecId);
598 
599     int32_t arrayMode = -1;
600     if (item->getInt32("android.media.mediacodec.array-mode", &arrayMode)) {
601         metrics_proto.set_array_mode(arrayMode);
602     }
603     AStatsEvent_writeInt32(event, arrayMode);
604 
605     int32_t operationMode = -1;
606     if (item->getInt32("android.media.mediacodec.operation-mode", &operationMode)) {
607         metrics_proto.set_operation_mode(operationMode);
608     }
609     AStatsEvent_writeInt32(event, operationMode);
610 
611     int32_t outputSurface = -1;
612     if (item->getInt32("android.media.mediacodec.output-surface", &outputSurface)) {
613         metrics_proto.set_output_surface(outputSurface);
614     }
615     AStatsEvent_writeInt32(event, outputSurface);
616 
617     int32_t appMaxInputSize = -1;
618     if (item->getInt32("android.media.mediacodec.app-max-input-size", &appMaxInputSize)) {
619         metrics_proto.set_app_max_input_size(appMaxInputSize);
620     }
621     AStatsEvent_writeInt32(event, appMaxInputSize);
622 
623     int32_t usedMaxInputSize = -1;
624     if (item->getInt32("android.media.mediacodec.used-max-input-size", &usedMaxInputSize)) {
625         metrics_proto.set_used_max_input_size(usedMaxInputSize);
626     }
627     AStatsEvent_writeInt32(event, usedMaxInputSize);
628 
629     int32_t codecMaxInputSize = -1;
630     if (item->getInt32("android.media.mediacodec.codec-max-input-size", &codecMaxInputSize)) {
631         metrics_proto.set_codec_max_input_size(codecMaxInputSize);
632     }
633     AStatsEvent_writeInt32(event, codecMaxInputSize);
634 
635     int32_t flushCount = -1;
636     if (item->getInt32("android.media.mediacodec.flush-count", &flushCount)) {
637         metrics_proto.set_flush_count(flushCount);
638     }
639     AStatsEvent_writeInt32(event, flushCount);
640 
641     int32_t setSurfaceCount = -1;
642     if (item->getInt32("android.media.mediacodec.set-surface-count", &setSurfaceCount)) {
643         metrics_proto.set_set_surface_count(setSurfaceCount);
644     }
645     AStatsEvent_writeInt32(event, setSurfaceCount);
646 
647     int32_t resolutionChangeCount = -1;
648     if (item->getInt32("android.media.mediacodec.resolution-change-count",
649             &resolutionChangeCount)) {
650         metrics_proto.set_resolution_change_count(resolutionChangeCount);
651     }
652     AStatsEvent_writeInt32(event, resolutionChangeCount);
653 
654     int32_t componentColorFormat = -1;
655     if (item->getInt32("android.media.mediacodec.component-color-format", &componentColorFormat)) {
656         metrics_proto.set_component_color_format(componentColorFormat);
657     }
658     AStatsEvent_writeInt32(event, componentColorFormat);
659 
660     uid_t app_uid = item->getUid();
661     metrics_proto.set_caller_uid(app_uid);
662     AStatsEvent_writeInt32(event, app_uid);
663 
664     int64_t pixelFormat = -1;
665     if (item->getInt64("android.media.mediacodec.pixel-format", &pixelFormat)) {
666         metrics_proto.set_pixel_format(pixelFormat);
667     }
668     AStatsEvent_writeInt64(event, pixelFormat);
669 
670     int64_t firstRenderTimeUs = -1;
671     item->getInt64("android.media.mediacodec.first-render-time-us", &firstRenderTimeUs);
672     int64_t framesReleased = -1;
673     item->getInt64("android.media.mediacodec.frames-released", &framesReleased);
674     int64_t framesRendered = -1;
675     item->getInt64("android.media.mediacodec.frames-rendered", &framesRendered);
676     int64_t framesDropped = -1;
677     item->getInt64("android.media.mediacodec.frames-dropped", &framesDropped);
678     int64_t framesSkipped = -1;
679     item->getInt64("android.media.mediacodec.frames-skipped", &framesSkipped);
680     double framerateContent = -1;
681     item->getDouble("android.media.mediacodec.framerate-content", &framerateContent);
682     double framerateActual = -1;
683     item->getDouble("android.media.mediacodec.framerate-actual", &framerateActual);
684     int64_t freezeScore = -1;
685     item->getInt64("android.media.mediacodec.freeze-score", &freezeScore);
686     double freezeRate = -1;
687     item->getDouble("android.media.mediacodec.freeze-rate", &freezeRate);
688     std::string freezeScoreHistogramStr;
689     item->getString("android.media.mediacodec.freeze-score-histogram", &freezeScoreHistogramStr);
690     std::string freezeScoreHistogramBucketsStr;
691     item->getString("android.media.mediacodec.freeze-score-histogram-buckets",
692                     &freezeScoreHistogramBucketsStr);
693     std::string freezeDurationMsHistogramStr;
694     item->getString("android.media.mediacodec.freeze-duration-ms-histogram",
695                     &freezeDurationMsHistogramStr);
696     std::string freezeDurationMsHistogramBucketsStr;
697     item->getString("android.media.mediacodec.freeze-duration-ms-histogram-buckets",
698                     &freezeDurationMsHistogramBucketsStr);
699     std::string freezeDistanceMsHistogramStr;
700     item->getString("android.media.mediacodec.freeze-distance-ms-histogram",
701                     &freezeDistanceMsHistogramStr);
702     std::string freezeDistanceMsHistogramBucketsStr;
703     item->getString("android.media.mediacodec.freeze-distance-ms-histogram-buckets",
704                     &freezeDistanceMsHistogramBucketsStr);
705     int64_t judderScore = -1;
706     item->getInt64("android.media.mediacodec.judder-score", &judderScore);
707     double judderRate = -1;
708     item->getDouble("android.media.mediacodec.judder-rate", &judderRate);
709     std::string judderScoreHistogramStr;
710     item->getString("android.media.mediacodec.judder-score-histogram", &judderScoreHistogramStr);
711     std::string judderScoreHistogramBucketsStr;
712     item->getString("android.media.mediacodec.judder-score-histogram-buckets",
713                     &judderScoreHistogramBucketsStr);
714 
715     int err = AStatsEvent_write(event);
716     if (err < 0) {
717       ALOGE("Failed to write codec metrics to statsd (%d)", err);
718     }
719     AStatsEvent_release(event);
720 
721     if (framesRendered > 0) {
722         int32_t statsUid = item->getUid();
723         int64_t statsCodecId = codecId;
724         char const *statsLogSessionId = sessionId.c_str();
725         int32_t statsIsHardware = isHardware;
726         int32_t statsIsSecure = isSecure;
727         int32_t statsIsTunneled = isTunneled;
728         int32_t statsCodec = getMetricsCodecEnum(mime, codec);
729         int32_t statsResolution = getMetricsResolutionEnum(width, height);
730         int32_t statsBitrate = BITRATE_UNKNOWN;
731         int32_t statsContentFramerate = getMetricsFramerateEnum(framerateContent);
732         int32_t statsActualFramerate = getMetricsFramerateEnum(framerateActual);
733         int32_t statsHdrFormat = getMetricsHdrFormatEnum(mime, codec, configColorTransfer,
734                                                          parsedColorTransfer, hdrStaticInfo,
735                                                          hdr10PlusInfo);
736         int64_t statsFirstRenderTimeUs = firstRenderTimeUs;
737         int64_t statsPlaybackDurationSeconds = playbackDurationSec;
738         int64_t statsFramesTotal = framesReleased + framesSkipped;
739         int64_t statsFramesReleased = framesReleased;
740         int64_t statsFramesRendered = framesRendered;
741         int64_t statsFramesDropped = framesDropped;
742         int64_t statsFramesSkipped = framesSkipped;
743         float statsFrameDropRate = float(double(framesDropped) / statsFramesTotal);
744         float statsFrameSkipRate = float(double(framesSkipped) / statsFramesTotal);
745         float statsFrameSkipDropRate = float(double(framesSkipped + framesDropped) /
746                                              statsFramesTotal);
747         int64_t statsFreezeScore = freezeScore;
748         float statsFreezeRate = freezeRate;
749         std::vector<int32_t> statsFreezeDurationMsHistogram;
750         parseVector(freezeDurationMsHistogramStr, &statsFreezeDurationMsHistogram);
751         std::vector<int32_t> statsFreezeDurationMsHistogramBuckets;
752         parseVector(freezeDurationMsHistogramBucketsStr, &statsFreezeDurationMsHistogramBuckets);
753         std::vector<int32_t> statsFreezeDistanceMsHistogram;
754         parseVector(freezeDistanceMsHistogramStr, &statsFreezeDistanceMsHistogram);
755         std::vector<int32_t> statsFreezeDistanceMsHistogramBuckets;
756         parseVector(freezeDistanceMsHistogramBucketsStr, &statsFreezeDistanceMsHistogramBuckets);
757         int64_t statsJudderScore = judderScore;
758         float statsJudderRate = judderRate;
759         std::vector<int32_t> statsJudderScoreHistogram;
760         parseVector(judderScoreHistogramStr, &statsJudderScoreHistogram);
761         std::vector<int32_t> statsJudderScoreHistogramBuckets;
762         parseVector(judderScoreHistogramBucketsStr, &statsJudderScoreHistogramBuckets);
763         int result = stats_write(
764             MEDIA_CODEC_RENDERED,
765             statsUid,
766             statsCodecId,
767             statsLogSessionId,
768             statsIsHardware,
769             statsIsSecure,
770             statsIsTunneled,
771             statsCodec,
772             statsResolution,
773             statsBitrate,
774             statsContentFramerate,
775             statsActualFramerate,
776             statsHdrFormat,
777             statsFirstRenderTimeUs,
778             statsPlaybackDurationSeconds,
779             statsFramesTotal,
780             statsFramesReleased,
781             statsFramesRendered,
782             statsFramesDropped,
783             statsFramesSkipped,
784             statsFrameDropRate,
785             statsFrameSkipRate,
786             statsFrameSkipDropRate,
787             statsFreezeScore,
788             statsFreezeRate,
789             statsFreezeDurationMsHistogram,
790             statsFreezeDurationMsHistogramBuckets,
791             statsFreezeDistanceMsHistogram,
792             statsFreezeDistanceMsHistogramBuckets,
793             statsJudderScore,
794             statsJudderRate,
795             statsJudderScoreHistogram,
796             statsJudderScoreHistogramBuckets);
797         ALOGE_IF(result < 0, "Failed to record MEDIA_CODEC_RENDERED atom (%d)", result);
798     }
799 
800     std::string serialized;
801     if (!metrics_proto.SerializeToString(&serialized)) {
802         ALOGE("Failed to serialize codec metrics");
803         return false;
804     }
805     const stats::media_metrics::BytesField bf_serialized(serialized.c_str(), serialized.size());
806     const int result = stats::media_metrics::stats_write(stats::media_metrics::MEDIAMETRICS_CODEC_REPORTED,
807                                timestampNanos, packageName.c_str(), packageVersionCode,
808                                mediaApexVersion,
809                                bf_serialized);
810 
811     std::stringstream log;
812     log << "result:" << result << " {"
813             << " mediametrics_codec_reported:"
814             << stats::media_metrics::MEDIAMETRICS_CODEC_REPORTED
815             << " timestamp_nanos:" << timestampNanos
816             << " package_name:" << packageName
817             << " package_version_code:" << packageVersionCode
818             << " media_apex_version:" << mediaApexVersion
819             << " codec:" << codec
820             << " mime:" << mime
821             << " mode:" << mode
822             << " encoder:" << isEncoder
823             << " secure:" << isSecure
824             << " width:" << width
825             << " height:" << height
826             << " rotation:" << rotation
827             << " crypto:" << crypto
828             << " profile:" << profile
829             << " level:" << level
830             << " max_width:" << maxWidth
831             << " max_height:" << maxHeight
832             << " error_code:" << errorCode
833             << " error_state:" << errorState
834             << " latency_max:" << latencyMax
835             << " latency_min:" << latencyMin
836             << " latency_avg:" << latencyAvg
837             << " latency_count:" << latencyCount
838             << " latency_unknown:" << latencyUnknown
839             << " queue_input_buffer_error:" << queueInputBufferError
840             << " queue_secure_input_buffer_error:" << queueSecureInputBufferError
841             << " bitrate_mode:" << bitrateMode
842             << " bitrate:" << bitrate
843             << " original_bitrate:" << originalBitrate
844             << " lifetime_millis:" << lifetimeMillis
845             << " playback_duration_seconds:" << playbackDurationSec
846             << " log_session_id:" << sessionId
847             << " channel_count:" << channelCount
848             << " sample_rate:" << sampleRate
849             << " encode_bytes:" << bytes
850             << " encode_frames:" << frames
851             << " encode_duration_us:" << durationUs
852             << " color_format:" << colorFormat
853             << " frame_rate:" << frameRate
854             << " capture_rate:" << captureRate
855             << " operating_rate:" << operatingRate
856             << " priority:" << priority
857             << " shaping_enhanced:" << shapingEnhanced
858             << " qp_i_min:" << qpIMin
859             << " qp_i_max:" << qpIMax
860             << " qp_p_min:" << qpPMin
861             << " qp_p_max:" << qpPMax
862             << " qp_b_min:" << qpBMin
863             << " qp_b_max:" << qpBMax
864             << " original_qp_i_min:" << qpIMinOri
865             << " original_qp_i_max:" << qpIMaxOri
866             << " original_qp_p_min:" << qpPMinOri
867             << " original_qp_p_max:" << qpPMaxOri
868             << " original_qp_b_min:" << qpBMinOri
869             << " original_qp_b_max:" << qpBMaxOri
870             << " app_uid:" << app_uid
871             << " }";
872     statsdLog->log(stats::media_metrics::MEDIAMETRICS_CODEC_REPORTED, log.str());
873 
874 
875     return true;
876 }
877 
878 } // namespace android
879