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

Commit 1e528c56 authored by Mohamad Mahmoud's avatar Mohamad Mahmoud Committed by Android (Google) Code Review
Browse files

Merge "Allow kernel logs to be appended to dropbox" into main

parents 53c403b8 ef79ae59
Loading
Loading
Loading
Loading
+11 −0
Original line number Original line Diff line number Diff line
@@ -14908,6 +14908,17 @@ public final class Settings {
        @Readable
        @Readable
        public static final String DROPBOX_TAG_PREFIX = "dropbox:";
        public static final String DROPBOX_TAG_PREFIX = "dropbox:";
        /**
         * Lines of kernel logs to include with system crash/ANR/etc. reports, as a
         * prefix of the dropbox tag of the report type. For example,
         * "kernel_logs_for_system_server_anr" controls the lines of kernel logs
         * captured with system server ANR reports. 0 to disable.
         *
         * @hide
         */
        @Readable
        public static final String ERROR_KERNEL_LOG_PREFIX = "kernel_logs_for_";
        /**
        /**
         * Lines of logcat to include with system crash/ANR/etc. reports, as a
         * Lines of logcat to include with system crash/ANR/etc. reports, as a
         * prefix of the dropbox tag of the report type. For example,
         * prefix of the dropbox tag of the report type. For example,
+1 −0
Original line number Original line Diff line number Diff line
@@ -233,6 +233,7 @@ public class SettingsBackupTest {
                    Settings.Global.ENHANCED_4G_MODE_ENABLED,
                    Settings.Global.ENHANCED_4G_MODE_ENABLED,
                    Settings.Global.ENABLE_16K_PAGES, // Added for 16K developer option
                    Settings.Global.ENABLE_16K_PAGES, // Added for 16K developer option
                    Settings.Global.EPHEMERAL_COOKIE_MAX_SIZE_BYTES,
                    Settings.Global.EPHEMERAL_COOKIE_MAX_SIZE_BYTES,
                    Settings.Global.ERROR_KERNEL_LOG_PREFIX,
                    Settings.Global.ERROR_LOGCAT_PREFIX,
                    Settings.Global.ERROR_LOGCAT_PREFIX,
                    Settings.Global.EUICC_PROVISIONED,
                    Settings.Global.EUICC_PROVISIONED,
                    Settings.Global.EUICC_SUPPORTED_COUNTRIES,
                    Settings.Global.EUICC_SUPPORTED_COUNTRIES,
+125 −117
Original line number Original line Diff line number Diff line
@@ -598,6 +598,9 @@ public class ActivityManagerService extends IActivityManager.Stub
    // as one line, but close enough for now.
    // as one line, but close enough for now.
    static final int RESERVED_BYTES_PER_LOGCAT_LINE = 100;
    static final int RESERVED_BYTES_PER_LOGCAT_LINE = 100;
    // How many seconds should the system wait before terminating the spawned logcat process.
    static final int LOGCAT_TIMEOUT_SEC = 10;
    // Necessary ApplicationInfo flags to mark an app as persistent
    // Necessary ApplicationInfo flags to mark an app as persistent
    static final int PERSISTENT_MASK =
    static final int PERSISTENT_MASK =
            ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT;
            ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT;
@@ -9939,8 +9942,7 @@ public class ActivityManagerService extends IActivityManager.Stub
        // If process is null, we are being called from some internal code
        // If process is null, we are being called from some internal code
        // and may be about to die -- run this synchronously.
        // and may be about to die -- run this synchronously.
        final boolean runSynchronously = process == null;
        final boolean runSynchronously = process == null;
        Thread worker =
        Thread worker = new Thread("Error dump: " + dropboxTag) {
                new Thread("Error dump: " + dropboxTag) {
            @Override
            @Override
            public void run() {
            public void run() {
                if (report != null) {
                if (report != null) {
@@ -9948,48 +9950,39 @@ public class ActivityManagerService extends IActivityManager.Stub
                }
                }
                String logcatSetting = Settings.Global.ERROR_LOGCAT_PREFIX + dropboxTag;
                String logcatSetting = Settings.Global.ERROR_LOGCAT_PREFIX + dropboxTag;
                        String maxBytesSetting =
                String kerLogSetting = Settings.Global.ERROR_KERNEL_LOG_PREFIX + dropboxTag;
                                Settings.Global.MAX_ERROR_BYTES_PREFIX + dropboxTag;
                String maxBytesSetting = Settings.Global.MAX_ERROR_BYTES_PREFIX + dropboxTag;
                        int lines =
                int logcatLines = Build.IS_USER
                                Build.IS_USER
                        ? 0
                        ? 0
                                        : Settings.Global.getInt(
                        : Settings.Global.getInt(mContext.getContentResolver(), logcatSetting, 0);
                                                mContext.getContentResolver(), logcatSetting, 0);
                int kernelLogLines = Build.IS_USER
                        int dropboxMaxSize =
                        ? 0
                                Settings.Global.getInt(
                        : Settings.Global.getInt(mContext.getContentResolver(), kerLogSetting, 0);
                                        mContext.getContentResolver(),
                int dropboxMaxSize = Settings.Global.getInt(
                                        maxBytesSetting,
                        mContext.getContentResolver(), maxBytesSetting, DROPBOX_DEFAULT_MAX_SIZE);
                                        DROPBOX_DEFAULT_MAX_SIZE);
                if (dataFile != null) {
                if (dataFile != null) {
                            // Attach the stack traces file to the report so collectors can load
                    // Attach the stack traces file to the report so collectors can load them
                            // them
                    // by file if they have access.
                    // by file if they have access.
                    sb.append(DATA_FILE_PATH_HEADER)
                    sb.append(DATA_FILE_PATH_HEADER)
                                    .append(dataFile.getAbsolutePath())
                            .append(dataFile.getAbsolutePath()).append('\n');
                                    .append('\n');
                            int maxDataFileSize =
                    int maxDataFileSize = dropboxMaxSize
                                    dropboxMaxSize
                            - sb.length()
                            - sb.length()
                                            - lines * RESERVED_BYTES_PER_LOGCAT_LINE
                            - logcatLines * RESERVED_BYTES_PER_LOGCAT_LINE
                            - kernelLogLines * RESERVED_BYTES_PER_LOGCAT_LINE
                            - DATA_FILE_PATH_FOOTER.length();
                            - DATA_FILE_PATH_FOOTER.length();
                    if (maxDataFileSize > 0) {
                    if (maxDataFileSize > 0) {
                        // Inline dataFile contents if there is room.
                        // Inline dataFile contents if there is room.
                        try {
                        try {
                                    sb.append(
                            sb.append(FileUtils.readTextFile(dataFile, maxDataFileSize,
                                            FileUtils.readTextFile(
                                                    dataFile,
                                                    maxDataFileSize,
                                    "\n\n[[TRUNCATED]]\n"));
                                    "\n\n[[TRUNCATED]]\n"));
                        } catch (IOException e) {
                        } catch (IOException e) {
                            Slog.e(TAG, "Error reading " + dataFile, e);
                            Slog.e(TAG, "Error reading " + dataFile, e);
                        }
                        }
                    }
                    }
                    // Always append the footer, even there wasn't enough space to inline the
                            // Always append the footer, even there wasn't enough space to inline
                            // the
                    // dataFile contents.
                    // dataFile contents.
                    sb.append(DATA_FILE_PATH_FOOTER);
                    sb.append(DATA_FILE_PATH_FOOTER);
                }
                }
@@ -9997,62 +9990,16 @@ public class ActivityManagerService extends IActivityManager.Stub
                if (crashInfo != null && crashInfo.stackTrace != null) {
                if (crashInfo != null && crashInfo.stackTrace != null) {
                    sb.append(crashInfo.stackTrace);
                    sb.append(crashInfo.stackTrace);
                }
                }
                boolean shouldAddLogs = logcatLines > 0 || kernelLogLines > 0;
                        if (lines > 0 && !runSynchronously) {
                if (!runSynchronously && shouldAddLogs) {
                    sb.append("\n");
                    sb.append("\n");
                    if (logcatLines > 0) {
                            InputStreamReader input = null;
                        fetchLogcatBuffers(sb, logcatLines, LOGCAT_TIMEOUT_SEC,
                            try {
                                List.of("events", "system", "main", "crash"));
                                java.lang.Process logcat =
                                        new ProcessBuilder(
                                                        // Time out after 10s of inactivity, but
                                                        // kill logcat with SEGV
                                                        // so we can investigate why it didn't
                                                        // finish.
                                                        "/system/bin/timeout",
                                                        "-i",
                                                        "-s",
                                                        "SEGV",
                                                        "10s",
                                                        // Merge several logcat streams, and take
                                                        // the last N lines.
                                                        "/system/bin/logcat",
                                                        "-v",
                                                        "threadtime",
                                                        "-b",
                                                        "events",
                                                        "-b",
                                                        "system",
                                                        "-b",
                                                        "main",
                                                        "-b",
                                                        "crash",
                                                        "-t",
                                                        String.valueOf(lines))
                                                .redirectErrorStream(true)
                                                .start();
                                try {
                                    logcat.getOutputStream().close();
                                } catch (IOException e) {
                                }
                                try {
                                    logcat.getErrorStream().close();
                                } catch (IOException e) {
                                }
                                input = new InputStreamReader(logcat.getInputStream());
                                int num;
                                char[] buf = new char[8192];
                                while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
                            } catch (IOException e) {
                                Slog.e(TAG, "Error running logcat", e);
                            } finally {
                                if (input != null)
                                    try {
                                        input.close();
                                    } catch (IOException e) {
                    }
                    }
                    if (kernelLogLines > 0) {
                        fetchLogcatBuffers(sb, kernelLogLines, LOGCAT_TIMEOUT_SEC / 2,
                                List.of("kernel"));
                    }
                    }
                }
                }
@@ -10320,6 +10267,67 @@ public class ActivityManagerService extends IActivityManager.Stub
                Binder.getCallingPid(), state);
                Binder.getCallingPid(), state);
    }
    }
    /**
     * Retrieves logs from specified logcat buffers and appends them to a StringBuilder
     * in the supplied order. The method executes a logcat command to fetch specific
     * log entries from the supplied buffers.
     *
     * @param sb the StringBuilder to append the logcat output to.
     * @param lines the number of lines to retrieve.
     * @param timeout the maximum allowed time in seconds for logcat to run before being terminated.
     * @param buffers the list of log buffers from which to retrieve logs.
     */
    private static void fetchLogcatBuffers(StringBuilder sb, int lines,
            int timeout, List<String> buffers) {
        if (buffers.size() == 0 || lines <= 0 || timeout <= 0) {
            return;
        }
        List<String> command = new ArrayList<>(10 + (2 * buffers.size()));
        // Time out after 10s of inactivity, but kill logcat with SEGV
        // so we can investigate why it didn't finish.
        command.add("/system/bin/timeout");
        command.add("-i");
        command.add("-s");
        command.add("SEGV");
        command.add(timeout + "s");
        // Merge several logcat streams, and take the last N lines.
        command.add("/system/bin/logcat");
        command.add("-v");
        // This adds a timestamp and thread info to each log line.
        command.add("threadtime");
        for (String buffer : buffers) {
            command.add("-b");
            command.add(buffer);
        }
        // Limit the output to the last N lines.
        command.add("-t");
        command.add(String.valueOf(lines));
        try {
            java.lang.Process proc =
                    new ProcessBuilder(command).redirectErrorStream(true).start();
            // Close the output stream immediately as we do not send input to the process.
            try {
                proc.getOutputStream().close();
            } catch (IOException e) {
            }
            try (InputStreamReader reader = new InputStreamReader(proc.getInputStream())) {
                char[] buffer = new char[8192];
                int numRead;
                while ((numRead = reader.read(buffer, 0, buffer.length)) > 0) {
                    sb.append(buffer, 0, numRead);
                }
            }
        } catch (IOException e) {
            Slog.e(TAG, "Error running logcat", e);
        }
    }
    /**
    /**
     * Check if the calling process has the permission to dump given package,
     * Check if the calling process has the permission to dump given package,
     * throw SecurityException if it doesn't have the permission.
     * throw SecurityException if it doesn't have the permission.