Home | History | Annotate | Download | only in setup
      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.setup;
     18 
     19 import android.animation.Animator;
     20 import android.animation.ObjectAnimator;
     21 import android.app.Fragment;
     22 import android.app.FragmentManager;
     23 import android.app.FragmentTransaction;
     24 import android.content.Context;
     25 import android.content.Intent;
     26 import android.net.ConnectivityManager;
     27 import android.net.NetworkInfo;
     28 import android.net.wifi.ScanResult;
     29 import android.net.wifi.WifiConfiguration;
     30 import android.net.wifi.WifiInfo;
     31 import android.net.wifi.WifiManager;
     32 import android.os.Bundle;
     33 import android.os.Handler;
     34 import android.os.Message;
     35 import android.text.TextUtils;
     36 import android.util.Pair;
     37 
     38 import com.android.settingslib.wifi.WifiTracker;
     39 import com.android.tv.settings.R;
     40 import com.android.tv.settings.connectivity.AdvancedWifiOptionsFlow;
     41 import com.android.tv.settings.connectivity.ConnectToWifiFragment;
     42 import com.android.tv.settings.connectivity.FormPageDisplayer;
     43 import com.android.tv.settings.connectivity.TimedMessageWizardFragment;
     44 import com.android.tv.settings.connectivity.WifiConfigHelper;
     45 import com.android.tv.settings.connectivity.WifiFormPageType;
     46 import com.android.tv.settings.connectivity.WifiMultiPagedFormActivity;
     47 import com.android.tv.settings.connectivity.WifiSecurity;
     48 import com.android.tv.settings.connectivity.WpsConnectionActivity;
     49 import com.android.tv.settings.connectivity.setup.SelectFromListWizardFragment.ListItem;
     50 import com.android.tv.settings.form.FormPage;
     51 import com.android.tv.settings.form.FormPageResultListener;
     52 import com.android.tv.settings.util.ThemeHelper;
     53 import com.android.tv.settings.util.TransitionUtils;
     54 
     55 import java.util.ArrayList;
     56 import java.util.Collections;
     57 import java.util.HashMap;
     58 import java.util.List;
     59 
     60 /**
     61  * Wi-Fi settings during initial setup for a large no-touch device
     62  */
     63 public class WifiSetupActivity extends WifiMultiPagedFormActivity
     64         implements ConnectToWifiFragment.Listener, TimedMessageWizardFragment.Listener {
     65 
     66     private static final String TAG = "WifiSetupActivity";
     67     private static final int NETWORK_REFRESH_BUFFER_DURATION = 5000;
     68 
     69     private static final String EXTRA_SHOW_SUMMARY = "extra_show_summary";
     70     private static final String EXTRA_SHOW_SKIP_NETWORK = "extra_show_skip_network";
     71     private static final String EXTRA_SHOW_WPS_AT_TOP = "extra_show_wps_at_top";
     72     // If you change this constant, make sure to change the constant in setup wizard
     73     private static final int RESULT_NETWORK_SKIPPED = 3;
     74 
     75     private boolean mShowSkipNetwork;
     76     private boolean mShowWpsAtTop;
     77     private AdvancedWifiOptionsFlow mAdvancedWifiOptionsFlow;
     78     private WifiTracker mWifiTracker;
     79     private WifiConfiguration mConfiguration;
     80     private String mConnectedNetwork;
     81     private WifiSecurity mWifiSecurity;
     82     private FormPageDisplayer.UserActivityListener mUserActivityListener;
     83     private FormPage mChooseNetworkPage;
     84     private FormPage mSsidPage;
     85     private FormPage mSecurityPage;
     86     private FormPage mPasswordPage;
     87     private SelectFromListWizardFragment mNetworkListFragment;
     88     private FormPage mConnectPage;
     89     private FormPage mSuccessPage;
     90     private long mNextNetworkRefreshTime;
     91 
     92     @Override
     93     protected void onCreate(Bundle savedInstanceState) {
     94         setTheme(ThemeHelper.getThemeResource(getIntent()));
     95 
     96         mConfiguration = new WifiConfiguration();
     97 
     98         WifiTracker.WifiListener wifiListener = new WifiTracker.WifiListener() {
     99             @Override
    100             public void onWifiStateChanged(int state) {}
    101 
    102             @Override
    103             public void onConnectedChanged() {}
    104 
    105             @Override
    106             public void onAccessPointsChanged() {
    107                 long currentTime = System.currentTimeMillis();
    108                 if (mNetworkListFragment != null && currentTime >= mNextNetworkRefreshTime) {
    109                     mNetworkListFragment.update(WifiFormPageType.CHOOSE_NETWORK.getChoices(
    110                             WifiSetupActivity.this, getNetworks()));
    111                     mNextNetworkRefreshTime = currentTime + NETWORK_REFRESH_BUFFER_DURATION;
    112                 }
    113             }
    114         };
    115         mWifiTracker = new WifiTracker(this, wifiListener, true, true);
    116         mNextNetworkRefreshTime = System.currentTimeMillis() + NETWORK_REFRESH_BUFFER_DURATION;
    117 
    118         mUserActivityListener = new FormPageDisplayer.UserActivityListener() {
    119             @Override
    120             public void onUserActivity() {
    121                 mNextNetworkRefreshTime =
    122                         System.currentTimeMillis() + NETWORK_REFRESH_BUFFER_DURATION;
    123             }
    124         };
    125 
    126         boolean showSummary = getIntent().getBooleanExtra(EXTRA_SHOW_SUMMARY, false);
    127         mShowSkipNetwork = getIntent().getBooleanExtra(EXTRA_SHOW_SKIP_NETWORK, false);
    128         mShowWpsAtTop = getIntent().getBooleanExtra(EXTRA_SHOW_WPS_AT_TOP, false);
    129 
    130         if (showSummary) {
    131             addSummaryPage();
    132         } else {
    133             addPage(WifiFormPageType.CHOOSE_NETWORK);
    134         }
    135 
    136         super.onCreate(savedInstanceState);
    137 
    138         // fade in
    139         ObjectAnimator animator = TransitionUtils.createActivityFadeInAnimator(getResources(),
    140                 true);
    141         animator.setTarget(getContentView());
    142         animator.start();
    143     }
    144 
    145     @Override
    146     public void onResume() {
    147         super.onResume();
    148         mWifiTracker.startTracking();
    149     }
    150 
    151     @Override
    152     public void onPause() {
    153         super.onPause();
    154         mWifiTracker.stopTracking();
    155     }
    156 
    157     @Override
    158     public void finish() {
    159         // fade out and really finish when we're done
    160         ObjectAnimator animator = TransitionUtils.createActivityFadeOutAnimator(getResources(),
    161                 true);
    162         animator.setTarget(getContentView());
    163         animator.addListener(new Animator.AnimatorListener() {
    164 
    165             @Override
    166             public void onAnimationStart(Animator animation) {
    167             }
    168 
    169             @Override
    170             public void onAnimationRepeat(Animator animation) {
    171             }
    172 
    173             @Override
    174             public void onAnimationEnd(Animator animation) {
    175                 doFinish();
    176             }
    177 
    178             @Override
    179             public void onAnimationCancel(Animator animation) {
    180             }
    181         });
    182         animator.start();
    183     }
    184 
    185     @Override
    186     public void onConnectToWifiCompleted(int reason) {
    187         Bundle result = new Bundle();
    188         result.putString(FormPage.DATA_KEY_SUMMARY_STRING, Integer.toString(reason));
    189         onBundlePageResult(mConnectPage, result);
    190     }
    191 
    192     @Override
    193     public void onTimedMessageCompleted() {
    194         Bundle result = new Bundle();
    195         result.putString(FormPage.DATA_KEY_SUMMARY_STRING, "");
    196         onBundlePageResult(mSuccessPage, result);
    197     }
    198 
    199     @Override
    200     public void addPage(WifiFormPageType formPageType) {
    201         for (int i = mFormPages.size() - 1; i >= 0; i--) {
    202             if (getFormPageType(mFormPages.get (i)) == formPageType) {
    203                 for (int j = mFormPages.size() - 1; j >= i; j--) {
    204                     mFormPages.remove(j);
    205                 }
    206                 break;
    207             }
    208         }
    209         addPage(formPageType.create());
    210     }
    211 
    212     @Override
    213     protected boolean onPageComplete(WifiFormPageType formPageType, FormPage formPage) {
    214 
    215         switch (formPageType) {
    216             case KNOWN_NETWORK:
    217                 if (choiceChosen(formPage, R.string.wifi_connect)) {
    218                     addStartPage();
    219                 } else if (choiceChosen(formPage, R.string.wifi_forget_network)) {
    220                     ((WifiManager) getSystemService(Context.WIFI_SERVICE)).forget(
    221                             mConfiguration.networkId, null);
    222                     addPage(WifiFormPageType.CHOOSE_NETWORK);
    223                 }
    224                 break;
    225             case CHOOSE_NETWORK:
    226                 if (choiceChosen(formPage, R.string.skip_network)) {
    227                     WifiConfigHelper.forgetWifiNetwork(this);
    228                     setResult(RESULT_NETWORK_SKIPPED);
    229                 } else {
    230                     mWifiTracker.pauseScanning();
    231                     mNetworkListFragment = null;
    232                     mChooseNetworkPage = formPage;
    233                     addPageBasedOnNetworkChoice(mChooseNetworkPage);
    234                 }
    235                 break;
    236             case ENTER_SSID:
    237                 mSsidPage = formPage;
    238                 String ssid = formPage.getDataSummary();
    239                 WifiConfigHelper.setConfigSsid(mConfiguration, ssid);
    240                 addPage(WifiFormPageType.CHOOSE_SECURITY);
    241                 break;
    242             case CHOOSE_SECURITY:
    243                 mSecurityPage = formPage;
    244                 if (choiceChosen(formPage, R.string.wifi_security_type_none)) {
    245                     mWifiSecurity = WifiSecurity.NONE;
    246                 } else if (choiceChosen(formPage, R.string.wifi_security_type_wep)) {
    247                     mWifiSecurity = WifiSecurity.WEP;
    248                 } else if (choiceChosen(formPage, R.string.wifi_security_type_wpa)) {
    249                     mWifiSecurity = WifiSecurity.PSK;
    250                 } else if (choiceChosen(formPage, R.string.wifi_security_type_eap)) {
    251                     mWifiSecurity = WifiSecurity.EAP;
    252                 }
    253                 WifiConfigHelper.setConfigKeyManagementBySecurity(mConfiguration, mWifiSecurity);
    254                 if (mWifiSecurity == WifiSecurity.NONE) {
    255                     optionsOrConnect();
    256                 } else {
    257                     addPage(WifiFormPageType.ENTER_PASSWORD);
    258                 }
    259                 break;
    260             case ENTER_PASSWORD:
    261                 mPasswordPage = formPage;
    262                 String password = formPage.getDataSummary();
    263                 setWifiConfigurationPassword(mConfiguration, mWifiSecurity, password);
    264                 optionsOrConnect();
    265                 break;
    266             case CONNECT:
    267                 switch (Integer.valueOf(formPage.getDataSummary())) {
    268                     case ConnectToWifiFragment.RESULT_REJECTED_BY_AP:
    269                         addPage(WifiFormPageType.CONNECT_REJECTED_BY_AP);
    270                         break;
    271                     case ConnectToWifiFragment.RESULT_UNKNOWN_ERROR:
    272                         addPage(WifiFormPageType.CONNECT_FAILED);
    273                         break;
    274                     case ConnectToWifiFragment.RESULT_TIMEOUT:
    275                         addPage(WifiFormPageType.CONNECT_TIMEOUT);
    276                         break;
    277                     case ConnectToWifiFragment.RESULT_BAD_AUTHENTICATION:
    278                         WifiConfigHelper.forgetConfiguration(this, mConfiguration);
    279                         addPage(WifiFormPageType.CONNECT_AUTHENTICATION_FAILURE);
    280                         break;
    281                     case ConnectToWifiFragment.RESULT_SUCCESS:
    282                         WifiConfigHelper.saveConfiguration(this, mConfiguration);
    283                         addPage(WifiFormPageType.SUCCESS);
    284                         break;
    285                     default:
    286                         break;
    287                 }
    288                 break;
    289             case CONNECT_TIMEOUT:
    290                 mAdvancedWifiOptionsFlow = new AdvancedWifiOptionsFlow(this, this, true, null);
    291                 // fall through
    292             case CONNECT_REJECTED_BY_AP:
    293                 if (choiceChosen(formPage, R.string.wifi_action_try_again)) {
    294                     optionsOrConnect();
    295                 } else {
    296                     mSsidPage = null;
    297                     mSecurityPage = null;
    298                     mPasswordPage = null;
    299                     addPage(WifiFormPageType.CHOOSE_NETWORK);
    300                 }
    301                 break;
    302             case CONNECT_FAILED:
    303                 // fall through
    304             case CONNECT_AUTHENTICATION_FAILURE:
    305                 if (choiceChosen(formPage, R.string.wifi_action_try_again)) {
    306                     addPageBasedOnNetworkChoice(mChooseNetworkPage);
    307                 } else {
    308                     mSsidPage = null;
    309                     mSecurityPage = null;
    310                     mPasswordPage = null;
    311                     addPage(WifiFormPageType.CHOOSE_NETWORK);
    312                 }
    313                 break;
    314             case SUMMARY_CONNECTED_WIFI:
    315                 if (choiceChosen(formPage, R.string.wifi_action_dont_change_network)) {
    316                     setResult(RESULT_OK);
    317                     finish();
    318                 } else if (choiceChosen(formPage, R.string.wifi_action_change_network)) {
    319                     addPage(WifiFormPageType.CHOOSE_NETWORK);
    320                 }
    321                 break;
    322             case SUMMARY_CONNECTED_NON_WIFI:
    323                 setResult(RESULT_OK);
    324                 finish();
    325                 break;
    326             case SUMMARY_NOT_CONNECTED:
    327                 addPage(WifiFormPageType.CHOOSE_NETWORK);
    328                 break;
    329             case SUCCESS:
    330                 setResult(RESULT_OK);
    331                 break;
    332             case WPS:
    333                 setResult(RESULT_OK);
    334                 break;
    335             default:
    336                 if (mAdvancedWifiOptionsFlow != null) {
    337                     switch (mAdvancedWifiOptionsFlow.handlePageComplete(formPageType, formPage)) {
    338                         case AdvancedWifiOptionsFlow.RESULT_ALL_PAGES_COMPLETE:
    339                             connect();
    340                             break;
    341                         case AdvancedWifiOptionsFlow.RESULT_UNKNOWN_PAGE:
    342                         case AdvancedWifiOptionsFlow.RESULT_PAGE_HANDLED:
    343                         default:
    344                             break;
    345                     }
    346                 }
    347                 break;
    348         }
    349         return true;
    350     }
    351 
    352     @Override
    353     protected void displayPage(FormPage formPage, FormPageResultListener listener,
    354             boolean forward) {
    355         WifiFormPageType formPageType = getFormPageType(formPage);
    356 
    357         if (formPageType == WifiFormPageType.CONNECT) {
    358             mConnectPage = formPage;
    359             Fragment fragment = ConnectToWifiFragment.newInstance(
    360                     getString(formPageType.getTitleResourceId(), mConfiguration.getPrintableSsid()),
    361                     true, mConfiguration);
    362             displayFragment(fragment, forward);
    363         } else if (formPageType == WifiFormPageType.SUCCESS) {
    364             mSuccessPage = formPage;
    365             Fragment fragment = TimedMessageWizardFragment.newInstance(
    366                     getString(formPageType.getTitleResourceId()));
    367             displayFragment(fragment, forward);
    368         } else if (formPageType == WifiFormPageType.WPS) {
    369             displayFragment(MessageWizardFragment.newInstance("", true), forward);
    370         } else {
    371             Fragment fragment = displayPage(formPageType, mConfiguration.getPrintableSsid(),
    372                     formPageType == WifiFormPageType.SUMMARY_CONNECTED_WIFI ? mConnectedNetwork
    373                             : null,
    374                     formPageType == WifiFormPageType.CHOOSE_NETWORK ? getNetworks() : null,
    375                     getLastPage(formPageType),
    376                     formPageType == WifiFormPageType.CHOOSE_NETWORK ? mUserActivityListener : null,
    377                     formPageType != WifiFormPageType.SUCCESS, formPage, listener, forward,
    378                             (mAdvancedWifiOptionsFlow != null) ? mAdvancedWifiOptionsFlow
    379                             .isEmptyTextAllowed(formPageType) : false);
    380             if (formPageType == WifiFormPageType.CHOOSE_NETWORK) {
    381                 mNetworkListFragment = (SelectFromListWizardFragment) fragment;
    382                 mWifiTracker.resumeScanning();
    383             }
    384         }
    385     }
    386 
    387     @Override
    388     protected void undisplayCurrentPage() {
    389         mWifiTracker.pauseScanning();
    390 
    391         FragmentManager fragMan = getFragmentManager();
    392         Fragment target = fragMan.findFragmentById(R.id.content);
    393         FragmentTransaction transaction = fragMan.beginTransaction();
    394         transaction.remove(target);
    395         transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_CLOSE);
    396         transaction.commit();
    397     }
    398 
    399     private void doFinish() {
    400         super.finish();
    401     }
    402 
    403     private void connect() {
    404         if (!WifiConfigHelper.isNetworkSaved(mConfiguration) &&
    405             mAdvancedWifiOptionsFlow != null) {
    406             mAdvancedWifiOptionsFlow.updateConfiguration(mConfiguration);
    407         }
    408         addPage(WifiFormPageType.CONNECT);
    409     }
    410 
    411     private void optionsOrConnect() {
    412         if (mAdvancedWifiOptionsFlow != null) {
    413             addPage(mAdvancedWifiOptionsFlow.getInitialPage());
    414         } else {
    415             connect();
    416         }
    417     }
    418 
    419     private FormPage getLastPage(WifiFormPageType formPageType) {
    420         switch (formPageType) {
    421             case CHOOSE_NETWORK:
    422                 return mChooseNetworkPage;
    423             case CHOOSE_SECURITY:
    424                 return mSecurityPage;
    425             case ENTER_PASSWORD:
    426                 return mPasswordPage;
    427             case ENTER_SSID:
    428                 return mSsidPage;
    429             default:
    430                 return (mAdvancedWifiOptionsFlow != null) ? mAdvancedWifiOptionsFlow
    431                         .getPreviousPage(formPageType)
    432                         : null;
    433         }
    434     }
    435 
    436     private ArrayList<ListItem> getNetworks() {
    437         ArrayList<SelectFromListWizardFragment.ListItem> listItems = new ArrayList<>();
    438         final List<ScanResult> results = mWifiTracker.getManager().getScanResults();
    439         final HashMap<Pair<String, WifiSecurity>, ScanResult> consolidatedScanResults =
    440                 new HashMap<>();
    441         for (ScanResult result : results) {
    442             if (TextUtils.isEmpty(result.SSID)) {
    443                 continue;
    444             }
    445 
    446             Pair<String, WifiSecurity> key =
    447                     new Pair<>(result.SSID, WifiSecurity.getSecurity(result));
    448             ScanResult existing = consolidatedScanResults.get(key);
    449             if (existing == null || existing.level < result.level) {
    450                 consolidatedScanResults.put(key, result);
    451             }
    452         }
    453         for (ScanResult result : consolidatedScanResults.values()) {
    454             listItems.add(new SelectFromListWizardFragment.ListItem(result));
    455         }
    456 
    457         int wpsPinnedPos = mShowWpsAtTop ? SelectFromListWizardFragment.PinnedListItem.FIRST
    458                                          : SelectFromListWizardFragment.PinnedListItem.LAST;
    459 
    460         SelectFromListWizardFragment.PinnedListItem wpsItem =
    461                 new SelectFromListWizardFragment.PinnedListItem(
    462                         getString(R.string.wps_network), R.drawable.setup_wps, wpsPinnedPos, 0);
    463 
    464         listItems.add(wpsItem);
    465 
    466         if (mShowSkipNetwork) {
    467             listItems.add(new SelectFromListWizardFragment.PinnedListItem(
    468                     getString(R.string.skip_network), R.drawable.ic_arrow_forward,
    469                     SelectFromListWizardFragment.PinnedListItem.LAST, 1));
    470         }
    471 
    472         return listItems;
    473     }
    474 
    475     private void addPageBasedOnNetworkChoice(FormPage chooseNetworkPage) {
    476         if (choiceChosen(chooseNetworkPage, R.string.other_network)) {
    477             mConfiguration.hiddenSSID = true;
    478             addPage(WifiFormPageType.ENTER_SSID);
    479         } else if (choiceChosen(chooseNetworkPage, R.string.wps_network)) {
    480             addPage(WifiFormPageType.WPS, new Intent(this, WpsConnectionActivity.class)
    481                     .putExtras(getIntent().getExtras()));
    482         } else {
    483             ScanResult scanResult = getListItem(chooseNetworkPage).getScanResult();
    484 
    485             // If we are entering password for an AP that is different from the previously saved AP,
    486             // clear out the saved password.
    487             if (mPasswordPage != null
    488                     && (mConfiguration == null
    489                                || !scanResult.SSID.equals(mConfiguration.getPrintableSsid()))) {
    490                 mPasswordPage.clearData();
    491             }
    492 
    493             mConfiguration = WifiConfigHelper.getConfiguration(this, scanResult.SSID,
    494                     WifiSecurity.getSecurity(scanResult));
    495             mWifiSecurity = WifiSecurity.getSecurity(scanResult);
    496 
    497             if (WifiConfigHelper.isNetworkSaved(mConfiguration)) {
    498                 addPage(WifiFormPageType.KNOWN_NETWORK);
    499             } else {
    500                 addStartPage();
    501             }
    502         }
    503     }
    504 
    505     private void addStartPage() {
    506         if ((mWifiSecurity == WifiSecurity.WEP && TextUtils.isEmpty(mConfiguration.wepKeys[0]))
    507                 || (!mWifiSecurity.isOpen() && TextUtils.isEmpty(mConfiguration.preSharedKey))) {
    508             addPage(WifiFormPageType.ENTER_PASSWORD);
    509         } else {
    510             connect();
    511         }
    512     }
    513 
    514     private void addSummaryPage() {
    515         ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(
    516                 Context.CONNECTIVITY_SERVICE);
    517         NetworkInfo currentConnection = connectivityManager.getActiveNetworkInfo();
    518         boolean isConnected = (currentConnection != null) && currentConnection.isConnected();
    519         if (isConnected) {
    520             if (currentConnection.getType() == ConnectivityManager.TYPE_WIFI) {
    521                 WifiInfo currentWifiConnection = mWifiTracker.getManager().getConnectionInfo();
    522                 mConnectedNetwork = WifiInfo.removeDoubleQuotes(
    523                         currentWifiConnection.getSSID());
    524                 if (mConnectedNetwork == null) {
    525                     mConnectedNetwork = getString(R.string.wifi_summary_unknown_network);
    526                 }
    527                 addPage(WifiFormPageType.SUMMARY_CONNECTED_WIFI);
    528             } else {
    529                 addPage(WifiFormPageType.SUMMARY_CONNECTED_NON_WIFI);
    530             }
    531         } else {
    532             addPage(WifiFormPageType.SUMMARY_NOT_CONNECTED);
    533         }
    534     }
    535 }
    536