/* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef ANDROID_MEDIA_NBLOG_MERGER_H #define ANDROID_MEDIA_NBLOG_MERGER_H #include #include #include #include #include #include #include #include #include #include #include #include #include namespace android { class String16; class String8; namespace NBLog { struct Shared; // TODO update comments to reflect current functionalities // This class is used to read data from each thread's individual FIFO in shared memory // and write it to a single FIFO in local memory. class Merger : public RefBase { public: Merger(const void *shared, size_t size); ~Merger() override = default; void addReader(const sp &reader); // TODO add removeReader void merge(); // FIXME This is returning a reference to a shared variable that needs a lock const std::vector>& getReaders() const; private: // vector of the readers the merger is supposed to merge from. // every reader reads from a writer's buffer // FIXME Needs to be protected by a lock std::vector> mReaders; Shared * const mShared; // raw pointer to shared memory std::unique_ptr mFifo; // FIFO itself std::unique_ptr mFifoWriter; // used to write to FIFO }; // This class has a pointer to the FIFO in local memory which stores the merged // data collected by NBLog::Merger from all Readers. It is used to process // this data and write the result to PerformanceAnalysis. class MergeReader : public Reader { public: MergeReader(const void *shared, size_t size, Merger &merger); // process a particular snapshot of the reader void processSnapshot(Snapshot &snap, int author); // call getSnapshot of the content of the reader's buffer and process the data void getAndProcessSnapshot(); // check for periodic push of performance data to media metrics, and perform // the send if it is time to do so. void checkPushToMediaMetrics(); void dump(int fd, const Vector& args); private: // FIXME Needs to be protected by a lock, // because even though our use of it is read-only there may be asynchronous updates // The object is owned by the Merger class. const std::vector>& mReaders; // analyzes, compresses and stores the merged data // contains a separate instance for every author (thread), and for every source file // location within each author ReportPerformance::PerformanceAnalysisMap mThreadPerformanceAnalysis; // compresses and stores audio performance data from each thread's buffers. // first parameter is author, i.e. thread index. std::map mThreadPerformanceData; // how often to push data to Media Metrics static constexpr nsecs_t kPeriodicMediaMetricsPush = s2ns((nsecs_t)2 * 60 * 60); // 2 hours // handle author entry by looking up the author's name and appending it to the body // returns number of bytes read from fmtEntry void handleAuthor(const AbstractEntry &fmtEntry, String8 *body); }; // MergeThread is a thread that contains a Merger. It works as a retriggerable one-shot: // when triggered, it awakes for a lapse of time, during which it periodically merges; if // retriggered, the timeout is reset. // The thread is triggered on AudioFlinger binder activity. class MergeThread : public Thread { public: MergeThread(Merger &merger, MergeReader &mergeReader); ~MergeThread() override; // Reset timeout and activate thread to merge periodically if it's idle void wakeup(); // Set timeout period until the merging thread goes idle again void setTimeoutUs(int time); private: bool threadLoop() override; // the merger who actually does the work of merging the logs Merger& mMerger; // the mergereader used to process data merged by mMerger MergeReader& mMergeReader; // mutex for the condition variable Mutex mMutex; // condition variable to activate merging on timeout >= 0 Condition mCond; // time left until the thread blocks again (in microseconds) int mTimeoutUs; // merging period when the thread is awake static const int kThreadSleepPeriodUs = 1000000 /*1s*/; // initial timeout value when triggered static const int kThreadWakeupPeriodUs = 3000000 /*3s*/; }; } // namespace NBLog } // namespace android #endif // ANDROID_MEDIA_NBLOG_MERGER_H