1 /* 2 * Copyright (C) 2023 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 <android-base/thread_annotations.h> 20 21 #include <memory> 22 #include <vector> 23 24 #include <stddef.h> 25 26 #include <memevents/bpf_types.h> 27 28 namespace android { 29 namespace bpf { 30 namespace memevents { 31 32 enum MemEventClient { 33 // BASE should always be first, used for lower-bound checks 34 BASE = 0, 35 AMS = BASE, 36 LMKD, 37 /* 38 * Flag to indicate whether this `MemEventListener` instance is used for 39 * testing purposes. This allows us to skip internal calls that would 40 * otherwise interfere with test setup, and mocks for BPF ring buffer, 41 * and BPF program behavior. 42 */ 43 TEST_CLIENT, 44 // NR_CLIENTS should always come after the last valid client 45 NR_CLIENTS 46 }; 47 48 class MemBpfRingbuf; 49 50 class MemEventListener final { 51 public: 52 /* 53 * MemEventListener will `std::abort` when failing to initialize 54 * the bpf ring buffer manager, on a bpf-rb supported kernel. 55 * 56 * If running on a kernel that doesn't support bpf-rb, the listener 57 * will initialize in an invalid state, preventing it from making 58 * any actions/calls. 59 * To check if the listener initialized correctly use `ok()`. 60 */ 61 MemEventListener(MemEventClient client, bool attachTpForTests = false); 62 ~MemEventListener(); 63 64 /** 65 * Check if the listener was initialized correctly, with a valid bpf 66 * ring buffer manager on a bpf-rb supported kernel. 67 * 68 * @return true if initialized with a valid bpf rb manager, false 69 * otherwise. 70 */ 71 bool ok(); 72 73 /** 74 * Registers the requested memory event to the listener. 75 * 76 * @param event_type Memory event type to listen for. 77 * @return true if registration was successful, false otherwise. 78 */ 79 bool registerEvent(mem_event_type_t event_type); 80 81 /** 82 * Waits for a [registered] memory event notification. 83 * 84 * `listen()` will block until either: 85 * - Receives a registered memory event 86 * - Timeout expires 87 * 88 * Note that the default timeout (-1) causes `listen()` to block 89 * indefinitely. 90 * 91 * @param timeout_ms number of milliseconds that listen will block. 92 * @return true if there are new memory events to read, false otherwise. 93 */ 94 bool listen(int timeout_ms = -1); 95 96 /** 97 * Stops listening for a specific memory event type. 98 * 99 * @param event_type Memory event type to stop listening to. 100 * @return true if unregistering was successful, false otherwise 101 */ 102 bool deregisterEvent(mem_event_type_t event_type); 103 104 /** 105 * Closes all the events' file descriptors and `mEpfd`. This will also 106 * gracefully terminate any ongoing `listen()`. 107 */ 108 void deregisterAllEvents(); 109 110 /** 111 * Retrieves unread [registered] memory events, and stores them into the 112 * provided `mem_events` vector. 113 * 114 * On first invocation, it will read/store all memory events. After the 115 * initial invocation, it will only read/store new, unread, events. 116 * 117 * @param mem_events vector in which we want to append the read 118 * memory events. 119 * @return true on success, false on failure. 120 */ 121 bool getMemEvents(std::vector<mem_event_t>& mem_events); 122 123 /** 124 * Expose the MemEventClient's ring-buffer file descriptor for polling purposes, 125 * not intended for consumption. To consume use `ConsumeAll()`. 126 * 127 * @return file descriptor (non negative integer), -1 on error. 128 */ 129 int getRingBufferFd(); 130 131 private: 132 bool mEventsRegistered[NR_MEM_EVENTS]; 133 int mNumEventsRegistered; 134 MemEventClient mClient; 135 /* 136 * BFP ring buffer is designed as single producer single consumer. 137 * Protect against concurrent accesses. 138 */ 139 std::mutex mRingBufMutex; 140 std::unique_ptr<MemBpfRingbuf> memBpfRb GUARDED_BY(mRingBufMutex); 141 bool mAttachTpForTests; 142 143 bool isValidEventType(mem_event_type_t event_type) const; 144 }; 145 146 } // namespace memevents 147 } // namespace bpf 148 } // namespace android 149