1/* 2 * Copyright 2014, The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.managedprovisioning.task; 18 19import android.content.Context; 20import android.content.Intent; 21import android.net.ConnectivityManager; 22import android.net.NetworkInfo; 23import android.net.wifi.WifiManager; 24import android.text.TextUtils; 25 26import java.lang.Thread; 27 28import com.android.managedprovisioning.NetworkMonitor; 29import com.android.managedprovisioning.ProvisionLogger; 30import com.android.managedprovisioning.WifiConfig; 31 32/** 33 * Adds a wifi network to system. 34 */ 35public class AddWifiNetworkTask implements NetworkMonitor.Callback { 36 private static final int RETRY_SLEEP_DURATION_BASE_MS = 500; 37 private static final int RETRY_SLEEP_MULTIPLIER = 2; 38 private static final int MAX_RETRIES = 6; 39 40 private final Context mContext; 41 private final String mSsid; 42 private final boolean mHidden; 43 private final String mSecurityType; 44 private final String mPassword; 45 private final String mProxyHost; 46 private final int mProxyPort; 47 private final String mProxyBypassHosts; 48 private final String mPacUrl; 49 private final Callback mCallback; 50 51 private WifiManager mWifiManager; 52 private NetworkMonitor mNetworkMonitor; 53 private WifiConfig mWifiConfig; 54 55 private int mDurationNextSleep = RETRY_SLEEP_DURATION_BASE_MS; 56 private int mRetriesLeft = MAX_RETRIES; 57 58 public AddWifiNetworkTask(Context context, String ssid, boolean hidden, String securityType, 59 String password, String proxyHost, int proxyPort, String proxyBypassHosts, 60 String pacUrl, Callback callback) { 61 mCallback = callback; 62 mContext = context; 63 mSsid = ssid; 64 mHidden = hidden; 65 mSecurityType = securityType; 66 mPassword = password; 67 mProxyHost = proxyHost; 68 mProxyPort = proxyPort; 69 mProxyBypassHosts = proxyBypassHosts; 70 mPacUrl = pacUrl; 71 mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); 72 mWifiConfig = new WifiConfig(mWifiManager); 73 } 74 75 public void run() { 76 if (!enableWifi()) { 77 ProvisionLogger.loge("Failed to enable wifi"); 78 mCallback.onError(); 79 return; 80 } 81 82 mNetworkMonitor = new NetworkMonitor(mContext, this); 83 84 if (!isConnectedToWifi(mContext)) { 85 if (TextUtils.isEmpty(mSsid)) { 86 ProvisionLogger.loge("Wifi is supposed to be setup in activity," + 87 " or a valid wifi ssid has to be specified."); 88 mCallback.onError(); 89 return; 90 } 91 92 connectToProvidedNetwork(); 93 } else { 94 mCallback.onSuccess(); 95 } 96 } 97 98 private void connectToProvidedNetwork() { 99 int netId = mWifiConfig.addNetwork(mSsid, mHidden, mSecurityType, mPassword, mProxyHost, 100 mProxyPort, mProxyBypassHosts, mPacUrl); 101 102 if (netId == -1) { 103 ProvisionLogger.loge("Failed to save network."); 104 if (mRetriesLeft > 0) { 105 ProvisionLogger.loge("Retrying in " + mDurationNextSleep + " ms."); 106 try { 107 Thread.sleep(mDurationNextSleep); 108 } catch (InterruptedException e) { 109 ProvisionLogger.loge("Retry interrupted."); 110 } 111 mDurationNextSleep *= RETRY_SLEEP_MULTIPLIER; 112 mRetriesLeft--; 113 connectToProvidedNetwork(); 114 return; 115 } else { 116 ProvisionLogger.loge("Already retried " + MAX_RETRIES + " times." 117 + " Quit retrying and report error."); 118 mCallback.onError(); 119 return; 120 } 121 } else { 122 if (!mWifiManager.reconnect()) { 123 ProvisionLogger.loge("Unable to connect to wifi"); 124 mCallback.onError(); 125 return; 126 } 127 } 128 129 // NetworkMonitor will call onNetworkConnected when in Wifi mode. 130 } 131 132 private boolean enableWifi() { 133 if (mWifiManager != null) { 134 int wifiState = mWifiManager.getWifiState(); 135 boolean wifiOn = wifiState == WifiManager.WIFI_STATE_ENABLED; 136 if (!wifiOn) { 137 if (!mWifiManager.setWifiEnabled(true)) { 138 return false; 139 } else { 140 return true; 141 } 142 } else { 143 return true; 144 } 145 } else { 146 return false; 147 } 148 } 149 150 @Override 151 public void onNetworkConnected() { 152 if (NetworkMonitor.isConnectedToWifi(mContext) && 153 mWifiManager.getConnectionInfo().getSSID().equals(mSsid)) { 154 ProvisionLogger.logd("Connected to the correct network"); 155 mNetworkMonitor.close(); 156 mNetworkMonitor = null; 157 mCallback.onSuccess(); 158 } 159 } 160 161 @Override 162 public void onNetworkDisconnected() { 163 164 } 165 166 public void cleanUp() { 167 if (mNetworkMonitor != null) { 168 mNetworkMonitor.close(); 169 mNetworkMonitor = null; 170 } 171 } 172 173 public static boolean isConnectedToWifi(Context context) { 174 ConnectivityManager cm = 175 (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); 176 NetworkInfo info = cm.getNetworkInfo(ConnectivityManager.TYPE_WIFI); 177 return info.isConnected(); 178 } 179 180 public static Intent getWifiPickIntent() { 181 Intent wifiIntent = new Intent(WifiManager.ACTION_PICK_WIFI_NETWORK); 182 wifiIntent.putExtra("only_access_points", true); 183 wifiIntent.putExtra("extra_prefs_show_button_bar", true); 184 wifiIntent.putExtra("wifi_enable_next_on_connect", true); 185 return wifiIntent; 186 } 187 188 public abstract static class Callback { 189 public abstract void onSuccess(); 190 public abstract void onError(); 191 } 192} 193