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