Loading core/java/com/android/internal/os/ProcLocksReader.java +40 −31 Original line number Diff line number Diff line Loading @@ -18,8 +18,6 @@ package com.android.internal.os; import com.android.internal.util.ProcFileReader; import libcore.io.IoUtils; import java.io.FileInputStream; import java.io.IOException; Loading @@ -36,6 +34,7 @@ import java.io.IOException; */ public class ProcLocksReader { private final String mPath; private ProcFileReader mReader = null; public ProcLocksReader() { mPath = "/proc/locks"; Loading @@ -45,45 +44,55 @@ public class ProcLocksReader { mPath = path; } /** * This interface is for AMS to run callback function on every processes one by one * that hold file locks blocking other processes. */ public interface ProcLocksReaderCallback { /** * Call the callback function of handleBlockingFileLocks(). * @param pid Each process that hold file locks blocking other processes. */ void onBlockingFileLock(int pid); } /** * Checks if a process corresponding to a specific pid owns any file locks. * @param pid The process ID for which we want to know the existence of file locks. * @return true If the process holds any file locks, false otherwise. * @throws IOException if /proc/locks can't be accessed. * @param callback Callback function, accepting pid as the input parameter. * @throws IOException if /proc/locks can't be accessed or correctly parsed. */ public boolean hasFileLocks(int pid) throws Exception { ProcFileReader reader = null; public void handleBlockingFileLocks(ProcLocksReaderCallback callback) throws IOException { long last = -1; long id; // ordinal position of the lock in the list int owner; // the PID of the process that owns the lock int owner = -1; // the PID of the process that owns the lock int pid = -1; // the PID of the process blocking others try { reader = new ProcFileReader(new FileInputStream(mPath)); if (mReader == null) { mReader = new ProcFileReader(new FileInputStream(mPath)); } else { mReader.rewind(); } while (reader.hasMoreData()) { id = reader.nextLong(true); // lock id while (mReader.hasMoreData()) { id = mReader.nextLong(true); // lock id if (id == last) { reader.finishLine(); // blocked lock mReader.finishLine(); // blocked lock if (pid < 0) { pid = owner; // get pid from the previous line callback.onBlockingFileLock(pid); } continue; } else { pid = -1; // a new lock } reader.nextIgnored(); // lock type: POSIX? reader.nextIgnored(); // lock type: MANDATORY? reader.nextIgnored(); // lock type: RW? mReader.nextIgnored(); // lock type: POSIX? mReader.nextIgnored(); // lock type: MANDATORY? mReader.nextIgnored(); // lock type: RW? owner = reader.nextInt(); // pid if (owner == pid) { return true; } reader.finishLine(); owner = mReader.nextInt(); // pid mReader.finishLine(); last = id; } } catch (IOException e) { // TODO: let ProcFileReader log the failed line throw new Exception("Exception parsing /proc/locks"); } finally { IoUtils.closeQuietly(reader); } return false; } } core/java/com/android/internal/util/ProcFileReader.java +22 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.internal.util; import java.io.Closeable; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.net.ProtocolException; Loading Loading @@ -47,6 +48,9 @@ public class ProcFileReader implements Closeable { public ProcFileReader(InputStream stream, int bufferSize) throws IOException { mStream = stream; mBuffer = new byte[bufferSize]; if (stream.markSupported()) { mStream.mark(0); } // read enough to answer hasMoreData fillBuf(); Loading Loading @@ -257,6 +261,24 @@ public class ProcFileReader implements Closeable { } } /** * Reset file position and internal buffer * @throws IOException */ public void rewind() throws IOException { if (mStream instanceof FileInputStream) { ((FileInputStream) mStream).getChannel().position(0); } else if (mStream.markSupported()) { mStream.reset(); } else { throw new IOException("The InputStream is NOT markable"); } mTail = 0; mLineFinished = false; fillBuf(); } @Override public void close() throws IOException { mStream.close(); Loading core/tests/coretests/src/com/android/internal/os/ProcLocksReaderTest.java +39 −17 Original line number Diff line number Diff line Loading @@ -16,7 +16,6 @@ package com.android.internal.os; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import android.content.Context; Loading @@ -33,11 +32,14 @@ import org.junit.runner.RunWith; import java.io.File; import java.nio.file.Files; import java.util.ArrayList; @SmallTest @RunWith(AndroidJUnit4.class) public class ProcLocksReaderTest { public class ProcLocksReaderTest implements ProcLocksReader.ProcLocksReaderCallback { private File mProcDirectory; private ArrayList<Integer> mPids = new ArrayList<>(); @Before public void setUp() { Loading @@ -55,14 +57,12 @@ public class ProcLocksReaderTest { String simpleLocks = "1: POSIX ADVISORY READ 18403 fd:09:9070 1073741826 1073742335\n" + "2: POSIX ADVISORY WRITE 18292 fd:09:34062 0 EOF\n"; assertFalse(runHasFileLocks(simpleLocks, 18402)); assertFalse(runHasFileLocks(simpleLocks, 18404)); assertTrue(runHasFileLocks(simpleLocks, 18403)); assertTrue(runHasFileLocks(simpleLocks, 18292)); runHandleBlockingFileLocks(simpleLocks); assertTrue(mPids.isEmpty()); } @Test public void testRunBlockedLocks() throws Exception { 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" + Loading @@ -70,21 +70,43 @@ public class ProcLocksReaderTest { "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"; assertFalse(runHasFileLocks(blockedLocks, 18402)); assertFalse(runHasFileLocks(blockedLocks, 18404)); assertTrue(runHasFileLocks(blockedLocks, 18403)); assertTrue(runHasFileLocks(blockedLocks, 18292)); runHandleBlockingFileLocks(blockedLocks); assertTrue(mPids.remove(0).equals(18292)); assertTrue(mPids.isEmpty()); } assertFalse(runHasFileLocks(blockedLocks, 18291)); assertFalse(runHasFileLocks(blockedLocks, 18293)); assertTrue(runHasFileLocks(blockedLocks, 3888)); @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"; runHandleBlockingFileLocks(blockedLocks); assertTrue(mPids.remove(0).equals(18292)); assertTrue(mPids.remove(0).equals(3840)); assertTrue(mPids.isEmpty()); } private boolean runHasFileLocks(String fileContents, int pid) throws Exception { private void runHandleBlockingFileLocks(String fileContents) throws Exception { File tempFile = File.createTempFile("locks", null, mProcDirectory); Files.write(tempFile.toPath(), fileContents.getBytes()); boolean result = new ProcLocksReader(tempFile.toString()).hasFileLocks(pid); mPids.clear(); new ProcLocksReader(tempFile.toString()).handleBlockingFileLocks(this); Files.delete(tempFile.toPath()); return result; } /** * Call the callback function of handleBlockingFileLocks(). * * @param pid Each process that hold file locks blocking other processes. */ @Override public void onBlockingFileLock(int pid) { mPids.add(pid); } } core/tests/utiltests/src/com/android/internal/util/ProcFileReaderTest.java +38 −0 Original line number Diff line number Diff line Loading @@ -19,8 +19,11 @@ package com.android.internal.util; import android.test.AndroidTestCase; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; /** * Tests for {@link ProcFileReader}. Loading Loading @@ -206,6 +209,41 @@ public class ProcFileReaderTest extends AndroidTestCase { assertFalse(reader.hasMoreData()); } public void testRewind() throws Exception { final ProcFileReader reader = buildReader("abc\n"); assertEquals("abc", reader.nextString()); reader.finishLine(); assertFalse(reader.hasMoreData()); reader.rewind(); assertTrue(reader.hasMoreData()); assertEquals("abc", reader.nextString()); reader.finishLine(); assertFalse(reader.hasMoreData()); } public void testRewindFileInputStream() throws Exception { File tempFile = File.createTempFile("procfile", null, null); Files.write(tempFile.toPath(), "abc\n".getBytes(StandardCharsets.US_ASCII)); final ProcFileReader reader = new ProcFileReader(new FileInputStream(tempFile)); assertEquals("abc", reader.nextString()); reader.finishLine(); assertFalse(reader.hasMoreData()); reader.rewind(); assertTrue(reader.hasMoreData()); assertEquals("abc", reader.nextString()); reader.finishLine(); assertFalse(reader.hasMoreData()); Files.delete(tempFile.toPath()); } private static ProcFileReader buildReader(String string) throws IOException { return buildReader(string, 2048); } Loading services/core/java/com/android/server/am/ActivityManagerService.java +2 −2 Original line number Diff line number Diff line Loading @@ -11837,8 +11837,8 @@ public class ActivityManagerService extends IActivityManager.Stub restart = app.onCleanupApplicationRecordLSP(mProcessStats, allowRestart, fromBinderDied || app.isolated /* unlinkDeath */); // Cancel pending frozen task if there is any. mOomAdjuster.mCachedAppOptimizer.unscheduleFreezeAppLSP(app); // Cancel pending frozen task and clean up frozen record if there is any. mOomAdjuster.mCachedAppOptimizer.onCleanupApplicationRecordLocked(app); } mAppProfiler.onCleanupApplicationRecordLocked(app); skipCurrentReceiverLocked(app); Loading Loading
core/java/com/android/internal/os/ProcLocksReader.java +40 −31 Original line number Diff line number Diff line Loading @@ -18,8 +18,6 @@ package com.android.internal.os; import com.android.internal.util.ProcFileReader; import libcore.io.IoUtils; import java.io.FileInputStream; import java.io.IOException; Loading @@ -36,6 +34,7 @@ import java.io.IOException; */ public class ProcLocksReader { private final String mPath; private ProcFileReader mReader = null; public ProcLocksReader() { mPath = "/proc/locks"; Loading @@ -45,45 +44,55 @@ public class ProcLocksReader { mPath = path; } /** * This interface is for AMS to run callback function on every processes one by one * that hold file locks blocking other processes. */ public interface ProcLocksReaderCallback { /** * Call the callback function of handleBlockingFileLocks(). * @param pid Each process that hold file locks blocking other processes. */ void onBlockingFileLock(int pid); } /** * Checks if a process corresponding to a specific pid owns any file locks. * @param pid The process ID for which we want to know the existence of file locks. * @return true If the process holds any file locks, false otherwise. * @throws IOException if /proc/locks can't be accessed. * @param callback Callback function, accepting pid as the input parameter. * @throws IOException if /proc/locks can't be accessed or correctly parsed. */ public boolean hasFileLocks(int pid) throws Exception { ProcFileReader reader = null; public void handleBlockingFileLocks(ProcLocksReaderCallback callback) throws IOException { long last = -1; long id; // ordinal position of the lock in the list int owner; // the PID of the process that owns the lock int owner = -1; // the PID of the process that owns the lock int pid = -1; // the PID of the process blocking others try { reader = new ProcFileReader(new FileInputStream(mPath)); if (mReader == null) { mReader = new ProcFileReader(new FileInputStream(mPath)); } else { mReader.rewind(); } while (reader.hasMoreData()) { id = reader.nextLong(true); // lock id while (mReader.hasMoreData()) { id = mReader.nextLong(true); // lock id if (id == last) { reader.finishLine(); // blocked lock mReader.finishLine(); // blocked lock if (pid < 0) { pid = owner; // get pid from the previous line callback.onBlockingFileLock(pid); } continue; } else { pid = -1; // a new lock } reader.nextIgnored(); // lock type: POSIX? reader.nextIgnored(); // lock type: MANDATORY? reader.nextIgnored(); // lock type: RW? mReader.nextIgnored(); // lock type: POSIX? mReader.nextIgnored(); // lock type: MANDATORY? mReader.nextIgnored(); // lock type: RW? owner = reader.nextInt(); // pid if (owner == pid) { return true; } reader.finishLine(); owner = mReader.nextInt(); // pid mReader.finishLine(); last = id; } } catch (IOException e) { // TODO: let ProcFileReader log the failed line throw new Exception("Exception parsing /proc/locks"); } finally { IoUtils.closeQuietly(reader); } return false; } }
core/java/com/android/internal/util/ProcFileReader.java +22 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.internal.util; import java.io.Closeable; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.net.ProtocolException; Loading Loading @@ -47,6 +48,9 @@ public class ProcFileReader implements Closeable { public ProcFileReader(InputStream stream, int bufferSize) throws IOException { mStream = stream; mBuffer = new byte[bufferSize]; if (stream.markSupported()) { mStream.mark(0); } // read enough to answer hasMoreData fillBuf(); Loading Loading @@ -257,6 +261,24 @@ public class ProcFileReader implements Closeable { } } /** * Reset file position and internal buffer * @throws IOException */ public void rewind() throws IOException { if (mStream instanceof FileInputStream) { ((FileInputStream) mStream).getChannel().position(0); } else if (mStream.markSupported()) { mStream.reset(); } else { throw new IOException("The InputStream is NOT markable"); } mTail = 0; mLineFinished = false; fillBuf(); } @Override public void close() throws IOException { mStream.close(); Loading
core/tests/coretests/src/com/android/internal/os/ProcLocksReaderTest.java +39 −17 Original line number Diff line number Diff line Loading @@ -16,7 +16,6 @@ package com.android.internal.os; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import android.content.Context; Loading @@ -33,11 +32,14 @@ import org.junit.runner.RunWith; import java.io.File; import java.nio.file.Files; import java.util.ArrayList; @SmallTest @RunWith(AndroidJUnit4.class) public class ProcLocksReaderTest { public class ProcLocksReaderTest implements ProcLocksReader.ProcLocksReaderCallback { private File mProcDirectory; private ArrayList<Integer> mPids = new ArrayList<>(); @Before public void setUp() { Loading @@ -55,14 +57,12 @@ public class ProcLocksReaderTest { String simpleLocks = "1: POSIX ADVISORY READ 18403 fd:09:9070 1073741826 1073742335\n" + "2: POSIX ADVISORY WRITE 18292 fd:09:34062 0 EOF\n"; assertFalse(runHasFileLocks(simpleLocks, 18402)); assertFalse(runHasFileLocks(simpleLocks, 18404)); assertTrue(runHasFileLocks(simpleLocks, 18403)); assertTrue(runHasFileLocks(simpleLocks, 18292)); runHandleBlockingFileLocks(simpleLocks); assertTrue(mPids.isEmpty()); } @Test public void testRunBlockedLocks() throws Exception { 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" + Loading @@ -70,21 +70,43 @@ public class ProcLocksReaderTest { "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"; assertFalse(runHasFileLocks(blockedLocks, 18402)); assertFalse(runHasFileLocks(blockedLocks, 18404)); assertTrue(runHasFileLocks(blockedLocks, 18403)); assertTrue(runHasFileLocks(blockedLocks, 18292)); runHandleBlockingFileLocks(blockedLocks); assertTrue(mPids.remove(0).equals(18292)); assertTrue(mPids.isEmpty()); } assertFalse(runHasFileLocks(blockedLocks, 18291)); assertFalse(runHasFileLocks(blockedLocks, 18293)); assertTrue(runHasFileLocks(blockedLocks, 3888)); @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"; runHandleBlockingFileLocks(blockedLocks); assertTrue(mPids.remove(0).equals(18292)); assertTrue(mPids.remove(0).equals(3840)); assertTrue(mPids.isEmpty()); } private boolean runHasFileLocks(String fileContents, int pid) throws Exception { private void runHandleBlockingFileLocks(String fileContents) throws Exception { File tempFile = File.createTempFile("locks", null, mProcDirectory); Files.write(tempFile.toPath(), fileContents.getBytes()); boolean result = new ProcLocksReader(tempFile.toString()).hasFileLocks(pid); mPids.clear(); new ProcLocksReader(tempFile.toString()).handleBlockingFileLocks(this); Files.delete(tempFile.toPath()); return result; } /** * Call the callback function of handleBlockingFileLocks(). * * @param pid Each process that hold file locks blocking other processes. */ @Override public void onBlockingFileLock(int pid) { mPids.add(pid); } }
core/tests/utiltests/src/com/android/internal/util/ProcFileReaderTest.java +38 −0 Original line number Diff line number Diff line Loading @@ -19,8 +19,11 @@ package com.android.internal.util; import android.test.AndroidTestCase; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; /** * Tests for {@link ProcFileReader}. Loading Loading @@ -206,6 +209,41 @@ public class ProcFileReaderTest extends AndroidTestCase { assertFalse(reader.hasMoreData()); } public void testRewind() throws Exception { final ProcFileReader reader = buildReader("abc\n"); assertEquals("abc", reader.nextString()); reader.finishLine(); assertFalse(reader.hasMoreData()); reader.rewind(); assertTrue(reader.hasMoreData()); assertEquals("abc", reader.nextString()); reader.finishLine(); assertFalse(reader.hasMoreData()); } public void testRewindFileInputStream() throws Exception { File tempFile = File.createTempFile("procfile", null, null); Files.write(tempFile.toPath(), "abc\n".getBytes(StandardCharsets.US_ASCII)); final ProcFileReader reader = new ProcFileReader(new FileInputStream(tempFile)); assertEquals("abc", reader.nextString()); reader.finishLine(); assertFalse(reader.hasMoreData()); reader.rewind(); assertTrue(reader.hasMoreData()); assertEquals("abc", reader.nextString()); reader.finishLine(); assertFalse(reader.hasMoreData()); Files.delete(tempFile.toPath()); } private static ProcFileReader buildReader(String string) throws IOException { return buildReader(string, 2048); } Loading
services/core/java/com/android/server/am/ActivityManagerService.java +2 −2 Original line number Diff line number Diff line Loading @@ -11837,8 +11837,8 @@ public class ActivityManagerService extends IActivityManager.Stub restart = app.onCleanupApplicationRecordLSP(mProcessStats, allowRestart, fromBinderDied || app.isolated /* unlinkDeath */); // Cancel pending frozen task if there is any. mOomAdjuster.mCachedAppOptimizer.unscheduleFreezeAppLSP(app); // Cancel pending frozen task and clean up frozen record if there is any. mOomAdjuster.mCachedAppOptimizer.onCleanupApplicationRecordLocked(app); } mAppProfiler.onCleanupApplicationRecordLocked(app); skipCurrentReceiverLocked(app); Loading