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 package com.android.internal.os;
18 
19 import com.android.internal.util.ProcFileReader;
20 
21 import java.io.FileInputStream;
22 import java.io.IOException;
23 import java.util.function.BiConsumer;
24 import java.util.function.Consumer;
25 import java.util.function.Predicate;
26 
27 /**
28  * Reads and parses {@code binder_logs/stats} file in the {@code binderfs} filesystem.
29  * Reuse procFileReader as the contents are generated by Linux kernel in the same way.
30  *
31  * A typical example of binderfs stats log
32  *
33  * binder stats:
34  * BC_TRANSACTION: 378004
35  * BC_REPLY: 268352
36  * BC_FREE_BUFFER: 665854
37  * ...
38  * proc 12645
39  * context binder
40  * threads: 12
41  * requested threads: 0+5/15
42  * ready threads 0
43  * free async space 520192
44  * ...
45  */
46 public class BinderfsStatsReader {
47     private final String mPath;
48 
BinderfsStatsReader()49     public BinderfsStatsReader() {
50         mPath = "/dev/binderfs/binder_logs/stats";
51     }
52 
BinderfsStatsReader(String path)53     public BinderfsStatsReader(String path) {
54         mPath = path;
55     }
56 
57     /**
58      * Read binderfs stats and call the consumer(pid, free) function for each valid process
59      *
60      * @param predicate  Test if the pid is valid.
61      * @param biConsumer Callback function for each valid pid and its free async space
62      * @param consumer   The error function to deal with exceptions
63      */
handleFreeAsyncSpace(Predicate<Integer> predicate, BiConsumer<Integer, Integer> biConsumer, Consumer<Exception> consumer)64     public void handleFreeAsyncSpace(Predicate<Integer> predicate,
65             BiConsumer<Integer, Integer> biConsumer, Consumer<Exception> consumer) {
66         try (ProcFileReader mReader = new ProcFileReader(new FileInputStream(mPath))) {
67             while (mReader.hasMoreData()) {
68                 // find the next process
69                 if (!mReader.nextString().equals("proc")) {
70                     mReader.finishLine();
71                     continue;
72                 }
73 
74                 // read pid
75                 int pid = mReader.nextInt();
76                 mReader.finishLine();
77 
78                 // check if we have interest in this process
79                 if (!predicate.test(pid)) {
80                     continue;
81                 }
82 
83                 // read free async space
84                 mReader.finishLine(); // context binder
85                 mReader.finishLine(); // threads:
86                 mReader.finishLine(); // requested threads:
87                 mReader.finishLine(); // ready threads
88                 if (!mReader.nextString().equals("free")) {
89                     mReader.finishLine();
90                     continue;
91                 }
92                 if (!mReader.nextString().equals("async")) {
93                     mReader.finishLine();
94                     continue;
95                 }
96                 if (!mReader.nextString().equals("space")) {
97                     mReader.finishLine();
98                     continue;
99                 }
100                 int free = mReader.nextInt();
101                 mReader.finishLine();
102                 biConsumer.accept(pid, free);
103             }
104         } catch (IOException | NumberFormatException e) {
105             consumer.accept(e);
106         }
107     }
108 }
109