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,const int64_t coolDownNs,const int64_t pullTimeoutNs,const std::vector<int> additiveFields)35 StatsPuller::StatsPuller(const int tagId, const int64_t coolDownNs, const int64_t pullTimeoutNs,
36                          const std::vector<int> additiveFields)
37     : mTagId(tagId),
38       mPullTimeoutNs(pullTimeoutNs),
39       mCoolDownNs(coolDownNs),
40       mAdditiveFields(additiveFields),
41       mLastPullTimeNs(0),
42       mLastEventTimeNs(0) {
43 }
44 
Pull(const int64_t eventTimeNs,std::vector<std::shared_ptr<LogEvent>> * data)45 bool StatsPuller::Pull(const int64_t eventTimeNs, std::vector<std::shared_ptr<LogEvent>>* data) {
46     lock_guard<std::mutex> lock(mLock);
47     const int64_t elapsedTimeNs = getElapsedRealtimeNs();
48     const int64_t systemUptimeMillis = getSystemUptimeMillis();
49     StatsdStats::getInstance().notePull(mTagId);
50     const bool shouldUseCache =
51             (mLastEventTimeNs == eventTimeNs) || (elapsedTimeNs - mLastPullTimeNs < mCoolDownNs);
52     if (shouldUseCache) {
53         if (mHasGoodData) {
54             (*data) = mCachedData;
55             StatsdStats::getInstance().notePullFromCache(mTagId);
56 
57         }
58         return mHasGoodData;
59     }
60     if (mLastPullTimeNs > 0) {
61         StatsdStats::getInstance().updateMinPullIntervalSec(
62                 mTagId, (elapsedTimeNs - mLastPullTimeNs) / NS_PER_SEC);
63     }
64     mCachedData.clear();
65     mLastPullTimeNs = elapsedTimeNs;
66     mLastEventTimeNs = eventTimeNs;
67     mHasGoodData = PullInternal(&mCachedData);
68     if (!mHasGoodData) {
69         return mHasGoodData;
70     }
71     const int64_t pullElapsedDurationNs = getElapsedRealtimeNs() - elapsedTimeNs;
72     const int64_t pullSystemUptimeDurationMillis = getSystemUptimeMillis() - systemUptimeMillis;
73     StatsdStats::getInstance().notePullTime(mTagId, pullElapsedDurationNs);
74     const bool pullTimeOut = pullElapsedDurationNs > mPullTimeoutNs;
75     if (pullTimeOut) {
76         // Something went wrong. Discard the data.
77         mCachedData.clear();
78         mHasGoodData = false;
79         StatsdStats::getInstance().notePullTimeout(
80                 mTagId, pullSystemUptimeDurationMillis, NanoToMillis(pullElapsedDurationNs));
81         ALOGW("Pull for atom %d exceeds timeout %lld nano seconds.", mTagId,
82               (long long)pullElapsedDurationNs);
83         return mHasGoodData;
84     }
85 
86     if (mCachedData.size() > 0) {
87         mapAndMergeIsolatedUidsToHostUid(mCachedData, mUidMap, mTagId, mAdditiveFields);
88     }
89 
90     if (mCachedData.empty()) {
91         VLOG("Data pulled is empty");
92         StatsdStats::getInstance().noteEmptyData(mTagId);
93     }
94 
95     (*data) = mCachedData;
96     return mHasGoodData;
97 }
98 
ForceClearCache()99 int StatsPuller::ForceClearCache() {
100     return clearCache();
101 }
102 
clearCache()103 int StatsPuller::clearCache() {
104     lock_guard<std::mutex> lock(mLock);
105     return clearCacheLocked();
106 }
107 
clearCacheLocked()108 int StatsPuller::clearCacheLocked() {
109     int ret = mCachedData.size();
110     mCachedData.clear();
111     mLastPullTimeNs = 0;
112     mLastEventTimeNs = 0;
113     return ret;
114 }
115 
ClearCacheIfNecessary(int64_t timestampNs)116 int StatsPuller::ClearCacheIfNecessary(int64_t timestampNs) {
117     if (timestampNs - mLastPullTimeNs > mCoolDownNs) {
118         return clearCache();
119     } else {
120         return 0;
121     }
122 }
123 
124 }  // namespace statsd
125 }  // namespace os
126 }  // namespace android
127