diff options
| author | 2017-02-11 02:15:04 +0900 | |
|---|---|---|
| committer | 2017-02-15 17:12:58 +0900 | |
| commit | d22edc28f5c8417f591a913c0a97e718ae988a6f (patch) | |
| tree | 4cba4b7bc425e77a13338635c0bfe50abadfdd5a | |
| parent | ed6d75d5f31dd69d2c91cd82cddd5ee1db49b2c7 (diff) | |
IP connectivity metrics: delete obsolete logger service
Test: - runtest frameworks-net
- manually verified $ adb shell dumpsys connmetrics
Bug: 32648597
Change-Id: I69f7dee5871508398d7f7209658a00c768e2d18e
5 files changed, 3 insertions, 804 deletions
diff --git a/core/java/android/net/ConnectivityMetricsLogger.java b/core/java/android/net/ConnectivityMetricsLogger.java index 9a2d4e0a3124..67b6908ed020 100644 --- a/core/java/android/net/ConnectivityMetricsLogger.java +++ b/core/java/android/net/ConnectivityMetricsLogger.java @@ -46,32 +46,7 @@ public class ConnectivityMetricsLogger { public static final String DATA_KEY_EVENTS_COUNT = "count"; - /** {@hide} */ protected IConnectivityMetricsLogger mService; - /** {@hide} */ protected volatile long mServiceUnblockedTimestampMillis; - private int mNumSkippedEvents; - public ConnectivityMetricsLogger() { - // TODO: consider not initializing mService in constructor - this(IConnectivityMetricsLogger.Stub.asInterface( - ServiceManager.getService(CONNECTIVITY_METRICS_LOGGER_SERVICE))); - } - - /** {@hide} */ - @VisibleForTesting - public ConnectivityMetricsLogger(IConnectivityMetricsLogger service) { - mService = service; - } - - /** {@hide} */ - protected boolean checkLoggerService() { - if (mService != null) { - return true; - } - // Two threads racing here will write the same pointer because getService - // is idempotent once MetricsLoggerService is initialized. - mService = IConnectivityMetricsLogger.Stub.asInterface( - ServiceManager.getService(CONNECTIVITY_METRICS_LOGGER_SERVICE)); - return mService != null; } /** @@ -88,62 +63,6 @@ public class ConnectivityMetricsLogger { * @param data is a Parcelable instance representing the event. */ public void logEvent(long timestamp, int componentTag, int eventTag, Parcelable data) { - if (mService == null) { - if (DBG) { - Log.d(TAG, "logEvent(" + componentTag + "," + eventTag + ") Service not ready"); - } - return; - } - - if (mServiceUnblockedTimestampMillis > 0) { - if (System.currentTimeMillis() < mServiceUnblockedTimestampMillis) { - // Service is throttling events. - // Don't send new events because they will be dropped. - mNumSkippedEvents++; - return; - } - } - - ConnectivityMetricsEvent skippedEventsEvent = null; - if (mNumSkippedEvents > 0) { - // Log number of skipped events - Bundle b = new Bundle(); - b.putInt(DATA_KEY_EVENTS_COUNT, mNumSkippedEvents); - - // Log the skipped event. - // TODO: Note that some of the clients push all states events into the server, - // If we lose some states logged here, we might mess up the statistics happened at the - // backend. One of the options is to introduce a non-skippable flag for important events - // that are logged. - skippedEventsEvent = new ConnectivityMetricsEvent(mServiceUnblockedTimestampMillis, - componentTag, TAG_SKIPPED_EVENTS, b); - - mServiceUnblockedTimestampMillis = 0; - } - - ConnectivityMetricsEvent event = new ConnectivityMetricsEvent(timestamp, componentTag, - eventTag, data); - - try { - long result; - if (skippedEventsEvent == null) { - result = mService.logEvent(event); - } else { - result = mService.logEvents(new ConnectivityMetricsEvent[] - {skippedEventsEvent, event}); - } - - if (result == 0) { - mNumSkippedEvents = 0; - } else { - mNumSkippedEvents++; - if (result > 0) { // events are throttled - mServiceUnblockedTimestampMillis = result; - } - } - } catch (RemoteException e) { - Log.e(TAG, "Error logging event", e); - } } /** @@ -157,33 +76,17 @@ public class ConnectivityMetricsLogger { * @return events */ public ConnectivityMetricsEvent[] getEvents(ConnectivityMetricsEvent.Reference reference) { - try { - return mService.getEvents(reference); - } catch (RemoteException e) { - Log.e(TAG, "IConnectivityMetricsLogger.getEvents", e); - return null; - } + return new ConnectivityMetricsEvent[0]; } /** * Register PendingIntent which will be sent when new events are ready to be retrieved. */ public boolean register(PendingIntent newEventsIntent) { - try { - return mService.register(newEventsIntent); - } catch (RemoteException e) { - Log.e(TAG, "IConnectivityMetricsLogger.register", e); - return false; - } + return false; } public boolean unregister(PendingIntent newEventsIntent) { - try { - mService.unregister(newEventsIntent); - return true; - } catch (RemoteException e) { - Log.e(TAG, "IConnectivityMetricsLogger.unregister", e); - return false; - } + return false; } } diff --git a/services/core/java/com/android/server/connectivity/MetricsLoggerService.java b/services/core/java/com/android/server/connectivity/MetricsLoggerService.java deleted file mode 100644 index 1c9feb2695f6..000000000000 --- a/services/core/java/com/android/server/connectivity/MetricsLoggerService.java +++ /dev/null @@ -1,375 +0,0 @@ -/* - * Copyright (C) 2016 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.connectivity; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.server.SystemService; - -import android.app.PendingIntent; -import android.content.Context; -import android.content.pm.PackageManager; -import android.net.ConnectivityMetricsEvent; -import android.net.ConnectivityMetricsLogger; -import android.net.IConnectivityMetricsLogger; -import android.os.Binder; -import android.os.Parcel; -import android.text.format.DateUtils; -import android.util.Log; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.util.ArrayDeque; -import java.util.ArrayList; - -/** {@hide} */ -public class MetricsLoggerService extends SystemService { - private static String TAG = "ConnectivityMetricsLoggerService"; - private static final boolean DBG = true; - private static final boolean VDBG = false; - - public MetricsLoggerService(Context context) { - super(context); - } - - @Override - public void onStart() { - resetThrottlingCounters(System.currentTimeMillis()); - } - - @Override - public void onBootPhase(int phase) { - if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) { - if (DBG) Log.d(TAG, "onBootPhase: PHASE_SYSTEM_SERVICES_READY"); - publishBinderService(ConnectivityMetricsLogger.CONNECTIVITY_METRICS_LOGGER_SERVICE, - mBinder); - } - } - - // TODO: read these constants from system property - private final int EVENTS_NOTIFICATION_THRESHOLD = 300; - private final int MAX_NUMBER_OF_EVENTS = 1000; - private final int THROTTLING_MAX_NUMBER_OF_MESSAGES_PER_COMPONENT = 1000; - private final long THROTTLING_TIME_INTERVAL_MILLIS = DateUtils.HOUR_IN_MILLIS; - - private int mEventCounter = 0; - - /** - * Reference of the last event in the list of cached events. - * - * When client of this service retrieves events by calling getEvents, it is passing - * ConnectivityMetricsEvent.Reference object. After getEvents returns, that object will - * contain this reference. The client can save it and use next time it calls getEvents. - * This way only new events will be returned. - */ - private long mLastEventReference = 0; - - private final int mThrottlingCounters[] = - new int[ConnectivityMetricsLogger.NUMBER_OF_COMPONENTS]; - - private long mThrottlingIntervalBoundaryMillis; - - private final ArrayDeque<ConnectivityMetricsEvent> mEvents = new ArrayDeque<>(); - - private void enforceConnectivityInternalPermission() { - getContext().enforceCallingOrSelfPermission( - android.Manifest.permission.CONNECTIVITY_INTERNAL, - "MetricsLoggerService"); - } - - private void enforceDumpPermission() { - getContext().enforceCallingOrSelfPermission( - android.Manifest.permission.DUMP, - "MetricsLoggerService"); - } - - private void resetThrottlingCounters(long currentTimeMillis) { - synchronized (mThrottlingCounters) { - for (int i = 0; i < mThrottlingCounters.length; i++) { - mThrottlingCounters[i] = 0; - } - mThrottlingIntervalBoundaryMillis = - currentTimeMillis + THROTTLING_TIME_INTERVAL_MILLIS; - } - } - - private void addEvent(ConnectivityMetricsEvent e) { - if (VDBG) { - Log.v(TAG, "writeEvent(" + e.toString() + ")"); - } - - while (mEvents.size() >= MAX_NUMBER_OF_EVENTS) { - mEvents.removeFirst(); - } - - mEvents.addLast(e); - } - - @VisibleForTesting - final MetricsLoggerImpl mBinder = new MetricsLoggerImpl(); - - /** - * Implementation of the IConnectivityMetricsLogger interface. - */ - final class MetricsLoggerImpl extends IConnectivityMetricsLogger.Stub { - - private final ArrayList<PendingIntent> mPendingIntents = new ArrayList<>(); - - @Override - protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP) - != PackageManager.PERMISSION_GRANTED) { - pw.println("Permission Denial: can't dump ConnectivityMetricsLoggerService " + - "from from pid=" + Binder.getCallingPid() + ", uid=" + - Binder.getCallingUid()); - return; - } - - boolean dumpSerializedSize = false; - boolean dumpEvents = false; - boolean dumpDebugInfo = false; - for (String arg : args) { - switch (arg) { - case "--debug": - dumpDebugInfo = true; - break; - - case "--events": - dumpEvents = true; - break; - - case "--size": - dumpSerializedSize = true; - break; - - case "--all": - dumpDebugInfo = true; - dumpEvents = true; - dumpSerializedSize = true; - break; - } - } - - synchronized (mEvents) { - pw.println("Number of events: " + mEvents.size()); - pw.println("Counter: " + mEventCounter); - if (mEvents.size() > 0) { - pw.println("Time span: " + - DateUtils.formatElapsedTime( - (System.currentTimeMillis() - mEvents.peekFirst().timestamp) - / 1000)); - } - - if (dumpSerializedSize) { - Parcel p = Parcel.obtain(); - for (ConnectivityMetricsEvent e : mEvents) { - p.writeParcelable(e, 0); - } - pw.println("Serialized data size: " + p.dataSize()); - p.recycle(); - } - - if (dumpEvents) { - pw.println(); - pw.println("Events:"); - for (ConnectivityMetricsEvent e : mEvents) { - pw.println(e.toString()); - } - } - } - - if (dumpDebugInfo) { - synchronized (mThrottlingCounters) { - pw.println(); - for (int i = 0; i < ConnectivityMetricsLogger.NUMBER_OF_COMPONENTS; i++) { - if (mThrottlingCounters[i] > 0) { - pw.println("Throttling Counter #" + i + ": " + mThrottlingCounters[i]); - } - } - pw.println("Throttling Time Remaining: " + - DateUtils.formatElapsedTime( - (mThrottlingIntervalBoundaryMillis - System.currentTimeMillis()) - / 1000)); - } - } - - synchronized (mPendingIntents) { - if (!mPendingIntents.isEmpty()) { - pw.println(); - pw.println("Pending intents:"); - for (PendingIntent pi : mPendingIntents) { - pw.println(pi.toString()); - } - } - } - } - - public long logEvent(ConnectivityMetricsEvent event) { - ConnectivityMetricsEvent[] events = new ConnectivityMetricsEvent[]{event}; - return logEvents(events); - } - - /** - * @param events - * - * Note: All events must belong to the same component. - * - * @return 0 on success - * <0 if error happened - * >0 timestamp after which new events will be accepted - */ - public long logEvents(ConnectivityMetricsEvent[] events) { - enforceConnectivityInternalPermission(); - - if (events == null || events.length == 0) { - Log.wtf(TAG, "No events passed to logEvents()"); - return -1; - } - - int componentTag = events[0].componentTag; - if (componentTag < 0 || - componentTag >= ConnectivityMetricsLogger.NUMBER_OF_COMPONENTS) { - Log.wtf(TAG, "Unexpected tag: " + componentTag); - return -1; - } - - synchronized (mThrottlingCounters) { - long currentTimeMillis = System.currentTimeMillis(); - if (currentTimeMillis > mThrottlingIntervalBoundaryMillis) { - resetThrottlingCounters(currentTimeMillis); - } - - mThrottlingCounters[componentTag] += events.length; - - if (mThrottlingCounters[componentTag] > - THROTTLING_MAX_NUMBER_OF_MESSAGES_PER_COMPONENT) { - Log.w(TAG, "Too many events from #" + componentTag + - ". Block until " + mThrottlingIntervalBoundaryMillis); - - return mThrottlingIntervalBoundaryMillis; - } - } - - boolean sendPendingIntents = false; - - synchronized (mEvents) { - for (ConnectivityMetricsEvent e : events) { - if (e.componentTag != componentTag) { - Log.wtf(TAG, "Unexpected tag: " + e.componentTag); - return -1; - } - - addEvent(e); - } - - mLastEventReference += events.length; - - mEventCounter += events.length; - if (mEventCounter >= EVENTS_NOTIFICATION_THRESHOLD) { - mEventCounter = 0; - sendPendingIntents = true; - } - } - - if (sendPendingIntents) { - synchronized (mPendingIntents) { - for (PendingIntent pi : mPendingIntents) { - if (VDBG) Log.v(TAG, "Send pending intent"); - try { - pi.send(getContext(), 0, null, null, null); - } catch (PendingIntent.CanceledException e) { - Log.e(TAG, "Pending intent canceled: " + pi); - mPendingIntents.remove(pi); - } - } - } - } - - return 0; - } - - /** - * Retrieve events - * - * @param reference of the last event previously returned. The function will return - * events following it. - * If 0 then all events will be returned. - * After the function call it will contain reference of the - * last returned event. - * @return events - */ - public ConnectivityMetricsEvent[] getEvents(ConnectivityMetricsEvent.Reference reference) { - enforceDumpPermission(); - long ref = reference.getValue(); - if (VDBG) Log.v(TAG, "getEvents(" + ref + ")"); - - ConnectivityMetricsEvent[] result; - synchronized (mEvents) { - if (ref > mLastEventReference) { - Log.e(TAG, "Invalid reference"); - reference.setValue(mLastEventReference); - return null; - } - if (ref < mLastEventReference - mEvents.size()) { - ref = mLastEventReference - mEvents.size(); - } - - int numEventsToSkip = - mEvents.size() // Total number of events - - (int)(mLastEventReference - ref); // Number of events to return - - result = new ConnectivityMetricsEvent[mEvents.size() - numEventsToSkip]; - int i = 0; - for (ConnectivityMetricsEvent e : mEvents) { - if (numEventsToSkip > 0) { - numEventsToSkip--; - } else { - result[i++] = e; - } - } - - reference.setValue(mLastEventReference); - } - - return result; - } - - public boolean register(PendingIntent newEventsIntent) { - enforceDumpPermission(); - if (VDBG) Log.v(TAG, "register(" + newEventsIntent + ")"); - - synchronized (mPendingIntents) { - if (mPendingIntents.remove(newEventsIntent)) { - Log.w(TAG, "Replacing registered pending intent"); - } - mPendingIntents.add(newEventsIntent); - } - - return true; - } - - public void unregister(PendingIntent newEventsIntent) { - enforceDumpPermission(); - if (VDBG) Log.v(TAG, "unregister(" + newEventsIntent + ")"); - - synchronized (mPendingIntents) { - if (!mPendingIntents.remove(newEventsIntent)) { - Log.e(TAG, "Pending intent is not registered"); - } - } - } - }; -} diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 27d95a4603a6..de4a55bc8d6a 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -61,7 +61,6 @@ import com.android.server.audio.AudioService; import com.android.server.camera.CameraService; import com.android.server.clipboard.ClipboardService; import com.android.server.connectivity.IpConnectivityMetrics; -import com.android.server.connectivity.MetricsLoggerService; import com.android.server.devicepolicy.DevicePolicyManagerService; import com.android.server.display.DisplayManagerService; import com.android.server.display.NightDisplayService; @@ -662,10 +661,6 @@ public final class SystemServer { mSystemServiceManager.startService(BluetoothService.class); } - traceBeginAndSlog("ConnectivityMetricsLoggerService"); - mSystemServiceManager.startService(MetricsLoggerService.class); - Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER); - traceBeginAndSlog("IpConnectivityMetrics"); mSystemServiceManager.startService(IpConnectivityMetrics.class); Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER); diff --git a/tests/net/java/android/net/ConnectivityMetricsLoggerTest.java b/tests/net/java/android/net/ConnectivityMetricsLoggerTest.java deleted file mode 100644 index f89603052213..000000000000 --- a/tests/net/java/android/net/ConnectivityMetricsLoggerTest.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (C) 2016, 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 android.net; - -import android.os.Bundle; -import android.os.Parcel; -import android.test.suitebuilder.annotation.SmallTest; -import java.util.List; -import junit.framework.TestCase; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -public class ConnectivityMetricsLoggerTest extends TestCase { - - // use same Parcel object everywhere for pointer equality - static final Bundle FAKE_EV = new Bundle(); - static final int FAKE_COMPONENT = 1; - static final int FAKE_EVENT = 2; - - @Mock IConnectivityMetricsLogger mService; - ArgumentCaptor<ConnectivityMetricsEvent> evCaptor; - ArgumentCaptor<ConnectivityMetricsEvent[]> evArrayCaptor; - - ConnectivityMetricsLogger mLog; - - public void setUp() { - MockitoAnnotations.initMocks(this); - evCaptor = ArgumentCaptor.forClass(ConnectivityMetricsEvent.class); - evArrayCaptor = ArgumentCaptor.forClass(ConnectivityMetricsEvent[].class); - mLog = new ConnectivityMetricsLogger(mService); - } - - @SmallTest - public void testLogEvents() throws Exception { - mLog.logEvent(1, FAKE_COMPONENT, FAKE_EVENT, FAKE_EV); - mLog.logEvent(2, FAKE_COMPONENT, FAKE_EVENT, FAKE_EV); - mLog.logEvent(3, FAKE_COMPONENT, FAKE_EVENT, FAKE_EV); - - List<ConnectivityMetricsEvent> gotEvents = verifyEvents(3); - assertEventsEqual(expectedEvent(1), gotEvents.get(0)); - assertEventsEqual(expectedEvent(2), gotEvents.get(1)); - assertEventsEqual(expectedEvent(3), gotEvents.get(2)); - } - - @SmallTest - public void testLogEventTriggerThrottling() throws Exception { - when(mService.logEvent(any())).thenReturn(1234L); - - mLog.logEvent(1, FAKE_COMPONENT, FAKE_EVENT, FAKE_EV); - mLog.logEvent(2, FAKE_COMPONENT, FAKE_EVENT, FAKE_EV); - - List<ConnectivityMetricsEvent> gotEvents = verifyEvents(1); - assertEventsEqual(expectedEvent(1), gotEvents.get(0)); - } - - @SmallTest - public void testLogEventFails() throws Exception { - when(mService.logEvent(any())).thenReturn(-1L); // Error. - - mLog.logEvent(1, FAKE_COMPONENT, FAKE_EVENT, FAKE_EV); - mLog.logEvent(2, FAKE_COMPONENT, FAKE_EVENT, FAKE_EV); - - List<ConnectivityMetricsEvent> gotEvents = verifyEvents(1); - assertEventsEqual(expectedEvent(1), gotEvents.get(0)); - } - - @SmallTest - public void testLogEventWhenThrottling() throws Exception { - when(mService.logEvent(any())).thenReturn(Long.MAX_VALUE); // Throttled - - // No events are logged. The service is only called once - // After that, throttling state is maintained locally. - mLog.logEvent(1, FAKE_COMPONENT, FAKE_EVENT, FAKE_EV); - mLog.logEvent(2, FAKE_COMPONENT, FAKE_EVENT, FAKE_EV); - - List<ConnectivityMetricsEvent> gotEvents = verifyEvents(1); - assertEventsEqual(expectedEvent(1), gotEvents.get(0)); - } - - @SmallTest - public void testLogEventRecoverFromThrottling() throws Exception { - final long throttleTimeout = System.currentTimeMillis() + 10; - when(mService.logEvent(any())).thenReturn(throttleTimeout, 0L); - - mLog.logEvent(1, FAKE_COMPONENT, FAKE_EVENT, FAKE_EV); - mLog.logEvent(2, FAKE_COMPONENT, FAKE_EVENT, FAKE_EV); - mLog.logEvent(3, FAKE_COMPONENT, FAKE_EVENT, FAKE_EV); - Thread.sleep(100); - mLog.logEvent(53, FAKE_COMPONENT, FAKE_EVENT, FAKE_EV); - - List<ConnectivityMetricsEvent> gotEvents = verifyEvents(1); - assertEventsEqual(expectedEvent(1), gotEvents.get(0)); - - verify(mService, times(1)).logEvents(evArrayCaptor.capture()); - ConnectivityMetricsEvent[] gotOtherEvents = evArrayCaptor.getAllValues().get(0); - assertEquals(ConnectivityMetricsLogger.TAG_SKIPPED_EVENTS, gotOtherEvents[0].eventTag); - assertEventsEqual(expectedEvent(53), gotOtherEvents[1]); - } - - List<ConnectivityMetricsEvent> verifyEvents(int n) throws Exception { - verify(mService, times(n)).logEvent(evCaptor.capture()); - return evCaptor.getAllValues(); - } - - static ConnectivityMetricsEvent expectedEvent(int timestamp) { - return new ConnectivityMetricsEvent((long)timestamp, FAKE_COMPONENT, FAKE_EVENT, FAKE_EV); - } - - /** Outer equality for ConnectivityMetricsEvent to avoid overriding equals() and hashCode(). */ - static void assertEventsEqual(ConnectivityMetricsEvent expected, ConnectivityMetricsEvent got) { - assertEquals(expected.timestamp, got.timestamp); - assertEquals(expected.componentTag, got.componentTag); - assertEquals(expected.eventTag, got.eventTag); - assertEquals(expected.data, got.data); - } -} diff --git a/tests/net/java/com/android/server/connectivity/MetricsLoggerServiceTest.java b/tests/net/java/com/android/server/connectivity/MetricsLoggerServiceTest.java deleted file mode 100644 index 5981f48e7ccd..000000000000 --- a/tests/net/java/com/android/server/connectivity/MetricsLoggerServiceTest.java +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Copyright (C) 2016, 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.connectivity; - -import android.content.Context; -import android.net.ConnectivityMetricsEvent; -import android.os.Bundle; -import android.os.RemoteException; -import android.test.suitebuilder.annotation.SmallTest; -import static android.net.ConnectivityMetricsEvent.Reference; - -import junit.framework.TestCase; -import org.junit.Before; -import org.junit.Test; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertArrayEquals; - -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.io.FileDescriptor; -import java.io.FileOutputStream; -import java.util.Arrays; -import java.util.Comparator; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -/* - * TODO: - * - allow overriding MetricsLoggerService constants in tests. - * - test intents are correctly sent after the notification threshold. - * - test oldest events are correctly pushed out when internal deque is full. - * - test throttling triggers correctly. - */ -public class MetricsLoggerServiceTest extends TestCase { - - static final int COMPONENT_TAG = 1; - static final long N_EVENTS = 10L; - static final ConnectivityMetricsEvent EVENTS[] = new ConnectivityMetricsEvent[(int)N_EVENTS]; - static { - for (int i = 0; i < N_EVENTS; i++) { - EVENTS[i] = new ConnectivityMetricsEvent(i, COMPONENT_TAG, i, new Bundle()); - } - } - - static final ConnectivityMetricsEvent NO_EVENTS[] = new ConnectivityMetricsEvent[0]; - - @Mock Context mContext; - MetricsLoggerService mService; - - public void setUp() { - MockitoAnnotations.initMocks(this); - mService = new MetricsLoggerService(mContext); - mService.onStart(); - } - - @SmallTest - public void testGetNoEvents() throws Exception { - Reference r = new Reference(0); - assertArrayEquals(NO_EVENTS, mService.mBinder.getEvents(r)); - assertEquals(0, r.getValue()); - } - - @SmallTest - public void testLogAndGetEvents() throws Exception { - mService.mBinder.logEvents(EVENTS); - - Reference r = new Reference(0); - - assertArrayEquals(EVENTS, mService.mBinder.getEvents(r)); - assertEquals(N_EVENTS, r.getValue()); - - assertArrayEquals(NO_EVENTS, mService.mBinder.getEvents(r)); - assertEquals(N_EVENTS, r.getValue()); - } - - @SmallTest - public void testLogOneByOne() throws Exception { - for (ConnectivityMetricsEvent ev : EVENTS) { - mService.mBinder.logEvent(ev); - } - - Reference r = new Reference(0); - - assertArrayEquals(EVENTS, mService.mBinder.getEvents(r)); - assertEquals(N_EVENTS, r.getValue()); - - assertArrayEquals(NO_EVENTS, mService.mBinder.getEvents(r)); - assertEquals(N_EVENTS, r.getValue()); - } - - @SmallTest - public void testInterleavedLogAndGet() throws Exception { - mService.mBinder.logEvents(Arrays.copyOfRange(EVENTS, 0, 3)); - - Reference r = new Reference(0); - - assertArrayEquals(Arrays.copyOfRange(EVENTS, 0, 3), mService.mBinder.getEvents(r)); - assertEquals(3, r.getValue()); - - mService.mBinder.logEvents(Arrays.copyOfRange(EVENTS, 3, 8)); - mService.mBinder.logEvents(Arrays.copyOfRange(EVENTS, 8, 10)); - - assertArrayEquals(Arrays.copyOfRange(EVENTS, 3, 10), mService.mBinder.getEvents(r)); - assertEquals(N_EVENTS, r.getValue()); - - assertArrayEquals(NO_EVENTS, mService.mBinder.getEvents(r)); - assertEquals(N_EVENTS, r.getValue()); - } - - @SmallTest - public void testMultipleGetAll() throws Exception { - mService.mBinder.logEvents(Arrays.copyOf(EVENTS, 3)); - - Reference r1 = new Reference(0); - assertArrayEquals(Arrays.copyOf(EVENTS, 3), mService.mBinder.getEvents(r1)); - assertEquals(3, r1.getValue()); - - mService.mBinder.logEvents(Arrays.copyOfRange(EVENTS, 3, 10)); - - Reference r2 = new Reference(0); - assertArrayEquals(EVENTS, mService.mBinder.getEvents(r2)); - assertEquals(N_EVENTS, r2.getValue()); - } - - @SmallTest - public void testLogAndDumpConcurrently() throws Exception { - for (int i = 0; i < 50; i++) { - mContext = null; - mService = null; - setUp(); - logAndDumpConcurrently(); - } - } - - public void logAndDumpConcurrently() throws Exception { - final CountDownLatch latch = new CountDownLatch((int)N_EVENTS); - final FileDescriptor fd = new FileOutputStream("/dev/null").getFD(); - - for (ConnectivityMetricsEvent ev : EVENTS) { - new Thread() { - public void run() { - mService.mBinder.logEvent(ev); - latch.countDown(); - } - }.start(); - } - - new Thread() { - public void run() { - while (latch.getCount() > 0) { - mService.mBinder.dump(fd, new String[]{"--all"}); - } - } - }.start(); - - latch.await(100, TimeUnit.MILLISECONDS); - - Reference r = new Reference(0); - ConnectivityMetricsEvent[] got = mService.mBinder.getEvents(r); - Arrays.sort(got, new EventComparator()); - assertArrayEquals(EVENTS, got); - assertEquals(N_EVENTS, r.getValue()); - } - - static class EventComparator implements Comparator<ConnectivityMetricsEvent> { - public int compare(ConnectivityMetricsEvent ev1, ConnectivityMetricsEvent ev2) { - return Long.compare(ev1.timestamp, ev2.timestamp); - } - public boolean equal(Object o) { - return o instanceof EventComparator; - } - }; -} |