1 /* 2 * Copyright (C) 2022 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 #pragma once 18 19 #include <aidl/android/os/IStatsSubscriptionCallback.h> 20 #include <aidl/android/os/StatsSubscriptionCallbackReason.h> 21 #include <android-base/file.h> 22 #include <android/util/ProtoOutputStream.h> 23 #include <private/android_filesystem_config.h> 24 25 #include <memory> 26 27 #include "external/StatsPullerManager.h" 28 #include "logd/LogEvent.h" 29 #include "packages/UidMap.h" 30 #include "socket/LogEventFilter.h" 31 #include "src/shell/shell_config.pb.h" 32 #include "src/statsd_config.pb.h" 33 34 using aidl::android::os::IStatsSubscriptionCallback; 35 using aidl::android::os::StatsSubscriptionCallbackReason; 36 37 namespace android { 38 namespace os { 39 namespace statsd { 40 41 // ShellSubscriberClient is not thread-safe. All calls must be 42 // guarded by the mutex in ShellSubscriber.h 43 class ShellSubscriberClient { 44 public: 45 struct PullInfo { 46 PullInfo(const SimpleAtomMatcher& matcher, int64_t startTimeMs, int64_t interval, 47 const std::vector<std::string>& packages, const std::vector<int32_t>& uids); 48 49 const SimpleAtomMatcher mPullerMatcher; 50 const int64_t mIntervalMs; 51 int64_t mPrevPullElapsedRealtimeMs; 52 const std::vector<std::string> mPullPackages; 53 const std::vector<int32_t> mPullUids; 54 }; 55 56 static std::unique_ptr<ShellSubscriberClient> create(int in, int out, int64_t timeoutSec, 57 int64_t startTimeSec, 58 const sp<UidMap>& uidMap, 59 const sp<StatsPullerManager>& pullerMgr); 60 61 static std::unique_ptr<ShellSubscriberClient> create( 62 const std::vector<uint8_t>& subscriptionConfig, 63 const std::shared_ptr<IStatsSubscriptionCallback>& callback, int64_t startTimeSec, 64 const sp<UidMap>& uidMap, const sp<StatsPullerManager>& pullerMgr); 65 66 // Should only be called by the create() factory. 67 explicit ShellSubscriberClient(int out, 68 const std::shared_ptr<IStatsSubscriptionCallback>& callback, 69 const std::vector<SimpleAtomMatcher>& pushedMatchers, 70 const std::vector<PullInfo>& pulledInfo, int64_t timeoutSec, 71 int64_t startTimeSec, const sp<UidMap>& uidMap, 72 const sp<StatsPullerManager>& pullerMgr); 73 74 void onLogEvent(const LogEvent& event); 75 76 int64_t pullAndSendHeartbeatsIfNeeded(int64_t nowSecs, int64_t nowMillis, int64_t nowNanos); 77 78 // Should only be called when mCallback is not nullptr. 79 void flush(); 80 81 // Should only be called when mCallback is not nullptr. 82 void onUnsubscribe(); 83 isAlive()84 bool isAlive() const { 85 return mClientAlive; 86 } 87 hasCallback(const std::shared_ptr<IStatsSubscriptionCallback> & callback)88 bool hasCallback(const std::shared_ptr<IStatsSubscriptionCallback>& callback) const { 89 return mCallback != nullptr && callback != nullptr && 90 callback->asBinder() == mCallback->asBinder(); 91 } 92 getMaxSizeKb()93 static size_t getMaxSizeKb() { 94 return kMaxSizeKb; 95 } 96 97 void addAllAtomIds(LogEventFilter::AtomIdSet& allAtomIds) const; 98 99 // Minimum pull interval for callback subscriptions. 100 static constexpr int64_t kMinCallbackPullIntervalMs = 60'000; // 60 seconds. 101 102 // Minimum sleep for the pull thread for callback subscriptions. 103 static constexpr int64_t kMinCallbackSleepIntervalMs = 2000; // 2 seconds. 104 private: 105 int64_t pullIfNeeded(int64_t nowSecs, int64_t nowMillis, int64_t nowNanos); 106 107 void writePulledAtomsLocked(const vector<std::shared_ptr<LogEvent>>& data, 108 const SimpleAtomMatcher& matcher); 109 110 void attemptWriteToPipeLocked(); 111 112 void getUidsForPullAtom(vector<int32_t>* uids, const PullInfo& pullInfo); 113 114 void flushProtoIfNeeded(); 115 116 bool writeEventToProtoIfMatched(const LogEvent& event, const SimpleAtomMatcher& matcher, 117 const sp<UidMap>& uidMap); 118 119 void clearCache(); 120 121 void triggerFdFlush(); 122 123 void triggerCallback(StatsSubscriptionCallbackReason reason); 124 125 const int32_t DEFAULT_PULL_UID = AID_SYSTEM; 126 127 const sp<UidMap> mUidMap; 128 129 const sp<StatsPullerManager> mPullerMgr; 130 131 android::base::unique_fd mDupOut; 132 133 const std::vector<SimpleAtomMatcher> mPushedMatchers; 134 135 std::vector<PullInfo> mPulledInfo; 136 137 std::shared_ptr<IStatsSubscriptionCallback> mCallback; 138 139 const int64_t mTimeoutSec; 140 141 const int64_t mStartTimeSec; 142 143 bool mClientAlive = true; 144 145 int64_t mLastWriteMs; 146 147 // Stores Atom proto messages for events along with their respective timestamps. 148 ProtoOutputStream mProtoOut; 149 150 // Stores the total approximate encoded proto byte-size for cached Atom events in 151 // mEventTimestampNs and mProtoOut. 152 size_t mCacheSize; 153 154 static constexpr int64_t kMsBetweenHeartbeats = 1000; 155 156 // Cap the buffer size of configs to guard against bad allocations 157 static constexpr size_t kMaxSizeKb = 50; 158 159 static constexpr size_t kMaxCacheSizeBytes = 2 * 1024; // 2 KB 160 161 static constexpr int64_t kMsBetweenCallbacks = 70'000; // 70 seconds. 162 }; 163 164 } // namespace statsd 165 } // namespace os 166 } // namespace android 167