Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 99abb789 authored by Lais Andrade's avatar Lais Andrade Committed by Android (Google) Code Review
Browse files

Merge "Fix NPE in ShutdownCheckPoints dumpDetails method."

parents 15820d51 a65f1c58
Loading
Loading
Loading
Loading
+40 −33
Original line number Diff line number Diff line
@@ -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));
    }
@@ -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();
        }
    }
@@ -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) {
@@ -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. */
@@ -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();
        }

@@ -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];
@@ -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]);
@@ -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
@@ -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);
            }
@@ -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;
        }
@@ -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: ");
+27 −3
Original line number Diff line number Diff line
@@ -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());
    }