Merge "Freezer: improve file lock exemption"
This commit is contained in:
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.internal.os;
|
||||
|
||||
import android.util.IntArray;
|
||||
|
||||
import com.android.internal.util.ProcFileReader;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
@@ -35,6 +37,7 @@ import java.io.IOException;
|
||||
public class ProcLocksReader {
|
||||
private final String mPath;
|
||||
private ProcFileReader mReader = null;
|
||||
private IntArray mPids = new IntArray();
|
||||
|
||||
public ProcLocksReader() {
|
||||
mPath = "/proc/locks";
|
||||
@@ -51,9 +54,13 @@ public class ProcLocksReader {
|
||||
public interface ProcLocksReaderCallback {
|
||||
/**
|
||||
* Call the callback function of handleBlockingFileLocks().
|
||||
* @param pid Each process that hold file locks blocking other processes.
|
||||
* @param pids Each process that hold file locks blocking other processes.
|
||||
* pids[0] is the process blocking others
|
||||
* pids[1..n-1] are the processes being blocked
|
||||
* NOTE: pids are cleared immediately after onBlockingFileLock() returns. If the caller
|
||||
* needs to cache it, please make a copy, e.g. by calling pids.toArray().
|
||||
*/
|
||||
void onBlockingFileLock(int pid);
|
||||
void onBlockingFileLock(IntArray pids);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -64,8 +71,7 @@ public class ProcLocksReader {
|
||||
public void handleBlockingFileLocks(ProcLocksReaderCallback callback) throws IOException {
|
||||
long last = -1;
|
||||
long id; // ordinal position of the lock in the list
|
||||
int owner = -1; // the PID of the process that owns the lock
|
||||
int pid = -1; // the PID of the process blocking others
|
||||
int pid = -1; // the PID of the process being blocked
|
||||
|
||||
if (mReader == null) {
|
||||
mReader = new ProcFileReader(new FileInputStream(mPath));
|
||||
@@ -73,26 +79,49 @@ public class ProcLocksReader {
|
||||
mReader.rewind();
|
||||
}
|
||||
|
||||
mPids.clear();
|
||||
while (mReader.hasMoreData()) {
|
||||
id = mReader.nextLong(true); // lock id
|
||||
if (id == last) {
|
||||
mReader.finishLine(); // blocked lock
|
||||
if (pid < 0) {
|
||||
pid = owner; // get pid from the previous line
|
||||
callback.onBlockingFileLock(pid);
|
||||
// blocked lock found
|
||||
mReader.nextIgnored(); // ->
|
||||
mReader.nextIgnored(); // lock type: POSIX?
|
||||
mReader.nextIgnored(); // lock type: MANDATORY?
|
||||
mReader.nextIgnored(); // lock type: RW?
|
||||
|
||||
pid = mReader.nextInt(); // pid
|
||||
if (pid > 0) {
|
||||
mPids.add(pid);
|
||||
}
|
||||
continue;
|
||||
|
||||
mReader.finishLine();
|
||||
} else {
|
||||
pid = -1; // a new lock
|
||||
// process blocking lock and move on to a new lock
|
||||
if (mPids.size() > 1) {
|
||||
callback.onBlockingFileLock(mPids);
|
||||
mPids.clear();
|
||||
}
|
||||
|
||||
// new lock found
|
||||
mReader.nextIgnored(); // lock type: POSIX?
|
||||
mReader.nextIgnored(); // lock type: MANDATORY?
|
||||
mReader.nextIgnored(); // lock type: RW?
|
||||
|
||||
pid = mReader.nextInt(); // pid
|
||||
if (pid > 0) {
|
||||
if (mPids.size() == 0) {
|
||||
mPids.add(pid);
|
||||
} else {
|
||||
mPids.set(0, pid);
|
||||
}
|
||||
}
|
||||
mReader.finishLine();
|
||||
last = id;
|
||||
}
|
||||
|
||||
mReader.nextIgnored(); // lock type: POSIX?
|
||||
mReader.nextIgnored(); // lock type: MANDATORY?
|
||||
mReader.nextIgnored(); // lock type: RW?
|
||||
|
||||
owner = mReader.nextInt(); // pid
|
||||
mReader.finishLine();
|
||||
last = id;
|
||||
}
|
||||
// The last unprocessed blocking lock immediately before EOF
|
||||
if (mPids.size() > 1) {
|
||||
callback.onBlockingFileLock(mPids);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import static org.junit.Assert.assertTrue;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.FileUtils;
|
||||
import android.util.IntArray;
|
||||
|
||||
import androidx.test.InstrumentationRegistry;
|
||||
import androidx.test.filters.SmallTest;
|
||||
@@ -33,13 +34,15 @@ import org.junit.runner.RunWith;
|
||||
import java.io.File;
|
||||
import java.nio.file.Files;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class ProcLocksReaderTest implements
|
||||
ProcLocksReader.ProcLocksReaderCallback {
|
||||
private File mProcDirectory;
|
||||
private ArrayList<Integer> mPids = new ArrayList<>();
|
||||
|
||||
private ArrayList<int[]> mPids = new ArrayList<>();
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
@@ -54,41 +57,51 @@ public class ProcLocksReaderTest implements
|
||||
|
||||
@Test
|
||||
public void testRunSimpleLocks() throws Exception {
|
||||
String simpleLocks =
|
||||
"1: POSIX ADVISORY READ 18403 fd:09:9070 1073741826 1073742335\n" +
|
||||
"2: POSIX ADVISORY WRITE 18292 fd:09:34062 0 EOF\n";
|
||||
String simpleLocks = "1: POSIX ADVISORY READ 18403 fd:09:9070 1073741826 1073742335\n"
|
||||
+ "2: POSIX ADVISORY WRITE 18292 fd:09:34062 0 EOF\n";
|
||||
runHandleBlockingFileLocks(simpleLocks);
|
||||
assertTrue(mPids.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRunBlockingLocks() throws Exception {
|
||||
String blockedLocks =
|
||||
"1: POSIX ADVISORY READ 18403 fd:09:9070 1073741826 1073742335\n" +
|
||||
"2: POSIX ADVISORY WRITE 18292 fd:09:34062 0 EOF\n" +
|
||||
"2: -> POSIX ADVISORY WRITE 18291 fd:09:34062 0 EOF\n" +
|
||||
"2: -> POSIX ADVISORY WRITE 18293 fd:09:34062 0 EOF\n" +
|
||||
"3: POSIX ADVISORY READ 3888 fd:09:13992 128 128\n" +
|
||||
"4: POSIX ADVISORY READ 3888 fd:09:14230 1073741826 1073742335\n";
|
||||
String blockedLocks = "1: POSIX ADVISORY READ 18403 fd:09:9070 1073741826 1073742335\n"
|
||||
+ "2: POSIX ADVISORY WRITE 18292 fd:09:34062 0 EOF\n"
|
||||
+ "2: -> POSIX ADVISORY WRITE 18291 fd:09:34062 0 EOF\n"
|
||||
+ "2: -> POSIX ADVISORY WRITE 18293 fd:09:34062 0 EOF\n"
|
||||
+ "3: POSIX ADVISORY READ 3888 fd:09:13992 128 128\n"
|
||||
+ "4: POSIX ADVISORY READ 3888 fd:09:14230 1073741826 1073742335\n";
|
||||
runHandleBlockingFileLocks(blockedLocks);
|
||||
assertTrue(mPids.remove(0).equals(18292));
|
||||
assertTrue(Arrays.equals(mPids.remove(0), new int[]{18292, 18291, 18293}));
|
||||
assertTrue(mPids.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRunLastBlockingLocks() throws Exception {
|
||||
String blockedLocks = "1: POSIX ADVISORY READ 18403 fd:09:9070 1073741826 1073742335\n"
|
||||
+ "2: POSIX ADVISORY WRITE 18292 fd:09:34062 0 EOF\n"
|
||||
+ "2: -> POSIX ADVISORY WRITE 18291 fd:09:34062 0 EOF\n"
|
||||
+ "2: -> POSIX ADVISORY WRITE 18293 fd:09:34062 0 EOF\n";
|
||||
runHandleBlockingFileLocks(blockedLocks);
|
||||
assertTrue(Arrays.equals(mPids.remove(0), new int[]{18292, 18291, 18293}));
|
||||
assertTrue(mPids.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRunMultipleBlockingLocks() throws Exception {
|
||||
String blockedLocks =
|
||||
"1: POSIX ADVISORY READ 18403 fd:09:9070 1073741826 1073742335\n" +
|
||||
"2: POSIX ADVISORY WRITE 18292 fd:09:34062 0 EOF\n" +
|
||||
"2: -> POSIX ADVISORY WRITE 18291 fd:09:34062 0 EOF\n" +
|
||||
"2: -> POSIX ADVISORY WRITE 18293 fd:09:34062 0 EOF\n" +
|
||||
"3: POSIX ADVISORY READ 3888 fd:09:13992 128 128\n" +
|
||||
"4: FLOCK ADVISORY WRITE 3840 fe:01:5111809 0 EOF\n" +
|
||||
"4: -> FLOCK ADVISORY WRITE 3841 fe:01:5111809 0 EOF\n" +
|
||||
"5: POSIX ADVISORY READ 3888 fd:09:14230 1073741826 1073742335\n";
|
||||
String blockedLocks = "1: POSIX ADVISORY READ 18403 fd:09:9070 1073741826 1073742335\n"
|
||||
+ "2: POSIX ADVISORY WRITE 18292 fd:09:34062 0 EOF\n"
|
||||
+ "2: -> POSIX ADVISORY WRITE 18291 fd:09:34062 0 EOF\n"
|
||||
+ "2: -> POSIX ADVISORY WRITE 18293 fd:09:34062 0 EOF\n"
|
||||
+ "3: POSIX ADVISORY READ 3888 fd:09:13992 128 128\n"
|
||||
+ "4: FLOCK ADVISORY WRITE 3840 fe:01:5111809 0 EOF\n"
|
||||
+ "4: -> FLOCK ADVISORY WRITE 3841 fe:01:5111809 0 EOF\n"
|
||||
+ "5: FLOCK ADVISORY READ 3888 fd:09:14230 0 EOF\n"
|
||||
+ "5: -> FLOCK ADVISORY READ 3887 fd:09:14230 0 EOF\n";
|
||||
runHandleBlockingFileLocks(blockedLocks);
|
||||
assertTrue(mPids.remove(0).equals(18292));
|
||||
assertTrue(mPids.remove(0).equals(3840));
|
||||
assertTrue(Arrays.equals(mPids.remove(0), new int[]{18292, 18291, 18293}));
|
||||
assertTrue(Arrays.equals(mPids.remove(0), new int[]{3840, 3841}));
|
||||
assertTrue(Arrays.equals(mPids.remove(0), new int[]{3888, 3887}));
|
||||
assertTrue(mPids.isEmpty());
|
||||
}
|
||||
|
||||
@@ -102,11 +115,12 @@ public class ProcLocksReaderTest implements
|
||||
|
||||
/**
|
||||
* Call the callback function of handleBlockingFileLocks().
|
||||
*
|
||||
* @param pid Each process that hold file locks blocking other processes.
|
||||
* @param pids Each process that hold file locks blocking other processes.
|
||||
* pids[0] is the process blocking others
|
||||
* pids[1..n-1] are the processes being blocked
|
||||
*/
|
||||
@Override
|
||||
public void onBlockingFileLock(int pid) {
|
||||
mPids.add(pid);
|
||||
public void onBlockingFileLock(IntArray pids) {
|
||||
mPids.add(pids.toArray());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ import android.provider.DeviceConfig.Properties;
|
||||
import android.provider.Settings;
|
||||
import android.text.TextUtils;
|
||||
import android.util.EventLog;
|
||||
import android.util.IntArray;
|
||||
import android.util.Pair;
|
||||
import android.util.Slog;
|
||||
import android.util.SparseArray;
|
||||
@@ -2110,15 +2111,28 @@ public final class CachedAppOptimizer {
|
||||
|
||||
@GuardedBy({"mAm"})
|
||||
@Override
|
||||
public void onBlockingFileLock(int pid) {
|
||||
public void onBlockingFileLock(IntArray pids) {
|
||||
if (DEBUG_FREEZER) {
|
||||
Slog.d(TAG_AM, "Process (pid=" + pid + ") holds blocking file lock");
|
||||
Slog.d(TAG_AM, "Blocking file lock found: " + pids);
|
||||
}
|
||||
synchronized (mProcLock) {
|
||||
int pid = pids.get(0);
|
||||
ProcessRecord app = mFrozenProcesses.get(pid);
|
||||
ProcessRecord pr;
|
||||
if (app != null) {
|
||||
Slog.i(TAG_AM, app.processName + " (" + pid + ") holds blocking file lock");
|
||||
unfreezeAppLSP(app, OomAdjuster.OOM_ADJ_REASON_NONE);
|
||||
for (int i = 1; i < pids.size(); i++) {
|
||||
int blocked = pids.get(i);
|
||||
synchronized (mAm.mPidsSelfLocked) {
|
||||
pr = mAm.mPidsSelfLocked.get(blocked);
|
||||
}
|
||||
if (pr != null && pr.mState.getCurAdj() < ProcessList.CACHED_APP_MIN_ADJ) {
|
||||
Slog.d(TAG_AM, app.processName + " (" + pid + ") blocks "
|
||||
+ pr.processName + " (" + blocked + ")");
|
||||
// Found at least one blocked non-cached process
|
||||
unfreezeAppLSP(app, OomAdjuster.OOM_ADJ_REASON_NONE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user