/*
 * Copyright (C) 2018 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 static android.net.ConnectivityManager.MULTIPATH_PREFERENCE_HANDOVER;
import static android.net.ConnectivityManager.MULTIPATH_PREFERENCE_RELIABILITY;
import static android.net.ConnectivityManager.TYPE_MOBILE;
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkPolicy.LIMIT_DISABLED;
import static android.net.NetworkPolicy.WARNING_DISABLED;
import static android.provider.Settings.Global.NETWORK_DEFAULT_DAILY_MULTIPATH_QUOTA_BYTES;

import static com.android.server.net.NetworkPolicyManagerInternal.QUOTA_TYPE_MULTIPATH;
import static com.android.server.net.NetworkPolicyManagerService.OPPORTUNISTIC_QUOTA_UNKNOWN;

import android.app.usage.NetworkStatsManager;
import android.app.usage.NetworkStatsManager.UsageCallback;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.ContentObserver;
import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkIdentity;
import android.net.NetworkPolicy;
import android.net.NetworkPolicyManager;
import android.net.NetworkRequest;
import android.net.NetworkStats;
import android.net.NetworkTemplate;
import android.net.StringNetworkSpecifier;
import android.os.BestClock;
import android.os.Handler;
import android.os.SystemClock;
import android.net.Uri;
import android.os.UserHandle;
import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.util.DataUnit;
import android.util.DebugUtils;
import android.util.Pair;
import android.util.Range;
import android.util.Slog;

import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.LocalServices;
import com.android.server.net.NetworkPolicyManagerInternal;
import com.android.server.net.NetworkStatsManagerInternal;

import java.time.Clock;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;
import java.util.Iterator;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

/**
 * Manages multipath data budgets.
 *
 * Informs the return value of ConnectivityManager#getMultipathPreference() based on:
 * - The user's data plan, as returned by getSubscriptionOpportunisticQuota().
 * - The amount of data usage that occurs on mobile networks while they are not the system default
 *   network (i.e., when the app explicitly selected such networks).
 *
 * Currently, quota is determined on a daily basis, from midnight to midnight local time.
 *
 * @hide
 */
public class MultipathPolicyTracker {
    private static String TAG = MultipathPolicyTracker.class.getSimpleName();

    private static final boolean DBG = false;

    private final Context mContext;
    private final Handler mHandler;
    private final Clock mClock;
    private final Dependencies mDeps;
    private final ContentResolver mResolver;
    private final ConfigChangeReceiver mConfigChangeReceiver;

    @VisibleForTesting
    final ContentObserver mSettingsObserver;

    private ConnectivityManager mCM;
    private NetworkPolicyManager mNPM;
    private NetworkStatsManager mStatsManager;

    private NetworkCallback mMobileNetworkCallback;
    private NetworkPolicyManager.Listener mPolicyListener;


    /**
     * Divider to calculate opportunistic quota from user-set data limit or warning: 5% of user-set
     * limit.
     */
    private static final int OPQUOTA_USER_SETTING_DIVIDER = 20;

    public static class Dependencies {
        public Clock getClock() {
            return new BestClock(ZoneOffset.UTC, SystemClock.currentNetworkTimeClock(),
                    Clock.systemUTC());
        }
    }

    public MultipathPolicyTracker(Context ctx, Handler handler) {
        this(ctx, handler, new Dependencies());
    }

    public MultipathPolicyTracker(Context ctx, Handler handler, Dependencies deps) {
        mContext = ctx;
        mHandler = handler;
        mClock = deps.getClock();
        mDeps = deps;
        mResolver = mContext.getContentResolver();
        mSettingsObserver = new SettingsObserver(mHandler);
        mConfigChangeReceiver = new ConfigChangeReceiver();
        // Because we are initialized by the ConnectivityService constructor, we can't touch any
        // connectivity APIs. Service initialization is done in start().
    }

