1 /*
2  * Copyright (C) 2017 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 DEBUG false  // STOPSHIP if true
18 #include "Log.h"
19 
20 #include "StatsPuller.h"
21 #include "StatsPullerManager.h"
22 #include "guardrail/StatsdStats.h"
23 #include "puller_util.h"
24 #include "stats_log_util.h"
25 
26 namespace android {
27 namespace os {
28 namespace statsd {
29 
30 using std::lock_guard;
31 
32 sp<UidMap> StatsPuller::mUidMap = nullptr;
SetUidMap(const sp<UidMap> & uidMap)33 void StatsPuller::SetUidMap(const sp<UidMap>& uidMap) { mUidMap = uidMap; }
34 
StatsPuller(const int tagId)35 StatsPuller::StatsPuller(const int tagId)
36     : mTagId(tagId), mLastPullTimeNs(0) {
37 }
38 
Pull(std::vector<std::shared_ptr<LogEvent>> * data)39 bool StatsPuller::Pull(std::vector<std::shared_ptr<LogEvent>>* data) {
40     lock_guard<std::mutex> lock(mLock);
41     int64_t elapsedTimeNs = getElapsedRealtimeNs();
42     StatsdStats::getInstance().notePull(mTagId);
43     const bool shouldUseCache = elapsedTimeNs - mLastPullTimeNs <
44                                 StatsPullerManager::kAllPullAtomInfo.at(mTagId).coolDownNs;
45     if (shouldUseCache) {
46         if (mHasGoodData) {
47             (*data) = mCachedData;
48             StatsdStats::getInstance().notePullFromCache(mTagId);
49         }
50         return mHasGoodData;
51     }
52 
53     if (mLastPullTimeNs > 0) {
54         StatsdStats::getInstance().updateMinPullIntervalSec(
55                 mTagId, (elapsedTimeNs - mLastPullTimeNs) / NS_PER_SEC);
56     }
57     mCachedData.clear();
58     mLastPullTimeNs = elapsedTimeNs;
59     mHasGoodData = PullInternal(&mCachedData);
60     if (!mHasGoodData) {
61         return mHasGoodData;
62     }
63     const int64_t pullDurationNs = getElapsedRealtimeNs() - elapsedTimeNs;
64     StatsdStats::getInstance().notePullTime(mTagId, pullDurationNs);
65     const bool pullTimeOut =
66             pullDurationNs > StatsPullerManager::kAllPullAtomInfo.at(mTagId).pullTimeoutNs;
67     if (pullTimeOut) {
68         // Something went wrong. Discard the data.
69         clearCacheLocked();
70         mHasGoodData = false;
71         StatsdStats::getInstance().notePullTimeout(mTagId);
72         ALOGW("Pull for atom %d exceeds timeout %lld nano seconds.", mTagId,
73               (long long)pullDurationNs);
74         return mHasGoodData;
75     }
76 
77     if (mCachedData.size() > 0) {
78         mapAndMergeIsolatedUidsToHostUid(mCachedData, mUidMap, mTagId);
79     }
80 
81     (*data) = mCachedData;
82     return mHasGoodData;
83 }
84 
ForceClearCache()85 int StatsPuller::ForceClearCache() {
86     return clearCache();
87 }
88 
clearCache()89 int StatsPuller::clearCache() {
90     lock_guard<std::mutex> lock(mLock);
91     return clearCacheLocked();
92 }
93 
clearCacheLocked()94 int StatsPuller::clearCacheLocked() {
95     int ret = mCachedData.size();
96     mCachedData.clear();
97     mLastPullTimeNs = 0;
98     return ret;
99 }
100 
ClearCacheIfNecessary(int64_t timestampNs)101 int StatsPuller::ClearCacheIfNecessary(int64_t timestampNs) {
102     if (timestampNs - mLastPullTimeNs >
103         StatsPullerManager::kAllPullAtomInfo.at(mTagId).coolDownNs) {
104         return clearCache();
105     } else {
106         return 0;
107     }
108 }
109 
110 }  // namespace statsd
111 }  // namespace os
112 }  // namespace android
113