/* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define STATSD_DEBUG false // STOPSHIP if true #include "Log.h" #include "StatsPuller.h" #include "StatsPullerManager.h" #include "guardrail/StatsdStats.h" #include "puller_util.h" #include "stats_log_util.h" #include "utils/api_tracing.h" namespace android { namespace os { namespace statsd { using std::lock_guard; sp StatsPuller::mUidMap = nullptr; void StatsPuller::SetUidMap(const sp& uidMap) { mUidMap = uidMap; } StatsPuller::StatsPuller(const int tagId, const int64_t coolDownNs, const int64_t pullTimeoutNs, const std::vector& additiveFields) : mTagId(tagId), mPullTimeoutNs(pullTimeoutNs), mCoolDownNs(coolDownNs), mAdditiveFields(additiveFields), mLastPullTimeNs(0), mLastEventTimeNs(0) { } PullErrorCode StatsPuller::Pull(const int64_t eventTimeNs, std::vector>* data) { ATRACE_CALL(); lock_guard lock(mLock); const int64_t elapsedTimeNs = getElapsedRealtimeNs(); const int64_t systemUptimeMillis = getSystemUptimeMillis(); StatsdStats::getInstance().notePull(mTagId); const bool shouldUseCache = (mLastEventTimeNs == eventTimeNs) || (elapsedTimeNs - mLastPullTimeNs < mCoolDownNs); if (shouldUseCache) { if (mHasGoodData) { (*data) = mCachedData; StatsdStats::getInstance().notePullFromCache(mTagId); } return mHasGoodData ? PULL_SUCCESS : PULL_FAIL; } if (mLastPullTimeNs > 0) { StatsdStats::getInstance().updateMinPullIntervalSec( mTagId, (elapsedTimeNs - mLastPullTimeNs) / NS_PER_SEC); } mCachedData.clear(); mLastPullTimeNs = elapsedTimeNs; mLastEventTimeNs = eventTimeNs; PullErrorCode status = PullInternal(&mCachedData); mHasGoodData = (status == PULL_SUCCESS); if (!mHasGoodData) { return status; } const int64_t pullElapsedDurationNs = getElapsedRealtimeNs() - elapsedTimeNs; const int64_t pullSystemUptimeDurationMillis = getSystemUptimeMillis() - systemUptimeMillis; StatsdStats::getInstance().notePullTime(mTagId, pullElapsedDurationNs); const bool pullTimeOut = pullElapsedDurationNs > mPullTimeoutNs; if (pullTimeOut) { // Something went wrong. Discard the data. mCachedData.clear(); mHasGoodData = false; StatsdStats::getInstance().notePullTimeout( mTagId, pullSystemUptimeDurationMillis, NanoToMillis(pullElapsedDurationNs)); ALOGW("Pull for atom %d exceeds timeout %lld nano seconds.", mTagId, (long long)pullElapsedDurationNs); return PULL_FAIL; } if (mCachedData.size() > 0) { mapAndMergeIsolatedUidsToHostUid(mCachedData, mUidMap, mTagId, mAdditiveFields); } if (mCachedData.empty()) { VLOG("Data pulled is empty"); StatsdStats::getInstance().noteEmptyData(mTagId); } (*data) = mCachedData; return PULL_SUCCESS; } int StatsPuller::ForceClearCache() { return clearCache(); } int StatsPuller::clearCache() { lock_guard lock(mLock); return clearCacheLocked(); } int StatsPuller::clearCacheLocked() { int ret = mCachedData.size(); mCachedData.clear(); mLastPullTimeNs = 0; mLastEventTimeNs = 0; return ret; } int StatsPuller::ClearCacheIfNecessary(int64_t timestampNs) { if (timestampNs - mLastPullTimeNs > mCoolDownNs) { return clearCache(); } else { return 0; } } } // namespace statsd } // namespace os } // namespace android