/*
 * 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 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.INetworkManagementEventObserver;
import android.net.InterfaceConfiguration;
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;

import com.android.server.net.BaseNetworkObserver;

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

    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);
            }
        }
    }
}
