| /* |
| * Copyright (C) 2012 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.server.net; |
| |
| import static android.net.ConnectivityManager.TYPE_MOBILE; |
| import static android.net.NetworkStats.SET_DEFAULT; |
| import static android.net.NetworkStats.TAG_NONE; |
| import static android.net.NetworkStats.UID_ALL; |
| import static android.net.NetworkTemplate.buildTemplateMobileAll; |
| import static android.text.format.DateUtils.HOUR_IN_MILLIS; |
| import static android.text.format.DateUtils.MINUTE_IN_MILLIS; |
| |
| import android.content.res.Resources; |
| import android.net.NetworkIdentity; |
| import android.net.NetworkStats; |
| import android.net.NetworkTemplate; |
| import android.os.Process; |
| import android.os.UserHandle; |
| import android.telephony.TelephonyManager; |
| import android.test.AndroidTestCase; |
| import android.test.MoreAsserts; |
| import android.test.suitebuilder.annotation.MediumTest; |
| |
| import com.android.frameworks.servicestests.R; |
| |
| import java.io.ByteArrayInputStream; |
| import java.io.ByteArrayOutputStream; |
| import java.io.DataOutputStream; |
| import java.io.File; |
| import java.io.FileOutputStream; |
| import java.io.InputStream; |
| import java.io.OutputStream; |
| |
| import libcore.io.IoUtils; |
| import libcore.io.Streams; |
| |
| /** |
| * Tests for {@link NetworkStatsCollection}. |
| */ |
| @MediumTest |
| public class NetworkStatsCollectionTest extends AndroidTestCase { |
| |
| private static final String TEST_FILE = "test.bin"; |
| private static final String TEST_IMSI = "310260000000000"; |
| |
| @Override |
| public void setUp() throws Exception { |
| super.setUp(); |
| |
| // ignore any device overlay while testing |
| NetworkTemplate.forceAllNetworkTypes(); |
| } |
| |
| public void testReadLegacyNetwork() throws Exception { |
| final File testFile = new File(getContext().getFilesDir(), TEST_FILE); |
| stageFile(R.raw.netstats_v1, testFile); |
| |
| final NetworkStatsCollection collection = new NetworkStatsCollection(30 * MINUTE_IN_MILLIS); |
| collection.readLegacyNetwork(testFile); |
| |
| // verify that history read correctly |
| assertSummaryTotal(collection, buildTemplateMobileAll(TEST_IMSI), |
| 636016770L, 709306L, 88038768L, 518836L, NetworkStatsAccess.Level.DEVICE); |
| |
| // now export into a unified format |
| final ByteArrayOutputStream bos = new ByteArrayOutputStream(); |
| collection.write(new DataOutputStream(bos)); |
| |
| // clear structure completely |
| collection.reset(); |
| assertSummaryTotal(collection, buildTemplateMobileAll(TEST_IMSI), |
| 0L, 0L, 0L, 0L, NetworkStatsAccess.Level.DEVICE); |
| |
| // and read back into structure, verifying that totals are same |
| collection.read(new ByteArrayInputStream(bos.toByteArray())); |
| assertSummaryTotal(collection, buildTemplateMobileAll(TEST_IMSI), |
| 636016770L, 709306L, 88038768L, 518836L, NetworkStatsAccess.Level.DEVICE); |
| } |
| |
| public void testReadLegacyUid() throws Exception { |
| final File testFile = new File(getContext().getFilesDir(), TEST_FILE); |
| stageFile(R.raw.netstats_uid_v4, testFile); |
| |
| final NetworkStatsCollection collection = new NetworkStatsCollection(30 * MINUTE_IN_MILLIS); |
| collection.readLegacyUid(testFile, false); |
| |
| // verify that history read correctly |
| assertSummaryTotal(collection, buildTemplateMobileAll(TEST_IMSI), |
| 637076152L, 711413L, 88343717L, 521022L, NetworkStatsAccess.Level.DEVICE); |
| |
| // now export into a unified format |
| final ByteArrayOutputStream bos = new ByteArrayOutputStream(); |
| collection.write(new DataOutputStream(bos)); |
| |
| // clear structure completely |
| collection.reset(); |
| assertSummaryTotal(collection, buildTemplateMobileAll(TEST_IMSI), |
| 0L, 0L, 0L, 0L, NetworkStatsAccess.Level.DEVICE); |
| |
| // and read back into structure, verifying that totals are same |
| collection.read(new ByteArrayInputStream(bos.toByteArray())); |
| assertSummaryTotal(collection, buildTemplateMobileAll(TEST_IMSI), |
| 637076152L, 711413L, 88343717L, 521022L, NetworkStatsAccess.Level.DEVICE); |
| } |
| |
| public void testReadLegacyUidTags() throws Exception { |
| final File testFile = new File(getContext().getFilesDir(), TEST_FILE); |
| stageFile(R.raw.netstats_uid_v4, testFile); |
| |
| final NetworkStatsCollection collection = new NetworkStatsCollection(30 * MINUTE_IN_MILLIS); |
| collection.readLegacyUid(testFile, true); |
| |
| // verify that history read correctly |
| assertSummaryTotalIncludingTags(collection, buildTemplateMobileAll(TEST_IMSI), |
| 77017831L, 100995L, 35436758L, 92344L); |
| |
| // now export into a unified format |
| final ByteArrayOutputStream bos = new ByteArrayOutputStream(); |
| collection.write(new DataOutputStream(bos)); |
| |
| // clear structure completely |
| collection.reset(); |
| assertSummaryTotalIncludingTags(collection, buildTemplateMobileAll(TEST_IMSI), |
| 0L, 0L, 0L, 0L); |
| |
| // and read back into structure, verifying that totals are same |
| collection.read(new ByteArrayInputStream(bos.toByteArray())); |
| assertSummaryTotalIncludingTags(collection, buildTemplateMobileAll(TEST_IMSI), |
| 77017831L, 100995L, 35436758L, 92344L); |
| } |
| |
| public void testStartEndAtomicBuckets() throws Exception { |
| final NetworkStatsCollection collection = new NetworkStatsCollection(HOUR_IN_MILLIS); |
| |
| // record empty data straddling between buckets |
| final NetworkStats.Entry entry = new NetworkStats.Entry(); |
| entry.rxBytes = 32; |
| collection.recordData(null, UID_ALL, SET_DEFAULT, TAG_NONE, 30 * MINUTE_IN_MILLIS, |
| 90 * MINUTE_IN_MILLIS, entry); |
| |
| // assert that we report boundary in atomic buckets |
| assertEquals(0, collection.getStartMillis()); |
| assertEquals(2 * HOUR_IN_MILLIS, collection.getEndMillis()); |
| } |
| |
| public void testAccessLevels() throws Exception { |
| final NetworkStatsCollection collection = new NetworkStatsCollection(HOUR_IN_MILLIS); |
| final NetworkStats.Entry entry = new NetworkStats.Entry(); |
| final NetworkIdentitySet identSet = new NetworkIdentitySet(); |
| identSet.add(new NetworkIdentity(TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN, |
| TEST_IMSI, null, false, true)); |
| |
| int myUid = Process.myUid(); |
| int otherUidInSameUser = Process.myUid() + 1; |
| int uidInDifferentUser = Process.myUid() + UserHandle.PER_USER_RANGE; |
| |
| // Record one entry for the current UID. |
| entry.rxBytes = 32; |
| collection.recordData(identSet, myUid, SET_DEFAULT, TAG_NONE, 0, 60 * MINUTE_IN_MILLIS, |
| entry); |
| |
| // Record one entry for another UID in this user. |
| entry.rxBytes = 64; |
| collection.recordData(identSet, otherUidInSameUser, SET_DEFAULT, TAG_NONE, 0, |
| 60 * MINUTE_IN_MILLIS, entry); |
| |
| // Record one entry for the system UID. |
| entry.rxBytes = 128; |
| collection.recordData(identSet, Process.SYSTEM_UID, SET_DEFAULT, TAG_NONE, 0, |
| 60 * MINUTE_IN_MILLIS, entry); |
| |
| // Record one entry for a UID in a different user. |
| entry.rxBytes = 256; |
| collection.recordData(identSet, uidInDifferentUser, SET_DEFAULT, TAG_NONE, 0, |
| 60 * MINUTE_IN_MILLIS, entry); |
| |
| // Verify the set of relevant UIDs for each access level. |
| MoreAsserts.assertEquals(new int[] { myUid }, |
| collection.getRelevantUids(NetworkStatsAccess.Level.DEFAULT)); |
| MoreAsserts.assertEquals(new int[] { Process.SYSTEM_UID, myUid, otherUidInSameUser }, |
| collection.getRelevantUids(NetworkStatsAccess.Level.USER)); |
| MoreAsserts.assertEquals( |
| new int[] { Process.SYSTEM_UID, myUid, otherUidInSameUser, uidInDifferentUser }, |
| collection.getRelevantUids(NetworkStatsAccess.Level.DEVICE)); |
| |
| // Verify security check in getHistory. |
| assertNotNull(collection.getHistory(buildTemplateMobileAll(TEST_IMSI), myUid, SET_DEFAULT, |
| TAG_NONE, 0, NetworkStatsAccess.Level.DEFAULT)); |
| try { |
| collection.getHistory(buildTemplateMobileAll(TEST_IMSI), otherUidInSameUser, |
| SET_DEFAULT, TAG_NONE, 0, NetworkStatsAccess.Level.DEFAULT); |
| fail("Should have thrown SecurityException for accessing different UID"); |
| } catch (SecurityException e) { |
| // expected |
| } |
| |
| // Verify appropriate aggregation in getSummary. |
| assertSummaryTotal(collection, buildTemplateMobileAll(TEST_IMSI), 32, 0, 0, 0, |
| NetworkStatsAccess.Level.DEFAULT); |
| assertSummaryTotal(collection, buildTemplateMobileAll(TEST_IMSI), 32 + 64 + 128, 0, 0, 0, |
| NetworkStatsAccess.Level.USER); |
| assertSummaryTotal(collection, buildTemplateMobileAll(TEST_IMSI), 32 + 64 + 128 + 256, 0, 0, |
| 0, NetworkStatsAccess.Level.DEVICE); |
| } |
| |
| /** |
| * Copy a {@link Resources#openRawResource(int)} into {@link File} for |
| * testing purposes. |
| */ |
| private void stageFile(int rawId, File file) throws Exception { |
| new File(file.getParent()).mkdirs(); |
| InputStream in = null; |
| OutputStream out = null; |
| try { |
| in = getContext().getResources().openRawResource(rawId); |
| out = new FileOutputStream(file); |
| Streams.copy(in, out); |
| } finally { |
| IoUtils.closeQuietly(in); |
| IoUtils.closeQuietly(out); |
| } |
| } |
| |
| private static void assertSummaryTotal(NetworkStatsCollection collection, |
| NetworkTemplate template, long rxBytes, long rxPackets, long txBytes, long txPackets, |
| @NetworkStatsAccess.Level int accessLevel) { |
| final NetworkStats.Entry entry = collection.getSummary( |
| template, Long.MIN_VALUE, Long.MAX_VALUE, accessLevel) |
| .getTotal(null); |
| assertEntry(entry, rxBytes, rxPackets, txBytes, txPackets); |
| } |
| |
| private static void assertSummaryTotalIncludingTags(NetworkStatsCollection collection, |
| NetworkTemplate template, long rxBytes, long rxPackets, long txBytes, long txPackets) { |
| final NetworkStats.Entry entry = collection.getSummary( |
| template, Long.MIN_VALUE, Long.MAX_VALUE, NetworkStatsAccess.Level.DEVICE) |
| .getTotalIncludingTags(null); |
| assertEntry(entry, rxBytes, rxPackets, txBytes, txPackets); |
| } |
| |
| private static void assertEntry( |
| NetworkStats.Entry entry, long rxBytes, long rxPackets, long txBytes, long txPackets) { |
| assertEquals("unexpected rxBytes", rxBytes, entry.rxBytes); |
| assertEquals("unexpected rxPackets", rxPackets, entry.rxPackets); |
| assertEquals("unexpected txBytes", txBytes, entry.txBytes); |
| assertEquals("unexpected txPackets", txPackets, entry.txPackets); |
| } |
| } |