/*
 * Copyright (C) 2012 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;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.net.InetAddress;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
import android.net.IConnectivityManager;
import android.net.INetworkManagementEventObserver;
import android.net.InterfaceConfiguration;
import android.net.NetworkInfo;
import android.os.Binder;
import android.os.CommonTimeConfig;
import android.os.Handler;
import android.os.IBinder;
import android.os.INetworkManagementService;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemProperties;
import android.util.Log;

/**
 * @hide
 * <p>CommonTimeManagementService manages the configuration of the native Common Time service,
 * reconfiguring the native service as appropriate in response to changes in network configuration.
 */
class CommonTimeManagementService extends Binder {
    /*
     * Constants and globals.
     */
    private static final String TAG = CommonTimeManagementService.class.getSimpleName();
    private static final int NATIVE_SERVICE_RECONNECT_TIMEOUT = 5000;
    private static final String AUTO_DISABLE_PROP = "ro.common_time.auto_disable";
    private static final String ALLOW_WIFI_PROP = "ro.common_time.allow_wifi";
    private static final String SERVER_PRIO_PROP = "ro.common_time.server_prio";
    private static final String NO_INTERFACE_TIMEOUT_PROP = "ro.common_time.no_iface_timeout";
    private static final boolean AUTO_DISABLE;
    private static final boolean ALLOW_WIFI;
    private static final byte BASE_SERVER_PRIO;
    private static final int NO_INTERFACE_TIMEOUT;
    private static final InterfaceScoreRule[] IFACE_SCORE_RULES;

    static {
        int tmp;
        AUTO_DISABLE         = (0 != SystemProperties.getInt(AUTO_DISABLE_PROP, 1));
        ALLOW_WIFI           = (0 != SystemProperties.getInt(ALLOW_WIFI_PROP, 0));
        tmp                  = SystemProperties.getInt(SERVER_PRIO_PROP, 1);
        NO_INTERFACE_TIMEOUT = SystemProperties.getInt(NO_INTERFACE_TIMEOUT_PROP, 60000);

        if (tmp < 1)
            BASE_SERVER_PRIO = 1;
        else
        if (tmp > 30)
            BASE_SERVER_PRIO = 30;
        else
            BASE_SERVER_PRIO = (byte)tmp;

        if (ALLOW_WIFI) {
            IFACE_SCORE_RULES = new InterfaceScoreRule[] {
                new InterfaceScoreRule("wlan", (byte)1),
                new InterfaceScoreRule("eth", (byte)2),
            };
        } else {
            IFACE_SCORE_RULES = new InterfaceScoreRule[] {
                new InterfaceScoreRule("eth", (byte)2),
            };
        }
    };

    /*
     * Internal state
     */
    private final Context mContext;
    private INetworkManagementService mNetMgr;
    private CommonTimeConfig mCTConfig;
    private String mCurIface;
    private Handler mReconnectHandler = new Handler();
    private Handler mNoInterfaceHandler = new Handler();
    private Object mLock = new Object();
    private boolean mDetectedAtStartup = false;
    private byte mEffectivePrio = BASE_SERVER_PRIO;

    /*
     * Callback handler implementations.
     */
    private INetworkManagementEventObserver mIfaceObserver =
        new INetworkManagementEventObserver.Stub() {

        public void interfaceStatusChanged(String iface, boolean up) {
            reevaluateServiceState();
        }
        public void interfaceLinkStateChanged(String iface, boolean up) {
            reevaluateServiceState();
        }
        public void interfaceAdded(String iface) {
            reevaluateServiceState();
        }
        public void interfaceRemoved(String iface) {
            reevaluateServiceState();
        }
        public void limitReached(String limitName, String iface) { }

        public void interfaceClassDataActivityChanged(String label, boolean active) {}
    };

