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