chromium/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/ElidedLogcatProvider.java

// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.chromecast.shell;

import android.os.SystemClock;

import androidx.annotation.VisibleForTesting;

import org.chromium.base.Log;
import org.chromium.base.task.AsyncTask;

import java.io.BufferedReader;
import java.io.IOException;

/**
 * Extracts logcat out of Android devices and elide PII sensitive info from it.
 *
 * <p>Elided information includes: Emails, IP address, MAC address, URL/domains as well as
 * Javascript console messages.
 */
abstract class ElidedLogcatProvider {
    private static final String TAG = "ElidedLogcatProv";

    protected abstract void getRawLogcat(RawLogcatCallback rawLogcatCallback);

    protected interface RawLogcatCallback {
        public void onLogsDone(BufferedReader logsFileReader);
    }

    public interface LogcatCallback {
        public void onLogsDone(String logs);
    }

    public void getElidedLogcat(LogcatCallback callback) {
        getRawLogcat((BufferedReader logsFileReader) -> {
            // Run elideLogcat in background thread because it can be very slow
            new AsyncTaskRunner(AsyncTask.THREAD_POOL_EXECUTOR).doAsync(
                    () -> elideLogcat(logsFileReader), callback::onLogsDone);
        });
    }

    @VisibleForTesting
    protected static String elideLogcat(BufferedReader logsFileReader) {
        long startTimeMillis = SystemClock.elapsedRealtime();
        StringBuilder builder = new StringBuilder();
        try (BufferedReader autoClosableBufferedReader = logsFileReader) {
            String logLn;
            while ((logLn = autoClosableBufferedReader.readLine()) != null) {
                builder.append(LogcatElision.elide(logLn + "\n"));
            }
            long elapsedMillis = SystemClock.elapsedRealtime() - startTimeMillis;
            Log.i(TAG, "elideLogcat took " + elapsedMillis + " ms");
        } catch (IOException e) {
            Log.e(TAG, "Can't read logs", e);
        } finally {
            return builder.toString();
        }
    }
}