1 /*
2  * Copyright (C) 2019 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.server.am;
18 
19 import com.android.internal.annotations.GuardedBy;
20 
21 /**
22  * Detects low memory using PSI.
23  *
24  * If the kernel doesn't support PSI, then this class is not available.
25  */
26 public final class LowMemDetector {
27     private static final String TAG = "LowMemDetector";
28     private final ActivityManagerService mAm;
29     private final LowMemThread mLowMemThread;
30     private boolean mAvailable;
31 
32     private final Object mPressureStateLock = new Object();
33 
34     @GuardedBy("mPressureStateLock")
35     private int mPressureState = MEM_PRESSURE_NONE;
36 
37     /* getPressureState return values */
38     public static final int MEM_PRESSURE_NONE = 0;
39     public static final int MEM_PRESSURE_LOW = 1;
40     public static final int MEM_PRESSURE_MEDIUM = 2;
41     public static final int MEM_PRESSURE_HIGH = 3;
42 
LowMemDetector(ActivityManagerService am)43     LowMemDetector(ActivityManagerService am) {
44         mAm = am;
45         mLowMemThread = new LowMemThread();
46         if (init() != 0) {
47             mAvailable = false;
48         } else {
49             mAvailable = true;
50             mLowMemThread.start();
51         }
52     }
53 
isAvailable()54     public boolean isAvailable() {
55         return mAvailable;
56     }
57 
58     /**
59      * Returns the current mem factor.
60      * Note that getMemFactor returns LowMemDetector.MEM_PRESSURE_XXX
61      * which match ProcessStats.ADJ_MEM_FACTOR_XXX values. If they deviate
62      * there should be conversion performed here to translate pressure state
63      * into memFactor.
64      */
getMemFactor()65     public int getMemFactor() {
66         synchronized (mPressureStateLock) {
67             return mPressureState;
68         }
69     }
70 
init()71     private native int init();
waitForPressure()72     private native int waitForPressure();
73 
74     private final class LowMemThread extends Thread {
run()75         public void run() {
76 
77             while (true) {
78                 // sleep waiting for a PSI event
79                 int newPressureState = waitForPressure();
80                 if (newPressureState == -1) {
81                     // epoll broke, tear this down
82                     mAvailable = false;
83                     break;
84                 }
85                 // got a PSI event? let's update lowmem info
86                 synchronized (mPressureStateLock) {
87                     mPressureState = newPressureState;
88                 }
89             }
90         }
91     }
92 }
93