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