/*
 * 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.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback;
import android.net.Network;
import android.net.NetworkRequest;
import android.net.metrics.DnsEvent;
import android.net.metrics.INetdEventListener;
import android.net.metrics.IpConnectivityLog;
import android.os.RemoteException;
import android.util.Log;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.IndentingPrintWriter;

import java.io.PrintWriter;
import java.util.Arrays;
import java.util.SortedMap;
import java.util.TreeMap;


/**
 * Implementation of the INetdEventListener interface.
 */
public class NetdEventListenerService extends INetdEventListener.Stub {

    public static final String SERVICE_NAME = "netd_listener";

    private static final String TAG = NetdEventListenerService.class.getSimpleName();
    private static final boolean DBG = false;
    private static final boolean VDBG = false;

    // TODO: read this constant from system property
    private static final int MAX_LOOKUPS_PER_DNS_EVENT = 100;

    // Stores the results of a number of consecutive DNS lookups on the same network.
    // This class is not thread-safe and it is the responsibility of the service to call its methods
    // on one thread at a time.
    private class DnsEventBatch {
        private final int mNetId;

        private final byte[] mEventTypes = new byte[MAX_LOOKUPS_PER_DNS_EVENT];
        private final byte[] mReturnCodes = new byte[MAX_LOOKUPS_PER_DNS_EVENT];
        private final int[] mLatenciesMs = new int[MAX_LOOKUPS_PER_DNS_EVENT];
        private int mEventCount;

        public DnsEventBatch(int netId) {
            mNetId = netId;
        }

        public void addResult(byte eventType, byte returnCode, int latencyMs) {
            mEventTypes[mEventCount] = eventType;
            mReturnCodes[mEventCount] = returnCode;
            mLatenciesMs[mEventCount] = latencyMs;
            mEventCount++;
            if (mEventCount == MAX_LOOKUPS_PER_DNS_EVENT) {
                logAndClear();
            }
        }

        public void logAndClear() {
            // Did we lose a race with addResult?
            if (mEventCount == 0) {
                return;
            }

            // Only log as many events as we actually have.
            byte[] eventTypes = Arrays.copyOf(mEventTypes, mEventCount);
            byte[] returnCodes = Arrays.copyOf(mReturnCodes, mEventCount);
            int[] latenciesMs = Arrays.copyOf(mLatenciesMs, mEventCount);
            mMetricsLog.log(new DnsEvent(mNetId, eventTypes, returnCodes, latenciesMs));
            maybeLog("Logging %d results for netId %d", mEventCount, mNetId);
            mEventCount = 0;
        }

        // For debugging and unit tests only.
        public String toString() {
            return String.format("%s %d %d", getClass().getSimpleName(), mNetId, mEventCount);
        }
    }

    // Only sorted for ease of debugging. Because we only typically have a handful of networks up
    // at any given time, performance is not a concern.
    @GuardedBy("this")
    private final SortedMap<Integer, DnsEventBatch> mEventBatches = new TreeMap<>();

    // We register a NetworkCallback to ensure that when a network disconnects, we flush the DNS
    // queries we've logged on that network. Because we do not do this periodically, we might lose
    // up to MAX_LOOKUPS_PER_DNS_EVENT lookup stats on each network when the system is shutting
    // down. We believe this to be sufficient for now.
    private final ConnectivityManager mCm;
    private final IpConnectivityLog mMetricsLog;
    private final NetworkCallback mNetworkCallback = new NetworkCallback() {
        @Override
        public void onLost(Network network) {
            synchronized (NetdEventListenerService.this) {
                DnsEventBatch batch = mEventBatches.remove(network.netId);
                if (batch != null) {
                    batch.logAndClear();
                }
            }
        }
    };

    public NetdEventListenerService(Context context) {
        this(context.getSystemService(ConnectivityManager.class), new IpConnectivityLog());
    }

    @VisibleForTesting
    public NetdEventListenerService(ConnectivityManager cm, IpConnectivityLog log) {
        // We are started when boot is complete, so ConnectivityService should already be running.
        mCm = cm;
        mMetricsLog = log;
        final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
        mCm.registerNetworkCallback(request, mNetworkCallback);
    }

    @Override
    // Called concurrently by multiple binder threads.
    // This method must not block or perform long-running operations.
    public synchronized void onDnsEvent(int netId, int eventType, int returnCode, int latencyMs,
            String hostname, String[] ipAddresses, int ipAddressesCount, int uid)
            throws RemoteException {
        maybeVerboseLog("onDnsEvent(%d, %d, %d, %dms)", netId, eventType, returnCode, latencyMs);

        DnsEventBatch batch = mEventBatches.get(netId);
        if (batch == null) {
            batch = new DnsEventBatch(netId);
            mEventBatches.put(netId, batch);
        }
        batch.addResult((byte) eventType, (byte) returnCode, latencyMs);
    }

    @Override
    // Called concurrently by multiple binder threads.
    // This method must not block or perform long-running operations.
    public synchronized void onConnectEvent(int netId, int error, int latencyMs, String ipAddr, int port,
            int uid) throws RemoteException {
        maybeVerboseLog("onConnectEvent(%d, %d, %dms)", netId, error, latencyMs);
    }

    public synchronized void dump(PrintWriter writer) {
        IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
        pw.println(TAG + ":");
        pw.increaseIndent();
        for (DnsEventBatch batch : mEventBatches.values()) {
            pw.println(batch.toString());
        }
        pw.decreaseIndent();
    }

    private static void maybeLog(String s, Object... args) {
        if (DBG) Log.d(TAG, String.format(s, args));
    }

    private static void maybeVerboseLog(String s, Object... args) {
        if (VDBG) Log.d(TAG, String.format(s, args));
    }
}
