1c157673a590e670a9a509ec13d47ffada0b56335John Grossman/*
2c157673a590e670a9a509ec13d47ffada0b56335John Grossman * Copyright (C) 2012 The Android Open Source Project
3c157673a590e670a9a509ec13d47ffada0b56335John Grossman *
4c157673a590e670a9a509ec13d47ffada0b56335John Grossman * Licensed under the Apache License, Version 2.0 (the "License");
5c157673a590e670a9a509ec13d47ffada0b56335John Grossman * you may not use this file except in compliance with the License.
6c157673a590e670a9a509ec13d47ffada0b56335John Grossman * You may obtain a copy of the License at
7c157673a590e670a9a509ec13d47ffada0b56335John Grossman *
8c157673a590e670a9a509ec13d47ffada0b56335John Grossman *      http://www.apache.org/licenses/LICENSE-2.0
9c157673a590e670a9a509ec13d47ffada0b56335John Grossman *
10c157673a590e670a9a509ec13d47ffada0b56335John Grossman * Unless required by applicable law or agreed to in writing, software
11c157673a590e670a9a509ec13d47ffada0b56335John Grossman * distributed under the License is distributed on an "AS IS" BASIS,
12c157673a590e670a9a509ec13d47ffada0b56335John Grossman * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c157673a590e670a9a509ec13d47ffada0b56335John Grossman * See the License for the specific language governing permissions and
14c157673a590e670a9a509ec13d47ffada0b56335John Grossman * limitations under the License.
15c157673a590e670a9a509ec13d47ffada0b56335John Grossman */
16c157673a590e670a9a509ec13d47ffada0b56335John Grossman
17c157673a590e670a9a509ec13d47ffada0b56335John Grossmanpackage com.android.server;
18c157673a590e670a9a509ec13d47ffada0b56335John Grossman
19c157673a590e670a9a509ec13d47ffada0b56335John Grossmanimport java.io.FileDescriptor;
20c157673a590e670a9a509ec13d47ffada0b56335John Grossmanimport java.io.PrintWriter;
21c157673a590e670a9a509ec13d47ffada0b56335John Grossman
22c157673a590e670a9a509ec13d47ffada0b56335John Grossmanimport android.content.BroadcastReceiver;
23c157673a590e670a9a509ec13d47ffada0b56335John Grossmanimport android.content.Context;
24c157673a590e670a9a509ec13d47ffada0b56335John Grossmanimport android.content.Intent;
25c157673a590e670a9a509ec13d47ffada0b56335John Grossmanimport android.content.IntentFilter;
26c157673a590e670a9a509ec13d47ffada0b56335John Grossmanimport android.content.pm.PackageManager;
27c157673a590e670a9a509ec13d47ffada0b56335John Grossmanimport android.net.ConnectivityManager;
28c157673a590e670a9a509ec13d47ffada0b56335John Grossmanimport android.net.INetworkManagementEventObserver;
29c157673a590e670a9a509ec13d47ffada0b56335John Grossmanimport android.net.InterfaceConfiguration;
30c157673a590e670a9a509ec13d47ffada0b56335John Grossmanimport android.os.Binder;
31c157673a590e670a9a509ec13d47ffada0b56335John Grossmanimport android.os.CommonTimeConfig;
32c157673a590e670a9a509ec13d47ffada0b56335John Grossmanimport android.os.Handler;
33c157673a590e670a9a509ec13d47ffada0b56335John Grossmanimport android.os.IBinder;
34c157673a590e670a9a509ec13d47ffada0b56335John Grossmanimport android.os.INetworkManagementService;
35c157673a590e670a9a509ec13d47ffada0b56335John Grossmanimport android.os.RemoteException;
36c157673a590e670a9a509ec13d47ffada0b56335John Grossmanimport android.os.ServiceManager;
37c157673a590e670a9a509ec13d47ffada0b56335John Grossmanimport android.os.SystemProperties;
38c157673a590e670a9a509ec13d47ffada0b56335John Grossmanimport android.util.Log;
39c157673a590e670a9a509ec13d47ffada0b56335John Grossman
40fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkeyimport com.android.internal.util.DumpUtils;
41df86a9f2e92d077386b146fe483b2cf14850737dLorenzo Colittiimport com.android.server.net.BaseNetworkObserver;
42df86a9f2e92d077386b146fe483b2cf14850737dLorenzo Colitti
43c157673a590e670a9a509ec13d47ffada0b56335John Grossman/**
44c157673a590e670a9a509ec13d47ffada0b56335John Grossman * @hide
45c157673a590e670a9a509ec13d47ffada0b56335John Grossman * <p>CommonTimeManagementService manages the configuration of the native Common Time service,
46c157673a590e670a9a509ec13d47ffada0b56335John Grossman * reconfiguring the native service as appropriate in response to changes in network configuration.
47c157673a590e670a9a509ec13d47ffada0b56335John Grossman */
48c157673a590e670a9a509ec13d47ffada0b56335John Grossmanclass CommonTimeManagementService extends Binder {
49c157673a590e670a9a509ec13d47ffada0b56335John Grossman    /*
50c157673a590e670a9a509ec13d47ffada0b56335John Grossman     * Constants and globals.
51c157673a590e670a9a509ec13d47ffada0b56335John Grossman     */
52c157673a590e670a9a509ec13d47ffada0b56335John Grossman    private static final String TAG = CommonTimeManagementService.class.getSimpleName();
53c157673a590e670a9a509ec13d47ffada0b56335John Grossman    private static final int NATIVE_SERVICE_RECONNECT_TIMEOUT = 5000;
54c157673a590e670a9a509ec13d47ffada0b56335John Grossman    private static final String AUTO_DISABLE_PROP = "ro.common_time.auto_disable";
55c157673a590e670a9a509ec13d47ffada0b56335John Grossman    private static final String ALLOW_WIFI_PROP = "ro.common_time.allow_wifi";
56c157673a590e670a9a509ec13d47ffada0b56335John Grossman    private static final String SERVER_PRIO_PROP = "ro.common_time.server_prio";
57c157673a590e670a9a509ec13d47ffada0b56335John Grossman    private static final String NO_INTERFACE_TIMEOUT_PROP = "ro.common_time.no_iface_timeout";
58c157673a590e670a9a509ec13d47ffada0b56335John Grossman    private static final boolean AUTO_DISABLE;
59c157673a590e670a9a509ec13d47ffada0b56335John Grossman    private static final boolean ALLOW_WIFI;
60c157673a590e670a9a509ec13d47ffada0b56335John Grossman    private static final byte BASE_SERVER_PRIO;
61c157673a590e670a9a509ec13d47ffada0b56335John Grossman    private static final int NO_INTERFACE_TIMEOUT;
62c157673a590e670a9a509ec13d47ffada0b56335John Grossman    private static final InterfaceScoreRule[] IFACE_SCORE_RULES;
63c157673a590e670a9a509ec13d47ffada0b56335John Grossman
64c157673a590e670a9a509ec13d47ffada0b56335John Grossman    static {
65c157673a590e670a9a509ec13d47ffada0b56335John Grossman        int tmp;
66c157673a590e670a9a509ec13d47ffada0b56335John Grossman        AUTO_DISABLE         = (0 != SystemProperties.getInt(AUTO_DISABLE_PROP, 1));
67c157673a590e670a9a509ec13d47ffada0b56335John Grossman        ALLOW_WIFI           = (0 != SystemProperties.getInt(ALLOW_WIFI_PROP, 0));
68c157673a590e670a9a509ec13d47ffada0b56335John Grossman        tmp                  = SystemProperties.getInt(SERVER_PRIO_PROP, 1);
69c157673a590e670a9a509ec13d47ffada0b56335John Grossman        NO_INTERFACE_TIMEOUT = SystemProperties.getInt(NO_INTERFACE_TIMEOUT_PROP, 60000);
70c157673a590e670a9a509ec13d47ffada0b56335John Grossman
71c157673a590e670a9a509ec13d47ffada0b56335John Grossman        if (tmp < 1)
72c157673a590e670a9a509ec13d47ffada0b56335John Grossman            BASE_SERVER_PRIO = 1;
73c157673a590e670a9a509ec13d47ffada0b56335John Grossman        else
74c157673a590e670a9a509ec13d47ffada0b56335John Grossman        if (tmp > 30)
75c157673a590e670a9a509ec13d47ffada0b56335John Grossman            BASE_SERVER_PRIO = 30;
76c157673a590e670a9a509ec13d47ffada0b56335John Grossman        else
77c157673a590e670a9a509ec13d47ffada0b56335John Grossman            BASE_SERVER_PRIO = (byte)tmp;
78c157673a590e670a9a509ec13d47ffada0b56335John Grossman
79c157673a590e670a9a509ec13d47ffada0b56335John Grossman        if (ALLOW_WIFI) {
80c157673a590e670a9a509ec13d47ffada0b56335John Grossman            IFACE_SCORE_RULES = new InterfaceScoreRule[] {
81c157673a590e670a9a509ec13d47ffada0b56335John Grossman                new InterfaceScoreRule("wlan", (byte)1),
82c157673a590e670a9a509ec13d47ffada0b56335John Grossman                new InterfaceScoreRule("eth", (byte)2),
83c157673a590e670a9a509ec13d47ffada0b56335John Grossman            };
84c157673a590e670a9a509ec13d47ffada0b56335John Grossman        } else {
85c157673a590e670a9a509ec13d47ffada0b56335John Grossman            IFACE_SCORE_RULES = new InterfaceScoreRule[] {
86c157673a590e670a9a509ec13d47ffada0b56335John Grossman                new InterfaceScoreRule("eth", (byte)2),
87c157673a590e670a9a509ec13d47ffada0b56335John Grossman            };
88c157673a590e670a9a509ec13d47ffada0b56335John Grossman        }
89c157673a590e670a9a509ec13d47ffada0b56335John Grossman    };
90c157673a590e670a9a509ec13d47ffada0b56335John Grossman
91c157673a590e670a9a509ec13d47ffada0b56335John Grossman    /*
92c157673a590e670a9a509ec13d47ffada0b56335John Grossman     * Internal state
93c157673a590e670a9a509ec13d47ffada0b56335John Grossman     */
94c157673a590e670a9a509ec13d47ffada0b56335John Grossman    private final Context mContext;
95c157673a590e670a9a509ec13d47ffada0b56335John Grossman    private INetworkManagementService mNetMgr;
96c157673a590e670a9a509ec13d47ffada0b56335John Grossman    private CommonTimeConfig mCTConfig;
97c157673a590e670a9a509ec13d47ffada0b56335John Grossman    private String mCurIface;
98c157673a590e670a9a509ec13d47ffada0b56335John Grossman    private Handler mReconnectHandler = new Handler();
99c157673a590e670a9a509ec13d47ffada0b56335John Grossman    private Handler mNoInterfaceHandler = new Handler();
100c157673a590e670a9a509ec13d47ffada0b56335John Grossman    private Object mLock = new Object();
101c157673a590e670a9a509ec13d47ffada0b56335John Grossman    private boolean mDetectedAtStartup = false;
102c157673a590e670a9a509ec13d47ffada0b56335John Grossman    private byte mEffectivePrio = BASE_SERVER_PRIO;
103c157673a590e670a9a509ec13d47ffada0b56335John Grossman
104c157673a590e670a9a509ec13d47ffada0b56335John Grossman    /*
105c157673a590e670a9a509ec13d47ffada0b56335John Grossman     * Callback handler implementations.
106c157673a590e670a9a509ec13d47ffada0b56335John Grossman     */
107df86a9f2e92d077386b146fe483b2cf14850737dLorenzo Colitti    private INetworkManagementEventObserver mIfaceObserver = new BaseNetworkObserver() {
108c157673a590e670a9a509ec13d47ffada0b56335John Grossman        public void interfaceStatusChanged(String iface, boolean up) {
109c157673a590e670a9a509ec13d47ffada0b56335John Grossman            reevaluateServiceState();
110c157673a590e670a9a509ec13d47ffada0b56335John Grossman        }
111c157673a590e670a9a509ec13d47ffada0b56335John Grossman        public void interfaceLinkStateChanged(String iface, boolean up) {
112c157673a590e670a9a509ec13d47ffada0b56335John Grossman            reevaluateServiceState();
113c157673a590e670a9a509ec13d47ffada0b56335John Grossman        }
114c157673a590e670a9a509ec13d47ffada0b56335John Grossman        public void interfaceAdded(String iface) {
115c157673a590e670a9a509ec13d47ffada0b56335John Grossman            reevaluateServiceState();
116c157673a590e670a9a509ec13d47ffada0b56335John Grossman        }
117c157673a590e670a9a509ec13d47ffada0b56335John Grossman        public void interfaceRemoved(String iface) {
118c157673a590e670a9a509ec13d47ffada0b56335John Grossman            reevaluateServiceState();
119c157673a590e670a9a509ec13d47ffada0b56335John Grossman        }
120c157673a590e670a9a509ec13d47ffada0b56335John Grossman    };
121c157673a590e670a9a509ec13d47ffada0b56335John Grossman
122c157673a590e670a9a509ec13d47ffada0b56335John Grossman    private BroadcastReceiver mConnectivityMangerObserver = new BroadcastReceiver() {
123c157673a590e670a9a509ec13d47ffada0b56335John Grossman        @Override
124c157673a590e670a9a509ec13d47ffada0b56335John Grossman        public void onReceive(Context context, Intent intent) {
125c157673a590e670a9a509ec13d47ffada0b56335John Grossman            reevaluateServiceState();
126c157673a590e670a9a509ec13d47ffada0b56335John Grossman        }
127c157673a590e670a9a509ec13d47ffada0b56335John Grossman    };
128c157673a590e670a9a509ec13d47ffada0b56335John Grossman
129c157673a590e670a9a509ec13d47ffada0b56335John Grossman    private CommonTimeConfig.OnServerDiedListener mCTServerDiedListener =
130c157673a590e670a9a509ec13d47ffada0b56335John Grossman        new CommonTimeConfig.OnServerDiedListener() {
131c157673a590e670a9a509ec13d47ffada0b56335John Grossman            public void onServerDied() {
132c157673a590e670a9a509ec13d47ffada0b56335John Grossman                scheduleTimeConfigReconnect();
133c157673a590e670a9a509ec13d47ffada0b56335John Grossman            }
134c157673a590e670a9a509ec13d47ffada0b56335John Grossman        };
135c157673a590e670a9a509ec13d47ffada0b56335John Grossman
136c157673a590e670a9a509ec13d47ffada0b56335John Grossman    private Runnable mReconnectRunnable = new Runnable() {
137c157673a590e670a9a509ec13d47ffada0b56335John Grossman        public void run() { connectToTimeConfig(); }
138c157673a590e670a9a509ec13d47ffada0b56335John Grossman    };
139c157673a590e670a9a509ec13d47ffada0b56335John Grossman
140c157673a590e670a9a509ec13d47ffada0b56335John Grossman    private Runnable mNoInterfaceRunnable = new Runnable() {
141c157673a590e670a9a509ec13d47ffada0b56335John Grossman        public void run() { handleNoInterfaceTimeout(); }
142c157673a590e670a9a509ec13d47ffada0b56335John Grossman    };
143c157673a590e670a9a509ec13d47ffada0b56335John Grossman
144c157673a590e670a9a509ec13d47ffada0b56335John Grossman    /*
145c157673a590e670a9a509ec13d47ffada0b56335John Grossman     * Public interface (constructor, systemReady and dump)
146c157673a590e670a9a509ec13d47ffada0b56335John Grossman     */
147c157673a590e670a9a509ec13d47ffada0b56335John Grossman    public CommonTimeManagementService(Context context) {
148c157673a590e670a9a509ec13d47ffada0b56335John Grossman        mContext = context;
149c157673a590e670a9a509ec13d47ffada0b56335John Grossman    }
150c157673a590e670a9a509ec13d47ffada0b56335John Grossman
151a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    void systemRunning() {
152c157673a590e670a9a509ec13d47ffada0b56335John Grossman        if (ServiceManager.checkService(CommonTimeConfig.SERVICE_NAME) == null) {
153c157673a590e670a9a509ec13d47ffada0b56335John Grossman            Log.i(TAG, "No common time service detected on this platform.  " +
154c157673a590e670a9a509ec13d47ffada0b56335John Grossman                       "Common time services will be unavailable.");
155c157673a590e670a9a509ec13d47ffada0b56335John Grossman            return;
156c157673a590e670a9a509ec13d47ffada0b56335John Grossman        }
157c157673a590e670a9a509ec13d47ffada0b56335John Grossman
158c157673a590e670a9a509ec13d47ffada0b56335John Grossman        mDetectedAtStartup = true;
159c157673a590e670a9a509ec13d47ffada0b56335John Grossman
160c157673a590e670a9a509ec13d47ffada0b56335John Grossman        IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
161c157673a590e670a9a509ec13d47ffada0b56335John Grossman        mNetMgr = INetworkManagementService.Stub.asInterface(b);
162c157673a590e670a9a509ec13d47ffada0b56335John Grossman
163c157673a590e670a9a509ec13d47ffada0b56335John Grossman        // Network manager is running along-side us, so we should never receiver a remote exception
164c157673a590e670a9a509ec13d47ffada0b56335John Grossman        // while trying to register this observer.
165c157673a590e670a9a509ec13d47ffada0b56335John Grossman        try {
166c157673a590e670a9a509ec13d47ffada0b56335John Grossman            mNetMgr.registerObserver(mIfaceObserver);
167c157673a590e670a9a509ec13d47ffada0b56335John Grossman        }
168c157673a590e670a9a509ec13d47ffada0b56335John Grossman        catch (RemoteException e) { }
169c157673a590e670a9a509ec13d47ffada0b56335John Grossman
170c157673a590e670a9a509ec13d47ffada0b56335John Grossman        // Register with the connectivity manager for connectivity changed intents.
171c157673a590e670a9a509ec13d47ffada0b56335John Grossman        IntentFilter filter = new IntentFilter();
172c157673a590e670a9a509ec13d47ffada0b56335John Grossman        filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
173c157673a590e670a9a509ec13d47ffada0b56335John Grossman        mContext.registerReceiver(mConnectivityMangerObserver, filter);
174c157673a590e670a9a509ec13d47ffada0b56335John Grossman
175c157673a590e670a9a509ec13d47ffada0b56335John Grossman        // Connect to the common time config service and apply the initial configuration.
176c157673a590e670a9a509ec13d47ffada0b56335John Grossman        connectToTimeConfig();
177c157673a590e670a9a509ec13d47ffada0b56335John Grossman    }
178c157673a590e670a9a509ec13d47ffada0b56335John Grossman
179c157673a590e670a9a509ec13d47ffada0b56335John Grossman    @Override
180c157673a590e670a9a509ec13d47ffada0b56335John Grossman    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
181fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey        if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
182c157673a590e670a9a509ec13d47ffada0b56335John Grossman
183c157673a590e670a9a509ec13d47ffada0b56335John Grossman        if (!mDetectedAtStartup) {
184c157673a590e670a9a509ec13d47ffada0b56335John Grossman            pw.println("Native Common Time service was not detected at startup.  " +
185c157673a590e670a9a509ec13d47ffada0b56335John Grossman                       "Service is unavailable");
186c157673a590e670a9a509ec13d47ffada0b56335John Grossman            return;
187c157673a590e670a9a509ec13d47ffada0b56335John Grossman        }
188c157673a590e670a9a509ec13d47ffada0b56335John Grossman
189c157673a590e670a9a509ec13d47ffada0b56335John Grossman        synchronized (mLock) {
190c157673a590e670a9a509ec13d47ffada0b56335John Grossman            pw.println("Current Common Time Management Service Config:");
191c157673a590e670a9a509ec13d47ffada0b56335John Grossman            pw.println(String.format("  Native service     : %s",
192c157673a590e670a9a509ec13d47ffada0b56335John Grossman                                     (null == mCTConfig) ? "reconnecting"
193c157673a590e670a9a509ec13d47ffada0b56335John Grossman                                                         : "alive"));
194c157673a590e670a9a509ec13d47ffada0b56335John Grossman            pw.println(String.format("  Bound interface    : %s",
195c157673a590e670a9a509ec13d47ffada0b56335John Grossman                                     (null == mCurIface ? "unbound" : mCurIface)));
196c157673a590e670a9a509ec13d47ffada0b56335John Grossman            pw.println(String.format("  Allow WiFi         : %s", ALLOW_WIFI ? "yes" : "no"));
197c157673a590e670a9a509ec13d47ffada0b56335John Grossman            pw.println(String.format("  Allow Auto Disable : %s", AUTO_DISABLE ? "yes" : "no"));
198c157673a590e670a9a509ec13d47ffada0b56335John Grossman            pw.println(String.format("  Server Priority    : %d", mEffectivePrio));
199c157673a590e670a9a509ec13d47ffada0b56335John Grossman            pw.println(String.format("  No iface timeout   : %d", NO_INTERFACE_TIMEOUT));
200c157673a590e670a9a509ec13d47ffada0b56335John Grossman        }
201c157673a590e670a9a509ec13d47ffada0b56335John Grossman    }
202c157673a590e670a9a509ec13d47ffada0b56335John Grossman
203c157673a590e670a9a509ec13d47ffada0b56335John Grossman    /*
204c157673a590e670a9a509ec13d47ffada0b56335John Grossman     * Inner helper classes
205c157673a590e670a9a509ec13d47ffada0b56335John Grossman     */
206c157673a590e670a9a509ec13d47ffada0b56335John Grossman    private static class InterfaceScoreRule {
207c157673a590e670a9a509ec13d47ffada0b56335John Grossman        public final String mPrefix;
208c157673a590e670a9a509ec13d47ffada0b56335John Grossman        public final byte mScore;
209c157673a590e670a9a509ec13d47ffada0b56335John Grossman        public InterfaceScoreRule(String prefix, byte score) {
210c157673a590e670a9a509ec13d47ffada0b56335John Grossman            mPrefix = prefix;
211c157673a590e670a9a509ec13d47ffada0b56335John Grossman            mScore = score;
212c157673a590e670a9a509ec13d47ffada0b56335John Grossman        }
213c157673a590e670a9a509ec13d47ffada0b56335John Grossman    };
214c157673a590e670a9a509ec13d47ffada0b56335John Grossman
215c157673a590e670a9a509ec13d47ffada0b56335John Grossman    /*
216c157673a590e670a9a509ec13d47ffada0b56335John Grossman     * Internal implementation
217c157673a590e670a9a509ec13d47ffada0b56335John Grossman     */
218c157673a590e670a9a509ec13d47ffada0b56335John Grossman    private void cleanupTimeConfig() {
219c157673a590e670a9a509ec13d47ffada0b56335John Grossman        mReconnectHandler.removeCallbacks(mReconnectRunnable);
220c157673a590e670a9a509ec13d47ffada0b56335John Grossman        mNoInterfaceHandler.removeCallbacks(mNoInterfaceRunnable);
221c157673a590e670a9a509ec13d47ffada0b56335John Grossman        if (null != mCTConfig) {
222c157673a590e670a9a509ec13d47ffada0b56335John Grossman            mCTConfig.release();
223c157673a590e670a9a509ec13d47ffada0b56335John Grossman            mCTConfig = null;
224c157673a590e670a9a509ec13d47ffada0b56335John Grossman        }
225c157673a590e670a9a509ec13d47ffada0b56335John Grossman    }
226c157673a590e670a9a509ec13d47ffada0b56335John Grossman
227c157673a590e670a9a509ec13d47ffada0b56335John Grossman    private void connectToTimeConfig() {
228c157673a590e670a9a509ec13d47ffada0b56335John Grossman        // Get access to the common time service configuration interface.  If we catch a remote
229c157673a590e670a9a509ec13d47ffada0b56335John Grossman        // exception in the process (service crashed or no running for w/e reason), schedule an
230c157673a590e670a9a509ec13d47ffada0b56335John Grossman        // attempt to reconnect in the future.
231c157673a590e670a9a509ec13d47ffada0b56335John Grossman        cleanupTimeConfig();
232c157673a590e670a9a509ec13d47ffada0b56335John Grossman        try {
233c157673a590e670a9a509ec13d47ffada0b56335John Grossman            synchronized (mLock) {
234c157673a590e670a9a509ec13d47ffada0b56335John Grossman                mCTConfig = new CommonTimeConfig();
235c157673a590e670a9a509ec13d47ffada0b56335John Grossman                mCTConfig.setServerDiedListener(mCTServerDiedListener);
236c157673a590e670a9a509ec13d47ffada0b56335John Grossman                mCurIface = mCTConfig.getInterfaceBinding();
237c157673a590e670a9a509ec13d47ffada0b56335John Grossman                mCTConfig.setAutoDisable(AUTO_DISABLE);
238c157673a590e670a9a509ec13d47ffada0b56335John Grossman                mCTConfig.setMasterElectionPriority(mEffectivePrio);
239c157673a590e670a9a509ec13d47ffada0b56335John Grossman            }
240c157673a590e670a9a509ec13d47ffada0b56335John Grossman
241c157673a590e670a9a509ec13d47ffada0b56335John Grossman            if (NO_INTERFACE_TIMEOUT >= 0)
242c157673a590e670a9a509ec13d47ffada0b56335John Grossman                mNoInterfaceHandler.postDelayed(mNoInterfaceRunnable, NO_INTERFACE_TIMEOUT);
243c157673a590e670a9a509ec13d47ffada0b56335John Grossman
244c157673a590e670a9a509ec13d47ffada0b56335John Grossman            reevaluateServiceState();
245c157673a590e670a9a509ec13d47ffada0b56335John Grossman        }
246c157673a590e670a9a509ec13d47ffada0b56335John Grossman        catch (RemoteException e) {
247c157673a590e670a9a509ec13d47ffada0b56335John Grossman            scheduleTimeConfigReconnect();
248c157673a590e670a9a509ec13d47ffada0b56335John Grossman        }
249c157673a590e670a9a509ec13d47ffada0b56335John Grossman    }
250c157673a590e670a9a509ec13d47ffada0b56335John Grossman
251c157673a590e670a9a509ec13d47ffada0b56335John Grossman    private void scheduleTimeConfigReconnect() {
252c157673a590e670a9a509ec13d47ffada0b56335John Grossman        cleanupTimeConfig();
253c157673a590e670a9a509ec13d47ffada0b56335John Grossman        Log.w(TAG, String.format("Native service died, will reconnect in %d mSec",
254c157673a590e670a9a509ec13d47ffada0b56335John Grossman                                 NATIVE_SERVICE_RECONNECT_TIMEOUT));
255c157673a590e670a9a509ec13d47ffada0b56335John Grossman        mReconnectHandler.postDelayed(mReconnectRunnable,
256c157673a590e670a9a509ec13d47ffada0b56335John Grossman                                      NATIVE_SERVICE_RECONNECT_TIMEOUT);
257c157673a590e670a9a509ec13d47ffada0b56335John Grossman    }
258c157673a590e670a9a509ec13d47ffada0b56335John Grossman
259c157673a590e670a9a509ec13d47ffada0b56335John Grossman    private void handleNoInterfaceTimeout() {
260c157673a590e670a9a509ec13d47ffada0b56335John Grossman        if (null != mCTConfig) {
261c157673a590e670a9a509ec13d47ffada0b56335John Grossman            Log.i(TAG, "Timeout waiting for interface to come up.  " +
262c157673a590e670a9a509ec13d47ffada0b56335John Grossman                       "Forcing networkless master mode.");
263c157673a590e670a9a509ec13d47ffada0b56335John Grossman            if (CommonTimeConfig.ERROR_DEAD_OBJECT == mCTConfig.forceNetworklessMasterMode())
264c157673a590e670a9a509ec13d47ffada0b56335John Grossman                scheduleTimeConfigReconnect();
265c157673a590e670a9a509ec13d47ffada0b56335John Grossman        }
266c157673a590e670a9a509ec13d47ffada0b56335John Grossman    }
267c157673a590e670a9a509ec13d47ffada0b56335John Grossman
268c157673a590e670a9a509ec13d47ffada0b56335John Grossman    private void reevaluateServiceState() {
269c157673a590e670a9a509ec13d47ffada0b56335John Grossman        String bindIface = null;
270c157673a590e670a9a509ec13d47ffada0b56335John Grossman        byte bestScore = -1;
271c157673a590e670a9a509ec13d47ffada0b56335John Grossman        try {
272c157673a590e670a9a509ec13d47ffada0b56335John Grossman            // Check to see if this interface is suitable to use for time synchronization.
273c157673a590e670a9a509ec13d47ffada0b56335John Grossman            //
274c157673a590e670a9a509ec13d47ffada0b56335John Grossman            // TODO : This selection algorithm needs to be enhanced for use with mobile devices.  In
275c157673a590e670a9a509ec13d47ffada0b56335John Grossman            // particular, the choice of whether to a wireless interface or not should not be an all
276c157673a590e670a9a509ec13d47ffada0b56335John Grossman            // or nothing thing controlled by properties.  It would probably be better if the
277c157673a590e670a9a509ec13d47ffada0b56335John Grossman            // platform had some concept of public wireless networks vs. home or friendly wireless
278c157673a590e670a9a509ec13d47ffada0b56335John Grossman            // networks (something a user would configure in settings or when a new interface is
279c157673a590e670a9a509ec13d47ffada0b56335John Grossman            // added).  Then this algorithm could pick only wireless interfaces which were flagged
280c157673a590e670a9a509ec13d47ffada0b56335John Grossman            // as friendly, and be dormant when on public wireless networks.
281c157673a590e670a9a509ec13d47ffada0b56335John Grossman            //
282c157673a590e670a9a509ec13d47ffada0b56335John Grossman            // Another issue which needs to be dealt with is the use of driver supplied interface
283c157673a590e670a9a509ec13d47ffada0b56335John Grossman            // name to determine the network type.  The fact that the wireless interface on a device
284c157673a590e670a9a509ec13d47ffada0b56335John Grossman            // is named "wlan0" is just a matter of convention; its not a 100% rule.  For example,
285c157673a590e670a9a509ec13d47ffada0b56335John Grossman            // there are devices out there where the wireless is name "tiwlan0", not "wlan0".  The
286c157673a590e670a9a509ec13d47ffada0b56335John Grossman            // internal network management interfaces in Android have all of the information needed
287c157673a590e670a9a509ec13d47ffada0b56335John Grossman            // to make a proper classification, there is just no way (currently) to fetch an
288c157673a590e670a9a509ec13d47ffada0b56335John Grossman            // interface's type (available from the ConnectionManager) as well as its address
289c157673a590e670a9a509ec13d47ffada0b56335John Grossman            // (available from either the java.net interfaces or from the NetworkManagment service).
290c157673a590e670a9a509ec13d47ffada0b56335John Grossman            // Both can enumerate interfaces, but that is no way to correlate their results (no
291c157673a590e670a9a509ec13d47ffada0b56335John Grossman            // common shared key; although using the interface name in the connection manager would
292c157673a590e670a9a509ec13d47ffada0b56335John Grossman            // be a good start).  Until this gets resolved, we resort to substring searching for
293c157673a590e670a9a509ec13d47ffada0b56335John Grossman            // tags like wlan and eth.
294c157673a590e670a9a509ec13d47ffada0b56335John Grossman            //
295c157673a590e670a9a509ec13d47ffada0b56335John Grossman            String ifaceList[] = mNetMgr.listInterfaces();
296c157673a590e670a9a509ec13d47ffada0b56335John Grossman            if (null != ifaceList) {
297c157673a590e670a9a509ec13d47ffada0b56335John Grossman                for (String iface : ifaceList) {
298c157673a590e670a9a509ec13d47ffada0b56335John Grossman
299c157673a590e670a9a509ec13d47ffada0b56335John Grossman                    byte thisScore = -1;
300c157673a590e670a9a509ec13d47ffada0b56335John Grossman                    for (InterfaceScoreRule r : IFACE_SCORE_RULES) {
301c157673a590e670a9a509ec13d47ffada0b56335John Grossman                        if (iface.contains(r.mPrefix)) {
302c157673a590e670a9a509ec13d47ffada0b56335John Grossman                            thisScore = r.mScore;
303c157673a590e670a9a509ec13d47ffada0b56335John Grossman                            break;
304c157673a590e670a9a509ec13d47ffada0b56335John Grossman                        }
305c157673a590e670a9a509ec13d47ffada0b56335John Grossman                    }
306c157673a590e670a9a509ec13d47ffada0b56335John Grossman
307c157673a590e670a9a509ec13d47ffada0b56335John Grossman                    if (thisScore <= bestScore)
308c157673a590e670a9a509ec13d47ffada0b56335John Grossman                        continue;
309c157673a590e670a9a509ec13d47ffada0b56335John Grossman
310c157673a590e670a9a509ec13d47ffada0b56335John Grossman                    InterfaceConfiguration config = mNetMgr.getInterfaceConfig(iface);
311c157673a590e670a9a509ec13d47ffada0b56335John Grossman                    if (null == config)
312c157673a590e670a9a509ec13d47ffada0b56335John Grossman                        continue;
313c157673a590e670a9a509ec13d47ffada0b56335John Grossman
314c157673a590e670a9a509ec13d47ffada0b56335John Grossman                    if (config.isActive()) {
315c157673a590e670a9a509ec13d47ffada0b56335John Grossman                        bindIface = iface;
316c157673a590e670a9a509ec13d47ffada0b56335John Grossman                        bestScore = thisScore;
317c157673a590e670a9a509ec13d47ffada0b56335John Grossman                    }
318c157673a590e670a9a509ec13d47ffada0b56335John Grossman                }
319c157673a590e670a9a509ec13d47ffada0b56335John Grossman            }
320c157673a590e670a9a509ec13d47ffada0b56335John Grossman        }
321c157673a590e670a9a509ec13d47ffada0b56335John Grossman        catch (RemoteException e) {
322c157673a590e670a9a509ec13d47ffada0b56335John Grossman            // Bad news; we should not be getting remote exceptions from the connectivity manager
323c157673a590e670a9a509ec13d47ffada0b56335John Grossman            // since it is running in SystemServer along side of us.  It probably does not matter
324c157673a590e670a9a509ec13d47ffada0b56335John Grossman            // what we do here, but go ahead and unbind the common time service in this case, just
325c157673a590e670a9a509ec13d47ffada0b56335John Grossman            // so we have some defined behavior.
326c157673a590e670a9a509ec13d47ffada0b56335John Grossman            bindIface = null;
327c157673a590e670a9a509ec13d47ffada0b56335John Grossman        }
328c157673a590e670a9a509ec13d47ffada0b56335John Grossman
329c157673a590e670a9a509ec13d47ffada0b56335John Grossman        boolean doRebind = true;
330c157673a590e670a9a509ec13d47ffada0b56335John Grossman        synchronized (mLock) {
331c157673a590e670a9a509ec13d47ffada0b56335John Grossman            if ((null != bindIface) && (null == mCurIface)) {
332c157673a590e670a9a509ec13d47ffada0b56335John Grossman                Log.e(TAG, String.format("Binding common time service to %s.", bindIface));
333c157673a590e670a9a509ec13d47ffada0b56335John Grossman                mCurIface = bindIface;
334c157673a590e670a9a509ec13d47ffada0b56335John Grossman            } else
335c157673a590e670a9a509ec13d47ffada0b56335John Grossman            if ((null == bindIface) && (null != mCurIface)) {
336c157673a590e670a9a509ec13d47ffada0b56335John Grossman                Log.e(TAG, "Unbinding common time service.");
337c157673a590e670a9a509ec13d47ffada0b56335John Grossman                mCurIface = null;
338c157673a590e670a9a509ec13d47ffada0b56335John Grossman            } else
339c157673a590e670a9a509ec13d47ffada0b56335John Grossman            if ((null != bindIface) && (null != mCurIface) && !bindIface.equals(mCurIface)) {
340c157673a590e670a9a509ec13d47ffada0b56335John Grossman                Log.e(TAG, String.format("Switching common time service binding from %s to %s.",
341c157673a590e670a9a509ec13d47ffada0b56335John Grossman                                         mCurIface, bindIface));
342c157673a590e670a9a509ec13d47ffada0b56335John Grossman                mCurIface = bindIface;
343c157673a590e670a9a509ec13d47ffada0b56335John Grossman            } else {
344c157673a590e670a9a509ec13d47ffada0b56335John Grossman                doRebind = false;
345c157673a590e670a9a509ec13d47ffada0b56335John Grossman            }
346c157673a590e670a9a509ec13d47ffada0b56335John Grossman        }
347c157673a590e670a9a509ec13d47ffada0b56335John Grossman
348c157673a590e670a9a509ec13d47ffada0b56335John Grossman        if (doRebind && (null != mCTConfig)) {
349c157673a590e670a9a509ec13d47ffada0b56335John Grossman            byte newPrio = (bestScore > 0)
350c157673a590e670a9a509ec13d47ffada0b56335John Grossman                         ? (byte)(bestScore * BASE_SERVER_PRIO)
351c157673a590e670a9a509ec13d47ffada0b56335John Grossman                         : BASE_SERVER_PRIO;
352c157673a590e670a9a509ec13d47ffada0b56335John Grossman            if (newPrio != mEffectivePrio) {
353c157673a590e670a9a509ec13d47ffada0b56335John Grossman                mEffectivePrio = newPrio;
354c157673a590e670a9a509ec13d47ffada0b56335John Grossman                mCTConfig.setMasterElectionPriority(mEffectivePrio);
355c157673a590e670a9a509ec13d47ffada0b56335John Grossman            }
356c157673a590e670a9a509ec13d47ffada0b56335John Grossman
357c157673a590e670a9a509ec13d47ffada0b56335John Grossman            int res = mCTConfig.setNetworkBinding(mCurIface);
358c157673a590e670a9a509ec13d47ffada0b56335John Grossman            if (res != CommonTimeConfig.SUCCESS)
359c157673a590e670a9a509ec13d47ffada0b56335John Grossman                scheduleTimeConfigReconnect();
360c157673a590e670a9a509ec13d47ffada0b56335John Grossman
361c157673a590e670a9a509ec13d47ffada0b56335John Grossman            else if (NO_INTERFACE_TIMEOUT >= 0) {
362c157673a590e670a9a509ec13d47ffada0b56335John Grossman                mNoInterfaceHandler.removeCallbacks(mNoInterfaceRunnable);
363c157673a590e670a9a509ec13d47ffada0b56335John Grossman                if (null == mCurIface)
364c157673a590e670a9a509ec13d47ffada0b56335John Grossman                    mNoInterfaceHandler.postDelayed(mNoInterfaceRunnable, NO_INTERFACE_TIMEOUT);
365c157673a590e670a9a509ec13d47ffada0b56335John Grossman            }
366c157673a590e670a9a509ec13d47ffada0b56335John Grossman        }
367c157673a590e670a9a509ec13d47ffada0b56335John Grossman    }
368c157673a590e670a9a509ec13d47ffada0b56335John Grossman}
369