    private BroadcastReceiver mConnectivityMangerObserver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            reevaluateServiceState();
        }
    };

    private CommonTimeConfig.OnServerDiedListener mCTServerDiedListener =
        new CommonTimeConfig.OnServerDiedListener() {
            public void onServerDied() {
                scheduleTimeConfigReconnect();
            }
        };

    private Runnable mReconnectRunnable = new Runnable() {
        public void run() { connectToTimeConfig(); }
    };

    private Runnable mNoInterfaceRunnable = new Runnable() {
        public void run() { handleNoInterfaceTimeout(); }
    };

    /*
     * Public interface (constructor, systemReady and dump)
     */
    public CommonTimeManagementService(Context context) {
        mContext = context;
    }

    void systemReady() {
        if (ServiceManager.checkService(CommonTimeConfig.SERVICE_NAME) == null) {
            Log.i(TAG, "No common time service detected on this platform.  " +
                       "Common time services will be unavailable.");
            return;
        }

        mDetectedAtStartup = true;

        IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
        mNetMgr = INetworkManagementService.Stub.asInterface(b);

        // Network manager is running along-side us, so we should never receiver a remote exception
        // while trying to register this observer.
        try {
            mNetMgr.registerObserver(mIfaceObserver);
        }
        catch (RemoteException e) { }

        // Register with the connectivity manager for connectivity changed intents.
        IntentFilter filter = new IntentFilter();
        filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
        mContext.registerReceiver(mConnectivityMangerObserver, filter);

        // Connect to the common time config service and apply the initial configuration.
        connectToTimeConfig();
    }

    @Override
    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
                != PackageManager.PERMISSION_GRANTED) {
            pw.println(String.format(
                        "Permission Denial: can't dump CommonTimeManagement service from from " +
                        "pid=%d, uid=%d", Binder.getCallingPid(), Binder.getCallingUid()));
            return;
        }

        if (!mDetectedAtStartup) {
            pw.println("Native Common Time service was not detected at startup.  " +
                       "Service is unavailable");
            return;
        }

        synchronized (mLock) {
            pw.println("Current Common Time Management Service Config:");
            pw.println(String.format("  Native service     : %s",
                                     (null == mCTConfig) ? "reconnecting"
                                                         : "alive"));
            pw.println(String.format("  Bound interface    : %s",
                                     (null == mCurIface ? "unbound" : mCurIface)));
            pw.println(String.format("  Allow WiFi         : %s", ALLOW_WIFI ? "yes" : "no"));
            pw.println(String.format("  Allow Auto Disable : %s", AUTO_DISABLE ? "yes" : "no"));
            pw.println(String.format("  Server Priority    : %d", mEffectivePrio));
            pw.println(String.format("  No iface timeout   : %d", NO_INTERFACE_TIMEOUT));
        }
    }

    /*
     * Inner helper classes
     */
    private static class InterfaceScoreRule {
        public final String mPrefix;
        public final byte mScore;
        public InterfaceScoreRule(String prefix, byte score) {
            mPrefix = prefix;
            mScore = score;
        }
    };

    /*
     * Internal implementation
     */
    private void cleanupTimeConfig() {
        mReconnectHandler.removeCallbacks(mReconnectRunnable);
        mNoInterfaceHandler.removeCallbacks(mNoInterfaceRunnable);
        if (null != mCTConfig) {
            mCTConfig.release();
            mCTConfig = null;
        }
    }

    private void connectToTimeConfig() {
        // Get access to the common time service configuration interface.  If we catch a remote
        // exception in the process (service crashed or no running for w/e reason), schedule an
        // attempt to reconnect in the future.
        cleanupTimeConfig();
        try {
            synchronized (mLock) {
                mCTConfig = new CommonTimeConfig();
                mCTConfig.setServerDiedListener(mCTServerDiedListener);
                mCurIface = mCTConfig.getInterfaceBinding();
                mCTConfig.setAutoDisable(AUTO_DISABLE);
                mCTConfig.setMasterElectionPriority(mEffectivePrio);
            }

            if (NO_INTERFACE_TIMEOUT >= 0)
                mNoInterfaceHandler.postDelayed(mNoInterfaceRunnable, NO_INTERFACE_TIMEOUT);

            reevaluateServiceState();
        }
        catch (RemoteException e) {
            scheduleTimeConfigReconnect();
        }
    }

    private void scheduleTimeConfigReconnect() {
        cleanupTimeConfig();
        Log.w(TAG, String.format("Native service died, will reconnect in %d mSec",
                                 NATIVE_SERVICE_RECONNECT_TIMEOUT));
        mReconnectHandler.postDelayed(mReconnectRunnable,
                                      NATIVE_SERVICE_RECONNECT_TIMEOUT);
    }

    private void handleNoInterfaceTimeout() {
        if (null != mCTConfig) {
            Log.i(TAG, "Timeout waiting for interface to come up.  " +
                       "Forcing networkless master mode.");
            if (CommonTimeConfig.ERROR_DEAD_OBJECT == mCTConfig.forceNetworklessMasterMode())
                scheduleTimeConfigReconnect();
        }
    }

    private void reevaluateServiceState() {
        String bindIface = null;
        byte bestScore = -1;
        try {
            // Check to see if this interface is suitable to use for time synchronization.
            //
            // TODO : This selection algorithm needs to be enhanced for use with mobile devices.  In
            // particular, the choice of whether to a wireless interface or not should not be an all
            // or nothing thing controlled by properties.  It would probably be better if the
            // platform had some concept of public wireless networks vs. home or friendly wireless
            // networks (something a user would configure in settings or when a new interface is
            // added).  Then this algorithm could pick only wireless interfaces which were flagged
            // as friendly, and be dormant when on public wireless networks.
            //
            // Another issue which needs to be dealt with is the use of driver supplied interface
            // name to determine the network type.  The fact that the wireless interface on a device
            // is named "wlan0" is just a matter of convention; its not a 100% rule.  For example,
            // there are devices out there where the wireless is name "tiwlan0", not "wlan0".  The
            // internal network management interfaces in Android have all of the information needed
            // to make a proper classification, there is just no way (currently) to fetch an
            // interface's type (available from the ConnectionManager) as well as its address
            // (available from either the java.net interfaces or from the NetworkManagment service).
            // Both can enumerate interfaces, but that is no way to correlate their results (no
            // common shared key; although using the interface name in the connection manager would
            // be a good start).  Until this gets resolved, we resort to substring searching for
            // tags like wlan and eth.
            //
            String ifaceList[] = mNetMgr.listInterfaces();
            if (null != ifaceList) {
                for (String iface : ifaceList) {

                    byte thisScore = -1;
                    for (InterfaceScoreRule r : IFACE_SCORE_RULES) {
                        if (iface.contains(r.mPrefix)) {
                            thisScore = r.mScore;
                            break;
                        }
                    }

                    if (thisScore <= bestScore)
                        continue;

                    InterfaceConfiguration config = mNetMgr.getInterfaceConfig(iface);
                    if (null == config)
                        continue;

                    if (config.isActive()) {
                        bindIface = iface;
                        bestScore = thisScore;
                    }
                }
            }
        }
        catch (RemoteException e) {
            // Bad news; we should not be getting remote exceptions from the connectivity manager
            // since it is running in SystemServer along side of us.  It probably does not matter
            // what we do here, but go ahead and unbind the common time service in this case, just
            // so we have some defined behavior.
            bindIface = null;
        }

        boolean doRebind = true;
        synchronized (mLock) {
            if ((null != bindIface) && (null == mCurIface)) {
                Log.e(TAG, String.format("Binding common time service to %s.", bindIface));
                mCurIface = bindIface;
            } else
            if ((null == bindIface) && (null != mCurIface)) {
                Log.e(TAG, "Unbinding common time service.");
                mCurIface = null;
            } else
            if ((null != bindIface) && (null != mCurIface) && !bindIface.equals(mCurIface)) {
                Log.e(TAG, String.format("Switching common time service binding from %s to %s.",
                                         mCurIface, bindIface));
                mCurIface = bindIface;
            } else {
                doRebind = false;
            }
        }

        if (doRebind && (null != mCTConfig)) {
            byte newPrio = (bestScore > 0)
                         ? (byte)(bestScore * BASE_SERVER_PRIO)
                         : BASE_SERVER_PRIO;
            if (newPrio != mEffectivePrio) {
                mEffectivePrio = newPrio;
                mCTConfig.setMasterElectionPriority(mEffectivePrio);
            }

            int res = mCTConfig.setNetworkBinding(mCurIface);
            if (res != CommonTimeConfig.SUCCESS)
                scheduleTimeConfigReconnect();

            else if (NO_INTERFACE_TIMEOUT >= 0) {
                mNoInterfaceHandler.removeCallbacks(mNoInterfaceRunnable);
                if (null == mCurIface)
                    mNoInterfaceHandler.postDelayed(mNoInterfaceRunnable, NO_INTERFACE_TIMEOUT);
            }
        }
    }
}
