blob: 60d2a2abd759e2594954c01b0b129ef63d21327e [file] [log] [blame]
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);
}
}