    public void start() {
        mCM = mContext.getSystemService(ConnectivityManager.class);
        mNPM = mContext.getSystemService(NetworkPolicyManager.class);
        mStatsManager = mContext.getSystemService(NetworkStatsManager.class);

        registerTrackMobileCallback();
        registerNetworkPolicyListener();
        final Uri defaultSettingUri =
                Settings.Global.getUriFor(NETWORK_DEFAULT_DAILY_MULTIPATH_QUOTA_BYTES);
        mResolver.registerContentObserver(defaultSettingUri, false, mSettingsObserver);

        final IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
        mContext.registerReceiverAsUser(
                mConfigChangeReceiver, UserHandle.ALL, intentFilter, null, mHandler);
    }

    public void shutdown() {
        maybeUnregisterTrackMobileCallback();
        unregisterNetworkPolicyListener();
        for (MultipathTracker t : mMultipathTrackers.values()) {
            t.shutdown();
        }
        mMultipathTrackers.clear();
        mResolver.unregisterContentObserver(mSettingsObserver);
        mContext.unregisterReceiver(mConfigChangeReceiver);
    }

    // Called on an arbitrary binder thread.
    public Integer getMultipathPreference(Network network) {
        if (network == null) {
            return null;
        }
        MultipathTracker t = mMultipathTrackers.get(network);
        if (t != null) {
            return t.getMultipathPreference();
        }
        return null;
    }

    // Track information on mobile networks as they come and go.
    class MultipathTracker {
        final Network network;
        final int subId;
        final String subscriberId;

        private long mQuota;
        /** Current multipath budget. Nonzero iff we have budget and a UsageCallback is armed. */
        private long mMultipathBudget;
        private final NetworkTemplate mNetworkTemplate;
        private final UsageCallback mUsageCallback;
        private NetworkCapabilities mNetworkCapabilities;

        public MultipathTracker(Network network, NetworkCapabilities nc) {
            this.network = network;
            this.mNetworkCapabilities = new NetworkCapabilities(nc);
            try {
                subId = Integer.parseInt(
                        ((StringNetworkSpecifier) nc.getNetworkSpecifier()).toString());
            } catch (ClassCastException | NullPointerException | NumberFormatException e) {
                throw new IllegalStateException(String.format(
                        "Can't get subId from mobile network %s (%s): %s",
                        network, nc, e.getMessage()));
            }

            TelephonyManager tele = mContext.getSystemService(TelephonyManager.class);
            if (tele == null) {
                throw new IllegalStateException(String.format("Missing TelephonyManager"));
            }
            tele = tele.createForSubscriptionId(subId);
            if (tele == null) {
                throw new IllegalStateException(String.format(
                        "Can't get TelephonyManager for subId %d", subId));
            }

            subscriberId = tele.getSubscriberId();
            mNetworkTemplate = new NetworkTemplate(
                    NetworkTemplate.MATCH_MOBILE, subscriberId, new String[] { subscriberId },
                    null, NetworkStats.METERED_ALL, NetworkStats.ROAMING_ALL,
                    NetworkStats.DEFAULT_NETWORK_NO);
            mUsageCallback = new UsageCallback() {
                @Override
                public void onThresholdReached(int networkType, String subscriberId) {
                    if (DBG) Slog.d(TAG, "onThresholdReached for network " + network);
                    mMultipathBudget = 0;
                    updateMultipathBudget();
                }
            };

            updateMultipathBudget();
        }

        public void setNetworkCapabilities(NetworkCapabilities nc) {
            mNetworkCapabilities = new NetworkCapabilities(nc);
        }

        // TODO: calculate with proper timezone information
        private long getDailyNonDefaultDataUsage() {
            final ZonedDateTime end =
                    ZonedDateTime.ofInstant(mClock.instant(), ZoneId.systemDefault());
            final ZonedDateTime start = end.truncatedTo(ChronoUnit.DAYS);

            final long bytes = getNetworkTotalBytes(
                    start.toInstant().toEpochMilli(),
                    end.toInstant().toEpochMilli());
            if (DBG) Slog.d(TAG, "Non-default data usage: " + bytes);
            return bytes;
        }

