xref: /aosp_15_r20/build/soong/ui/metrics/proc/status_linux.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
1*333d2b36SAndroid Build Coastguard Workerpackage proc
2*333d2b36SAndroid Build Coastguard Worker
3*333d2b36SAndroid Build Coastguard Workerimport (
4*333d2b36SAndroid Build Coastguard Worker	"io/ioutil"
5*333d2b36SAndroid Build Coastguard Worker	"path/filepath"
6*333d2b36SAndroid Build Coastguard Worker	"strconv"
7*333d2b36SAndroid Build Coastguard Worker	"strings"
8*333d2b36SAndroid Build Coastguard Worker
9*333d2b36SAndroid Build Coastguard Worker	"android/soong/finder/fs"
10*333d2b36SAndroid Build Coastguard Worker)
11*333d2b36SAndroid Build Coastguard Worker
12*333d2b36SAndroid Build Coastguard Worker// NewProcStatus returns an instance of the ProcStatus that contains memory
13*333d2b36SAndroid Build Coastguard Worker// information of the process. The memory information is extracted from the
14*333d2b36SAndroid Build Coastguard Worker// "/proc/<pid>/status" text file. This is only available for Linux
15*333d2b36SAndroid Build Coastguard Worker// distribution that supports /proc.
16*333d2b36SAndroid Build Coastguard Workerfunc NewProcStatus(pid int, fileSystem fs.FileSystem) (*ProcStatus, error) {
17*333d2b36SAndroid Build Coastguard Worker	statusFname := filepath.Join("/proc", strconv.Itoa(pid), "status")
18*333d2b36SAndroid Build Coastguard Worker	r, err := fileSystem.Open(statusFname)
19*333d2b36SAndroid Build Coastguard Worker	if err != nil {
20*333d2b36SAndroid Build Coastguard Worker		return &ProcStatus{}, err
21*333d2b36SAndroid Build Coastguard Worker	}
22*333d2b36SAndroid Build Coastguard Worker	defer r.Close()
23*333d2b36SAndroid Build Coastguard Worker
24*333d2b36SAndroid Build Coastguard Worker	data, err := ioutil.ReadAll(r)
25*333d2b36SAndroid Build Coastguard Worker	if err != nil {
26*333d2b36SAndroid Build Coastguard Worker		return &ProcStatus{}, err
27*333d2b36SAndroid Build Coastguard Worker	}
28*333d2b36SAndroid Build Coastguard Worker
29*333d2b36SAndroid Build Coastguard Worker	s := &ProcStatus{
30*333d2b36SAndroid Build Coastguard Worker		pid: pid,
31*333d2b36SAndroid Build Coastguard Worker	}
32*333d2b36SAndroid Build Coastguard Worker
33*333d2b36SAndroid Build Coastguard Worker	for _, l := range strings.Split(string(data), "\n") {
34*333d2b36SAndroid Build Coastguard Worker		// If the status file does not contain "key: values", just skip the line
35*333d2b36SAndroid Build Coastguard Worker		// as the information we are looking for is not needed.
36*333d2b36SAndroid Build Coastguard Worker		if !strings.Contains(l, ":") {
37*333d2b36SAndroid Build Coastguard Worker			continue
38*333d2b36SAndroid Build Coastguard Worker		}
39*333d2b36SAndroid Build Coastguard Worker
40*333d2b36SAndroid Build Coastguard Worker		// At this point, we're only considering entries that has key, single value pairs.
41*333d2b36SAndroid Build Coastguard Worker		kv := strings.SplitN(l, ":", 2)
42*333d2b36SAndroid Build Coastguard Worker		fillProcStatus(s, strings.TrimSpace(kv[0]), strings.TrimSpace(kv[1]))
43*333d2b36SAndroid Build Coastguard Worker	}
44*333d2b36SAndroid Build Coastguard Worker
45*333d2b36SAndroid Build Coastguard Worker	return s, nil
46*333d2b36SAndroid Build Coastguard Worker}
47