102b3e6bfc5bbd5f1a8ce1ce68976e59142073b6fPavel Zhamaitsiak/*
202b3e6bfc5bbd5f1a8ce1ce68976e59142073b6fPavel Zhamaitsiak * Copyright (C) 2016 The Android Open Source Project
302b3e6bfc5bbd5f1a8ce1ce68976e59142073b6fPavel Zhamaitsiak *
402b3e6bfc5bbd5f1a8ce1ce68976e59142073b6fPavel Zhamaitsiak * Licensed under the Apache License, Version 2.0 (the "License");
502b3e6bfc5bbd5f1a8ce1ce68976e59142073b6fPavel Zhamaitsiak * you may not use this file except in compliance with the License.
602b3e6bfc5bbd5f1a8ce1ce68976e59142073b6fPavel Zhamaitsiak * You may obtain a copy of the License at
702b3e6bfc5bbd5f1a8ce1ce68976e59142073b6fPavel Zhamaitsiak *
802b3e6bfc5bbd5f1a8ce1ce68976e59142073b6fPavel Zhamaitsiak *      http://www.apache.org/licenses/LICENSE-2.0
902b3e6bfc5bbd5f1a8ce1ce68976e59142073b6fPavel Zhamaitsiak *
1002b3e6bfc5bbd5f1a8ce1ce68976e59142073b6fPavel Zhamaitsiak * Unless required by applicable law or agreed to in writing, software
1102b3e6bfc5bbd5f1a8ce1ce68976e59142073b6fPavel Zhamaitsiak * distributed under the License is distributed on an "AS IS" BASIS,
1202b3e6bfc5bbd5f1a8ce1ce68976e59142073b6fPavel Zhamaitsiak * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1302b3e6bfc5bbd5f1a8ce1ce68976e59142073b6fPavel Zhamaitsiak * See the License for the specific language governing permissions and
1402b3e6bfc5bbd5f1a8ce1ce68976e59142073b6fPavel Zhamaitsiak * limitations under the License.
1502b3e6bfc5bbd5f1a8ce1ce68976e59142073b6fPavel Zhamaitsiak */
1602b3e6bfc5bbd5f1a8ce1ce68976e59142073b6fPavel Zhamaitsiakpackage android.net;
1702b3e6bfc5bbd5f1a8ce1ce68976e59142073b6fPavel Zhamaitsiak
18f6f24c03f39016ee927e8bdbcff75a53841829c8Pavel Zhamaitsiakimport android.annotation.SystemApi;
19c2c39e28f3ae7f993821dda55b69605989967f60Pavel Zhamaitsiakimport android.app.PendingIntent;
20d1cb256b3efd2c00f1c44541b5589c2ea17b3cb8Pavel Zhamaitsiakimport android.os.Bundle;
2102b3e6bfc5bbd5f1a8ce1ce68976e59142073b6fPavel Zhamaitsiakimport android.os.Parcelable;
2202b3e6bfc5bbd5f1a8ce1ce68976e59142073b6fPavel Zhamaitsiakimport android.os.RemoteException;
2302b3e6bfc5bbd5f1a8ce1ce68976e59142073b6fPavel Zhamaitsiakimport android.os.ServiceManager;
2402b3e6bfc5bbd5f1a8ce1ce68976e59142073b6fPavel Zhamaitsiakimport android.util.Log;
2502b3e6bfc5bbd5f1a8ce1ce68976e59142073b6fPavel Zhamaitsiak
2602b3e6bfc5bbd5f1a8ce1ce68976e59142073b6fPavel Zhamaitsiak/** {@hide} */
27f6f24c03f39016ee927e8bdbcff75a53841829c8Pavel Zhamaitsiak@SystemApi
2802b3e6bfc5bbd5f1a8ce1ce68976e59142073b6fPavel Zhamaitsiakpublic class ConnectivityMetricsLogger {
2902b3e6bfc5bbd5f1a8ce1ce68976e59142073b6fPavel Zhamaitsiak    private static String TAG = "ConnectivityMetricsLogger";
3002b3e6bfc5bbd5f1a8ce1ce68976e59142073b6fPavel Zhamaitsiak    private static final boolean DBG = true;
3102b3e6bfc5bbd5f1a8ce1ce68976e59142073b6fPavel Zhamaitsiak
3202b3e6bfc5bbd5f1a8ce1ce68976e59142073b6fPavel Zhamaitsiak    public static final String CONNECTIVITY_METRICS_LOGGER_SERVICE = "connectivity_metrics_logger";
3302b3e6bfc5bbd5f1a8ce1ce68976e59142073b6fPavel Zhamaitsiak
3402b3e6bfc5bbd5f1a8ce1ce68976e59142073b6fPavel Zhamaitsiak    // Component Tags
35d1cb256b3efd2c00f1c44541b5589c2ea17b3cb8Pavel Zhamaitsiak    public static final int COMPONENT_TAG_CONNECTIVITY = 0;
36d1cb256b3efd2c00f1c44541b5589c2ea17b3cb8Pavel Zhamaitsiak    public static final int COMPONENT_TAG_BLUETOOTH = 1;
37d1cb256b3efd2c00f1c44541b5589c2ea17b3cb8Pavel Zhamaitsiak    public static final int COMPONENT_TAG_WIFI = 2;
38d1cb256b3efd2c00f1c44541b5589c2ea17b3cb8Pavel Zhamaitsiak    public static final int COMPONENT_TAG_TELECOM = 3;
39d1cb256b3efd2c00f1c44541b5589c2ea17b3cb8Pavel Zhamaitsiak    public static final int COMPONENT_TAG_TELEPHONY = 4;
40d1cb256b3efd2c00f1c44541b5589c2ea17b3cb8Pavel Zhamaitsiak
41d1cb256b3efd2c00f1c44541b5589c2ea17b3cb8Pavel Zhamaitsiak    public static final int NUMBER_OF_COMPONENTS = 5;
42d1cb256b3efd2c00f1c44541b5589c2ea17b3cb8Pavel Zhamaitsiak
43d1cb256b3efd2c00f1c44541b5589c2ea17b3cb8Pavel Zhamaitsiak    // Event Tag
44d1cb256b3efd2c00f1c44541b5589c2ea17b3cb8Pavel Zhamaitsiak    public static final int TAG_SKIPPED_EVENTS = -1;
45d1cb256b3efd2c00f1c44541b5589c2ea17b3cb8Pavel Zhamaitsiak
46d1cb256b3efd2c00f1c44541b5589c2ea17b3cb8Pavel Zhamaitsiak    public static final String DATA_KEY_EVENTS_COUNT = "count";
4702b3e6bfc5bbd5f1a8ce1ce68976e59142073b6fPavel Zhamaitsiak
4802b3e6bfc5bbd5f1a8ce1ce68976e59142073b6fPavel Zhamaitsiak    private IConnectivityMetricsLogger mService;
4902b3e6bfc5bbd5f1a8ce1ce68976e59142073b6fPavel Zhamaitsiak
50d1cb256b3efd2c00f1c44541b5589c2ea17b3cb8Pavel Zhamaitsiak    private long mServiceUnblockedTimestampMillis = 0;
51d1cb256b3efd2c00f1c44541b5589c2ea17b3cb8Pavel Zhamaitsiak    private int mNumSkippedEvents = 0;
52d1cb256b3efd2c00f1c44541b5589c2ea17b3cb8Pavel Zhamaitsiak
5302b3e6bfc5bbd5f1a8ce1ce68976e59142073b6fPavel Zhamaitsiak    public ConnectivityMetricsLogger() {
5402b3e6bfc5bbd5f1a8ce1ce68976e59142073b6fPavel Zhamaitsiak        mService = IConnectivityMetricsLogger.Stub.asInterface(ServiceManager.getService(
5502b3e6bfc5bbd5f1a8ce1ce68976e59142073b6fPavel Zhamaitsiak                CONNECTIVITY_METRICS_LOGGER_SERVICE));
5602b3e6bfc5bbd5f1a8ce1ce68976e59142073b6fPavel Zhamaitsiak    }
5702b3e6bfc5bbd5f1a8ce1ce68976e59142073b6fPavel Zhamaitsiak
5802b3e6bfc5bbd5f1a8ce1ce68976e59142073b6fPavel Zhamaitsiak    public void logEvent(long timestamp, int componentTag, int eventTag, Parcelable data) {
5902b3e6bfc5bbd5f1a8ce1ce68976e59142073b6fPavel Zhamaitsiak        if (mService == null) {
6002b3e6bfc5bbd5f1a8ce1ce68976e59142073b6fPavel Zhamaitsiak            if (DBG) {
6102b3e6bfc5bbd5f1a8ce1ce68976e59142073b6fPavel Zhamaitsiak                Log.d(TAG, "logEvent(" + componentTag + "," + eventTag + ") Service not ready");
6202b3e6bfc5bbd5f1a8ce1ce68976e59142073b6fPavel Zhamaitsiak            }
63d1cb256b3efd2c00f1c44541b5589c2ea17b3cb8Pavel Zhamaitsiak            return;
64d1cb256b3efd2c00f1c44541b5589c2ea17b3cb8Pavel Zhamaitsiak        }
65d1cb256b3efd2c00f1c44541b5589c2ea17b3cb8Pavel Zhamaitsiak
66d1cb256b3efd2c00f1c44541b5589c2ea17b3cb8Pavel Zhamaitsiak        if (mServiceUnblockedTimestampMillis > 0) {
67d1cb256b3efd2c00f1c44541b5589c2ea17b3cb8Pavel Zhamaitsiak            if (System.currentTimeMillis() < mServiceUnblockedTimestampMillis) {
68d1cb256b3efd2c00f1c44541b5589c2ea17b3cb8Pavel Zhamaitsiak                // Service is throttling events.
69d1cb256b3efd2c00f1c44541b5589c2ea17b3cb8Pavel Zhamaitsiak                // Don't send new events because they will be dropped.
70d1cb256b3efd2c00f1c44541b5589c2ea17b3cb8Pavel Zhamaitsiak                mNumSkippedEvents++;
71d1cb256b3efd2c00f1c44541b5589c2ea17b3cb8Pavel Zhamaitsiak                return;
72d1cb256b3efd2c00f1c44541b5589c2ea17b3cb8Pavel Zhamaitsiak            }
73d1cb256b3efd2c00f1c44541b5589c2ea17b3cb8Pavel Zhamaitsiak        }
74d1cb256b3efd2c00f1c44541b5589c2ea17b3cb8Pavel Zhamaitsiak
75d1cb256b3efd2c00f1c44541b5589c2ea17b3cb8Pavel Zhamaitsiak        ConnectivityMetricsEvent skippedEventsEvent = null;
76d1cb256b3efd2c00f1c44541b5589c2ea17b3cb8Pavel Zhamaitsiak        if (mNumSkippedEvents > 0) {
77d1cb256b3efd2c00f1c44541b5589c2ea17b3cb8Pavel Zhamaitsiak            // Log number of skipped events
78d1cb256b3efd2c00f1c44541b5589c2ea17b3cb8Pavel Zhamaitsiak            Bundle b = new Bundle();
79d1cb256b3efd2c00f1c44541b5589c2ea17b3cb8Pavel Zhamaitsiak            b.putInt(DATA_KEY_EVENTS_COUNT, mNumSkippedEvents);
80d1cb256b3efd2c00f1c44541b5589c2ea17b3cb8Pavel Zhamaitsiak            skippedEventsEvent = new ConnectivityMetricsEvent(mServiceUnblockedTimestampMillis,
81d1cb256b3efd2c00f1c44541b5589c2ea17b3cb8Pavel Zhamaitsiak                    componentTag, TAG_SKIPPED_EVENTS, b);
82d1cb256b3efd2c00f1c44541b5589c2ea17b3cb8Pavel Zhamaitsiak
83d1cb256b3efd2c00f1c44541b5589c2ea17b3cb8Pavel Zhamaitsiak            mServiceUnblockedTimestampMillis = 0;
84d1cb256b3efd2c00f1c44541b5589c2ea17b3cb8Pavel Zhamaitsiak        }
85d1cb256b3efd2c00f1c44541b5589c2ea17b3cb8Pavel Zhamaitsiak
86d1cb256b3efd2c00f1c44541b5589c2ea17b3cb8Pavel Zhamaitsiak        ConnectivityMetricsEvent event = new ConnectivityMetricsEvent(timestamp, componentTag,
87d1cb256b3efd2c00f1c44541b5589c2ea17b3cb8Pavel Zhamaitsiak                eventTag, data);
88d1cb256b3efd2c00f1c44541b5589c2ea17b3cb8Pavel Zhamaitsiak
89d1cb256b3efd2c00f1c44541b5589c2ea17b3cb8Pavel Zhamaitsiak        try {
90d1cb256b3efd2c00f1c44541b5589c2ea17b3cb8Pavel Zhamaitsiak            long result;
91d1cb256b3efd2c00f1c44541b5589c2ea17b3cb8Pavel Zhamaitsiak            if (skippedEventsEvent == null) {
92d1cb256b3efd2c00f1c44541b5589c2ea17b3cb8Pavel Zhamaitsiak                result = mService.logEvent(event);
93d1cb256b3efd2c00f1c44541b5589c2ea17b3cb8Pavel Zhamaitsiak            } else {
94d1cb256b3efd2c00f1c44541b5589c2ea17b3cb8Pavel Zhamaitsiak                result = mService.logEvents(new ConnectivityMetricsEvent[]
95d1cb256b3efd2c00f1c44541b5589c2ea17b3cb8Pavel Zhamaitsiak                        {skippedEventsEvent, event});
96d1cb256b3efd2c00f1c44541b5589c2ea17b3cb8Pavel Zhamaitsiak            }
97d1cb256b3efd2c00f1c44541b5589c2ea17b3cb8Pavel Zhamaitsiak
98d1cb256b3efd2c00f1c44541b5589c2ea17b3cb8Pavel Zhamaitsiak            if (result == 0) {
99d1cb256b3efd2c00f1c44541b5589c2ea17b3cb8Pavel Zhamaitsiak                mNumSkippedEvents = 0;
100d1cb256b3efd2c00f1c44541b5589c2ea17b3cb8Pavel Zhamaitsiak            } else {
101d1cb256b3efd2c00f1c44541b5589c2ea17b3cb8Pavel Zhamaitsiak                mNumSkippedEvents++;
102d1cb256b3efd2c00f1c44541b5589c2ea17b3cb8Pavel Zhamaitsiak                if (result > 0) { // events are throttled
103d1cb256b3efd2c00f1c44541b5589c2ea17b3cb8Pavel Zhamaitsiak                    mServiceUnblockedTimestampMillis = result;
104d1cb256b3efd2c00f1c44541b5589c2ea17b3cb8Pavel Zhamaitsiak                }
10502b3e6bfc5bbd5f1a8ce1ce68976e59142073b6fPavel Zhamaitsiak            }
106d1cb256b3efd2c00f1c44541b5589c2ea17b3cb8Pavel Zhamaitsiak        } catch (RemoteException e) {
107d1cb256b3efd2c00f1c44541b5589c2ea17b3cb8Pavel Zhamaitsiak            Log.e(TAG, "Error logging event " + e.getMessage());
10802b3e6bfc5bbd5f1a8ce1ce68976e59142073b6fPavel Zhamaitsiak        }
10902b3e6bfc5bbd5f1a8ce1ce68976e59142073b6fPavel Zhamaitsiak    }
110c2c39e28f3ae7f993821dda55b69605989967f60Pavel Zhamaitsiak
111c2c39e28f3ae7f993821dda55b69605989967f60Pavel Zhamaitsiak    /**
112c2c39e28f3ae7f993821dda55b69605989967f60Pavel Zhamaitsiak     * Retrieve events
113c2c39e28f3ae7f993821dda55b69605989967f60Pavel Zhamaitsiak     *
114c2c39e28f3ae7f993821dda55b69605989967f60Pavel Zhamaitsiak     * @param reference of the last event previously returned. The function will return
115c2c39e28f3ae7f993821dda55b69605989967f60Pavel Zhamaitsiak     *                  events following it.
116c2c39e28f3ae7f993821dda55b69605989967f60Pavel Zhamaitsiak     *                  If 0 then all events will be returned.
117c2c39e28f3ae7f993821dda55b69605989967f60Pavel Zhamaitsiak     *                  After the function call it will contain reference of the
118c2c39e28f3ae7f993821dda55b69605989967f60Pavel Zhamaitsiak     *                  last returned event.
119c2c39e28f3ae7f993821dda55b69605989967f60Pavel Zhamaitsiak     * @return events
120c2c39e28f3ae7f993821dda55b69605989967f60Pavel Zhamaitsiak     */
121c2c39e28f3ae7f993821dda55b69605989967f60Pavel Zhamaitsiak    public ConnectivityMetricsEvent[] getEvents(ConnectivityMetricsEvent.Reference reference) {
122c2c39e28f3ae7f993821dda55b69605989967f60Pavel Zhamaitsiak        try {
123c2c39e28f3ae7f993821dda55b69605989967f60Pavel Zhamaitsiak            return mService.getEvents(reference);
124c2c39e28f3ae7f993821dda55b69605989967f60Pavel Zhamaitsiak        } catch (RemoteException ex) {
125c2c39e28f3ae7f993821dda55b69605989967f60Pavel Zhamaitsiak            Log.e(TAG, "IConnectivityMetricsLogger.getEvents: " + ex);
126c2c39e28f3ae7f993821dda55b69605989967f60Pavel Zhamaitsiak            return null;
127c2c39e28f3ae7f993821dda55b69605989967f60Pavel Zhamaitsiak        }
128c2c39e28f3ae7f993821dda55b69605989967f60Pavel Zhamaitsiak    }
129c2c39e28f3ae7f993821dda55b69605989967f60Pavel Zhamaitsiak
130c2c39e28f3ae7f993821dda55b69605989967f60Pavel Zhamaitsiak    /**
131c2c39e28f3ae7f993821dda55b69605989967f60Pavel Zhamaitsiak     * Register PendingIntent which will be sent when new events are ready to be retrieved.
132c2c39e28f3ae7f993821dda55b69605989967f60Pavel Zhamaitsiak     */
133c2c39e28f3ae7f993821dda55b69605989967f60Pavel Zhamaitsiak    public boolean register(PendingIntent newEventsIntent) {
134c2c39e28f3ae7f993821dda55b69605989967f60Pavel Zhamaitsiak        try {
135c2c39e28f3ae7f993821dda55b69605989967f60Pavel Zhamaitsiak            return mService.register(newEventsIntent);
136c2c39e28f3ae7f993821dda55b69605989967f60Pavel Zhamaitsiak        } catch (RemoteException ex) {
137c2c39e28f3ae7f993821dda55b69605989967f60Pavel Zhamaitsiak            Log.e(TAG, "IConnectivityMetricsLogger.register: " + ex);
138c2c39e28f3ae7f993821dda55b69605989967f60Pavel Zhamaitsiak            return false;
139c2c39e28f3ae7f993821dda55b69605989967f60Pavel Zhamaitsiak        }
140c2c39e28f3ae7f993821dda55b69605989967f60Pavel Zhamaitsiak    }
141c2c39e28f3ae7f993821dda55b69605989967f60Pavel Zhamaitsiak
142c2c39e28f3ae7f993821dda55b69605989967f60Pavel Zhamaitsiak    public boolean unregister(PendingIntent newEventsIntent) {
143c2c39e28f3ae7f993821dda55b69605989967f60Pavel Zhamaitsiak        try {
144c2c39e28f3ae7f993821dda55b69605989967f60Pavel Zhamaitsiak            mService.unregister(newEventsIntent);
145c2c39e28f3ae7f993821dda55b69605989967f60Pavel Zhamaitsiak        } catch (RemoteException ex) {
146c2c39e28f3ae7f993821dda55b69605989967f60Pavel Zhamaitsiak            Log.e(TAG, "IConnectivityMetricsLogger.unregister: " + ex);
147c2c39e28f3ae7f993821dda55b69605989967f60Pavel Zhamaitsiak            return false;
148c2c39e28f3ae7f993821dda55b69605989967f60Pavel Zhamaitsiak        }
149c2c39e28f3ae7f993821dda55b69605989967f60Pavel Zhamaitsiak
150c2c39e28f3ae7f993821dda55b69605989967f60Pavel Zhamaitsiak        return true;
151c2c39e28f3ae7f993821dda55b69605989967f60Pavel Zhamaitsiak    }
15202b3e6bfc5bbd5f1a8ce1ce68976e59142073b6fPavel Zhamaitsiak}
153