1 /* 2 * Copyright (C) 2018 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 21 #include <condition_variable> 22 #include <mutex> 23 #include <thread> 24 25 #include "external/StatsPullerManager.h" 26 #include "packages/UidMap.h" 27 #include "shell/ShellSubscriberClient.h" 28 #include "src/shell/shell_config.pb.h" 29 #include "src/statsd_config.pb.h" 30 31 namespace android { 32 namespace os { 33 namespace statsd { 34 35 /** 36 * Handles atoms subscription via shell cmd. 37 * 38 * A shell subscription lasts *until shell exits*. Unlike config based clients, a shell client 39 * communicates with statsd via file descriptors. They can subscribe pushed and pulled atoms. 40 * The atoms are sent back to the client in real time, as opposed to keeping the data in memory. 41 * Shell clients do not subscribe aggregated metrics, as they are responsible for doing the 42 * aggregation after receiving the atom events. 43 * 44 * Shell clients pass ShellSubscription in the proto binary format. Clients can update the 45 * subscription by sending a new subscription. The new subscription would replace the old one. 46 * Input data stream format is: 47 * 48 * |size_t|subscription proto|size_t|subscription proto|.... 49 * 50 * statsd sends the events back in Atom proto binary format. Each Atom message is preceded 51 * with sizeof(size_t) bytes indicating the size of the proto message payload. 52 * 53 * The stream would be in the following format: 54 * |size_t|shellData proto|size_t|shellData proto|.... 55 * 56 */ 57 class ShellSubscriber : public virtual RefBase { 58 public: ShellSubscriber(const sp<UidMap> & uidMap,const sp<StatsPullerManager> & pullerMgr,const std::shared_ptr<LogEventFilter> & logEventFilter)59 ShellSubscriber(const sp<UidMap>& uidMap, const sp<StatsPullerManager>& pullerMgr, 60 const std::shared_ptr<LogEventFilter>& logEventFilter) 61 : mUidMap(uidMap), mPullerMgr(pullerMgr), mLogEventFilter(logEventFilter){}; 62 63 ~ShellSubscriber(); 64 65 // Create new ShellSubscriberClient with file descriptors to manage a new subscription. 66 bool startNewSubscription(int inFd, int outFd, int64_t timeoutSec); 67 68 // Create new ShellSubscriberClient with Binder callback to manage a new subscription. 69 bool startNewSubscription( 70 const vector<uint8_t>& subscriptionConfig, 71 const shared_ptr<aidl::android::os::IStatsSubscriptionCallback>& callback); 72 73 void onLogEvent(const LogEvent& event); 74 75 void flushSubscription( 76 const shared_ptr<aidl::android::os::IStatsSubscriptionCallback>& callback); 77 78 void unsubscribe(const shared_ptr<aidl::android::os::IStatsSubscriptionCallback>& callback); 79 getMaxSizeKb()80 static size_t getMaxSizeKb() { 81 return ShellSubscriberClient::getMaxSizeKb(); 82 } 83 getMaxSubscriptions()84 static size_t getMaxSubscriptions() { 85 return kMaxSubscriptions; 86 } 87 88 private: 89 bool startNewSubscriptionLocked(unique_ptr<ShellSubscriberClient> client); 90 91 void pullAndSendHeartbeats(); 92 93 /* Tells LogEventFilter about atom ids to parse */ 94 void updateLogEventFilterLocked() const; 95 96 sp<UidMap> mUidMap; 97 98 sp<StatsPullerManager> mPullerMgr; 99 100 std::shared_ptr<LogEventFilter> mLogEventFilter; 101 102 // Protects mClientSet, mThreadAlive, and ShellSubscriberClient 103 mutable std::mutex mMutex; 104 105 std::set<unique_ptr<ShellSubscriberClient>> mClientSet; 106 107 bool mThreadAlive = false; 108 109 std::condition_variable mThreadSleepCV; 110 111 std::thread mThread; 112 113 static constexpr size_t kMaxSubscriptions = 20; 114 }; 115 116 } // namespace statsd 117 } // namespace os 118 } // namespace android 119