blob: 4711bb62fa8305aa9b093be41e711fca15960cb1 [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 /**
59 * Returns a pair consisting of the dump string, and the number of lines in the string.
60 *
61 * The number of lines in the returned pair is used as an optimization
62 * for subsequent line limiting.
63 *
64 * The TimeMachine and the TransactionLog are dumped separately under
65 * different locks, so may not be 100% consistent with the last data
66 * delivered.
67 *
68 * \param lines the maximum number of lines in the string returned.
69 */
70 std::pair<std::string, int32_t> dump(int32_t lines = INT32_MAX) const {
71 std::stringstream ss;
72 int32_t ll = lines;
73
74 if (ll > 0) {
75 ss << "TransactionLog:\n";
76 --ll;
77 }
78 if (ll > 0) {
79 auto [s, l] = mTransactionLog.dump(ll);
80 ss << s;
81 ll -= l;
82 }
83 if (ll > 0) {
84 ss << "TimeMachine:\n";
85 --ll;
86 }
87 if (ll > 0) {
88 auto [s, l] = mTimeMachine.dump(ll);
89 ss << s;
90 ll -= l;
91 }
92 return { ss.str(), lines - ll };
93 }
94
95 /**
96 * Clears the AnalyticsState.
97 */
98 void clear() {
99 mTimeMachine.clear();
100 mTransactionLog.clear();
101 }
102
103private:
104 // Note: TimeMachine and TransactionLog are individually locked.
105 // Access to these objects under multiple threads will be weakly synchronized,
106 // which is acceptable as modifications only increase the history (or with GC,
107 // eliminates very old history).
108
109 TimeMachine mTimeMachine;
110 TransactionLog mTransactionLog;
111};
112
113} // namespace android::mediametrics