1 /* 2 * Copyright (C) 2020 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 "TimeMachine.h" 20 #include "TransactionLog.h" 21 22 namespace android::mediametrics { 23 24 /** 25 * AnalyticsState consists of a TimeMachine and TransactionLog for a set 26 * of MediaMetrics Items. 27 * 28 * One can add new Items with the submit() method. 29 * 30 * The AnalyticsState may be cleared or duplicated to preserve state after crashes 31 * in services are detected. 32 * 33 * As its members may not be moveable due to mutexes, we use this encapsulation 34 * with a shared pointer in order to save it or duplicate it. 35 */ 36 class AnalyticsState { 37 public: 38 /** 39 * Returns success if AnalyticsState accepts the item. 40 * 41 * A trusted source can create a new key, an untrusted source 42 * can only modify the key if the uid will match that authorized 43 * on the existing key. 44 * 45 * \param item the item to be submitted. 46 * \param isTrusted whether the transaction comes from a trusted source. 47 * In this case, a trusted source is verified by binder 48 * UID to be a system service by MediaMetrics service. 49 * Do not use true if you haven't really checked! 50 * 51 * \return NO_ERROR on success or 52 * PERMISSION_DENIED if the item cannot be put into the AnalyticsState. 53 */ submit(const std::shared_ptr<const mediametrics::Item> & item,bool isTrusted)54 status_t submit(const std::shared_ptr<const mediametrics::Item>& item, bool isTrusted) { 55 return mTimeMachine.put(item, isTrusted) ?: mTransactionLog.put(item); 56 } 57 58 /** 59 * Returns the TimeMachine. 60 * 61 * The TimeMachine object is internally locked, so access is safe and defined, 62 * but multiple threaded access may change results after calling. 63 */ timeMachine()64 TimeMachine& timeMachine() { return mTimeMachine; } timeMachine()65 const TimeMachine& timeMachine() const { return mTimeMachine; } 66 67 /** 68 * Returns the TransactionLog. 69 * 70 * The TransactionLog object is internally locked, so access is safe and defined, 71 * but multiple threaded access may change results after calling. 72 */ transactionLog()73 TransactionLog& transactionLog() { return mTransactionLog; } transactionLog()74 const TransactionLog& transactionLog() const { return mTransactionLog; } 75 76 /** 77 * Returns a pair consisting of the dump string, and the number of lines in the string. 78 * 79 * The number of lines in the returned pair is used as an optimization 80 * for subsequent line limiting. 81 * 82 * The TimeMachine and the TransactionLog are dumped separately under 83 * different locks, so may not be 100% consistent with the last data 84 * delivered. 85 * 86 * \param lines the maximum number of lines in the string returned. 87 * \param sinceNs the nanoseconds since Unix epoch to start dump (0 shows all) 88 * \param prefix the desired key prefix to match (nullptr shows all) 89 */ 90 std::pair<std::string, int32_t> dump( 91 int32_t lines = INT32_MAX, int64_t sinceNs = 0, const char *prefix = nullptr) const { 92 std::stringstream ss; 93 int32_t ll = lines; 94 95 if (ll > 0) { 96 ss << "TransactionLog: gc(" << mTransactionLog.getGarbageCollectionCount() << ")\n"; 97 --ll; 98 } 99 if (ll > 0) { 100 auto [s, l] = mTransactionLog.dump(ll, sinceNs, prefix); 101 ss << s; 102 ll -= l; 103 } 104 if (ll > 0) { 105 ss << "TimeMachine: gc(" << mTimeMachine.getGarbageCollectionCount() << ")\n"; 106 --ll; 107 } 108 if (ll > 0) { 109 auto [s, l] = mTimeMachine.dump(ll, sinceNs, prefix); 110 ss << s; 111 ll -= l; 112 } 113 return { ss.str(), lines - ll }; 114 } 115 116 /** 117 * Clears the AnalyticsState. 118 */ clear()119 void clear() { 120 mTimeMachine.clear(); 121 mTransactionLog.clear(); 122 } 123 124 private: 125 // Note: TimeMachine and TransactionLog are individually locked. 126 // Access to these objects under multiple threads will be weakly synchronized, 127 // which is acceptable as modifications only increase the history (or with GC, 128 // eliminates very old history). 129 130 TimeMachine mTimeMachine; 131 TransactionLog mTransactionLog; 132 }; 133 134 } // namespace android::mediametrics 135