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