/*
 * 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.devicepolicy;

import android.app.admin.ConnectEvent;
import android.app.admin.DnsEvent;
import android.app.admin.NetworkEvent;
import android.content.pm.PackageManagerInternal;
import android.net.IIpConnectivityMetrics;
import android.net.INetdEventCallback;
import android.os.Bundle;
import android.os.Message;
import android.os.Process;
import android.os.RemoteException;
import android.util.Log;
import android.util.Slog;

import com.android.server.ServiceThread;
import com.android.server.net.BaseNetdEventCallback;

import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * A class for managing network logging.
 * This class is not thread-safe, callers should synchronize access.
 */
final class NetworkLogger {

    private static final String TAG = NetworkLogger.class.getSimpleName();

    private final DevicePolicyManagerService mDpm;
    private final PackageManagerInternal mPm;
    private final AtomicBoolean mIsLoggingEnabled = new AtomicBoolean(false);

    private IIpConnectivityMetrics mIpConnectivityMetrics;
    private ServiceThread mHandlerThread;
    private NetworkLoggingHandler mNetworkLoggingHandler;

    private final INetdEventCallback mNetdEventCallback = new BaseNetdEventCallback() {
        @Override
        public void onDnsEvent(int netId, int eventType, int returnCode, String hostname,
                String[] ipAddresses, int ipAddressesCount, long timestamp, int uid) {
            if (!mIsLoggingEnabled.get()) {
                return;
            }
            DnsEvent dnsEvent = new DnsEvent(hostname, ipAddresses, ipAddressesCount,
                    mPm.getNameForUid(uid), timestamp);
            sendNetworkEvent(dnsEvent);
        }

        @Override
        public void onConnectEvent(String ipAddr, int port, long timestamp, int uid) {
            if (!mIsLoggingEnabled.get()) {
                return;
            }
            ConnectEvent connectEvent = new ConnectEvent(ipAddr, port, mPm.getNameForUid(uid),
                    timestamp);
            sendNetworkEvent(connectEvent);
        }

        private void sendNetworkEvent(NetworkEvent event) {
            Message msg = mNetworkLoggingHandler.obtainMessage(
                    NetworkLoggingHandler.LOG_NETWORK_EVENT_MSG);
            Bundle bundle = new Bundle();
            bundle.putParcelable(NetworkLoggingHandler.NETWORK_EVENT_KEY, event);
            msg.setData(bundle);
            mNetworkLoggingHandler.sendMessage(msg);
        }
    };

    NetworkLogger(DevicePolicyManagerService dpm, PackageManagerInternal pm) {
        mDpm = dpm;
        mPm = pm;
    }

    private boolean checkIpConnectivityMetricsService() {
        if (mIpConnectivityMetrics != null) {
            return true;
        }
        final IIpConnectivityMetrics service = mDpm.mInjector.getIIpConnectivityMetrics();
        if (service == null) {
            return false;
        }
        mIpConnectivityMetrics = service;
        return true;
    }

    boolean startNetworkLogging() {
        Log.d(TAG, "Starting network logging.");
        if (!checkIpConnectivityMetricsService()) {
            // the IIpConnectivityMetrics service should have been present at this point
            Slog.wtf(TAG, "Failed to register callback with IIpConnectivityMetrics.");
            return false;
        }
        try {
           if (mIpConnectivityMetrics.addNetdEventCallback(
                   INetdEventCallback.CALLBACK_CALLER_DEVICE_POLICY, mNetdEventCallback)) {
                mHandlerThread = new ServiceThread(TAG, Process.THREAD_PRIORITY_BACKGROUND,
                        /* allowIo */ false);
                mHandlerThread.start();
                mNetworkLoggingHandler = new NetworkLoggingHandler(mHandlerThread.getLooper(),
                        mDpm);
                mNetworkLoggingHandler.scheduleBatchFinalization();
                mIsLoggingEnabled.set(true);
                return true;
            } else {
                return false;
            }
        } catch (RemoteException re) {
            Slog.wtf(TAG, "Failed to make remote calls to register the callback", re);
            return false;
        }
    }

    boolean stopNetworkLogging() {
        Log.d(TAG, "Stopping network logging");
        // stop the logging regardless of whether we fail to unregister listener
        mIsLoggingEnabled.set(false);
        discardLogs();

        try {
            if (!checkIpConnectivityMetricsService()) {
                // the IIpConnectivityMetrics service should have been present at this point
                Slog.wtf(TAG, "Failed to unregister callback with IIpConnectivityMetrics.");
                // logging is forcefully disabled even if unregistering fails
                return true;
            }
            return mIpConnectivityMetrics.removeNetdEventCallback(
                    INetdEventCallback.CALLBACK_CALLER_DEVICE_POLICY);
        } catch (RemoteException re) {
            Slog.wtf(TAG, "Failed to make remote calls to unregister the callback", re);
            return true;
        } finally {
            if (mHandlerThread != null) {
                mHandlerThread.quitSafely();
            }
        }
    }

    /**
     * If logs are being collected, keep collecting them but stop notifying the device owner that
     * new logs are available (since they cannot be retrieved)
     */
    void pause() {
        if (mNetworkLoggingHandler != null) {
            mNetworkLoggingHandler.pause();
        }
    }

    /**
     * If logs are being collected, start notifying the device owner when logs are ready to be
     * collected again (if it was paused).
     * <p>If logging is enabled and there are logs ready to be retrieved, this method will attempt
     * to notify the device owner. Therefore calling identity should be cleared before calling it
     * (in case the method is called from a user other than the DO's user).
     */
    void resume() {
        if (mNetworkLoggingHandler != null) {
            mNetworkLoggingHandler.resume();
        }
    }

    /**
     * Discard all collected logs.
     */
    void discardLogs() {
        if (mNetworkLoggingHandler != null) {
            mNetworkLoggingHandler.discardLogs();
        }
    }

    List<NetworkEvent> retrieveLogs(long batchToken) {
        return mNetworkLoggingHandler.retrieveFullLogBatch(batchToken);
    }

    long forceBatchFinalization() {
        return mNetworkLoggingHandler.forceBatchFinalization();
    }
}
