ActivityManager: don't freeze processes holding file locks
As a temporary measure waiting for the more robust b/176927978 to be implemented, query the file lock status of processes prior freezing them, and skip freeze if any locks are held. Test: verified form the logs that processes holding file locks are not frozen Bug: 176928302 Change-Id: Ib7e1715effb63c1b304ce22a9451294fd9f7b10d Merged-In: Ib7e1715effb63c1b304ce22a9451294fd9f7b10d
This commit is contained in:
@@ -31,8 +31,12 @@ import dalvik.system.VMRuntime;
|
||||
|
||||
import libcore.io.IoUtils;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
/**
|
||||
@@ -1393,4 +1397,38 @@ public class Process {
|
||||
}
|
||||
|
||||
private static native int nativePidFdOpen(int pid, int flags) throws ErrnoException;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static boolean hasFileLocks(int pid) throws IOException {
|
||||
BufferedReader br = null;
|
||||
|
||||
try {
|
||||
br = new BufferedReader(new FileReader("/proc/locks"));
|
||||
String line;
|
||||
|
||||
while ((line = br.readLine()) != null) {
|
||||
StringTokenizer st = new StringTokenizer(line);
|
||||
|
||||
for (int i = 0; i < 5 && st.hasMoreTokens(); i++) {
|
||||
String str = st.nextToken();
|
||||
if (i == 4 && Integer.parseInt(str) == pid) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
} finally {
|
||||
if (br != null) {
|
||||
br.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1101,15 +1101,26 @@ public final class CachedAppOptimizer {
|
||||
}
|
||||
|
||||
private void freezeProcess(ProcessRecord proc) {
|
||||
final int pid;
|
||||
final String name;
|
||||
final int pid = proc.pid;
|
||||
final String name = proc.processName;
|
||||
final long unfrozenDuration;
|
||||
final boolean frozen;
|
||||
|
||||
synchronized (mAm) {
|
||||
pid = proc.pid;
|
||||
name = proc.processName;
|
||||
try {
|
||||
// pre-check for locks to avoid unnecessary freeze/unfreeze operations
|
||||
if (Process.hasFileLocks(pid)) {
|
||||
if (DEBUG_FREEZER) {
|
||||
Slog.d(TAG_AM, name + " (" + pid + ") holds file locks, not freezing");
|
||||
}
|
||||
return;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Slog.e(TAG_AM, "Not freezing. Unable to check file locks for " + name + "(" + pid
|
||||
+ "): " + e);
|
||||
return;
|
||||
}
|
||||
|
||||
synchronized (mAm) {
|
||||
if (proc.curAdj < ProcessList.CACHED_APP_MIN_ADJ
|
||||
|| proc.shouldNotFreeze) {
|
||||
if (DEBUG_FREEZER) {
|
||||
@@ -1141,29 +1152,50 @@ public final class CachedAppOptimizer {
|
||||
frozen = proc.frozen;
|
||||
}
|
||||
|
||||
if (frozen) {
|
||||
if (DEBUG_FREEZER) {
|
||||
Slog.d(TAG_AM, "froze " + pid + " " + name);
|
||||
if (!frozen) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (DEBUG_FREEZER) {
|
||||
Slog.d(TAG_AM, "froze " + pid + " " + name);
|
||||
}
|
||||
|
||||
EventLog.writeEvent(EventLogTags.AM_FREEZE, pid, name);
|
||||
|
||||
try {
|
||||
freezeBinder(pid, true);
|
||||
} catch (RuntimeException e) {
|
||||
Slog.e(TAG_AM, "Unable to freeze binder for " + pid + " " + name);
|
||||
proc.kill("Unable to freeze binder interface",
|
||||
ApplicationExitInfo.REASON_OTHER,
|
||||
ApplicationExitInfo.SUBREASON_INVALID_STATE, true);
|
||||
}
|
||||
|
||||
// See above for why we're not taking mPhenotypeFlagLock here
|
||||
if (mRandom.nextFloat() < mFreezerStatsdSampleRate) {
|
||||
FrameworkStatsLog.write(FrameworkStatsLog.APP_FREEZE_CHANGED,
|
||||
FrameworkStatsLog.APP_FREEZE_CHANGED__ACTION__FREEZE_APP,
|
||||
pid,
|
||||
name,
|
||||
unfrozenDuration);
|
||||
}
|
||||
|
||||
try {
|
||||
// post-check to prevent races
|
||||
if (Process.hasFileLocks(pid)) {
|
||||
if (DEBUG_FREEZER) {
|
||||
Slog.d(TAG_AM, name + " (" + pid + ") holds file locks, reverting freeze");
|
||||
}
|
||||
|
||||
synchronized (mAm) {
|
||||
unfreezeAppLocked(proc);
|
||||
}
|
||||
}
|
||||
|
||||
EventLog.writeEvent(EventLogTags.AM_FREEZE, pid, name);
|
||||
|
||||
try {
|
||||
freezeBinder(pid, true);
|
||||
} catch (RuntimeException e) {
|
||||
Slog.e(TAG_AM, "Unable to freeze binder for " + pid + " " + name);
|
||||
proc.kill("Unable to freeze binder interface",
|
||||
ApplicationExitInfo.REASON_OTHER,
|
||||
ApplicationExitInfo.SUBREASON_INVALID_STATE, true);
|
||||
}
|
||||
|
||||
// See above for why we're not taking mPhenotypeFlagLock here
|
||||
if (mRandom.nextFloat() < mFreezerStatsdSampleRate) {
|
||||
FrameworkStatsLog.write(FrameworkStatsLog.APP_FREEZE_CHANGED,
|
||||
FrameworkStatsLog.APP_FREEZE_CHANGED__ACTION__FREEZE_APP,
|
||||
pid,
|
||||
name,
|
||||
unfrozenDuration);
|
||||
} catch (IOException e) {
|
||||
Slog.e(TAG_AM, "Unable to check file locks for " + name + "(" + pid + "): " + e);
|
||||
synchronized (mAm) {
|
||||
unfreezeAppLocked(proc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user