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