Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 623ab7d7 authored by Hugo Benichi's avatar Hugo Benichi
Browse files

ConnectivityMetricsLogger subclass for IpConnectivity

IpConnectivityEvent was using ConnectivityMetricsLogger directly for
logging events. However ConnectivityMetricsLogger keeps track in a
thread-unsafe way of skipped events rejected by MetricsLoggerService.

This patch introduces a subclass of ConnectivityMetricsLogger that
does not track skipped events, for using in IpConnectivityEvent.

It also qualifies the mServiceBlockedTimestampMillis variable as
volatile so that throttling is effective accross concurrent callers
of logEvent.

Bug: 28204408
Bug: 29023888
Change-Id: I33707ba1d07487b42f3ce9a1ad9a66d785e99fa7
parent 0118fbd3
Loading
Loading
Loading
Loading
+28 −17
Original line number Diff line number Diff line
@@ -37,7 +37,6 @@ public class ConnectivityMetricsLogger {
    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
@@ -45,16 +44,28 @@ public class ConnectivityMetricsLogger {

    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;
        }

+5 −12
Original line number Diff line number Diff line
@@ -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 ConnectivityMetricsLogger sMetricsLogger = new ConnectivityMetricsLogger();
    private static final IpConnectivityLog sMetricsLog = new IpConnectivityLog();

    public static <T extends IpConnectivityEvent & Parcelable> void logEvent(T event) {
        // TODO: consider using different component for DNS event.
        sMetricsLogger.logEvent(System.currentTimeMillis(), COMPONENT_TAG, 0, event);
    static <T extends IpConnectivityEvent & Parcelable> void logEvent(T event) {
        sMetricsLog.log(System.currentTimeMillis(), event);
    }
}
};
+70 −0
Original line number Diff line number Diff line
/*
 * 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 <T extends IpConnectivityEvent & Parcelable> 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;
        }
    }
}