1 /* 2 * Copyright (C) 2017 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 #pragma once 18 19 #include <atomic> 20 #include <deque> 21 #include <future> 22 #include <mutex> 23 #include <unordered_map> 24 25 // IMediaMetricsService must include Vector, String16, Errors 26 #include <android-base/thread_annotations.h> 27 #include <media/IMediaMetricsService.h> 28 #include <mediautils/ServiceUtilities.h> 29 #include <utils/String8.h> 30 31 #include "AudioAnalytics.h" 32 33 namespace android { 34 35 class MediaMetricsService : public BnMediaMetricsService 36 { 37 public: 38 MediaMetricsService(); 39 ~MediaMetricsService() override; 40 41 /** 42 * Submits the indicated record to the mediaanalytics service. 43 * 44 * \param item the item to submit. 45 * \return status failure, which is negative on binder transaction failure. 46 * As the transaction is one-way, remote failures will not be reported. 47 */ submit(mediametrics::Item * item)48 status_t submit(mediametrics::Item *item) override { 49 return submitInternal(item, false /* release */); 50 } 51 submitBuffer(const char * buffer,size_t length)52 status_t submitBuffer(const char *buffer, size_t length) override { 53 mediametrics::Item *item = new mediametrics::Item(); 54 return item->readFromByteString(buffer, length) 55 ?: submitInternal(item, true /* release */); 56 } 57 58 status_t dump(int fd, const Vector<String16>& args) override; 59 60 static constexpr const char * const kServiceName = "media.metrics"; 61 62 /** 63 * Rounds time to the nearest second. 64 */ 65 static nsecs_t roundTime(nsecs_t timeNs); 66 67 /** 68 * Returns true if we should use uid for package name when uploading to statsd. 69 */ 70 static bool useUidForPackage(const std::string& package, const std::string& installer); 71 72 /** 73 * Returns a std::pair of packageName and versionCode for a given uid. 74 * 75 * The value is sanitized - i.e. if the result is not approved to send, 76 * we use the uid as a string and a version code of 0. 77 */ 78 static std::pair<std::string, int64_t> getSanitizedPackageNameAndVersionCode(uid_t uid); 79 80 protected: 81 82 // Internal call where release is true if ownership of item is transferred 83 // to the service (that is, the service will eventually delete the item). 84 status_t submitInternal(mediametrics::Item *item, bool release) override; 85 86 private: 87 void processExpirations(); 88 // input validation after arrival from client 89 static bool isContentValid(const mediametrics::Item *item, bool isTrusted); 90 bool isRateLimited(mediametrics::Item *) const; 91 void saveItem(const std::shared_ptr<const mediametrics::Item>& item); 92 93 bool expirations(const std::shared_ptr<const mediametrics::Item>& item) REQUIRES(mLock); 94 95 // support for generating output 96 void dumpQueue(String8 &result, int64_t sinceNs, const char* prefix) REQUIRES(mLock); 97 void dumpHeaders(String8 &result, int64_t sinceNs, const char* prefix) REQUIRES(mLock); 98 99 // The following variables accessed without mLock 100 101 // limit how many records we'll retain 102 // by count (in each queue (open, finalized)) 103 const size_t mMaxRecords; 104 // by time (none older than this) 105 const nsecs_t mMaxRecordAgeNs; 106 // max to expire per expirations_l() invocation 107 const size_t mMaxRecordsExpiredAtOnce; 108 109 std::atomic<int64_t> mItemsSubmitted{}; // accessed outside of lock. 110 111 mediametrics::AudioAnalytics mAudioAnalytics; // mAudioAnalytics is locked internally. 112 113 std::mutex mLock; 114 // statistics about our analytics 115 int64_t mItemsFinalized GUARDED_BY(mLock) = 0; 116 int64_t mItemsDiscarded GUARDED_BY(mLock) = 0; 117 int64_t mItemsDiscardedExpire GUARDED_BY(mLock) = 0; 118 int64_t mItemsDiscardedCount GUARDED_BY(mLock) = 0; 119 120 // If we have a worker thread to garbage collect 121 std::future<void> mExpireFuture GUARDED_BY(mLock); 122 123 // Our item queue, generally (oldest at front) 124 // TODO: Make separate class, use segmented queue, write lock only end. 125 // Note: Another analytics module might have ownership of an item longer than the log. 126 std::deque<std::shared_ptr<const mediametrics::Item>> mItems GUARDED_BY(mLock); 127 }; 128 129 } // namespace android 130