1 /* 2 * Copyright (C) 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 17 package com.android.tv.settings.connectivity; 18 19 import android.content.Context; 20 import android.net.IpConfiguration; 21 import android.net.IpConfiguration.IpAssignment; 22 import android.net.IpConfiguration.ProxySettings; 23 import android.net.LinkAddress; 24 import android.net.NetworkUtils; 25 import android.net.ProxyInfo; 26 import android.net.StaticIpConfiguration; 27 import android.net.wifi.WifiConfiguration; 28 import android.os.Bundle; 29 import android.text.TextUtils; 30 31 import com.android.tv.settings.R; 32 import com.android.tv.settings.form.FormPage; 33 34 import java.net.Inet4Address; 35 import java.net.InetAddress; 36 37 /** 38 * Handles the form page flow of setting advanced options. 39 */ 40 public class AdvancedWifiOptionsFlow { 41 42 public interface PageHandler { addPage(WifiFormPageType formPageType)43 void addPage(WifiFormPageType formPageType); 44 removePage(FormPage formPage)45 void removePage(FormPage formPage); 46 choiceChosen(FormPage formPage, int choiceResourceId)47 boolean choiceChosen(FormPage formPage, int choiceResourceId); 48 } 49 50 public static final int RESULT_UNKNOWN_PAGE = 0; 51 public static final int RESULT_PAGE_HANDLED = 1; 52 public static final int RESULT_ALL_PAGES_COMPLETE = 2; 53 54 private final Context mContext; 55 private final PageHandler mPageHandler; 56 private final boolean mAskFirst; 57 private final NetworkConfiguration mInitialConfiguration; 58 private FormPage mAdvancedOptionsPage; 59 private FormPage mProxySettingsPage; 60 private FormPage mIpSettingsPage; 61 private FormPage mProxyHostnamePage; 62 private FormPage mProxyPortPage; 63 private FormPage mProxyBypassPage; 64 private FormPage mIpAddressPage; 65 private FormPage mGatewayPage; 66 private FormPage mNetworkPrefixLengthPage; 67 private FormPage mDns1Page; 68 private FormPage mDns2Page; 69 private final IpConfiguration mIpConfiguration; 70 private final boolean mSettingsFlow; 71 AdvancedWifiOptionsFlow(Context context, PageHandler pageHandler, NetworkConfiguration initialConfiguration)72 public AdvancedWifiOptionsFlow(Context context, PageHandler pageHandler, 73 NetworkConfiguration initialConfiguration) { 74 mContext = context; 75 mPageHandler = pageHandler; 76 mAskFirst = false; 77 mSettingsFlow = true; 78 mInitialConfiguration = initialConfiguration; 79 mIpConfiguration = (initialConfiguration != null) ? 80 mInitialConfiguration.getIpConfiguration() : 81 new IpConfiguration(); 82 } 83 AdvancedWifiOptionsFlow(Context context, PageHandler pageHandler, boolean askFirst, NetworkConfiguration initialConfiguration)84 public AdvancedWifiOptionsFlow(Context context, PageHandler pageHandler, boolean askFirst, 85 NetworkConfiguration initialConfiguration) { 86 mContext = context; 87 mPageHandler = pageHandler; 88 mAskFirst = askFirst; 89 mSettingsFlow = false; 90 mInitialConfiguration = initialConfiguration; 91 mIpConfiguration = (initialConfiguration != null) ? 92 mInitialConfiguration.getIpConfiguration() : 93 new IpConfiguration(); 94 } 95 getInitialPage()96 public WifiFormPageType getInitialPage() { 97 return (mAskFirst) ? WifiFormPageType.ADVANCED_OPTIONS : WifiFormPageType.PROXY_SETTINGS; 98 } 99 getInitialProxySettingsPage()100 public WifiFormPageType getInitialProxySettingsPage() { 101 return WifiFormPageType.PROXY_SETTINGS; 102 } 103 getInitialIpSettingsPage()104 public WifiFormPageType getInitialIpSettingsPage() { 105 return WifiFormPageType.IP_SETTINGS; 106 } 107 108 /** 109 * @param formPageType the type of page that completed. 110 * @param formPage the page that complete. 111 * @return RESULT_PAGE_HANDLED if the page has been handled. 112 * RESULT_UNKNOWN_PAGE if the page is unrecognized and was ignored. 113 * RESULT_ALL_PAGES_COMPLETE if all pages have been completed. 114 */ handlePageComplete(WifiFormPageType formPageType, FormPage formPage)115 public int handlePageComplete(WifiFormPageType formPageType, FormPage formPage) { 116 117 switch (formPageType) { 118 case ADVANCED_OPTIONS: 119 mAdvancedOptionsPage = formPage; 120 if (mPageHandler.choiceChosen(formPage, R.string.wifi_action_advanced_no)) { 121 processProxySettings(); 122 processIpSettings(); 123 return RESULT_ALL_PAGES_COMPLETE; 124 } else { 125 mPageHandler.addPage(WifiFormPageType.PROXY_SETTINGS); 126 } 127 break; 128 case PROXY_SETTINGS: 129 mProxySettingsPage = formPage; 130 if (mPageHandler.choiceChosen(formPage, R.string.wifi_action_proxy_none)) { 131 processProxySettings(); 132 if (mSettingsFlow) { 133 return RESULT_ALL_PAGES_COMPLETE; 134 } else { 135 mPageHandler.addPage(WifiFormPageType.IP_SETTINGS); 136 } 137 } else { 138 mPageHandler.addPage(WifiFormPageType.PROXY_HOSTNAME); 139 } 140 break; 141 case PROXY_HOSTNAME: 142 mProxyHostnamePage = formPage; 143 mPageHandler.addPage(WifiFormPageType.PROXY_PORT); 144 break; 145 case PROXY_PORT: 146 mProxyPortPage = formPage; 147 mPageHandler.addPage(WifiFormPageType.PROXY_BYPASS); 148 break; 149 case PROXY_BYPASS: 150 mProxyBypassPage = formPage; 151 int proxySettingsResult = processProxySettings(); 152 if (proxySettingsResult == 0) { 153 if (mSettingsFlow) { 154 return RESULT_ALL_PAGES_COMPLETE; 155 } else { 156 mPageHandler.addPage(WifiFormPageType.IP_SETTINGS); 157 } 158 } else { 159 mPageHandler.addPage(WifiFormPageType.PROXY_SETTINGS_INVALID); 160 } 161 break; 162 case PROXY_SETTINGS_INVALID: 163 mPageHandler.removePage(mProxySettingsPage); 164 mPageHandler.removePage(mProxyHostnamePage); 165 mPageHandler.removePage(mProxyPortPage); 166 mPageHandler.removePage(mProxyBypassPage); 167 mPageHandler.addPage(WifiFormPageType.PROXY_SETTINGS); 168 break; 169 case IP_SETTINGS: 170 mIpSettingsPage = formPage; 171 if (mPageHandler.choiceChosen(formPage, R.string.wifi_action_dhcp)) { 172 processIpSettings(); 173 return RESULT_ALL_PAGES_COMPLETE; 174 } else { 175 mPageHandler.addPage(WifiFormPageType.IP_ADDRESS); 176 } 177 break; 178 case IP_ADDRESS: 179 mIpAddressPage = formPage; 180 mPageHandler.addPage(WifiFormPageType.GATEWAY); 181 break; 182 case GATEWAY: 183 mGatewayPage = formPage; 184 mPageHandler.addPage(WifiFormPageType.NETWORK_PREFIX_LENGTH); 185 break; 186 case NETWORK_PREFIX_LENGTH: 187 mNetworkPrefixLengthPage = formPage; 188 mPageHandler.addPage(WifiFormPageType.DNS1); 189 break; 190 case DNS1: 191 mDns1Page = formPage; 192 mPageHandler.addPage(WifiFormPageType.DNS2); 193 break; 194 case DNS2: 195 mDns2Page = formPage; 196 int ipSettingsResult = processIpSettings(); 197 if (ipSettingsResult == 0) { 198 return RESULT_ALL_PAGES_COMPLETE; 199 } else { 200 mPageHandler.addPage(WifiFormPageType.IP_SETTINGS_INVALID); 201 } 202 break; 203 case IP_SETTINGS_INVALID: 204 mPageHandler.removePage(mIpSettingsPage); 205 mPageHandler.removePage(mIpAddressPage); 206 mPageHandler.removePage(mGatewayPage); 207 mPageHandler.removePage(mDns1Page); 208 mPageHandler.removePage(mDns2Page); 209 mPageHandler.addPage(WifiFormPageType.IP_SETTINGS); 210 break; 211 default: 212 return RESULT_UNKNOWN_PAGE; 213 } 214 return RESULT_PAGE_HANDLED; 215 } 216 getPreviousPage(WifiFormPageType formPageType)217 public FormPage getPreviousPage(WifiFormPageType formPageType) { 218 switch (formPageType) { 219 case ADVANCED_OPTIONS: 220 return mAdvancedOptionsPage; 221 case PROXY_SETTINGS: 222 if (mProxySettingsPage == null && getInitialProxyInfo() != null) { 223 return createFormPage(R.string.wifi_action_proxy_manual); 224 } 225 return mProxySettingsPage; 226 case PROXY_HOSTNAME: 227 if (mProxyHostnamePage == null && getInitialProxyInfo() != null) { 228 return createFormPage(getInitialProxyInfo().getHost()); 229 } 230 return mProxyHostnamePage; 231 case PROXY_PORT: 232 if (mProxyPortPage == null && getInitialProxyInfo() != null) { 233 return createFormPage(Integer.toString(getInitialProxyInfo().getPort())); 234 } 235 return mProxyPortPage; 236 case PROXY_BYPASS: 237 if (mProxyBypassPage == null && getInitialProxyInfo() != null) { 238 return createFormPage(getInitialProxyInfo().getExclusionListAsString()); 239 } 240 return mProxyBypassPage; 241 case IP_SETTINGS: 242 if (mIpSettingsPage == null && getInitialLinkAddress() != null) { 243 return createFormPage(R.string.wifi_action_static); 244 } 245 return mIpSettingsPage; 246 case IP_ADDRESS: 247 if (mIpAddressPage == null && getInitialLinkAddress() != null) { 248 return createFormPage(getInitialLinkAddress().getAddress().getHostAddress()); 249 } 250 return mIpAddressPage; 251 case GATEWAY: 252 if (mGatewayPage == null && getInitialGateway() != null) { 253 return createFormPage(getInitialGateway().getHostAddress()); 254 } 255 return mGatewayPage; 256 case NETWORK_PREFIX_LENGTH: 257 if (mNetworkPrefixLengthPage == null && getInitialLinkAddress() != null) { 258 return createFormPage( 259 Integer.toString(getInitialLinkAddress().getNetworkPrefixLength())); 260 } 261 return mNetworkPrefixLengthPage; 262 case DNS1: 263 if (mDns1Page == null && getInitialDns(0) != null) { 264 return createFormPage(getInitialDns(0).getHostAddress()); 265 } 266 return mDns1Page; 267 case DNS2: 268 if (mDns2Page == null && getInitialDns(1) != null) { 269 return createFormPage(getInitialDns(1).getHostAddress()); 270 } 271 return mDns2Page; 272 case IP_SETTINGS_INVALID: 273 case PROXY_SETTINGS_INVALID: 274 default: 275 return null; 276 } 277 } 278 isEmptyTextAllowed(WifiFormPageType formPageType)279 public boolean isEmptyTextAllowed(WifiFormPageType formPageType) { 280 switch (formPageType) { 281 case PROXY_BYPASS: 282 case DNS1: 283 case DNS2: 284 case GATEWAY: 285 return true; 286 default: 287 return false; 288 } 289 } 290 getCurrentIpConfiguration()291 private IpConfiguration getCurrentIpConfiguration() { 292 return mIpConfiguration; 293 } 294 updateConfiguration(WifiConfiguration configuration)295 public void updateConfiguration(WifiConfiguration configuration) { 296 configuration.setIpConfiguration(mIpConfiguration); 297 } 298 updateConfiguration(NetworkConfiguration configuration)299 public void updateConfiguration(NetworkConfiguration configuration) { 300 configuration.setIpConfiguration(mIpConfiguration); 301 } 302 getInitialDns(int index)303 private InetAddress getInitialDns(int index) { 304 try { 305 return mInitialConfiguration.getIpConfiguration().getStaticIpConfiguration() 306 .dnsServers.get(index); 307 } catch (IndexOutOfBoundsException|NullPointerException e) { 308 return null; 309 } 310 } 311 getInitialGateway()312 private InetAddress getInitialGateway() { 313 try { 314 return mInitialConfiguration.getIpConfiguration().getStaticIpConfiguration().gateway; 315 } catch (NullPointerException e) { 316 return null; 317 } 318 } 319 getInitialLinkAddress()320 private LinkAddress getInitialLinkAddress() { 321 try { 322 return mInitialConfiguration.getIpConfiguration().getStaticIpConfiguration().ipAddress; 323 } catch (NullPointerException e) { 324 return null; 325 } 326 } 327 getInitialProxyInfo()328 private ProxyInfo getInitialProxyInfo() { 329 try { 330 return mInitialConfiguration.getIpConfiguration().getHttpProxy(); 331 } catch (NullPointerException e) { 332 return null; 333 } 334 } 335 createFormPage(int resultStringResourceId)336 private FormPage createFormPage(int resultStringResourceId) { 337 return createFormPage(mContext.getString(resultStringResourceId)); 338 } 339 createFormPage(String resultString)340 private FormPage createFormPage(String resultString) { 341 Bundle result = new Bundle(); 342 result.putString(FormPage.DATA_KEY_SUMMARY_STRING, resultString); 343 FormPage formPage = FormPage.createTextInputForm(resultString); 344 formPage.complete(result); 345 return formPage; 346 } 347 processProxySettings()348 private int processProxySettings() { 349 boolean hasProxySettings = (mAdvancedOptionsPage == null || !mPageHandler.choiceChosen( 350 mAdvancedOptionsPage, R.string.wifi_action_advanced_no)) 351 && !mPageHandler.choiceChosen(mProxySettingsPage, R.string.wifi_action_proxy_none); 352 mIpConfiguration.setProxySettings(hasProxySettings ? 353 ProxySettings.STATIC : ProxySettings.NONE); 354 if (hasProxySettings) { 355 String host = mProxyHostnamePage.getDataSummary(); 356 String portStr = mProxyPortPage.getDataSummary(); 357 String exclusionList = mProxyBypassPage.getDataSummary(); 358 int port = 0; 359 int result = 0; 360 try { 361 port = Integer.parseInt(portStr); 362 result = WifiConfigHelper.validate(host, portStr, exclusionList); 363 } catch (NumberFormatException e) { 364 result = R.string.proxy_error_invalid_port; 365 } 366 if (result == 0) { 367 mIpConfiguration.setHttpProxy(new ProxyInfo(host, port, exclusionList)); 368 } else { 369 return result; 370 } 371 } else { 372 mIpConfiguration.setHttpProxy(null); 373 } 374 375 return 0; 376 } 377 processIpSettings()378 private int processIpSettings() { 379 boolean hasIpSettings = (mAdvancedOptionsPage == null || !mPageHandler.choiceChosen( 380 mAdvancedOptionsPage, R.string.wifi_action_advanced_no)) 381 && !mPageHandler.choiceChosen(mIpSettingsPage, R.string.wifi_action_dhcp); 382 mIpConfiguration.setIpAssignment(hasIpSettings ? IpAssignment.STATIC : IpAssignment.DHCP); 383 384 if (hasIpSettings) { 385 StaticIpConfiguration staticConfig = new StaticIpConfiguration(); 386 mIpConfiguration.setStaticIpConfiguration(staticConfig); 387 388 String ipAddr = mIpAddressPage.getDataSummary(); 389 if (TextUtils.isEmpty(ipAddr)) 390 return R.string.wifi_ip_settings_invalid_ip_address; 391 392 Inet4Address inetAddr = null; 393 try { 394 inetAddr = (Inet4Address) NetworkUtils.numericToInetAddress(ipAddr); 395 } catch (IllegalArgumentException|ClassCastException e) { 396 return R.string.wifi_ip_settings_invalid_ip_address; 397 } 398 399 int networkPrefixLength = -1; 400 try { 401 networkPrefixLength = Integer.parseInt(mNetworkPrefixLengthPage.getDataSummary()); 402 if (networkPrefixLength < 0 || networkPrefixLength > 32) { 403 return R.string.wifi_ip_settings_invalid_network_prefix_length; 404 } 405 staticConfig.ipAddress = new LinkAddress(inetAddr, networkPrefixLength); 406 } catch (NumberFormatException e) { 407 return R.string.wifi_ip_settings_invalid_ip_address; 408 } 409 410 String gateway = mGatewayPage.getDataSummary(); 411 if (!TextUtils.isEmpty(gateway)) { 412 try { 413 staticConfig.gateway = 414 (Inet4Address) NetworkUtils.numericToInetAddress(gateway); 415 } catch (IllegalArgumentException|ClassCastException e) { 416 return R.string.wifi_ip_settings_invalid_gateway; 417 } 418 } 419 420 String dns1 = mDns1Page.getDataSummary(); 421 if (!TextUtils.isEmpty(dns1)) { 422 try { 423 staticConfig.dnsServers.add( 424 (Inet4Address) NetworkUtils.numericToInetAddress(dns1)); 425 } catch (IllegalArgumentException|ClassCastException e) { 426 return R.string.wifi_ip_settings_invalid_dns; 427 } 428 } 429 430 String dns2 = mDns2Page.getDataSummary(); 431 if (!TextUtils.isEmpty(dns2)) { 432 try { 433 staticConfig.dnsServers.add( 434 (Inet4Address) NetworkUtils.numericToInetAddress(dns2)); 435 } catch (IllegalArgumentException|ClassCastException e) { 436 return R.string.wifi_ip_settings_invalid_dns; 437 } 438 } 439 } else { 440 mIpConfiguration.setStaticIpConfiguration(null); 441 } 442 return 0; 443 } 444 } 445