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