xref: /aosp_15_r20/frameworks/av/services/mediametrics/include/mediametricsservice/AnalyticsState.h (revision ec779b8e0859a360c3d303172224686826e6e0e1)
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