1 /* 2 * Copyright (C) 2019 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 "StatsCallbackPuller.h" 21 #include "PullResultReceiver.h" 22 #include "StatsPullerManager.h" 23 #include "logd/LogEvent.h" 24 #include "stats_log_util.h" 25 26 #include <aidl/android/util/StatsEventParcel.h> 27 28 using namespace std; 29 30 using Status = ::ndk::ScopedAStatus; 31 using aidl::android::util::StatsEventParcel; 32 using ::ndk::SharedRefBase; 33 34 namespace android { 35 namespace os { 36 namespace statsd { 37 38 StatsCallbackPuller::StatsCallbackPuller(int tagId, const shared_ptr<IPullAtomCallback>& callback, 39 const int64_t coolDownNs, int64_t timeoutNs, 40 const vector<int> additiveFields) 41 : StatsPuller(tagId, coolDownNs, timeoutNs, additiveFields), mCallback(callback) { 42 VLOG("StatsCallbackPuller created for tag %d", tagId); 43 } 44 45 bool StatsCallbackPuller::PullInternal(vector<shared_ptr<LogEvent>>* data) { 46 VLOG("StatsCallbackPuller called for tag %d", mTagId); 47 if(mCallback == nullptr) { 48 ALOGW("No callback registered"); 49 return false; 50 } 51 52 // Shared variables needed in the result receiver. 53 shared_ptr<mutex> cv_mutex = make_shared<mutex>(); 54 shared_ptr<condition_variable> cv = make_shared<condition_variable>(); 55 shared_ptr<bool> pullFinish = make_shared<bool>(false); 56 shared_ptr<bool> pullSuccess = make_shared<bool>(false); 57 shared_ptr<vector<shared_ptr<LogEvent>>> sharedData = 58 make_shared<vector<shared_ptr<LogEvent>>>(); 59 60 shared_ptr<PullResultReceiver> resultReceiver = SharedRefBase::make<PullResultReceiver>( 61 [cv_mutex, cv, pullFinish, pullSuccess, sharedData]( 62 int32_t atomTag, bool success, const vector<StatsEventParcel>& output) { 63 // This is the result of the pull, executing in a statsd binder thread. 64 // The pull could have taken a long time, and we should only modify 65 // data (the output param) if the pointer is in scope and the pull did not time out. 66 { 67 lock_guard<mutex> lk(*cv_mutex); 68 for (const StatsEventParcel& parcel: output) { 69 shared_ptr<LogEvent> event = make_shared<LogEvent>(/*uid=*/-1, /*pid=*/-1); 70 bool valid = event->parseBuffer((uint8_t*)parcel.buffer.data(), 71 parcel.buffer.size()); 72 if (valid) { 73 sharedData->push_back(event); 74 } else { 75 StatsdStats::getInstance().noteAtomError(event->GetTagId(), 76 /*pull=*/true); 77 } 78 } 79 *pullSuccess = success; 80 *pullFinish = true; 81 } 82 cv->notify_one(); 83 }); 84 85 // Initiate the pull. This is a oneway call to a different process, except 86 // in unit tests. In process calls are not oneway. 87 Status status = mCallback->onPullAtom(mTagId, resultReceiver); 88 if (!status.isOk()) { 89 StatsdStats::getInstance().notePullBinderCallFailed(mTagId); 90 return false; 91 } 92 93 { 94 unique_lock<mutex> unique_lk(*cv_mutex); 95 // Wait until the pull finishes, or until the pull timeout. 96 cv->wait_for(unique_lk, chrono::nanoseconds(mPullTimeoutNs), 97 [pullFinish] { return *pullFinish; }); 98 if (!*pullFinish) { 99 // Note: The parent stats puller will also note that there was a timeout and that the 100 // cache should be cleared. Once we migrate all pullers to this callback, we could 101 // consolidate the logic. 102 return true; 103 } else { 104 // Only copy the data if we did not timeout and the pull was successful. 105 if (*pullSuccess) { 106 *data = std::move(*sharedData); 107 } 108 VLOG("StatsCallbackPuller::pull succeeded for %d", mTagId); 109 return *pullSuccess; 110 } 111 } 112 } 113 114 } // namespace statsd 115 } // namespace os 116 } // namespace android 117