Handle overflow of id in NetworkEvent.
Test: runtest --path frameworks/base/services/tests/servicestests/src/com/android/server/devicepolicy/NetworkEventTest.java Bug: 63910201 Change-Id: I48e1ac0fabae4db7913ce6698a1cf932898d9642
This commit is contained in:
@@ -29,10 +29,10 @@ import android.util.LongSparseArray;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* A Handler class for managing network logging on a background thread.
|
||||
@@ -81,6 +81,7 @@ final class NetworkLoggingHandler extends Handler {
|
||||
}
|
||||
};
|
||||
|
||||
@VisibleForTesting
|
||||
static final int LOG_NETWORK_EVENT_MSG = 1;
|
||||
|
||||
/** Network events accumulated so far to be finalized into a batch at some point. */
|
||||
@@ -106,9 +107,15 @@ final class NetworkLoggingHandler extends Handler {
|
||||
private long mLastRetrievedBatchToken;
|
||||
|
||||
NetworkLoggingHandler(Looper looper, DevicePolicyManagerService dpm) {
|
||||
this(looper, dpm, 0 /* event id */);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
NetworkLoggingHandler(Looper looper, DevicePolicyManagerService dpm, long id) {
|
||||
super(looper);
|
||||
mDpm = dpm;
|
||||
mAlarmManager = mDpm.mInjector.getAlarmManager();
|
||||
this.mDpm = dpm;
|
||||
this.mAlarmManager = mDpm.mInjector.getAlarmManager();
|
||||
this.mId = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -189,7 +196,13 @@ final class NetworkLoggingHandler extends Handler {
|
||||
if (mNetworkEvents.size() > 0) {
|
||||
// Assign ids to the events.
|
||||
for (NetworkEvent event : mNetworkEvents) {
|
||||
event.setId(mId++);
|
||||
event.setId(mId);
|
||||
if (mId == Long.MAX_VALUE) {
|
||||
Slog.i(TAG, "Reached maximum id value; wrapping around ." + mCurrentBatchToken);
|
||||
mId = 0;
|
||||
} else {
|
||||
mId++;
|
||||
}
|
||||
}
|
||||
// Finalize the batch and start a new one from scratch.
|
||||
if (mBatches.size() >= MAX_BATCHES) {
|
||||
|
||||
@@ -15,13 +15,131 @@
|
||||
*/
|
||||
package com.android.server.devicepolicy;
|
||||
|
||||
import static com.android.server.devicepolicy.NetworkLoggingHandler.LOG_NETWORK_EVENT_MSG;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.app.admin.ConnectEvent;
|
||||
import android.app.admin.DeviceAdminReceiver;
|
||||
import android.app.admin.DevicePolicyManagerInternal;
|
||||
import android.app.admin.DnsEvent;
|
||||
import android.app.admin.NetworkEvent;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.Message;
|
||||
import android.os.Parcel;
|
||||
import android.os.SystemClock;
|
||||
import android.os.UserHandle;
|
||||
import android.os.test.TestLooper;
|
||||
import android.test.suitebuilder.annotation.SmallTest;
|
||||
|
||||
import com.android.server.LocalServices;
|
||||
import com.android.server.SystemService;
|
||||
|
||||
import org.mockito.ArgumentCaptor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@SmallTest
|
||||
public class NetworkEventTest extends DpmTestBase {
|
||||
private static final int MAX_EVENTS_PER_BATCH = 1200;
|
||||
|
||||
private DpmMockContext mSpiedDpmMockContext;
|
||||
private DevicePolicyManagerServiceTestable mDpmTestable;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
mSpiedDpmMockContext = spy(mMockContext);
|
||||
mSpiedDpmMockContext.callerPermissions.add(
|
||||
android.Manifest.permission.MANAGE_DEVICE_ADMINS);
|
||||
doNothing().when(mSpiedDpmMockContext).sendBroadcastAsUser(any(Intent.class),
|
||||
any(UserHandle.class));
|
||||
LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class);
|
||||
mDpmTestable = new DevicePolicyManagerServiceTestable(getServices(), mSpiedDpmMockContext);
|
||||
setUpPackageManagerForAdmin(admin1, DpmMockContext.CALLER_UID);
|
||||
mDpmTestable.setActiveAdmin(admin1, true, DpmMockContext.CALLER_USER_HANDLE);
|
||||
}
|
||||
|
||||
public void testNetworkEventId_monotonicallyIncreasing() throws Exception {
|
||||
// GIVEN the handler has not processed any events.
|
||||
long startingId = 0;
|
||||
|
||||
// WHEN the handler has processed the events.
|
||||
List<NetworkEvent> events = fillHandlerWithFullBatchOfEvents(startingId);
|
||||
|
||||
// THEN the events are in a batch.
|
||||
assertTrue("Batch not at the returned token.",
|
||||
events != null && events.size() == MAX_EVENTS_PER_BATCH);
|
||||
// THEN event ids are monotonically increasing.
|
||||
long expectedId = startingId;
|
||||
for (int i = 0; i < MAX_EVENTS_PER_BATCH; i++) {
|
||||
assertEquals("At index " + i + ", the event has the wrong id.", expectedId,
|
||||
events.get(i).getId());
|
||||
expectedId++;
|
||||
}
|
||||
}
|
||||
|
||||
public void testNetworkEventId_wrapsAround() throws Exception {
|
||||
// GIVEN the handler has almost processed Long.MAX_VALUE events.
|
||||
int gap = 5;
|
||||
long startingId = Long.MAX_VALUE - gap;
|
||||
|
||||
// WHEN the handler has processed the events.
|
||||
List<NetworkEvent> events = fillHandlerWithFullBatchOfEvents(startingId);
|
||||
|
||||
// THEN the events are in a batch.
|
||||
assertTrue("Batch not at the returned token.",
|
||||
events != null && events.size() == MAX_EVENTS_PER_BATCH);
|
||||
// THEN event ids are monotonically increasing.
|
||||
long expectedId = startingId;
|
||||
for (int i = 0; i < gap; i++) {
|
||||
assertEquals("At index " + i + ", the event has the wrong id.", expectedId,
|
||||
events.get(i).getId());
|
||||
expectedId++;
|
||||
}
|
||||
// THEN event ids are reset when the id reaches the maximum possible value.
|
||||
assertEquals("Event was not assigned the maximum id value.", Long.MAX_VALUE,
|
||||
events.get(gap).getId());
|
||||
assertEquals("Event id was not reset.", 0, events.get(gap + 1).getId());
|
||||
// THEN event ids are monotonically increasing.
|
||||
expectedId = 0;
|
||||
for (int i = gap + 1; i < MAX_EVENTS_PER_BATCH; i++) {
|
||||
assertEquals("At index " + i + ", the event has the wrong id.", expectedId,
|
||||
events.get(i).getId());
|
||||
expectedId++;
|
||||
}
|
||||
}
|
||||
|
||||
private List<NetworkEvent> fillHandlerWithFullBatchOfEvents(long startingId) throws Exception {
|
||||
// GIVEN a handler with events
|
||||
NetworkLoggingHandler handler = new NetworkLoggingHandler(new TestLooper().getLooper(),
|
||||
mDpmTestable, startingId);
|
||||
// GIVEN network events are sent to the handler.
|
||||
for (int i = 0; i < MAX_EVENTS_PER_BATCH; i++) {
|
||||
ConnectEvent event = new ConnectEvent("some_ip_address", 800, "com.google.foo",
|
||||
SystemClock.currentThreadTimeMillis());
|
||||
Message msg = new Message();
|
||||
msg.what = LOG_NETWORK_EVENT_MSG;
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putParcelable(NetworkLoggingHandler.NETWORK_EVENT_KEY, event);
|
||||
msg.setData(bundle);
|
||||
handler.handleMessage(msg);
|
||||
}
|
||||
|
||||
// WHEN the handler processes the events.
|
||||
ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
|
||||
verify(mSpiedDpmMockContext).sendBroadcastAsUser(intentCaptor.capture(),
|
||||
any(UserHandle.class));
|
||||
assertEquals(intentCaptor.getValue().getAction(),
|
||||
DeviceAdminReceiver.ACTION_NETWORK_LOGS_AVAILABLE);
|
||||
long token = intentCaptor.getValue().getExtras().getLong(
|
||||
DeviceAdminReceiver.EXTRA_NETWORK_LOGS_TOKEN, 0);
|
||||
return handler.retrieveFullLogBatch(token);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test parceling and unparceling of a ConnectEvent.
|
||||
|
||||
Reference in New Issue
Block a user