blob: 09c0b4c32017bdf34609ffa7f4a67f6fe4f538de [file] [log] [blame]
Andy Hung0f7ad8c2020-01-03 13:24:34 -08001/*
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
22namespace 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 */
36class AnalyticsState {
37public:
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 */
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 /**
Andy Hungea186fa2020-01-09 18:13:15 -080059 * 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 */
64 TimeMachine& timeMachine() { return mTimeMachine; }
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 */
73 TransactionLog& transactionLog() { return mTransactionLog; }
74 const TransactionLog& transactionLog() const { return mTransactionLog; }
75
76 /**
Andy Hung0f7ad8c2020-01-03 13:24:34 -080077 * 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.
Andy Hung709b91e2020-04-04 14:23:36 -070087 * \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)
Andy Hung0f7ad8c2020-01-03 13:24:34 -080089 */
Andy Hung709b91e2020-04-04 14:23:36 -070090 std::pair<std::string, int32_t> dump(
91 int32_t lines = INT32_MAX, int64_t sinceNs = 0, const char *prefix = nullptr) const {
Andy Hung0f7ad8c2020-01-03 13:24:34 -080092 std::stringstream ss;
93 int32_t ll = lines;
94
95 if (ll > 0) {
Andy Hung47178c22020-06-18 18:57:35 -070096 ss << "TransactionLog: gc(" << mTransactionLog.getGarbageCollectionCount() << ")\n";
Andy Hung0f7ad8c2020-01-03 13:24:34 -080097 --ll;
98 }
99 if (ll > 0) {
Andy Hung709b91e2020-04-04 14:23:36 -0700100 auto [s, l] = mTransactionLog.dump(ll, sinceNs, prefix);
Andy Hungb744faf2020-04-09 13:09:26 -0700101 ss << s;
Andy Hung0f7ad8c2020-01-03 13:24:34 -0800102 ll -= l;
103 }
104 if (ll > 0) {
Andy Hung47178c22020-06-18 18:57:35 -0700105 ss << "TimeMachine: gc(" << mTimeMachine.getGarbageCollectionCount() << ")\n";
Andy Hung0f7ad8c2020-01-03 13:24:34 -0800106 --ll;
107 }
108 if (ll > 0) {
Andy Hung709b91e2020-04-04 14:23:36 -0700109 auto [s, l] = mTimeMachine.dump(ll, sinceNs, prefix);
Andy Hungb744faf2020-04-09 13:09:26 -0700110 ss << s;
Andy Hung0f7ad8c2020-01-03 13:24:34 -0800111 ll -= l;
112 }
113 return { ss.str(), lines - ll };
114 }
115
116 /**
117 * Clears the AnalyticsState.
118 */
119 void clear() {
120 mTimeMachine.clear();
121 mTransactionLog.clear();
122 }
123
124private:
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