1 /*
2 * Copyright (C) 2019, 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 #define STATSD_DEBUG false // STOPSHIP if true
18 #include "Log.h"
19
20 #include "StateManager.h"
21
22 #include <private/android_filesystem_config.h>
23 #include <statslog_statsd.h>
24
25 #include <unordered_set>
26
27 namespace android {
28 namespace os {
29 namespace statsd {
30
StateManager()31 StateManager::StateManager()
32 : mAllowedPkg({
33 "com.android.systemui",
34 }) {
35 }
36
getInstance()37 StateManager& StateManager::getInstance() {
38 static StateManager sStateManager;
39 return sStateManager;
40 }
41
clear()42 void StateManager::clear() {
43 mStateTrackers.clear();
44 }
45
onLogEvent(const LogEvent & event)46 void StateManager::onLogEvent(const LogEvent& event) {
47 // Only process state events from uids in AID_* and packages that are whitelisted in
48 // mAllowedPkg.
49 // Allowlisted AIDs are AID_ROOT and all AIDs in [1000, 2000) which is [AID_SYSTEM, AID_SHELL)
50 if (event.GetUid() == AID_ROOT ||
51 (event.GetUid() >= AID_SYSTEM && event.GetUid() < AID_SHELL) ||
52 mAllowedLogSources.find(event.GetUid()) != mAllowedLogSources.end()) {
53 const int tagId = event.GetTagId();
54 if (tagId == util::STATS_SOCKET_LOSS_REPORTED) {
55 // Hard coded logic to handle socket loss info to highlight metric corruption reason
56 const std::optional<SocketLossInfo>& lossInfo = toSocketLossInfo(event);
57 if (lossInfo) {
58 handleSocketLossInfo(*lossInfo);
59 }
60 } else {
61 auto stateTrackersForEvent = mStateTrackers.find(tagId);
62 if (stateTrackersForEvent != mStateTrackers.end()) {
63 stateTrackersForEvent->second->onLogEvent(event);
64 }
65 }
66 }
67 }
68
handleSocketLossInfo(const SocketLossInfo & socketLossInfo)69 void StateManager::handleSocketLossInfo(const SocketLossInfo& socketLossInfo) {
70 // socketLossInfo stores atomId per UID - to eliminate duplicates using set
71 const std::unordered_set<int> uniqueLostAtomIds(socketLossInfo.atomIds.begin(),
72 socketLossInfo.atomIds.end());
73
74 // pass lost atom id to all relevant metrics
75 for (const auto lostAtomId : uniqueLostAtomIds) {
76 onLogEventLost(lostAtomId, DATA_CORRUPTED_SOCKET_LOSS);
77 }
78 }
79
onLogEventLost(int32_t lostAtomId,DataCorruptedReason reason)80 bool StateManager::onLogEventLost(int32_t lostAtomId, DataCorruptedReason reason) {
81 auto stateTrackersIt = mStateTrackers.find(lostAtomId);
82 if (stateTrackersIt != mStateTrackers.end()) {
83 stateTrackersIt->second->onLogEventLost(reason);
84 return true;
85 }
86 return false;
87 }
88
registerListener(const int32_t atomId,const wp<StateListener> & listener)89 void StateManager::registerListener(const int32_t atomId, const wp<StateListener>& listener) {
90 // Check if state tracker already exists.
91 if (mStateTrackers.find(atomId) == mStateTrackers.end()) {
92 mStateTrackers[atomId] = new StateTracker(atomId);
93 }
94 mStateTrackers[atomId]->registerListener(listener);
95 }
96
unregisterListener(const int32_t atomId,const wp<StateListener> & listener)97 void StateManager::unregisterListener(const int32_t atomId, const wp<StateListener>& listener) {
98 std::unique_lock<std::mutex> lock(mMutex);
99
100 // Hold the sp<> until the lock is released so that ~StateTracker() is
101 // not called while the lock is held.
102 sp<StateTracker> toRemove;
103
104 // Unregister listener from correct StateTracker
105 auto it = mStateTrackers.find(atomId);
106 if (it != mStateTrackers.end()) {
107 it->second->unregisterListener(listener);
108
109 // Remove the StateTracker if it has no listeners
110 if (it->second->getListenersCount() == 0) {
111 toRemove = it->second;
112 mStateTrackers.erase(it);
113 }
114 } else {
115 ALOGE("StateManager cannot unregister listener, StateTracker for atom %d does not exist",
116 atomId);
117 }
118 lock.unlock();
119 }
120
getStateValue(const int32_t atomId,const HashableDimensionKey & key,FieldValue * output) const121 bool StateManager::getStateValue(const int32_t atomId, const HashableDimensionKey& key,
122 FieldValue* output) const {
123 auto it = mStateTrackers.find(atomId);
124 if (it != mStateTrackers.end()) {
125 return it->second->getStateValue(key, output);
126 }
127 ALOGE("StateManager cannot get state value, no StateTracker for atom %d", atomId);
128 return false;
129 }
130
updateLogSources(const sp<UidMap> & uidMap)131 void StateManager::updateLogSources(const sp<UidMap>& uidMap) {
132 mAllowedLogSources.clear();
133 for (const auto& pkg : mAllowedPkg) {
134 auto uids = uidMap->getAppUid(pkg);
135 mAllowedLogSources.insert(uids.begin(), uids.end());
136 }
137 }
138
notifyAppChanged(const string & apk,const sp<UidMap> & uidMap)139 void StateManager::notifyAppChanged(const string& apk, const sp<UidMap>& uidMap) {
140 if (mAllowedPkg.find(apk) != mAllowedPkg.end()) {
141 updateLogSources(uidMap);
142 }
143 }
144
addAllAtomIds(LogEventFilter::AtomIdSet & allIds) const145 void StateManager::addAllAtomIds(LogEventFilter::AtomIdSet& allIds) const {
146 for (const auto& stateTracker : mStateTrackers) {
147 allIds.insert(stateTracker.first);
148 }
149 }
150
151 } // namespace statsd
152 } // namespace os
153 } // namespace android
154