package android.net.cts.legacy.api22.permission;

import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.net.TrafficStats;
import android.support.test.filters.MediumTest;
import android.test.AndroidTestCase;

import java.io.File;
import java.net.ServerSocket;
import java.net.Socket;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class QtaguidPermissionTest extends AndroidTestCase {

    private static final String QTAGUID_STATS_FILE = "/proc/net/xt_qtaguid/stats";

    @MediumTest
    public void testDevQtaguidSane() throws Exception {
        File f = new File("/dev/xt_qtaguid");
        assertTrue(f.canRead());
        assertFalse(f.canWrite());
        assertFalse(f.canExecute());
    }

    public void testAccessPrivateTrafficStats() throws IOException {

        final int ownAppUid = getContext().getApplicationInfo().uid;
        try {
            BufferedReader qtaguidReader = new BufferedReader(new FileReader(QTAGUID_STATS_FILE));
            String line;
            // Skip the header line;
            qtaguidReader.readLine();
            while ((line = qtaguidReader.readLine()) != null) {
                String tokens[] = line.split(" ");
                // Go through all the entries we find the qtaguid stats and fail if we find a stats
                // with different uid.
                if (tokens.length > 3 && !tokens[3].equals(String.valueOf(ownAppUid))) {
                    fail("Other apps detailed traffic stats leaked, self uid: "
                         + String.valueOf(ownAppUid) + " find uid: " + tokens[3]);
                }
            }
            qtaguidReader.close();
        } catch (FileNotFoundException e) {
            fail("Was not able to access qtaguid/stats: " + e);
        }
    }

    private void accessOwnTrafficStats(long expectedTxBytes) throws IOException {

        final int ownAppUid = getContext().getApplicationInfo().uid;

        long totalTxBytes = 0;
        try {
            BufferedReader qtaguidReader = new BufferedReader(new FileReader(QTAGUID_STATS_FILE));
            String line;
            while ((line = qtaguidReader.readLine()) != null) {
                String tokens[] = line.split(" ");
                if (tokens.length > 3 && tokens[3].equals(String.valueOf(ownAppUid))) {
                    // Check the total stats of this uid is larger then 1MB
                    if (tokens[2].equals("0x0")) {
                        totalTxBytes += Integer.parseInt(tokens[7]);
                    }
                }
            }
            qtaguidReader.close();
        } catch (FileNotFoundException e) {
            fail("Was not able to access qtaguid/stats: " + e);
        }
        assertTrue(totalTxBytes + " expected to be greater than or equal to"
            + expectedTxBytes + "bytes", totalTxBytes >= expectedTxBytes);
    }

    public void testAccessOwnQtaguidTrafficStats() throws IOException {

        // Transfer 1MB of data across an explicitly localhost socket.
        final int byteCount = 1024;
        final int packetCount = 1024;

        final ServerSocket server = new ServerSocket(0);
        new Thread("CreatePrivateDataTest.createTrafficStatsWithTags") {
            @Override
            public void run() {
                try {
                    Socket socket = new Socket("localhost", server.getLocalPort());
                    // Make sure that each write()+flush() turns into a packet:
                    // disable Nagle.
                    socket.setTcpNoDelay(true);
                    OutputStream out = socket.getOutputStream();
                    byte[] buf = new byte[byteCount];
                    for (int i = 0; i < packetCount; i++) {
                        TrafficStats.setThreadStatsTag(i % 10);
                        TrafficStats.tagSocket(socket);
                        out.write(buf);
                        out.flush();
                    }
                    out.close();
                    socket.close();
                } catch (IOException e) {
                  assertTrue("io exception" + e, false);
                }
            }
        }.start();

        try {
            Socket socket = server.accept();
            InputStream in = socket.getInputStream();
            byte[] buf = new byte[byteCount];
            int read = 0;
            while (read < byteCount * packetCount) {
                int n = in.read(buf);
                assertTrue("Unexpected EOF", n > 0);
                read += n;
            }
        } finally {
            server.close();
        }

        accessOwnTrafficStats(byteCount * packetCount);
    }
}
