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 details dumps the detailed internal state. 87 * \param lines the maximum number of lines in the string returned. 88 * \param sinceNs the nanoseconds since Unix epoch to start dump (0 shows all) 89 * \param prefix the desired key prefix to match (nullptr shows all) 90 */ 91 std::pair<std::string, int32_t> dump(bool details, 92 int32_t lines = INT32_MAX, int64_t sinceNs = 0, const char *prefix = nullptr) const { 93 std::stringstream ss; 94 int32_t ll = lines; 95 96 if (ll > 0) { 97 ss << "TransactionLog: gc(" << mTransactionLog.getGarbageCollectionCount() << ")\n"; 98 --ll; 99 } 100 if (details && ll > 0) { 101 auto [s, l] = mTransactionLog.dump(ll, sinceNs, prefix); 102 ss << s; 103 ll -= l; 104 } 105 if (ll > 0) { 106 ss << "TimeMachine: gc(" << mTimeMachine.getGarbageCollectionCount() << ")\n"; 107 --ll; 108 } 109 if (details && ll > 0) { 110 auto [s, l] = mTimeMachine.dump(ll, sinceNs, prefix); 111 ss << s; 112 ll -= l; 113 } 114 return { ss.str(), lines - ll }; 115 } 116 117 /** 118 * Clears the AnalyticsState. 119 */ clear()120 void clear() { 121 mTimeMachine.clear(); 122 mTransactionLog.clear(); 123 } 124 125 private: 126 // Note: TimeMachine and TransactionLog are individually locked. 127 // Access to these objects under multiple threads will be weakly synchronized, 128 // which is acceptable as modifications only increase the history (or with GC, 129 // eliminates very old history). 130 131 TimeMachine mTimeMachine; 132 TransactionLog mTransactionLog; 133 }; 134 135 } // namespace android::mediametrics 136