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