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