Loading cmds/screenrecord/screenrecord.cpp +7 −8 Original line number Diff line number Diff line Loading @@ -84,14 +84,13 @@ using android::Vector; using android::sp; using android::status_t; using android::DISPLAY_ORIENTATION_0; using android::DISPLAY_ORIENTATION_180; using android::DISPLAY_ORIENTATION_90; using android::INVALID_OPERATION; using android::NAME_NOT_FOUND; using android::NO_ERROR; using android::UNKNOWN_ERROR; namespace ui = android::ui; static const uint32_t kMinBitRate = 100000; // 0.1Mbps static const uint32_t kMaxBitRate = 200 * 1000000; // 200Mbps static const uint32_t kMaxTimeLimitSec = 180; // 3 minutes Loading Loading @@ -328,7 +327,7 @@ static status_t setDisplayProjection( } t.setDisplayProjection(dpy, gRotate ? DISPLAY_ORIENTATION_90 : DISPLAY_ORIENTATION_0, gRotate ? ui::ROTATION_90 : ui::ROTATION_0, layerStackRect, displayRect); return NO_ERROR; } Loading Loading @@ -414,7 +413,7 @@ static status_t writeWinscopeMetadata(const Vector<int64_t>& timestamps, */ static status_t runEncoder(const sp<MediaCodec>& encoder, AMediaMuxer *muxer, FILE* rawFp, const sp<IBinder>& display, const sp<IBinder>& virtualDpy, uint8_t orientation) { const sp<IBinder>& virtualDpy, ui::Rotation orientation) { static int kTimeout = 250000; // be responsive on signal status_t err; ssize_t trackIdx = -1; Loading Loading @@ -484,7 +483,7 @@ static status_t runEncoder(const sp<MediaCodec>& encoder, if (err != NO_ERROR) { ALOGW("getDisplayInfo(main) failed: %d", err); } else if (orientation != displayInfo.orientation) { ALOGD("orientation changed, now %d", displayInfo.orientation); ALOGD("orientation changed, now %s", toCString(displayInfo.orientation)); SurfaceComposerClient::Transaction t; setDisplayProjection(t, virtualDpy, displayInfo); t.apply(); Loading Loading @@ -691,9 +690,9 @@ static status_t recordScreen(const char* fileName) { } if (gVerbose) { printf("Display is %dx%d @%.2ffps (orientation=%u), layerStack=%u\n", printf("Display is %dx%d @%.2ffps (orientation=%s), layerStack=%u\n", displayInfo.viewportW, displayInfo.viewportH, displayInfo.fps, displayInfo.orientation, displayInfo.layerStack); toCString(displayInfo.orientation), displayInfo.layerStack); fflush(stdout); } Loading media/libmediametrics/include/MediaMetricsItem.h +43 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,49 @@ namespace android { /* * MediaMetrics Keys and Properties for Audio. * * C/C++ friendly constants that ensure * 1) Compilation error on misspelling * 2) Consistent behavior and documentation. * * TODO: Move to separate header file. */ // Taxonomy of audio keys // Key Prefixes are used for MediaMetrics Item Keys and ends with a ".". // They must be appended with another value to make a key. #define AMEDIAMETRICS_KEY_PREFIX_AUDIO "audio." // The AudioRecord key appends the "trackId" to the prefix. #define AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD AMEDIAMETRICS_KEY_PREFIX_AUDIO "record." // The AudioThread key appends the "threadId" to the prefix. #define AMEDIAMETRICS_KEY_PREFIX_AUDIO_THREAD AMEDIAMETRICS_KEY_PREFIX_AUDIO "thread." // The AudioTrack key appends the "trackId" to the prefix. #define AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK AMEDIAMETRICS_KEY_PREFIX_AUDIO "track." // Keys are strings used for MediaMetrics Item Keys #define AMEDIAMETRICS_KEY_AUDIO_FLINGER AMEDIAMETRICS_KEY_PREFIX_AUDIO "flinger" #define AMEDIAMETRICS_KEY_AUDIO_POLICY AMEDIAMETRICS_KEY_PREFIX_AUDIO "policy" // Props are properties allowed for Mediametrics Items. #define AMEDIAMETRICS_PROP_EVENT "event" // string value (often func name) #define AMEDIAMETRICS_PROP_LATENCYMS "latencyMs" // double value #define AMEDIAMETRICS_PROP_OUTPUTDEVICES "outputDevices" // string value #define AMEDIAMETRICS_PROP_STARTUPMS "startupMs" // double value #define AMEDIAMETRICS_PROP_THREADID "threadId" // int32 value io handle // Values are strings accepted for a given property. // An event is a general description, which often is a function name. #define AMEDIAMETRICS_PROP_EVENT_VALUE_CTOR "ctor" #define AMEDIAMETRICS_PROP_EVENT_VALUE_DTOR "dtor" #define AMEDIAMETRICS_PROP_EVENT_VALUE_UNDERRUN "underrun" // from Thread class IMediaMetricsService; class Parcel; Loading media/tests/benchmark/src/native/encoder/Encoder.cpp +1 −0 Original line number Diff line number Diff line Loading @@ -159,6 +159,7 @@ void Encoder::deInitCodec() { AMediaFormat_delete(mFormat); mFormat = nullptr; } if (!mCodec) return; AMediaCodec_stop(mCodec); AMediaCodec_delete(mCodec); int64_t eTime = mStats->getCurTime(); Loading services/mediametrics/AnalyticsState.h +18 −0 Original line number Diff line number Diff line Loading @@ -55,6 +55,24 @@ public: return mTimeMachine.put(item, isTrusted) ?: mTransactionLog.put(item); } /** * Returns the TimeMachine. * * The TimeMachine object is internally locked, so access is safe and defined, * but multiple threaded access may change results after calling. */ TimeMachine& timeMachine() { return mTimeMachine; } const TimeMachine& timeMachine() const { return mTimeMachine; } /** * Returns the TransactionLog. * * The TransactionLog object is internally locked, so access is safe and defined, * but multiple threaded access may change results after calling. */ TransactionLog& transactionLog() { return mTransactionLog; } const TransactionLog& transactionLog() const { return mTransactionLog; } /** * Returns a pair consisting of the dump string, and the number of lines in the string. * Loading services/mediametrics/AudioAnalytics.cpp +61 −5 Original line number Diff line number Diff line Loading @@ -32,16 +32,60 @@ AudioAnalytics::AudioAnalytics() // This triggers on an item of "audio.flinger" // with a property "event" set to "AudioFlinger" (the constructor). mActions.addAction( "audio.flinger.event", std::string("AudioFlinger"), AMEDIAMETRICS_KEY_AUDIO_FLINGER "." AMEDIAMETRICS_PROP_EVENT, std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_CTOR), std::make_shared<AnalyticsActions::Function>( [this](const std::shared_ptr<const android::mediametrics::Item> &){ ALOGW("Audioflinger() constructor event detected"); [this](const std::shared_ptr<const android::mediametrics::Item> &item){ ALOGW("(key=%s) Audioflinger constructor event detected", item->getKey().c_str()); mPreviousAnalyticsState.set(std::make_shared<AnalyticsState>( *mAnalyticsState.get())); // Note: get returns shared_ptr temp, whose lifetime is extended // to end of full expression. mAnalyticsState->clear(); // TODO: filter the analytics state. // Perhaps report this. })); // Check underruns mActions.addAction( AMEDIAMETRICS_KEY_PREFIX_AUDIO_THREAD "*." AMEDIAMETRICS_PROP_EVENT, std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_UNDERRUN), std::make_shared<AnalyticsActions::Function>( [this](const std::shared_ptr<const android::mediametrics::Item> &item){ std::string threadId = item->getKey().substr( sizeof(AMEDIAMETRICS_KEY_PREFIX_AUDIO_THREAD) - 1); std::string outputDevices; mAnalyticsState->timeMachine().get( item->getKey(), AMEDIAMETRICS_PROP_OUTPUTDEVICES, &outputDevices); ALOGD("(key=%s) Thread underrun event detected on io handle:%s device:%s", item->getKey().c_str(), threadId.c_str(), outputDevices.c_str()); if (outputDevices.find("AUDIO_DEVICE_OUT_BLUETOOTH") != std::string::npos) { // report this for Bluetooth } })); // Check latencies, playback and startup mActions.addAction( AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK "*." AMEDIAMETRICS_PROP_LATENCYMS, std::monostate{}, // accept any value std::make_shared<AnalyticsActions::Function>( [this](const std::shared_ptr<const android::mediametrics::Item> &item){ double latencyMs{}; double startupMs{}; if (!item->get(AMEDIAMETRICS_PROP_LATENCYMS, &latencyMs) || !item->get(AMEDIAMETRICS_PROP_STARTUPMS, &startupMs)) return; std::string trackId = item->getKey().substr( sizeof(AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK) - 1); std::string thread = getThreadFromTrack(item->getKey()); std::string outputDevices; mAnalyticsState->timeMachine().get( thread, AMEDIAMETRICS_PROP_OUTPUTDEVICES, &outputDevices); ALOGD("(key=%s) Track latencyMs:%lf startupMs:%lf detected on port:%s device:%s", item->getKey().c_str(), latencyMs, startupMs, trackId.c_str(), outputDevices.c_str()); if (outputDevices.find("AUDIO_DEVICE_OUT_BLUETOOTH") != std::string::npos) { // report this for Bluetooth } })); } Loading @@ -53,7 +97,7 @@ AudioAnalytics::~AudioAnalytics() status_t AudioAnalytics::submit( const std::shared_ptr<const mediametrics::Item>& item, bool isTrusted) { if (!startsWith(item->getKey(), "audio.")) return BAD_VALUE; if (!startsWith(item->getKey(), AMEDIAMETRICS_KEY_PREFIX_AUDIO)) return BAD_VALUE; status_t status = mAnalyticsState->submit(item, isTrusted); if (status != NO_ERROR) return status; // may not be permitted. Loading Loading @@ -94,4 +138,16 @@ void AudioAnalytics::checkActions(const std::shared_ptr<const mediametrics::Item } } // HELPER METHODS std::string AudioAnalytics::getThreadFromTrack(const std::string& track) const { int32_t threadId_int32{}; if (mAnalyticsState->timeMachine().get( track, AMEDIAMETRICS_PROP_THREADID, &threadId_int32) != NO_ERROR) { return {}; } return std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_THREAD) + std::to_string(threadId_int32); } } // namespace android Loading
cmds/screenrecord/screenrecord.cpp +7 −8 Original line number Diff line number Diff line Loading @@ -84,14 +84,13 @@ using android::Vector; using android::sp; using android::status_t; using android::DISPLAY_ORIENTATION_0; using android::DISPLAY_ORIENTATION_180; using android::DISPLAY_ORIENTATION_90; using android::INVALID_OPERATION; using android::NAME_NOT_FOUND; using android::NO_ERROR; using android::UNKNOWN_ERROR; namespace ui = android::ui; static const uint32_t kMinBitRate = 100000; // 0.1Mbps static const uint32_t kMaxBitRate = 200 * 1000000; // 200Mbps static const uint32_t kMaxTimeLimitSec = 180; // 3 minutes Loading Loading @@ -328,7 +327,7 @@ static status_t setDisplayProjection( } t.setDisplayProjection(dpy, gRotate ? DISPLAY_ORIENTATION_90 : DISPLAY_ORIENTATION_0, gRotate ? ui::ROTATION_90 : ui::ROTATION_0, layerStackRect, displayRect); return NO_ERROR; } Loading Loading @@ -414,7 +413,7 @@ static status_t writeWinscopeMetadata(const Vector<int64_t>& timestamps, */ static status_t runEncoder(const sp<MediaCodec>& encoder, AMediaMuxer *muxer, FILE* rawFp, const sp<IBinder>& display, const sp<IBinder>& virtualDpy, uint8_t orientation) { const sp<IBinder>& virtualDpy, ui::Rotation orientation) { static int kTimeout = 250000; // be responsive on signal status_t err; ssize_t trackIdx = -1; Loading Loading @@ -484,7 +483,7 @@ static status_t runEncoder(const sp<MediaCodec>& encoder, if (err != NO_ERROR) { ALOGW("getDisplayInfo(main) failed: %d", err); } else if (orientation != displayInfo.orientation) { ALOGD("orientation changed, now %d", displayInfo.orientation); ALOGD("orientation changed, now %s", toCString(displayInfo.orientation)); SurfaceComposerClient::Transaction t; setDisplayProjection(t, virtualDpy, displayInfo); t.apply(); Loading Loading @@ -691,9 +690,9 @@ static status_t recordScreen(const char* fileName) { } if (gVerbose) { printf("Display is %dx%d @%.2ffps (orientation=%u), layerStack=%u\n", printf("Display is %dx%d @%.2ffps (orientation=%s), layerStack=%u\n", displayInfo.viewportW, displayInfo.viewportH, displayInfo.fps, displayInfo.orientation, displayInfo.layerStack); toCString(displayInfo.orientation), displayInfo.layerStack); fflush(stdout); } Loading
media/libmediametrics/include/MediaMetricsItem.h +43 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,49 @@ namespace android { /* * MediaMetrics Keys and Properties for Audio. * * C/C++ friendly constants that ensure * 1) Compilation error on misspelling * 2) Consistent behavior and documentation. * * TODO: Move to separate header file. */ // Taxonomy of audio keys // Key Prefixes are used for MediaMetrics Item Keys and ends with a ".". // They must be appended with another value to make a key. #define AMEDIAMETRICS_KEY_PREFIX_AUDIO "audio." // The AudioRecord key appends the "trackId" to the prefix. #define AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD AMEDIAMETRICS_KEY_PREFIX_AUDIO "record." // The AudioThread key appends the "threadId" to the prefix. #define AMEDIAMETRICS_KEY_PREFIX_AUDIO_THREAD AMEDIAMETRICS_KEY_PREFIX_AUDIO "thread." // The AudioTrack key appends the "trackId" to the prefix. #define AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK AMEDIAMETRICS_KEY_PREFIX_AUDIO "track." // Keys are strings used for MediaMetrics Item Keys #define AMEDIAMETRICS_KEY_AUDIO_FLINGER AMEDIAMETRICS_KEY_PREFIX_AUDIO "flinger" #define AMEDIAMETRICS_KEY_AUDIO_POLICY AMEDIAMETRICS_KEY_PREFIX_AUDIO "policy" // Props are properties allowed for Mediametrics Items. #define AMEDIAMETRICS_PROP_EVENT "event" // string value (often func name) #define AMEDIAMETRICS_PROP_LATENCYMS "latencyMs" // double value #define AMEDIAMETRICS_PROP_OUTPUTDEVICES "outputDevices" // string value #define AMEDIAMETRICS_PROP_STARTUPMS "startupMs" // double value #define AMEDIAMETRICS_PROP_THREADID "threadId" // int32 value io handle // Values are strings accepted for a given property. // An event is a general description, which often is a function name. #define AMEDIAMETRICS_PROP_EVENT_VALUE_CTOR "ctor" #define AMEDIAMETRICS_PROP_EVENT_VALUE_DTOR "dtor" #define AMEDIAMETRICS_PROP_EVENT_VALUE_UNDERRUN "underrun" // from Thread class IMediaMetricsService; class Parcel; Loading
media/tests/benchmark/src/native/encoder/Encoder.cpp +1 −0 Original line number Diff line number Diff line Loading @@ -159,6 +159,7 @@ void Encoder::deInitCodec() { AMediaFormat_delete(mFormat); mFormat = nullptr; } if (!mCodec) return; AMediaCodec_stop(mCodec); AMediaCodec_delete(mCodec); int64_t eTime = mStats->getCurTime(); Loading
services/mediametrics/AnalyticsState.h +18 −0 Original line number Diff line number Diff line Loading @@ -55,6 +55,24 @@ public: return mTimeMachine.put(item, isTrusted) ?: mTransactionLog.put(item); } /** * Returns the TimeMachine. * * The TimeMachine object is internally locked, so access is safe and defined, * but multiple threaded access may change results after calling. */ TimeMachine& timeMachine() { return mTimeMachine; } const TimeMachine& timeMachine() const { return mTimeMachine; } /** * Returns the TransactionLog. * * The TransactionLog object is internally locked, so access is safe and defined, * but multiple threaded access may change results after calling. */ TransactionLog& transactionLog() { return mTransactionLog; } const TransactionLog& transactionLog() const { return mTransactionLog; } /** * Returns a pair consisting of the dump string, and the number of lines in the string. * Loading
services/mediametrics/AudioAnalytics.cpp +61 −5 Original line number Diff line number Diff line Loading @@ -32,16 +32,60 @@ AudioAnalytics::AudioAnalytics() // This triggers on an item of "audio.flinger" // with a property "event" set to "AudioFlinger" (the constructor). mActions.addAction( "audio.flinger.event", std::string("AudioFlinger"), AMEDIAMETRICS_KEY_AUDIO_FLINGER "." AMEDIAMETRICS_PROP_EVENT, std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_CTOR), std::make_shared<AnalyticsActions::Function>( [this](const std::shared_ptr<const android::mediametrics::Item> &){ ALOGW("Audioflinger() constructor event detected"); [this](const std::shared_ptr<const android::mediametrics::Item> &item){ ALOGW("(key=%s) Audioflinger constructor event detected", item->getKey().c_str()); mPreviousAnalyticsState.set(std::make_shared<AnalyticsState>( *mAnalyticsState.get())); // Note: get returns shared_ptr temp, whose lifetime is extended // to end of full expression. mAnalyticsState->clear(); // TODO: filter the analytics state. // Perhaps report this. })); // Check underruns mActions.addAction( AMEDIAMETRICS_KEY_PREFIX_AUDIO_THREAD "*." AMEDIAMETRICS_PROP_EVENT, std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_UNDERRUN), std::make_shared<AnalyticsActions::Function>( [this](const std::shared_ptr<const android::mediametrics::Item> &item){ std::string threadId = item->getKey().substr( sizeof(AMEDIAMETRICS_KEY_PREFIX_AUDIO_THREAD) - 1); std::string outputDevices; mAnalyticsState->timeMachine().get( item->getKey(), AMEDIAMETRICS_PROP_OUTPUTDEVICES, &outputDevices); ALOGD("(key=%s) Thread underrun event detected on io handle:%s device:%s", item->getKey().c_str(), threadId.c_str(), outputDevices.c_str()); if (outputDevices.find("AUDIO_DEVICE_OUT_BLUETOOTH") != std::string::npos) { // report this for Bluetooth } })); // Check latencies, playback and startup mActions.addAction( AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK "*." AMEDIAMETRICS_PROP_LATENCYMS, std::monostate{}, // accept any value std::make_shared<AnalyticsActions::Function>( [this](const std::shared_ptr<const android::mediametrics::Item> &item){ double latencyMs{}; double startupMs{}; if (!item->get(AMEDIAMETRICS_PROP_LATENCYMS, &latencyMs) || !item->get(AMEDIAMETRICS_PROP_STARTUPMS, &startupMs)) return; std::string trackId = item->getKey().substr( sizeof(AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK) - 1); std::string thread = getThreadFromTrack(item->getKey()); std::string outputDevices; mAnalyticsState->timeMachine().get( thread, AMEDIAMETRICS_PROP_OUTPUTDEVICES, &outputDevices); ALOGD("(key=%s) Track latencyMs:%lf startupMs:%lf detected on port:%s device:%s", item->getKey().c_str(), latencyMs, startupMs, trackId.c_str(), outputDevices.c_str()); if (outputDevices.find("AUDIO_DEVICE_OUT_BLUETOOTH") != std::string::npos) { // report this for Bluetooth } })); } Loading @@ -53,7 +97,7 @@ AudioAnalytics::~AudioAnalytics() status_t AudioAnalytics::submit( const std::shared_ptr<const mediametrics::Item>& item, bool isTrusted) { if (!startsWith(item->getKey(), "audio.")) return BAD_VALUE; if (!startsWith(item->getKey(), AMEDIAMETRICS_KEY_PREFIX_AUDIO)) return BAD_VALUE; status_t status = mAnalyticsState->submit(item, isTrusted); if (status != NO_ERROR) return status; // may not be permitted. Loading Loading @@ -94,4 +138,16 @@ void AudioAnalytics::checkActions(const std::shared_ptr<const mediametrics::Item } } // HELPER METHODS std::string AudioAnalytics::getThreadFromTrack(const std::string& track) const { int32_t threadId_int32{}; if (mAnalyticsState->timeMachine().get( track, AMEDIAMETRICS_PROP_THREADID, &threadId_int32) != NO_ERROR) { return {}; } return std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_THREAD) + std::to_string(threadId_int32); } } // namespace android