        private long getNetworkTotalBytes(long start, long end) {
            try {
                return LocalServices.getService(NetworkStatsManagerInternal.class)
                        .getNetworkTotalBytes(mNetworkTemplate, start, end);
            } catch (RuntimeException e) {
                Slog.w(TAG, "Failed to get data usage: " + e);
                return -1;
            }
        }

        private NetworkIdentity getTemplateMatchingNetworkIdentity(NetworkCapabilities nc) {
            return new NetworkIdentity(
                    ConnectivityManager.TYPE_MOBILE,
                    0 /* subType, unused for template matching */,
                    subscriberId,
                    null /* networkId, unused for matching mobile networks */,
                    !nc.hasCapability(NET_CAPABILITY_NOT_ROAMING),
                    !nc.hasCapability(NET_CAPABILITY_NOT_METERED),
                    false /* defaultNetwork, templates should have DEFAULT_NETWORK_ALL */);
        }

        private long getRemainingDailyBudget(long limitBytes,
                Range<ZonedDateTime> cycle) {
            final long start = cycle.getLower().toInstant().toEpochMilli();
            final long end = cycle.getUpper().toInstant().toEpochMilli();
            final long totalBytes = getNetworkTotalBytes(start, end);
            final long remainingBytes = totalBytes == -1 ? 0 : Math.max(0, limitBytes - totalBytes);
            // 1 + ((end - now - 1) / millisInDay with integers is equivalent to:
            // ceil((double)(end - now) / millisInDay)
            final long remainingDays =
                    1 + ((end - mClock.millis() - 1) / TimeUnit.DAYS.toMillis(1));

            return remainingBytes / Math.max(1, remainingDays);
        }

        private long getUserPolicyOpportunisticQuotaBytes() {
            // Keep the most restrictive applicable policy
            long minQuota = Long.MAX_VALUE;
            final NetworkIdentity identity = getTemplateMatchingNetworkIdentity(
                    mNetworkCapabilities);

            final NetworkPolicy[] policies = mNPM.getNetworkPolicies();
            for (NetworkPolicy policy : policies) {
                if (policy.hasCycle() && policy.template.matches(identity)) {
                    final long cycleStart = policy.cycleIterator().next().getLower()
                            .toInstant().toEpochMilli();
                    // Prefer user-defined warning, otherwise use hard limit
                    final long activeWarning = getActiveWarning(policy, cycleStart);
                    final long policyBytes = (activeWarning == WARNING_DISABLED)
                            ? getActiveLimit(policy, cycleStart)
                            : activeWarning;

                    if (policyBytes != LIMIT_DISABLED && policyBytes != WARNING_DISABLED) {
                        final long policyBudget = getRemainingDailyBudget(policyBytes,
                                policy.cycleIterator().next());
                        minQuota = Math.min(minQuota, policyBudget);
                    }
                }
            }

            if (minQuota == Long.MAX_VALUE) {
                return OPPORTUNISTIC_QUOTA_UNKNOWN;
            }

            return minQuota / OPQUOTA_USER_SETTING_DIVIDER;
        }

