• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_CRITICAL;
20 import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_LOW;
21 import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_MODERATE;
22 import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_NORMAL;
23 import static com.android.internal.app.procstats.ProcessStats.ADJ_NOTHING;
24 
25 import android.annotation.IntDef;
26 
27 import com.android.internal.annotations.GuardedBy;
28 
29 import java.lang.annotation.Retention;
30 import java.lang.annotation.RetentionPolicy;
31 
32 /**
33  * Detects low memory using PSI.
34  *
35  * If the kernel doesn't support PSI, then this class is not available.
36  */
37 public final class LowMemDetector {
38     private static final String TAG = "LowMemDetector";
39     private final ActivityManagerService mAm;
40     private final LowMemThread mLowMemThread;
41     private boolean mAvailable;
42 
43     private final Object mPressureStateLock = new Object();
44 
45     @GuardedBy("mPressureStateLock")
46     private int mPressureState = ADJ_MEM_FACTOR_NORMAL;
47 
48     public static final int ADJ_MEM_FACTOR_NOTHING = ADJ_NOTHING;
49 
50     /* getPressureState return values */
51     @IntDef(prefix = { "ADJ_MEM_FACTOR_" }, value = {
52         ADJ_MEM_FACTOR_NOTHING,
53         ADJ_MEM_FACTOR_NORMAL,
54         ADJ_MEM_FACTOR_MODERATE,
55         ADJ_MEM_FACTOR_LOW,
56         ADJ_MEM_FACTOR_CRITICAL,
57     })
58     @Retention(RetentionPolicy.SOURCE)
59     public @interface MemFactor{}
60 
LowMemDetector(ActivityManagerService am)61     LowMemDetector(ActivityManagerService am) {
62         mAm = am;
63         mLowMemThread = new LowMemThread();
64         if (init() != 0) {
65             mAvailable = false;
66         } else {
67             mAvailable = true;
68             mLowMemThread.start();
69         }
70     }
71 
isAvailable()72     public boolean isAvailable() {
73         return mAvailable;
74     }
75 
76     /**
77      * Returns the current mem factor.
78      * Note that getMemFactor returns LowMemDetector.MEM_PRESSURE_XXX
79      * which match ProcessStats.ADJ_MEM_FACTOR_XXX values. If they deviate
80      * there should be conversion performed here to translate pressure state
81      * into memFactor.
82      */
getMemFactor()83     public @MemFactor int getMemFactor() {
84         synchronized (mPressureStateLock) {
85             return mPressureState;
86         }
87     }
88 
init()89     private native int init();
waitForPressure()90     private native int waitForPressure();
91 
92     private final class LowMemThread extends Thread {
run()93         public void run() {
94 
95             while (true) {
96                 // sleep waiting for a PSI event
97                 int newPressureState = waitForPressure();
98                 if (newPressureState == -1) {
99                     // epoll broke, tear this down
100                     mAvailable = false;
101                     break;
102                 }
103                 // got a PSI event? let's update lowmem info
104                 synchronized (mPressureStateLock) {
105                     mPressureState = newPressureState;
106                 }
107             }
108         }
109     }
110 }
111