// Path: Android/app/src/main/java/app/intra/net/doh/Transaction.java
// public class Transaction implements Serializable {
// 
//   public enum Status {
//     COMPLETE,
//     SEND_FAIL,
//     HTTP_ERROR,
//     BAD_RESPONSE,
//     INTERNAL_ERROR,
//     CANCELED
//   }
// 
//   public Transaction(DnsPacket query, long timestamp) {
//     this.name = query.getQueryName();
//     this.type = query.getQueryType();
//     this.queryTime = timestamp;
//   }
// 
//   public final long queryTime;
//   public final String name;
//   public final short type;
//   public long responseTime;
//   public Status status;
//   public byte[] response;
//   public Calendar responseCalendar;
//   public String serverIp;
// }


import static android.content.Context.MODE_PRIVATE;
import android.content.Context;
import android.content.SharedPreferences;
import app.intra.net.doh.Transaction;
import java.util.Collections;
import java.util.LinkedList;
import java.util.Queue;

  public synchronized long getNumRequests() {
    return numRequests;
  }

  public synchronized Queue<Transaction> getRecentTransactions() {
    return new LinkedList<>(recentTransactions);
  }

  /**
   * Provide the receiver with temporary read-only access to the recent activity time-sequence.
   */
  public synchronized void showActivity(ActivityReceiver receiver) {
    receiver.receive(Collections.unmodifiableCollection(recentActivity));
  }

  public synchronized int countQueriesSince(long startTime) {
    // Linearly scan recent activity.  Due to the small scale (N ~ 300), a more efficient algorithm
    // does not appear to be necessary.
    int queries = recentActivity.size();
    for (long time : recentActivity) {
      if (time < startTime) {
        --queries;
      } else {
        break;
      }
    }
    return queries;
  }

// Path: Android/app/src/main/java/app/intra/net/doh/Transaction.java
// public class Transaction implements Serializable {
// 
//   public enum Status {
//     COMPLETE,
//     SEND_FAIL,
//     HTTP_ERROR,
//     BAD_RESPONSE,
//     INTERNAL_ERROR,
//     CANCELED
//   }
// 
//   public Transaction(DnsPacket query, long timestamp) {
//     this.name = query.getQueryName();
//     this.type = query.getQueryType();
//     this.queryTime = timestamp;
//   }
// 
//   public final long queryTime;
//   public final String name;
//   public final short type;
//   public long responseTime;
//   public Status status;
//   public byte[] response;
//   public Calendar responseCalendar;
//   public String serverIp;
// }


// Path: Android/app/src/main/java/app/intra/sys/QueryTracker.java
import static android.content.Context.MODE_PRIVATE;
import android.content.Context;
import android.content.SharedPreferences;
import app.intra.net.doh.Transaction;
import java.util.Collections;
import java.util.LinkedList;
import java.util.Queue;


  public synchronized long getNumRequests() {
    return numRequests;
  }

  public synchronized Queue<Transaction> getRecentTransactions() {
    return new LinkedList<>(recentTransactions);
  }

  /**
   * Provide the receiver with temporary read-only access to the recent activity time-sequence.
   */
  public synchronized void showActivity(ActivityReceiver receiver) {
    receiver.receive(Collections.unmodifiableCollection(recentActivity));
  }

  public synchronized int countQueriesSince(long startTime) {
    // Linearly scan recent activity.  Due to the small scale (N ~ 300), a more efficient algorithm
    // does not appear to be necessary.
    int queries = recentActivity.size();
    for (long time : recentActivity) {
      if (time < startTime) {
        --queries;
      } else {
        break;
      }
    }
    return queries;
  }

  public synchronized void setHistoryEnabled(boolean enabled) {