        void updateMultipathBudget() {
            long quota = LocalServices.getService(NetworkPolicyManagerInternal.class)
                    .getSubscriptionOpportunisticQuota(this.network, QUOTA_TYPE_MULTIPATH);
            if (DBG) Slog.d(TAG, "Opportunistic quota from data plan: " + quota + " bytes");

            // Fallback to user settings-based quota if not available from phone plan
            if (quota == OPPORTUNISTIC_QUOTA_UNKNOWN) {
                quota = getUserPolicyOpportunisticQuotaBytes();
                if (DBG) Slog.d(TAG, "Opportunistic quota from user policy: " + quota + " bytes");
            }

            if (quota == OPPORTUNISTIC_QUOTA_UNKNOWN) {
                quota = getDefaultDailyMultipathQuotaBytes();
                if (DBG) Slog.d(TAG, "Setting quota: " + quota + " bytes");
            }

            // TODO: re-register if day changed: budget may have run out but should be refreshed.
            if (haveMultipathBudget() && quota == mQuota) {
                // If there is already a usage callback pending , there's no need to re-register it
                // if the quota hasn't changed. The callback will simply fire as expected when the
                // budget is spent.
                if (DBG) Slog.d(TAG, "Quota still " + quota + ", not updating.");
                return;
            }
            mQuota = quota;

            // If we can't get current usage, assume the worst and don't give
            // ourselves any budget to work with.
            final long usage = getDailyNonDefaultDataUsage();
            final long budget = (usage == -1) ? 0 : Math.max(0, quota - usage);

            // Only consider budgets greater than MIN_THRESHOLD_BYTES, otherwise the callback will
            // fire late, after data usage went over budget. Also budget should be 0 if remaining
            // data is close to 0.
            // This is necessary because the usage callback does not accept smaller thresholds.
            // Because it snaps everything to MIN_THRESHOLD_BYTES, the lesser of the two evils is
            // to snap to 0 here.
            // This will only be called if the total quota for the day changed, not if usage changed
            // since last time, so even if this is called very often the budget will not snap to 0
            // as soon as there are less than 2MB left for today.
            if (budget > NetworkStatsManager.MIN_THRESHOLD_BYTES) {
                if (DBG) Slog.d(TAG, "Setting callback for " + budget +
                        " bytes on network " + network);
                registerUsageCallback(budget);
            } else {
                maybeUnregisterUsageCallback();
            }
        }

        public int getMultipathPreference() {
            if (haveMultipathBudget()) {
                return MULTIPATH_PREFERENCE_HANDOVER | MULTIPATH_PREFERENCE_RELIABILITY;
            }
            return 0;
        }

        // For debugging only.
        public long getQuota() {
            return mQuota;
        }

        // For debugging only.
        public long getMultipathBudget() {
            return mMultipathBudget;
        }

        private boolean haveMultipathBudget() {
            return mMultipathBudget > 0;
        }

        private void registerUsageCallback(long budget) {
            maybeUnregisterUsageCallback();
            mStatsManager.registerUsageCallback(mNetworkTemplate, TYPE_MOBILE, budget,
                    mUsageCallback, mHandler);
            mMultipathBudget = budget;
        }

        private void maybeUnregisterUsageCallback() {
            if (haveMultipathBudget()) {
                if (DBG) Slog.d(TAG, "Unregistering callback, budget was " + mMultipathBudget);
                mStatsManager.unregisterUsageCallback(mUsageCallback);
                mMultipathBudget = 0;
            }
        }

        void shutdown() {
            maybeUnregisterUsageCallback();
        }
    }

    private static long getActiveWarning(NetworkPolicy policy, long cycleStart) {
        return policy.lastWarningSnooze < cycleStart
                ? policy.warningBytes
                : WARNING_DISABLED;
    }

    private static long getActiveLimit(NetworkPolicy policy, long cycleStart) {
        return policy.lastLimitSnooze < cycleStart
                ? policy.limitBytes
                : LIMIT_DISABLED;
    }

    // Only ever updated on the handler thread. Accessed from other binder threads to retrieve
    // the tracker for a specific network.
    private final ConcurrentHashMap <Network, MultipathTracker> mMultipathTrackers =
            new ConcurrentHashMap<>();

    private long getDefaultDailyMultipathQuotaBytes() {
        final String setting = Settings.Global.getString(mContext.getContentResolver(),
                NETWORK_DEFAULT_DAILY_MULTIPATH_QUOTA_BYTES);
        if (setting != null) {
            try {
                return Long.parseLong(setting);
            } catch(NumberFormatException e) {
                // fall through
            }
        }

        return mContext.getResources().getInteger(
                R.integer.config_networkDefaultDailyMultipathQuotaBytes);
    }

