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