/* * Copyright (C) 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.am; import com.android.internal.annotations.GuardedBy; /** * Detects low memory using PSI. * * If the kernel doesn't support PSI, then this class is not available. */ public final class LowMemDetector { private static final String TAG = "LowMemDetector"; private final ActivityManagerService mAm; private final LowMemThread mLowMemThread; private boolean mAvailable; private final Object mPressureStateLock = new Object(); @GuardedBy("mPressureStateLock") private int mPressureState = MEM_PRESSURE_NONE; /* getPressureState return values */ public static final int MEM_PRESSURE_NONE = 0; public static final int MEM_PRESSURE_LOW = 1; public static final int MEM_PRESSURE_MEDIUM = 2; public static final int MEM_PRESSURE_HIGH = 3; LowMemDetector(ActivityManagerService am) { mAm = am; mLowMemThread = new LowMemThread(); if (init() != 0) { mAvailable = false; } else { mAvailable = true; mLowMemThread.start(); } } public boolean isAvailable() { return mAvailable; } /** * Returns the current mem factor. * Note that getMemFactor returns LowMemDetector.MEM_PRESSURE_XXX * which match ProcessStats.ADJ_MEM_FACTOR_XXX values. If they deviate * there should be conversion performed here to translate pressure state * into memFactor. */ public int getMemFactor() { synchronized (mPressureStateLock) { return mPressureState; } } private native int init(); private native int waitForPressure(); private final class LowMemThread extends Thread { public void run() { while (true) { // sleep waiting for a PSI event int newPressureState = waitForPressure(); if (newPressureState == -1) { // epoll broke, tear this down mAvailable = false; break; } // got a PSI event? let's update lowmem info synchronized (mPressureStateLock) { mPressureState = newPressureState; } } } } }