diff --git a/core/java/android/net/ConnectivityMetricsLogger.java b/core/java/android/net/ConnectivityMetricsLogger.java index d8cdde94a2f18..73734958f5123 100644 --- a/core/java/android/net/ConnectivityMetricsLogger.java +++ b/core/java/android/net/ConnectivityMetricsLogger.java @@ -33,28 +33,39 @@ public class ConnectivityMetricsLogger { // Component Tags public static final int COMPONENT_TAG_CONNECTIVITY = 0; - public static final int COMPONENT_TAG_BLUETOOTH = 1; - public static final int COMPONENT_TAG_WIFI = 2; - public static final int COMPONENT_TAG_TELECOM = 3; - public static final int COMPONENT_TAG_TELEPHONY = 4; - - public static final int NUMBER_OF_COMPONENTS = 5; + public static final int COMPONENT_TAG_BLUETOOTH = 1; + public static final int COMPONENT_TAG_WIFI = 2; + public static final int COMPONENT_TAG_TELECOM = 3; + public static final int COMPONENT_TAG_TELEPHONY = 4; + public static final int NUMBER_OF_COMPONENTS = 5; // Event Tag public static final int TAG_SKIPPED_EVENTS = -1; public static final String DATA_KEY_EVENTS_COUNT = "count"; - private IConnectivityMetricsLogger mService; - - private long mServiceUnblockedTimestampMillis = 0; - private int mNumSkippedEvents = 0; + /** {@hide} */ protected final IConnectivityMetricsLogger mService; + /** {@hide} */ protected volatile long mServiceUnblockedTimestampMillis; + private int mNumSkippedEvents; public ConnectivityMetricsLogger() { mService = IConnectivityMetricsLogger.Stub.asInterface(ServiceManager.getService( CONNECTIVITY_METRICS_LOGGER_SERVICE)); } + /** + * Log a ConnectivityMetricsEvent. + * + * This method keeps track of skipped events when MetricsLoggerService throttles input events. + * It skips logging when MetricsLoggerService is active. When throttling ends, it logs a + * meta-event containing the number of events dropped. It is not safe to call this method + * concurrently from different threads. + * + * @param timestamp is the epoch timestamp of the event in ms. + * @param componentTag is the COMPONENT_* constant the event belongs to. + * @param eventTag is an event type constant whose meaning is specific to the component tag. + * @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) { @@ -104,7 +115,7 @@ public class ConnectivityMetricsLogger { } } } catch (RemoteException e) { - Log.e(TAG, "Error logging event " + e.getMessage()); + Log.e(TAG, "Error logging event", e); } } @@ -121,8 +132,8 @@ public class ConnectivityMetricsLogger { public ConnectivityMetricsEvent[] getEvents(ConnectivityMetricsEvent.Reference reference) { try { return mService.getEvents(reference); - } catch (RemoteException ex) { - Log.e(TAG, "IConnectivityMetricsLogger.getEvents: " + ex); + } catch (RemoteException e) { + Log.e(TAG, "IConnectivityMetricsLogger.getEvents", e); return null; } } @@ -133,8 +144,8 @@ public class ConnectivityMetricsLogger { public boolean register(PendingIntent newEventsIntent) { try { return mService.register(newEventsIntent); - } catch (RemoteException ex) { - Log.e(TAG, "IConnectivityMetricsLogger.register: " + ex); + } catch (RemoteException e) { + Log.e(TAG, "IConnectivityMetricsLogger.register", e); return false; } } @@ -142,8 +153,8 @@ public class ConnectivityMetricsLogger { public boolean unregister(PendingIntent newEventsIntent) { try { mService.unregister(newEventsIntent); - } catch (RemoteException ex) { - Log.e(TAG, "IConnectivityMetricsLogger.unregister: " + ex); + } catch (RemoteException e) { + Log.e(TAG, "IConnectivityMetricsLogger.unregister", e); return false; } diff --git a/core/java/android/net/metrics/IpConnectivityEvent.java b/core/java/android/net/metrics/IpConnectivityEvent.java index 95576c2853dde..d3771dcb60af8 100644 --- a/core/java/android/net/metrics/IpConnectivityEvent.java +++ b/core/java/android/net/metrics/IpConnectivityEvent.java @@ -16,20 +16,13 @@ package android.net.metrics; -import android.net.ConnectivityMetricsLogger; -import android.os.Parcel; import android.os.Parcelable; -/** - * {@hide} - */ +/** {@hide} */ public abstract class IpConnectivityEvent { - private static final int COMPONENT_TAG = ConnectivityMetricsLogger.COMPONENT_TAG_CONNECTIVITY; + private static final IpConnectivityLog sMetricsLog = new IpConnectivityLog(); - private static final ConnectivityMetricsLogger sMetricsLogger = new ConnectivityMetricsLogger(); - - public static void logEvent(T event) { - // TODO: consider using different component for DNS event. - sMetricsLogger.logEvent(System.currentTimeMillis(), COMPONENT_TAG, 0, event); + static void logEvent(T event) { + sMetricsLog.log(System.currentTimeMillis(), event); } -}; +} diff --git a/core/java/android/net/metrics/IpConnectivityLog.java b/core/java/android/net/metrics/IpConnectivityLog.java new file mode 100644 index 0000000000000..233ff74a145be --- /dev/null +++ b/core/java/android/net/metrics/IpConnectivityLog.java @@ -0,0 +1,70 @@ +/* + * 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.metrics; + +import android.net.ConnectivityMetricsEvent; +import android.net.ConnectivityMetricsLogger; +import android.os.Parcelable; +import android.os.RemoteException; +import android.util.Log; + +/** + * Specialization of the ConnectivityMetricsLogger class for recording IP connectivity events. + * {@hide} + */ +class IpConnectivityLog extends ConnectivityMetricsLogger { + private static String TAG = "IpConnectivityMetricsLogger"; + private static final boolean DBG = false; + + /** + * Log an IpConnectivity event. Contrary to logEvent(), this method does not + * keep track of skipped events and is thread-safe for callers. + * + * @param timestamp is the epoch timestamp of the event in ms. + * @param data is a Parcelable IpConnectivityEvent instance representing the event. + * + * @return true if the event was successfully logged. + */ + public boolean log(long timestamp, T data) { + if (mService == null) { + if (DBG) { + Log.d(TAG, CONNECTIVITY_METRICS_LOGGER_SERVICE + " service not ready"); + } + return false; + } + + if (System.currentTimeMillis() < mServiceUnblockedTimestampMillis) { + if (DBG) { + Log.d(TAG, "skipping logging due to throttling for IpConnectivity component"); + } + return false; + } + + try { + final ConnectivityMetricsEvent event = + new ConnectivityMetricsEvent(timestamp, COMPONENT_TAG_CONNECTIVITY, 0, data); + final long result = mService.logEvent(event); + if (result >= 0) { + mServiceUnblockedTimestampMillis = result; + } + return (result == 0); + } catch (RemoteException e) { + Log.e(TAG, "Error logging event", e); + return false; + } + } +}