/*
 * 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 systemRunning() {
        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);
            }
        }
    }
}
