private static void addAuditErrorsToDropBox(
      DropBoxManager db, SharedPreferences prefs, String headers, int maxSize, String tag)
      throws IOException {
    if (db == null || !db.isTagEnabled(tag)) return; // Logging disabled
    Slog.i(TAG, "Copying audit failures to DropBox");

    File file = new File("/proc/last_kmsg");
    long fileTime = file.lastModified();
    if (fileTime <= 0) {
      file = new File("/sys/fs/pstore/console-ramoops");
      fileTime = file.lastModified();
    }

    if (fileTime <= 0) return; // File does not exist

    if (prefs != null) {
      long lastTime = prefs.getLong(tag, 0);
      if (lastTime == fileTime) return; // Already logged this particular file
      // TODO: move all these SharedPreferences Editor commits
      // outside this function to the end of logBootEvents
      prefs.edit().putLong(tag, fileTime).apply();
    }

    String log = FileUtils.readTextFile(file, maxSize, "[[TRUNCATED]]\n");
    StringBuilder sb = new StringBuilder();
    for (String line : log.split("\n")) {
      if (line.contains("audit")) {
        sb.append(line + "\n");
      }
    }
    Slog.i(TAG, "Copied " + sb.toString().length() + " worth of audits to DropBox");
    db.addText(tag, headers + sb.toString());
  }
  private static void addFsckErrorsToDropBox(
      DropBoxManager db, SharedPreferences prefs, String headers, int maxSize, String tag)
      throws IOException {
    boolean upload_needed = false;
    if (db == null || !db.isTagEnabled(tag)) return; // Logging disabled
    Slog.i(TAG, "Checking for fsck errors");

    File file = new File("/dev/fscklogs/log");
    long fileTime = file.lastModified();
    if (fileTime <= 0) return; // File does not exist

    String log = FileUtils.readTextFile(file, maxSize, "[[TRUNCATED]]\n");
    StringBuilder sb = new StringBuilder();
    for (String line : log.split("\n")) {
      if (line.contains("FILE SYSTEM WAS MODIFIED")) {
        upload_needed = true;
        break;
      }
    }

    if (upload_needed) {
      addFileToDropBox(db, prefs, headers, "/dev/fscklogs/log", maxSize, tag);
    }

    // Remove the file so we don't re-upload if the runtime restarts.
    file.delete();
  }
  private static void addFileWithFootersToDropBox(
      DropBoxManager db,
      SharedPreferences prefs,
      String headers,
      String footers,
      String filename,
      int maxSize,
      String tag)
      throws IOException {
    if (db == null || !db.isTagEnabled(tag)) return; // Logging disabled

    File file = new File(filename);
    if (file.isDirectory()) return; // Skip subdirectories (likely vendor-specific)
    long fileTime = file.lastModified();
    if (fileTime <= 0) return; // File does not exist

    if (prefs != null) {
      long lastTime = prefs.getLong(filename, 0);
      if (lastTime == fileTime) return; // Already logged this particular file
      // TODO: move all these SharedPreferences Editor commits
      // outside this function to the end of logBootEvents
      prefs.edit().putLong(filename, fileTime).apply();
    }

    Slog.i(TAG, "Copying " + filename + " to DropBox (" + tag + ")");
    db.addText(tag, headers + FileUtils.readTextFile(file, maxSize, "[[TRUNCATED]]\n") + footers);
  }
  private static void addFileToDropBox(
      DropBoxManager db,
      SharedPreferences prefs,
      String headers,
      String filename,
      int maxSize,
      String tag)
      throws IOException {
    if (db == null || !db.isTagEnabled(tag)) return; // Logging disabled

    File file = new File(filename);
    long fileTime = file.lastModified();
    if (fileTime <= 0) return; // File does not exist

    if (prefs != null) {
      long lastTime = prefs.getLong(filename, 0);
      if (lastTime == fileTime) return; // Already logged this particular file
      prefs.edit().putLong(filename, fileTime).commit();
    }

    Slog.i(TAG, "Copying " + filename + " to DropBox (" + tag + ")");
    db.addText(tag, headers + FileUtils.readTextFile(file, maxSize, "[[TRUNCATED]]\n"));
  }
  private void logBatteryStatsLocked() {
    IBinder batteryInfoService = ServiceManager.getService(BatteryStats.SERVICE_NAME);
    if (batteryInfoService == null) return;

    DropBoxManager db = (DropBoxManager) mContext.getSystemService(Context.DROPBOX_SERVICE);
    if (db == null || !db.isTagEnabled("BATTERY_DISCHARGE_INFO")) return;

    File dumpFile = null;
    FileOutputStream dumpStream = null;
    try {
      // dump the service to a file
      dumpFile = new File(DUMPSYS_DATA_PATH + BatteryStats.SERVICE_NAME + ".dump");
      dumpStream = new FileOutputStream(dumpFile);
      batteryInfoService.dump(dumpStream.getFD(), DUMPSYS_ARGS);
      FileUtils.sync(dumpStream);

      // add dump file to drop box
      db.addFile("BATTERY_DISCHARGE_INFO", dumpFile, DropBoxManager.IS_TEXT);
    } catch (RemoteException e) {
      Slog.e(TAG, "failed to dump battery service", e);
    } catch (IOException e) {
      Slog.e(TAG, "failed to write dumpsys file", e);
    } finally {
      // make sure we clean up
      if (dumpStream != null) {
        try {
          dumpStream.close();
        } catch (IOException e) {
          Slog.e(TAG, "failed to close dumpsys output stream");
        }
      }
      if (dumpFile != null && !dumpFile.delete()) {
        Slog.e(TAG, "failed to delete temporary dumpsys file: " + dumpFile.getAbsolutePath());
      }
    }
  }