    // TODO: this races with app code that might respond to onAvailable() by immediately calling
    // getMultipathPreference. Fix this by adding to ConnectivityService the ability to directly
    // invoke NetworkCallbacks on tightly-coupled classes such as this one which run on its
    // handler thread.
    private void registerTrackMobileCallback() {
        final NetworkRequest request = new NetworkRequest.Builder()
                .addCapability(NET_CAPABILITY_INTERNET)
                .addTransportType(TRANSPORT_CELLULAR)
                .build();
        mMobileNetworkCallback = new ConnectivityManager.NetworkCallback() {
            @Override
            public void onCapabilitiesChanged(Network network, NetworkCapabilities nc) {
                MultipathTracker existing = mMultipathTrackers.get(network);
                if (existing != null) {
                    existing.setNetworkCapabilities(nc);
                    existing.updateMultipathBudget();
                    return;
                }

                try {
                    mMultipathTrackers.put(network, new MultipathTracker(network, nc));
                } catch (IllegalStateException e) {
                    Slog.e(TAG, "Can't track mobile network " + network + ": " + e.getMessage());
                }
                if (DBG) Slog.d(TAG, "Tracking mobile network " + network);
            }

            @Override
            public void onLost(Network network) {
                MultipathTracker existing = mMultipathTrackers.get(network);
                if (existing != null) {
                    existing.shutdown();
                    mMultipathTrackers.remove(network);
                }
                if (DBG) Slog.d(TAG, "No longer tracking mobile network " + network);
            }
        };

        mCM.registerNetworkCallback(request, mMobileNetworkCallback, mHandler);
    }

    /**
     * Update multipath budgets for all trackers. To be called on the mHandler thread.
     */
    private void updateAllMultipathBudgets() {
        for (MultipathTracker t : mMultipathTrackers.values()) {
            t.updateMultipathBudget();
        }
    }

    private void maybeUnregisterTrackMobileCallback() {
        if (mMobileNetworkCallback != null) {
            mCM.unregisterNetworkCallback(mMobileNetworkCallback);
        }
        mMobileNetworkCallback = null;
    }

    private void registerNetworkPolicyListener() {
        mPolicyListener = new NetworkPolicyManager.Listener() {
            @Override
            public void onMeteredIfacesChanged(String[] meteredIfaces) {
                // Dispatched every time opportunistic quota is recalculated.
                mHandler.post(() -> updateAllMultipathBudgets());
            }
        };
        mNPM.registerListener(mPolicyListener);
    }

    private void unregisterNetworkPolicyListener() {
        mNPM.unregisterListener(mPolicyListener);
    }

    private final class SettingsObserver extends ContentObserver {
        public SettingsObserver(Handler handler) {
            super(handler);
        }

        @Override
        public void onChange(boolean selfChange) {
            Slog.wtf(TAG, "Should never be reached.");
        }

        @Override
        public void onChange(boolean selfChange, Uri uri) {
            if (!Settings.Global.getUriFor(NETWORK_DEFAULT_DAILY_MULTIPATH_QUOTA_BYTES)
                    .equals(uri)) {
                Slog.wtf(TAG, "Unexpected settings observation: " + uri);
            }
            if (DBG) Slog.d(TAG, "Settings change: updating budgets.");
            updateAllMultipathBudgets();
        }
    }

    private final class ConfigChangeReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (DBG) Slog.d(TAG, "Configuration change: updating budgets.");
            updateAllMultipathBudgets();
        }
    }

    public void dump(IndentingPrintWriter pw) {
        // Do not use in production. Access to class data is only safe on the handler thrad.
        pw.println("MultipathPolicyTracker:");
        pw.increaseIndent();
        for (MultipathTracker t : mMultipathTrackers.values()) {
            pw.println(String.format("Network %s: quota %d, budget %d. Preference: %s",
                    t.network, t.getQuota(), t.getMultipathBudget(),
                    DebugUtils.flagsToString(ConnectivityManager.class, "MULTIPATH_PREFERENCE_",
                            t.getMultipathPreference())));
        }
        pw.decreaseIndent();
    }
}
