1623ab7d7a6a7d948fa6338a3992b2680d0192427Hugo Benichi/*
2623ab7d7a6a7d948fa6338a3992b2680d0192427Hugo Benichi * Copyright (C) 2016 The Android Open Source Project
3623ab7d7a6a7d948fa6338a3992b2680d0192427Hugo Benichi *
4623ab7d7a6a7d948fa6338a3992b2680d0192427Hugo Benichi * Licensed under the Apache License, Version 2.0 (the "License");
5623ab7d7a6a7d948fa6338a3992b2680d0192427Hugo Benichi * you may not use this file except in compliance with the License.
6623ab7d7a6a7d948fa6338a3992b2680d0192427Hugo Benichi * You may obtain a copy of the License at
7623ab7d7a6a7d948fa6338a3992b2680d0192427Hugo Benichi *
8623ab7d7a6a7d948fa6338a3992b2680d0192427Hugo Benichi *      http://www.apache.org/licenses/LICENSE-2.0
9623ab7d7a6a7d948fa6338a3992b2680d0192427Hugo Benichi *
10623ab7d7a6a7d948fa6338a3992b2680d0192427Hugo Benichi * Unless required by applicable law or agreed to in writing, software
11623ab7d7a6a7d948fa6338a3992b2680d0192427Hugo Benichi * distributed under the License is distributed on an "AS IS" BASIS,
12623ab7d7a6a7d948fa6338a3992b2680d0192427Hugo Benichi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13623ab7d7a6a7d948fa6338a3992b2680d0192427Hugo Benichi * See the License for the specific language governing permissions and
14623ab7d7a6a7d948fa6338a3992b2680d0192427Hugo Benichi * limitations under the License.
15623ab7d7a6a7d948fa6338a3992b2680d0192427Hugo Benichi */
16623ab7d7a6a7d948fa6338a3992b2680d0192427Hugo Benichi
17623ab7d7a6a7d948fa6338a3992b2680d0192427Hugo Benichipackage android.net.metrics;
18623ab7d7a6a7d948fa6338a3992b2680d0192427Hugo Benichi
19623ab7d7a6a7d948fa6338a3992b2680d0192427Hugo Benichiimport android.net.ConnectivityMetricsEvent;
2000a42d4c885bf7440c2677750ad8b10974b16d7fHugo Benichiimport android.net.IIpConnectivityMetrics;
21623ab7d7a6a7d948fa6338a3992b2680d0192427Hugo Benichiimport android.os.Parcelable;
22623ab7d7a6a7d948fa6338a3992b2680d0192427Hugo Benichiimport android.os.RemoteException;
2300a42d4c885bf7440c2677750ad8b10974b16d7fHugo Benichiimport android.os.ServiceManager;
24623ab7d7a6a7d948fa6338a3992b2680d0192427Hugo Benichiimport android.util.Log;
253bba249c4711b10b2ba5335c7b6653dc570aae64Hugo Benichiimport com.android.internal.annotations.VisibleForTesting;
26a365bace7a8e3e6da016531e26a6046a827acaa5Hugo Benichiimport com.android.internal.util.BitUtils;
273bba249c4711b10b2ba5335c7b6653dc570aae64Hugo Benichi
28623ab7d7a6a7d948fa6338a3992b2680d0192427Hugo Benichi/**
2900a42d4c885bf7440c2677750ad8b10974b16d7fHugo Benichi * Class for logging IpConnectvity events with IpConnectivityMetrics
30623ab7d7a6a7d948fa6338a3992b2680d0192427Hugo Benichi * {@hide}
31623ab7d7a6a7d948fa6338a3992b2680d0192427Hugo Benichi */
3200a42d4c885bf7440c2677750ad8b10974b16d7fHugo Benichipublic class IpConnectivityLog {
3300a42d4c885bf7440c2677750ad8b10974b16d7fHugo Benichi    private static final String TAG = IpConnectivityLog.class.getSimpleName();
3400a42d4c885bf7440c2677750ad8b10974b16d7fHugo Benichi    private static final boolean DBG = false;
35623ab7d7a6a7d948fa6338a3992b2680d0192427Hugo Benichi
36eab511b582cc00364dee7835534bb511719f9231Hugo Benichi    public static final String SERVICE_NAME = "connmetrics";
37eab511b582cc00364dee7835534bb511719f9231Hugo Benichi
3800a42d4c885bf7440c2677750ad8b10974b16d7fHugo Benichi    private IIpConnectivityMetrics mService;
3900a42d4c885bf7440c2677750ad8b10974b16d7fHugo Benichi
403bba249c4711b10b2ba5335c7b6653dc570aae64Hugo Benichi    public IpConnectivityLog() {
413bba249c4711b10b2ba5335c7b6653dc570aae64Hugo Benichi    }
423bba249c4711b10b2ba5335c7b6653dc570aae64Hugo Benichi
433bba249c4711b10b2ba5335c7b6653dc570aae64Hugo Benichi    @VisibleForTesting
4400a42d4c885bf7440c2677750ad8b10974b16d7fHugo Benichi    public IpConnectivityLog(IIpConnectivityMetrics service) {
4500a42d4c885bf7440c2677750ad8b10974b16d7fHugo Benichi        mService = service;
4600a42d4c885bf7440c2677750ad8b10974b16d7fHugo Benichi    }
4700a42d4c885bf7440c2677750ad8b10974b16d7fHugo Benichi
4800a42d4c885bf7440c2677750ad8b10974b16d7fHugo Benichi    private boolean checkLoggerService() {
4900a42d4c885bf7440c2677750ad8b10974b16d7fHugo Benichi        if (mService != null) {
5000a42d4c885bf7440c2677750ad8b10974b16d7fHugo Benichi            return true;
5100a42d4c885bf7440c2677750ad8b10974b16d7fHugo Benichi        }
5200a42d4c885bf7440c2677750ad8b10974b16d7fHugo Benichi        final IIpConnectivityMetrics service =
5300a42d4c885bf7440c2677750ad8b10974b16d7fHugo Benichi                IIpConnectivityMetrics.Stub.asInterface(ServiceManager.getService(SERVICE_NAME));
5400a42d4c885bf7440c2677750ad8b10974b16d7fHugo Benichi        if (service == null) {
5500a42d4c885bf7440c2677750ad8b10974b16d7fHugo Benichi            return false;
5600a42d4c885bf7440c2677750ad8b10974b16d7fHugo Benichi        }
5700a42d4c885bf7440c2677750ad8b10974b16d7fHugo Benichi        // Two threads racing here will write the same pointer because getService
5800a42d4c885bf7440c2677750ad8b10974b16d7fHugo Benichi        // is idempotent once MetricsLoggerService is initialized.
5900a42d4c885bf7440c2677750ad8b10974b16d7fHugo Benichi        mService = service;
6000a42d4c885bf7440c2677750ad8b10974b16d7fHugo Benichi        return true;
613bba249c4711b10b2ba5335c7b6653dc570aae64Hugo Benichi    }
623bba249c4711b10b2ba5335c7b6653dc570aae64Hugo Benichi
63623ab7d7a6a7d948fa6338a3992b2680d0192427Hugo Benichi    /**
64946b7e424e0e4d5bffc65ef405f32b966d192d3cHugo Benichi     * Log a ConnectivityMetricsEvent.
65946b7e424e0e4d5bffc65ef405f32b966d192d3cHugo Benichi     * @param ev the event to log. If the event timestamp is 0,
66946b7e424e0e4d5bffc65ef405f32b966d192d3cHugo Benichi     * the timestamp is set to the current time in milliseconds.
67623ab7d7a6a7d948fa6338a3992b2680d0192427Hugo Benichi     * @return true if the event was successfully logged.
68623ab7d7a6a7d948fa6338a3992b2680d0192427Hugo Benichi     */
69946b7e424e0e4d5bffc65ef405f32b966d192d3cHugo Benichi    public boolean log(ConnectivityMetricsEvent ev) {
7090cbc5b44450e9806ce0227d125fe7d5107c7c4bHugo Benichi        if (!checkLoggerService()) {
71623ab7d7a6a7d948fa6338a3992b2680d0192427Hugo Benichi            if (DBG) {
7200a42d4c885bf7440c2677750ad8b10974b16d7fHugo Benichi                Log.d(TAG, SERVICE_NAME + " service was not ready");
73623ab7d7a6a7d948fa6338a3992b2680d0192427Hugo Benichi            }
74623ab7d7a6a7d948fa6338a3992b2680d0192427Hugo Benichi            return false;
75623ab7d7a6a7d948fa6338a3992b2680d0192427Hugo Benichi        }
76946b7e424e0e4d5bffc65ef405f32b966d192d3cHugo Benichi        if (ev.timestamp == 0) {
77946b7e424e0e4d5bffc65ef405f32b966d192d3cHugo Benichi            ev.timestamp = System.currentTimeMillis();
78946b7e424e0e4d5bffc65ef405f32b966d192d3cHugo Benichi        }
79623ab7d7a6a7d948fa6338a3992b2680d0192427Hugo Benichi        try {
80ec27c4d9f33615be1f94d6bb5c5fd1358580ac05Hugo Benichi            int left = mService.logEvent(ev);
8100a42d4c885bf7440c2677750ad8b10974b16d7fHugo Benichi            return left >= 0;
82623ab7d7a6a7d948fa6338a3992b2680d0192427Hugo Benichi        } catch (RemoteException e) {
83623ab7d7a6a7d948fa6338a3992b2680d0192427Hugo Benichi            Log.e(TAG, "Error logging event", e);
84623ab7d7a6a7d948fa6338a3992b2680d0192427Hugo Benichi            return false;
85623ab7d7a6a7d948fa6338a3992b2680d0192427Hugo Benichi        }
86623ab7d7a6a7d948fa6338a3992b2680d0192427Hugo Benichi    }
87cfddd6879283860bb4d2cf2972ea086f585a37ecHugo Benichi
88946b7e424e0e4d5bffc65ef405f32b966d192d3cHugo Benichi    /**
89946b7e424e0e4d5bffc65ef405f32b966d192d3cHugo Benichi     * Log an IpConnectivity event.
90946b7e424e0e4d5bffc65ef405f32b966d192d3cHugo Benichi     * @param timestamp is the epoch timestamp of the event in ms.
91946b7e424e0e4d5bffc65ef405f32b966d192d3cHugo Benichi     * If the timestamp is 0, the timestamp is set to the current time in milliseconds.
92946b7e424e0e4d5bffc65ef405f32b966d192d3cHugo Benichi     * @param data is a Parcelable instance representing the event.
93946b7e424e0e4d5bffc65ef405f32b966d192d3cHugo Benichi     * @return true if the event was successfully logged.
94946b7e424e0e4d5bffc65ef405f32b966d192d3cHugo Benichi     */
95946b7e424e0e4d5bffc65ef405f32b966d192d3cHugo Benichi    public boolean log(long timestamp, Parcelable data) {
96946b7e424e0e4d5bffc65ef405f32b966d192d3cHugo Benichi        ConnectivityMetricsEvent ev = makeEv(data);
97946b7e424e0e4d5bffc65ef405f32b966d192d3cHugo Benichi        ev.timestamp = timestamp;
98946b7e424e0e4d5bffc65ef405f32b966d192d3cHugo Benichi        return log(ev);
99946b7e424e0e4d5bffc65ef405f32b966d192d3cHugo Benichi    }
100946b7e424e0e4d5bffc65ef405f32b966d192d3cHugo Benichi
101946b7e424e0e4d5bffc65ef405f32b966d192d3cHugo Benichi    /**
102946b7e424e0e4d5bffc65ef405f32b966d192d3cHugo Benichi     * Log an IpConnectivity event.
103948a85948dcccea4aaa9d70a74405308581b0925Hugo Benichi     * @param ifname the network interface associated with the event.
104948a85948dcccea4aaa9d70a74405308581b0925Hugo Benichi     * @param data is a Parcelable instance representing the event.
105948a85948dcccea4aaa9d70a74405308581b0925Hugo Benichi     * @return true if the event was successfully logged.
106948a85948dcccea4aaa9d70a74405308581b0925Hugo Benichi     */
107948a85948dcccea4aaa9d70a74405308581b0925Hugo Benichi    public boolean log(String ifname, Parcelable data) {
108948a85948dcccea4aaa9d70a74405308581b0925Hugo Benichi        ConnectivityMetricsEvent ev = makeEv(data);
109948a85948dcccea4aaa9d70a74405308581b0925Hugo Benichi        ev.ifname = ifname;
110948a85948dcccea4aaa9d70a74405308581b0925Hugo Benichi        return log(ev);
111948a85948dcccea4aaa9d70a74405308581b0925Hugo Benichi    }
112948a85948dcccea4aaa9d70a74405308581b0925Hugo Benichi
113948a85948dcccea4aaa9d70a74405308581b0925Hugo Benichi    /**
114948a85948dcccea4aaa9d70a74405308581b0925Hugo Benichi     * Log an IpConnectivity event.
115f927f0c52e7df5b057e7d28888c3cfed164d241aHugo Benichi     * @param netid the id of the network associated with the event.
116f927f0c52e7df5b057e7d28888c3cfed164d241aHugo Benichi     * @param transports the current transports of the network associated with the event, as defined
117f927f0c52e7df5b057e7d28888c3cfed164d241aHugo Benichi     * in NetworkCapabilities.
118f927f0c52e7df5b057e7d28888c3cfed164d241aHugo Benichi     * @param data is a Parcelable instance representing the event.
119f927f0c52e7df5b057e7d28888c3cfed164d241aHugo Benichi     * @return true if the event was successfully logged.
120f927f0c52e7df5b057e7d28888c3cfed164d241aHugo Benichi     */
121a365bace7a8e3e6da016531e26a6046a827acaa5Hugo Benichi    public boolean log(int netid, int[] transports, Parcelable data) {
122f927f0c52e7df5b057e7d28888c3cfed164d241aHugo Benichi        ConnectivityMetricsEvent ev = makeEv(data);
123f927f0c52e7df5b057e7d28888c3cfed164d241aHugo Benichi        ev.netId = netid;
124a365bace7a8e3e6da016531e26a6046a827acaa5Hugo Benichi        ev.transports = BitUtils.packBits(transports);
125f927f0c52e7df5b057e7d28888c3cfed164d241aHugo Benichi        return log(ev);
126f927f0c52e7df5b057e7d28888c3cfed164d241aHugo Benichi    }
127f927f0c52e7df5b057e7d28888c3cfed164d241aHugo Benichi
128f927f0c52e7df5b057e7d28888c3cfed164d241aHugo Benichi    /**
129f927f0c52e7df5b057e7d28888c3cfed164d241aHugo Benichi     * Log an IpConnectivity event.
130946b7e424e0e4d5bffc65ef405f32b966d192d3cHugo Benichi     * @param data is a Parcelable instance representing the event.
131946b7e424e0e4d5bffc65ef405f32b966d192d3cHugo Benichi     * @return true if the event was successfully logged.
132946b7e424e0e4d5bffc65ef405f32b966d192d3cHugo Benichi     */
133946b7e424e0e4d5bffc65ef405f32b966d192d3cHugo Benichi    public boolean log(Parcelable data) {
134946b7e424e0e4d5bffc65ef405f32b966d192d3cHugo Benichi        return log(makeEv(data));
135946b7e424e0e4d5bffc65ef405f32b966d192d3cHugo Benichi    }
136946b7e424e0e4d5bffc65ef405f32b966d192d3cHugo Benichi
137946b7e424e0e4d5bffc65ef405f32b966d192d3cHugo Benichi    private static ConnectivityMetricsEvent makeEv(Parcelable data) {
138946b7e424e0e4d5bffc65ef405f32b966d192d3cHugo Benichi        ConnectivityMetricsEvent ev = new ConnectivityMetricsEvent();
139946b7e424e0e4d5bffc65ef405f32b966d192d3cHugo Benichi        ev.data = data;
140946b7e424e0e4d5bffc65ef405f32b966d192d3cHugo Benichi        return ev;
141cfddd6879283860bb4d2cf2972ea086f585a37ecHugo Benichi    }
142623ab7d7a6a7d948fa6338a3992b2680d0192427Hugo Benichi}
143