Loading services/core/java/com/android/server/power/ShutdownCheckPoints.java +40 −33 Original line number Diff line number Diff line Loading @@ -121,23 +121,25 @@ public final class ShutdownCheckPoints { @VisibleForTesting void recordCheckPointInternal(@Nullable String reason) { recordCheckPointInternal(new SystemServerCheckPoint(mInjector, reason)); recordCheckPointInternal(new SystemServerCheckPoint(mInjector.currentTimeMillis(), reason)); Slog.v(TAG, "System server shutdown checkpoint recorded"); } @VisibleForTesting void recordCheckPointInternal(int callerProcessId, @Nullable String reason) { long timestamp = mInjector.currentTimeMillis(); recordCheckPointInternal(callerProcessId == Process.myPid() ? new SystemServerCheckPoint(mInjector, reason) : new BinderCheckPoint(mInjector, callerProcessId, reason)); ? new SystemServerCheckPoint(timestamp, reason) : new BinderCheckPoint(timestamp, callerProcessId, reason)); Slog.v(TAG, "Binder shutdown checkpoint recorded with pid=" + callerProcessId); } @VisibleForTesting void recordCheckPointInternal(String intentName, String packageName, @Nullable String reason) { long timestamp = mInjector.currentTimeMillis(); recordCheckPointInternal("android".equals(packageName) ? new SystemServerCheckPoint(mInjector, reason) : new IntentCheckPoint(mInjector, intentName, packageName, reason)); ? new SystemServerCheckPoint(timestamp, reason) : new IntentCheckPoint(timestamp, intentName, packageName, reason)); Slog.v(TAG, String.format("Shutdown intent checkpoint recorded intent=%s from package=%s", intentName, packageName)); } Loading @@ -156,7 +158,7 @@ public final class ShutdownCheckPoints { records = new ArrayList<>(mCheckPoints); } for (CheckPoint record : records) { record.dump(printWriter); record.dump(mInjector, printWriter); printWriter.println(); } } Loading Loading @@ -185,12 +187,12 @@ public final class ShutdownCheckPoints { private final long mTimestamp; @Nullable private final String mReason; CheckPoint(Injector injector, @Nullable String reason) { mTimestamp = injector.currentTimeMillis(); CheckPoint(long timestamp, @Nullable String reason) { mTimestamp = timestamp; mReason = reason; } final void dump(PrintWriter printWriter) { final void dump(Injector injector, PrintWriter printWriter) { printWriter.print("Shutdown request from "); printWriter.print(getOrigin()); if (mReason != null) { Loading @@ -200,12 +202,12 @@ public final class ShutdownCheckPoints { printWriter.print(" at "); printWriter.print(DATE_FORMAT.format(new Date(mTimestamp))); printWriter.println(" (epoch=" + mTimestamp + ")"); dumpDetails(printWriter); dumpDetails(injector, printWriter); } abstract String getOrigin(); abstract void dumpDetails(PrintWriter printWriter); abstract void dumpDetails(Injector injector, PrintWriter printWriter); } /** Representation of a shutdown call from the system server, with stack trace. */ Loading @@ -213,8 +215,8 @@ public final class ShutdownCheckPoints { private final StackTraceElement[] mStackTraceElements; SystemServerCheckPoint(Injector injector, @Nullable String reason) { super(injector, reason); SystemServerCheckPoint(long timestamp, @Nullable String reason) { super(timestamp, reason); mStackTraceElements = Thread.currentThread().getStackTrace(); } Loading @@ -224,14 +226,14 @@ public final class ShutdownCheckPoints { } @Override void dumpDetails(PrintWriter printWriter) { String methodName = getMethodName(); void dumpDetails(Injector injector, PrintWriter printWriter) { String methodName = findMethodName(); printWriter.println(methodName == null ? "Failed to get method name" : methodName); printStackTrace(printWriter); } @Nullable String getMethodName() { String findMethodName() { int idx = findCallSiteIndex(); if (idx < mStackTraceElements.length) { StackTraceElement element = mStackTraceElements[idx]; Loading @@ -241,7 +243,7 @@ public final class ShutdownCheckPoints { } void printStackTrace(PrintWriter printWriter) { // Skip the call site line, as it's already considered with getMethodName. // Skip the call site line, as it's already considered with findMethodName. for (int i = findCallSiteIndex() + 1; i < mStackTraceElements.length; i++) { printWriter.print(" at "); printWriter.println(mStackTraceElements[i]); Loading @@ -268,12 +270,10 @@ public final class ShutdownCheckPoints { /** Representation of a shutdown call to {@link android.os.Binder}, with caller process id. */ private static class BinderCheckPoint extends SystemServerCheckPoint { private final int mCallerProcessId; private final IActivityManager mActivityManager; BinderCheckPoint(Injector injector, int callerProcessId, @Nullable String reason) { super(injector, reason); BinderCheckPoint(long timestamp, int callerProcessId, @Nullable String reason) { super(timestamp, reason); mCallerProcessId = callerProcessId; mActivityManager = injector.activityManager(); } @Override Loading @@ -282,26 +282,33 @@ public final class ShutdownCheckPoints { } @Override void dumpDetails(PrintWriter printWriter) { String methodName = getMethodName(); void dumpDetails(Injector injector, PrintWriter printWriter) { String methodName = findMethodName(); printWriter.println(methodName == null ? "Failed to get method name" : methodName); String processName = getProcessName(); String processName = findProcessName(injector.activityManager()); printWriter.print("From process "); printWriter.print(processName == null ? "?" : processName); printWriter.println(" (pid=" + mCallerProcessId + ")"); } @Nullable String getProcessName() { private String findProcessName(@Nullable IActivityManager activityManager) { try { List<ActivityManager.RunningAppProcessInfo> runningProcesses = mActivityManager.getRunningAppProcesses(); List<ActivityManager.RunningAppProcessInfo> runningProcesses = null; if (activityManager != null) { runningProcesses = activityManager.getRunningAppProcesses(); } else { Slog.v(TAG, "No ActivityManager to find name of process with pid=" + mCallerProcessId); } if (runningProcesses != null) { for (ActivityManager.RunningAppProcessInfo processInfo : runningProcesses) { if (processInfo.pid == mCallerProcessId) { return processInfo.processName; } } } } catch (RemoteException e) { Slog.e(TAG, "Failed to get running app processes from ActivityManager", e); } Loading @@ -315,8 +322,8 @@ public final class ShutdownCheckPoints { private final String mPackageName; IntentCheckPoint( Injector injector, String intentName, String packageName, @Nullable String reason) { super(injector, reason); long timestamp, String intentName, String packageName, @Nullable String reason) { super(timestamp, reason); mIntentName = intentName; mPackageName = packageName; } Loading @@ -327,7 +334,7 @@ public final class ShutdownCheckPoints { } @Override void dumpDetails(PrintWriter printWriter) { void dumpDetails(Injector injector, PrintWriter printWriter) { printWriter.print("Intent: "); printWriter.println(mIntentName); printWriter.print("Package: "); Loading services/tests/servicestests/src/com/android/server/power/ShutdownCheckPointsTest.java +27 −3 Original line number Diff line number Diff line Loading @@ -103,21 +103,45 @@ public class ShutdownCheckPointsTest { } @Test public void testCallerProcessBinderEntry() throws RemoteException { public void testCallerProcessBinderEntries() throws RemoteException { List<ActivityManager.RunningAppProcessInfo> runningAppProcessInfos = new ArrayList<>(); runningAppProcessInfos.add( new ActivityManager.RunningAppProcessInfo("process_name", 1, new String[0])); when(mActivityManager.getRunningAppProcesses()).thenReturn(runningAppProcessInfos); mTestInjector.setCurrentTime(1000); // Matching pid in getRunningAppProcesses mInstance.recordCheckPointInternal(1, "reason1"); // Missing pid in getRunningAppProcesses mInstance.recordCheckPointInternal(2, "reason2"); assertEquals( "Shutdown request from BINDER for reason reason1 " + "at 1970-01-01 00:00:01.000 UTC (epoch=1000)\n" + "com.android.server.power.ShutdownCheckPointsTest" + ".testCallerProcessBinderEntry\n" + "From process process_name (pid=1)\n\n", + ".testCallerProcessBinderEntries\n" + "From process process_name (pid=1)\n\n" + "Shutdown request from BINDER for reason reason2 " + "at 1970-01-01 00:00:01.000 UTC (epoch=1000)\n" + "com.android.server.power.ShutdownCheckPointsTest" + ".testCallerProcessBinderEntries\n" + "From process ? (pid=2)\n\n", dumpToString()); } @Test public void testNullCallerProcessBinderEntries() throws RemoteException { when(mActivityManager.getRunningAppProcesses()).thenReturn(null); mTestInjector.setCurrentTime(1000); mInstance.recordCheckPointInternal(1, "reason1"); assertEquals( "Shutdown request from BINDER for reason reason1 " + "at 1970-01-01 00:00:01.000 UTC (epoch=1000)\n" + "com.android.server.power.ShutdownCheckPointsTest" + ".testNullCallerProcessBinderEntries\n" + "From process ? (pid=1)\n\n", dumpToString()); } Loading Loading
services/core/java/com/android/server/power/ShutdownCheckPoints.java +40 −33 Original line number Diff line number Diff line Loading @@ -121,23 +121,25 @@ public final class ShutdownCheckPoints { @VisibleForTesting void recordCheckPointInternal(@Nullable String reason) { recordCheckPointInternal(new SystemServerCheckPoint(mInjector, reason)); recordCheckPointInternal(new SystemServerCheckPoint(mInjector.currentTimeMillis(), reason)); Slog.v(TAG, "System server shutdown checkpoint recorded"); } @VisibleForTesting void recordCheckPointInternal(int callerProcessId, @Nullable String reason) { long timestamp = mInjector.currentTimeMillis(); recordCheckPointInternal(callerProcessId == Process.myPid() ? new SystemServerCheckPoint(mInjector, reason) : new BinderCheckPoint(mInjector, callerProcessId, reason)); ? new SystemServerCheckPoint(timestamp, reason) : new BinderCheckPoint(timestamp, callerProcessId, reason)); Slog.v(TAG, "Binder shutdown checkpoint recorded with pid=" + callerProcessId); } @VisibleForTesting void recordCheckPointInternal(String intentName, String packageName, @Nullable String reason) { long timestamp = mInjector.currentTimeMillis(); recordCheckPointInternal("android".equals(packageName) ? new SystemServerCheckPoint(mInjector, reason) : new IntentCheckPoint(mInjector, intentName, packageName, reason)); ? new SystemServerCheckPoint(timestamp, reason) : new IntentCheckPoint(timestamp, intentName, packageName, reason)); Slog.v(TAG, String.format("Shutdown intent checkpoint recorded intent=%s from package=%s", intentName, packageName)); } Loading @@ -156,7 +158,7 @@ public final class ShutdownCheckPoints { records = new ArrayList<>(mCheckPoints); } for (CheckPoint record : records) { record.dump(printWriter); record.dump(mInjector, printWriter); printWriter.println(); } } Loading Loading @@ -185,12 +187,12 @@ public final class ShutdownCheckPoints { private final long mTimestamp; @Nullable private final String mReason; CheckPoint(Injector injector, @Nullable String reason) { mTimestamp = injector.currentTimeMillis(); CheckPoint(long timestamp, @Nullable String reason) { mTimestamp = timestamp; mReason = reason; } final void dump(PrintWriter printWriter) { final void dump(Injector injector, PrintWriter printWriter) { printWriter.print("Shutdown request from "); printWriter.print(getOrigin()); if (mReason != null) { Loading @@ -200,12 +202,12 @@ public final class ShutdownCheckPoints { printWriter.print(" at "); printWriter.print(DATE_FORMAT.format(new Date(mTimestamp))); printWriter.println(" (epoch=" + mTimestamp + ")"); dumpDetails(printWriter); dumpDetails(injector, printWriter); } abstract String getOrigin(); abstract void dumpDetails(PrintWriter printWriter); abstract void dumpDetails(Injector injector, PrintWriter printWriter); } /** Representation of a shutdown call from the system server, with stack trace. */ Loading @@ -213,8 +215,8 @@ public final class ShutdownCheckPoints { private final StackTraceElement[] mStackTraceElements; SystemServerCheckPoint(Injector injector, @Nullable String reason) { super(injector, reason); SystemServerCheckPoint(long timestamp, @Nullable String reason) { super(timestamp, reason); mStackTraceElements = Thread.currentThread().getStackTrace(); } Loading @@ -224,14 +226,14 @@ public final class ShutdownCheckPoints { } @Override void dumpDetails(PrintWriter printWriter) { String methodName = getMethodName(); void dumpDetails(Injector injector, PrintWriter printWriter) { String methodName = findMethodName(); printWriter.println(methodName == null ? "Failed to get method name" : methodName); printStackTrace(printWriter); } @Nullable String getMethodName() { String findMethodName() { int idx = findCallSiteIndex(); if (idx < mStackTraceElements.length) { StackTraceElement element = mStackTraceElements[idx]; Loading @@ -241,7 +243,7 @@ public final class ShutdownCheckPoints { } void printStackTrace(PrintWriter printWriter) { // Skip the call site line, as it's already considered with getMethodName. // Skip the call site line, as it's already considered with findMethodName. for (int i = findCallSiteIndex() + 1; i < mStackTraceElements.length; i++) { printWriter.print(" at "); printWriter.println(mStackTraceElements[i]); Loading @@ -268,12 +270,10 @@ public final class ShutdownCheckPoints { /** Representation of a shutdown call to {@link android.os.Binder}, with caller process id. */ private static class BinderCheckPoint extends SystemServerCheckPoint { private final int mCallerProcessId; private final IActivityManager mActivityManager; BinderCheckPoint(Injector injector, int callerProcessId, @Nullable String reason) { super(injector, reason); BinderCheckPoint(long timestamp, int callerProcessId, @Nullable String reason) { super(timestamp, reason); mCallerProcessId = callerProcessId; mActivityManager = injector.activityManager(); } @Override Loading @@ -282,26 +282,33 @@ public final class ShutdownCheckPoints { } @Override void dumpDetails(PrintWriter printWriter) { String methodName = getMethodName(); void dumpDetails(Injector injector, PrintWriter printWriter) { String methodName = findMethodName(); printWriter.println(methodName == null ? "Failed to get method name" : methodName); String processName = getProcessName(); String processName = findProcessName(injector.activityManager()); printWriter.print("From process "); printWriter.print(processName == null ? "?" : processName); printWriter.println(" (pid=" + mCallerProcessId + ")"); } @Nullable String getProcessName() { private String findProcessName(@Nullable IActivityManager activityManager) { try { List<ActivityManager.RunningAppProcessInfo> runningProcesses = mActivityManager.getRunningAppProcesses(); List<ActivityManager.RunningAppProcessInfo> runningProcesses = null; if (activityManager != null) { runningProcesses = activityManager.getRunningAppProcesses(); } else { Slog.v(TAG, "No ActivityManager to find name of process with pid=" + mCallerProcessId); } if (runningProcesses != null) { for (ActivityManager.RunningAppProcessInfo processInfo : runningProcesses) { if (processInfo.pid == mCallerProcessId) { return processInfo.processName; } } } } catch (RemoteException e) { Slog.e(TAG, "Failed to get running app processes from ActivityManager", e); } Loading @@ -315,8 +322,8 @@ public final class ShutdownCheckPoints { private final String mPackageName; IntentCheckPoint( Injector injector, String intentName, String packageName, @Nullable String reason) { super(injector, reason); long timestamp, String intentName, String packageName, @Nullable String reason) { super(timestamp, reason); mIntentName = intentName; mPackageName = packageName; } Loading @@ -327,7 +334,7 @@ public final class ShutdownCheckPoints { } @Override void dumpDetails(PrintWriter printWriter) { void dumpDetails(Injector injector, PrintWriter printWriter) { printWriter.print("Intent: "); printWriter.println(mIntentName); printWriter.print("Package: "); Loading
services/tests/servicestests/src/com/android/server/power/ShutdownCheckPointsTest.java +27 −3 Original line number Diff line number Diff line Loading @@ -103,21 +103,45 @@ public class ShutdownCheckPointsTest { } @Test public void testCallerProcessBinderEntry() throws RemoteException { public void testCallerProcessBinderEntries() throws RemoteException { List<ActivityManager.RunningAppProcessInfo> runningAppProcessInfos = new ArrayList<>(); runningAppProcessInfos.add( new ActivityManager.RunningAppProcessInfo("process_name", 1, new String[0])); when(mActivityManager.getRunningAppProcesses()).thenReturn(runningAppProcessInfos); mTestInjector.setCurrentTime(1000); // Matching pid in getRunningAppProcesses mInstance.recordCheckPointInternal(1, "reason1"); // Missing pid in getRunningAppProcesses mInstance.recordCheckPointInternal(2, "reason2"); assertEquals( "Shutdown request from BINDER for reason reason1 " + "at 1970-01-01 00:00:01.000 UTC (epoch=1000)\n" + "com.android.server.power.ShutdownCheckPointsTest" + ".testCallerProcessBinderEntry\n" + "From process process_name (pid=1)\n\n", + ".testCallerProcessBinderEntries\n" + "From process process_name (pid=1)\n\n" + "Shutdown request from BINDER for reason reason2 " + "at 1970-01-01 00:00:01.000 UTC (epoch=1000)\n" + "com.android.server.power.ShutdownCheckPointsTest" + ".testCallerProcessBinderEntries\n" + "From process ? (pid=2)\n\n", dumpToString()); } @Test public void testNullCallerProcessBinderEntries() throws RemoteException { when(mActivityManager.getRunningAppProcesses()).thenReturn(null); mTestInjector.setCurrentTime(1000); mInstance.recordCheckPointInternal(1, "reason1"); assertEquals( "Shutdown request from BINDER for reason reason1 " + "at 1970-01-01 00:00:01.000 UTC (epoch=1000)\n" + "com.android.server.power.ShutdownCheckPointsTest" + ".testNullCallerProcessBinderEntries\n" + "From process ? (pid=1)\n\n", dumpToString()); } Loading