/*
 * Copyright (C) 2014 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.job.controllers;


import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.util.Slog;

import com.android.server.ConnectivityService;
import com.android.server.job.JobSchedulerService;
import com.android.server.job.StateChangedListener;

import java.io.PrintWriter;
import java.util.LinkedList;
import java.util.List;

/**
 * Handles changes in connectivity.
 * We are only interested in metered vs. unmetered networks, and we're interested in them on a
 * per-user basis.
 */
public class ConnectivityController extends StateController implements
        ConnectivityManager.OnNetworkActiveListener {
    private static final String TAG = "JobScheduler.Conn";

    private final List<JobStatus> mTrackedJobs = new LinkedList<JobStatus>();
    private final BroadcastReceiver mConnectivityChangedReceiver =
            new ConnectivityChangedReceiver();
    /** Singleton. */
    private static ConnectivityController mSingleton;
    private static Object sCreationLock = new Object();
    /** Track whether the latest active network is metered. */
    private boolean mNetworkUnmetered;
    /** Track whether the latest active network is connected. */
    private boolean mNetworkConnected;

    public static ConnectivityController get(JobSchedulerService jms) {
        synchronized (sCreationLock) {
            if (mSingleton == null) {
                mSingleton = new ConnectivityController(jms, jms.getContext());
            }
            return mSingleton;
        }
    }

    private ConnectivityController(StateChangedListener stateChangedListener, Context context) {
        super(stateChangedListener, context);
        // Register connectivity changed BR.
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
        mContext.registerReceiverAsUser(
                mConnectivityChangedReceiver, UserHandle.ALL, intentFilter, null, null);
        ConnectivityService cs =
                (ConnectivityService)ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
        if (cs != null) {
            if (cs.getActiveNetworkInfo() != null) {
                mNetworkConnected = cs.getActiveNetworkInfo().isConnected();
            }
            mNetworkUnmetered = mNetworkConnected && !cs.isActiveNetworkMetered();
        }
    }

    @Override
    public void maybeStartTrackingJob(JobStatus jobStatus) {
        if (jobStatus.hasConnectivityConstraint() || jobStatus.hasUnmeteredConstraint()) {
            synchronized (mTrackedJobs) {
                jobStatus.connectivityConstraintSatisfied.set(mNetworkConnected);
                jobStatus.unmeteredConstraintSatisfied.set(mNetworkUnmetered);
                mTrackedJobs.add(jobStatus);
            }
        }
    }

    @Override
    public void maybeStopTrackingJob(JobStatus jobStatus) {
        if (jobStatus.hasConnectivityConstraint() || jobStatus.hasUnmeteredConstraint()) {
            synchronized (mTrackedJobs) {
                mTrackedJobs.remove(jobStatus);
            }
        }
    }

    /**
     * @param userId Id of the user for whom we are updating the connectivity state.
     */
    private void updateTrackedJobs(int userId) {
        synchronized (mTrackedJobs) {
            boolean changed = false;
            for (JobStatus js : mTrackedJobs) {
                if (js.getUserId() != userId) {
                    continue;
                }
                boolean prevIsConnected =
                        js.connectivityConstraintSatisfied.getAndSet(mNetworkConnected);
                boolean prevIsMetered = js.unmeteredConstraintSatisfied.getAndSet(mNetworkUnmetered);
                if (prevIsConnected != mNetworkConnected || prevIsMetered != mNetworkUnmetered) {
                    changed = true;
                }
            }
            if (changed) {
                mStateChangedListener.onControllerStateChanged();
            }
        }
    }

    /**
     * We know the network has just come up. We want to run any jobs that are ready.
     */
    public synchronized void onNetworkActive() {
        synchronized (mTrackedJobs) {
            for (JobStatus js : mTrackedJobs) {
                if (js.isReady()) {
                    if (DEBUG) {
                        Slog.d(TAG, "Running " + js + " due to network activity.");
                    }
                    mStateChangedListener.onRunJobNow(js);
                }
            }
        }
    }

    class ConnectivityChangedReceiver extends BroadcastReceiver {
        /**
         * We'll receive connectivity changes for each user here, which we process independently.
         * We are only interested in the active network here. We're only interested in the active
         * network, b/c the end result of this will be for apps to try to hit the network.
         * @param context The Context in which the receiver is running.
         * @param intent The Intent being received.
         */
        // TODO: Test whether this will be called twice for each user.
        @Override
        public void onReceive(Context context, Intent intent) {
            if (DEBUG) {
                Slog.d(TAG, "Received connectivity event: " + intent.getAction() + " u"
                        + context.getUserId());
            }
            final String action = intent.getAction();
            if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
                final int networkType =
                        intent.getIntExtra(ConnectivityManager.EXTRA_NETWORK_TYPE,
                                ConnectivityManager.TYPE_NONE);
                // Connectivity manager for THIS context - important!
                final ConnectivityManager connManager = (ConnectivityManager)
                        context.getSystemService(Context.CONNECTIVITY_SERVICE);
                final NetworkInfo activeNetwork = connManager.getActiveNetworkInfo();
                final int userid = context.getUserId();
                // This broadcast gets sent a lot, only update if the active network has changed.
                if (activeNetwork == null) {
                    mNetworkUnmetered = false;
                    mNetworkConnected = false;
                    updateTrackedJobs(userid);
                } else if (activeNetwork.getType() == networkType) {
                    mNetworkUnmetered = false;
                    mNetworkConnected = !intent.getBooleanExtra(
                            ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
                    if (mNetworkConnected) {  // No point making the call if we know there's no conn.
                        mNetworkUnmetered = !connManager.isActiveNetworkMetered();
                    }
                    updateTrackedJobs(userid);
                }
            } else {
                if (DEBUG) {
                    Slog.d(TAG, "Unrecognised action in intent: " + action);
                }
            }
        }
    };

    @Override
    public void dumpControllerState(PrintWriter pw) {
        pw.println("Conn.");
        pw.println("connected: " + mNetworkConnected + " unmetered: " + mNetworkUnmetered);
        for (JobStatus js: mTrackedJobs) {
            pw.println(String.valueOf(js.hashCode()).substring(0, 3) + ".."
                    + ": C=" + js.hasConnectivityConstraint()
                    + ", UM=" + js.hasUnmeteredConstraint());
        }
    }
}