Merge "WatchDog: dump hal pids when killing a process."
This commit is contained in:
committed by
Android (Google) Code Review
commit
e784f7a0a3
@@ -22,7 +22,8 @@ LOCAL_JAVA_LIBRARIES := \
|
||||
services.net \
|
||||
android.hardware.light@2.0-java \
|
||||
android.hardware.power@1.0-java \
|
||||
android.hardware.tv.cec@1.0-java
|
||||
android.hardware.tv.cec@1.0-java \
|
||||
android.hidl.manager@1.0-java
|
||||
|
||||
LOCAL_STATIC_JAVA_LIBRARIES := \
|
||||
tzdata_shared2 \
|
||||
|
||||
@@ -26,6 +26,7 @@ import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.hidl.manager.V1_0.IServiceManager;
|
||||
import android.os.Debug;
|
||||
import android.os.Handler;
|
||||
import android.os.IPowerManager;
|
||||
@@ -42,6 +43,9 @@ import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
/** This class calls its monitor every minute. Killing this process if they don't return **/
|
||||
public class Watchdog extends Thread {
|
||||
@@ -75,6 +79,14 @@ public class Watchdog extends Thread {
|
||||
"com.android.bluetooth", // Bluetooth service
|
||||
};
|
||||
|
||||
public static final List<String> HAL_INTERFACES_OF_INTEREST = Arrays.asList(
|
||||
"android.hardware.audio@2.0::IDevicesFactory",
|
||||
"android.hardware.bluetooth@1.0::IBluetoothHci",
|
||||
"android.hardware.camera.provider@2.4::ICameraProvider",
|
||||
"android.hardware.vr@1.0::IVr",
|
||||
"android.hardware.media.omx@1.0::IOmx"
|
||||
);
|
||||
|
||||
static Watchdog sWatchdog;
|
||||
|
||||
/* This handler will be used to post message back onto the main thread */
|
||||
@@ -344,6 +356,43 @@ public class Watchdog extends Thread {
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private ArrayList<Integer> getInterestingHalPids() {
|
||||
try {
|
||||
IServiceManager serviceManager = IServiceManager.getService();
|
||||
ArrayList<IServiceManager.InstanceDebugInfo> dump =
|
||||
serviceManager.debugDump();
|
||||
HashSet<Integer> pids = new HashSet<>();
|
||||
for (IServiceManager.InstanceDebugInfo info : dump) {
|
||||
if (info.pid == IServiceManager.PidConstant.NO_PID) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!HAL_INTERFACES_OF_INTEREST.contains(info.interfaceName)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
pids.add(info.pid);
|
||||
}
|
||||
return new ArrayList<Integer>(pids);
|
||||
} catch (RemoteException e) {
|
||||
return new ArrayList<Integer>();
|
||||
}
|
||||
}
|
||||
|
||||
private ArrayList<Integer> getInterestingNativePids() {
|
||||
ArrayList<Integer> pids = getInterestingHalPids();
|
||||
|
||||
int[] nativePids = Process.getPidsForCommands(NATIVE_STACKS_OF_INTEREST);
|
||||
if (nativePids != null) {
|
||||
pids.ensureCapacity(pids.size() + nativePids.length);
|
||||
for (int i : nativePids) {
|
||||
pids.add(i);
|
||||
}
|
||||
}
|
||||
|
||||
return pids;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
boolean waitedHalf = false;
|
||||
@@ -400,7 +449,7 @@ public class Watchdog extends Thread {
|
||||
ArrayList<Integer> pids = new ArrayList<Integer>();
|
||||
pids.add(Process.myPid());
|
||||
ActivityManagerService.dumpStackTraces(true, pids, null, null,
|
||||
NATIVE_STACKS_OF_INTEREST);
|
||||
getInterestingNativePids());
|
||||
waitedHalf = true;
|
||||
}
|
||||
continue;
|
||||
@@ -417,13 +466,13 @@ public class Watchdog extends Thread {
|
||||
// Then kill this process so that the system will restart.
|
||||
EventLog.writeEvent(EventLogTags.WATCHDOG, subject);
|
||||
|
||||
ArrayList<Integer> pids = new ArrayList<Integer>();
|
||||
ArrayList<Integer> pids = new ArrayList<>();
|
||||
pids.add(Process.myPid());
|
||||
if (mPhonePid > 0) pids.add(mPhonePid);
|
||||
// Pass !waitedHalf so that just in case we somehow wind up here without having
|
||||
// dumped the halfway stacks, we properly re-initialize the trace file.
|
||||
final File stack = ActivityManagerService.dumpStackTraces(
|
||||
!waitedHalf, pids, null, null, NATIVE_STACKS_OF_INTEREST);
|
||||
!waitedHalf, pids, null, null, getInterestingNativePids());
|
||||
|
||||
// Give some extra time to make sure the stack traces get written.
|
||||
// The system's been hanging for a minute, another second or two won't hurt much.
|
||||
|
||||
@@ -5468,11 +5468,12 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
* appended to any existing file content.
|
||||
* @param firstPids of dalvik VM processes to dump stack traces for first
|
||||
* @param lastPids of dalvik VM processes to dump stack traces for last
|
||||
* @param nativeProcs optional list of native process names to dump stack crawls
|
||||
* @param nativePids optional list of native pids to dump stack crawls
|
||||
* @return file containing stack traces, or null if no dump file is configured
|
||||
*/
|
||||
public static File dumpStackTraces(boolean clearTraces, ArrayList<Integer> firstPids,
|
||||
ProcessCpuTracker processCpuTracker, SparseArray<Boolean> lastPids, String[] nativeProcs) {
|
||||
ProcessCpuTracker processCpuTracker, SparseArray<Boolean> lastPids,
|
||||
ArrayList<Integer> nativePids) {
|
||||
String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
|
||||
if (tracesPath == null || tracesPath.length() == 0) {
|
||||
return null;
|
||||
@@ -5488,7 +5489,7 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
return null;
|
||||
}
|
||||
|
||||
dumpStackTraces(tracesPath, firstPids, processCpuTracker, lastPids, nativeProcs);
|
||||
dumpStackTraces(tracesPath, firstPids, processCpuTracker, lastPids, nativePids);
|
||||
return tracesFile;
|
||||
}
|
||||
|
||||
@@ -5530,7 +5531,8 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
}
|
||||
|
||||
private static void dumpStackTraces(String tracesPath, ArrayList<Integer> firstPids,
|
||||
ProcessCpuTracker processCpuTracker, SparseArray<Boolean> lastPids, String[] nativeProcs) {
|
||||
ProcessCpuTracker processCpuTracker, SparseArray<Boolean> lastPids,
|
||||
ArrayList<Integer> nativePids) {
|
||||
// Use a FileObserver to detect when traces finish writing.
|
||||
// The order of traces is considered important to maintain for legibility.
|
||||
DumpStackFileObserver observer = new DumpStackFileObserver(tracesPath);
|
||||
@@ -5551,18 +5553,15 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
}
|
||||
|
||||
// Next collect the stacks of the native pids
|
||||
if (nativeProcs != null) {
|
||||
int[] pids = Process.getPidsForCommands(nativeProcs);
|
||||
if (pids != null) {
|
||||
for (int pid : pids) {
|
||||
if (DEBUG_ANR) Slog.d(TAG, "Collecting stacks for native pid " + pid);
|
||||
final long sime = SystemClock.elapsedRealtime();
|
||||
if (nativePids != null) {
|
||||
for (int pid : nativePids) {
|
||||
if (DEBUG_ANR) Slog.d(TAG, "Collecting stacks for native pid " + pid);
|
||||
final long sime = SystemClock.elapsedRealtime();
|
||||
|
||||
Debug.dumpNativeBacktraceToFileTimeout(
|
||||
pid, tracesPath, DumpStackFileObserver.TRACE_DUMP_TIMEOUT_SECONDS);
|
||||
if (DEBUG_ANR) Slog.d(TAG, "Done with native pid " + pid
|
||||
+ " in " + (SystemClock.elapsedRealtime()-sime) + "ms");
|
||||
}
|
||||
Debug.dumpNativeBacktraceToFileTimeout(
|
||||
pid, tracesPath, DumpStackFileObserver.TRACE_DUMP_TIMEOUT_SECONDS);
|
||||
if (DEBUG_ANR) Slog.d(TAG, "Done with native pid " + pid
|
||||
+ " in " + (SystemClock.elapsedRealtime()-sime) + "ms");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -870,12 +870,22 @@ class AppErrors {
|
||||
nativeProcs = NATIVE_STACKS_OF_INTEREST;
|
||||
}
|
||||
|
||||
int[] pids = Process.getPidsForCommands(nativeProcs);
|
||||
ArrayList<Integer> nativePids = null;
|
||||
|
||||
if (pids != null) {
|
||||
nativePids = new ArrayList<Integer>(pids.length);
|
||||
for (int i : pids) {
|
||||
nativePids.add(i);
|
||||
}
|
||||
}
|
||||
|
||||
// For background ANRs, don't pass the ProcessCpuTracker to
|
||||
// avoid spending 1/2 second collecting stats to rank lastPids.
|
||||
File tracesFile = mService.dumpStackTraces(true, firstPids,
|
||||
(isSilentANR) ? null : processCpuTracker,
|
||||
(isSilentANR) ? null : lastPids,
|
||||
nativeProcs);
|
||||
nativePids);
|
||||
|
||||
String cpuInfo = null;
|
||||
if (ActivityManagerService.MONITOR_CPU_USAGE) {
|
||||
|
||||
Reference in New Issue
Block a user