Home | History | Annotate | Download | only in wifi
      1 /*
      2  * Copyright (C) 2017 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 package com.android.car.settings.wifi;
     17 
     18 import android.net.wifi.WifiConfiguration;
     19 import android.net.wifi.WifiManager;
     20 import android.os.Bundle;
     21 import android.support.annotation.Nullable;
     22 import android.util.Log;
     23 import android.view.View;
     24 import android.widget.AdapterView;
     25 import android.widget.TextView;
     26 import android.widget.Toast;
     27 
     28 import com.android.car.settings.R;
     29 import com.android.car.settings.common.EditTextLineItem;
     30 import com.android.car.settings.common.ListSettingsFragment;
     31 import com.android.car.settings.common.PasswordLineItem;
     32 import com.android.car.settings.common.SpinnerLineItem;
     33 import com.android.car.settings.common.TypedPagedListAdapter;
     34 import com.android.settingslib.wifi.AccessPoint;
     35 
     36 import java.util.ArrayList;
     37 import java.util.List;
     38 import java.util.regex.Pattern;
     39 
     40 /**
     41  * Adds a wifi network, the network can be public or private. If ADD_NETWORK_MODE is not specified
     42  * in the intent, then it needs to contain AccessPoint information, which is be use that to
     43  * render UI, e.g. show SSID etc.
     44  */
     45 public class AddWifiFragment extends ListSettingsFragment implements
     46         AdapterView.OnItemSelectedListener{
     47     public static final String EXTRA_AP_STATE = "extra_ap_state";
     48 
     49     private static final String TAG = "AddWifiFragment";
     50     private static final Pattern HEX_PATTERN = Pattern.compile("^[0-9A-F]+$");
     51     private static final Pattern VALID_SSID_PATTERN =
     52             Pattern.compile("^[A-Za-z]+[\\w\\-\\:\\.]*$");
     53     @Nullable private AccessPoint mAccessPoint;
     54     @Nullable private SpinnerLineItem<AccessPointSecurity> mSpinnerLineItem;
     55     private WifiManager mWifiManager;
     56     private TextView mAddWifiButton;
     57     private final WifiManager.ActionListener mConnectionListener =
     58             new WifiManager.ActionListener() {
     59         @Override
     60         public void onSuccess() {
     61         }
     62 
     63         @Override
     64         public void onFailure(int reason) {
     65             Toast.makeText(getContext(),
     66                     R.string.wifi_failed_connect_message,
     67                     Toast.LENGTH_SHORT).show();
     68         }
     69     };
     70     private EditTextLineItem mWifiNameInput;
     71     private EditTextLineItem mWifiPasswordInput;
     72 
     73     private int mSelectedPosition = AccessPointSecurity.SECURITY_NONE_POSITION;
     74 
     75     public static AddWifiFragment getInstance(AccessPoint accessPoint) {
     76         AddWifiFragment addWifiFragment = new AddWifiFragment();
     77         Bundle bundle = ListSettingsFragment.getBundle();
     78         bundle.putInt(EXTRA_TITLE_ID, R.string.wifi_setup_add_network);
     79         bundle.putInt(EXTRA_ACTION_BAR_LAYOUT, R.layout.action_bar_with_button);
     80         Bundle accessPointState = new Bundle();
     81         if (accessPoint != null) {
     82             accessPoint.saveWifiState(accessPointState);
     83             bundle.putBundle(EXTRA_AP_STATE, accessPointState);
     84         }
     85         addWifiFragment.setArguments(bundle);
     86         return addWifiFragment;
     87     }
     88 
     89     @Override
     90     public void onCreate(Bundle savedInstanceState) {
     91         super.onCreate(savedInstanceState);
     92         if (getArguments().keySet().contains(EXTRA_AP_STATE)) {
     93             mAccessPoint = new AccessPoint(getContext(), getArguments().getBundle(EXTRA_AP_STATE));
     94         }
     95         mWifiManager = getContext().getSystemService(WifiManager.class);
     96     }
     97 
     98     @Override
     99     public void onActivityCreated(Bundle savedInstanceState) {
    100         super.onActivityCreated(savedInstanceState);
    101 
    102         mAddWifiButton = getActivity().findViewById(R.id.action_button1);
    103         mAddWifiButton.setText(R.string.wifi_setup_connect);
    104         mAddWifiButton.setOnClickListener(v -> {
    105             connectToAccessPoint();
    106             mFragmentController.goBack();
    107         });
    108         mAddWifiButton.setEnabled(mAccessPoint != null) ;
    109     }
    110 
    111     @Override
    112     public ArrayList<TypedPagedListAdapter.LineItem> getLineItems() {
    113         ArrayList<TypedPagedListAdapter.LineItem> lineItems = new ArrayList<>();
    114         if (mAccessPoint != null) {
    115             mWifiNameInput = new EditTextLineItem(
    116                     getContext().getText(R.string.wifi_ssid), mAccessPoint.getSsid());
    117             mWifiNameInput.setTextType(EditTextLineItem.TextType.NONE);
    118         } else {
    119             mWifiNameInput = new EditTextLineItem(
    120                     getContext().getText(R.string.wifi_ssid));
    121             mWifiNameInput.setTextType(EditTextLineItem.TextType.TEXT);
    122             mWifiNameInput.setTextChangeListener(s ->
    123                     mAddWifiButton.setEnabled(VALID_SSID_PATTERN.matcher(s).matches()));
    124         }
    125         lineItems.add(mWifiNameInput);
    126 
    127         if (mAccessPoint == null) {
    128             List<AccessPointSecurity> securities =
    129                     AccessPointSecurity.getSecurityTypes(getContext());
    130             mSpinnerLineItem = new SpinnerLineItem<>(
    131                     getContext(),
    132                     this,
    133                     securities,
    134                     getContext().getText(R.string.wifi_security),
    135                     mSelectedPosition);
    136             lineItems.add(mSpinnerLineItem);
    137         }
    138 
    139         if (mAccessPoint!= null
    140                 || mSelectedPosition != AccessPointSecurity.SECURITY_NONE_POSITION) {
    141             mWifiPasswordInput = new PasswordLineItem(getContext().getText(R.string.wifi_password));
    142             lineItems.add(mWifiPasswordInput);
    143         }
    144         return lineItems;
    145     }
    146 
    147     @Override
    148     public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
    149         if (position == mSelectedPosition) {
    150             return;
    151         }
    152         mSelectedPosition = position;
    153         mPagedListAdapter.updateList(getLineItems());
    154     }
    155 
    156     @Override
    157     public void onNothingSelected(AdapterView<?> parent) {
    158     }
    159 
    160     private void connectToAccessPoint() {
    161         WifiConfiguration wifiConfig = new WifiConfiguration();
    162         wifiConfig.SSID = String.format("\"%s\"", getSsId());
    163         wifiConfig.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
    164         wifiConfig.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
    165         wifiConfig.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
    166         wifiConfig.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
    167         wifiConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
    168         wifiConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);
    169         int security;
    170         if (mAccessPoint == null) {
    171             security = mSpinnerLineItem.getItem(mSelectedPosition).getSecurityType();
    172             wifiConfig.hiddenSSID = true;
    173         } else {
    174             security = mAccessPoint.getSecurity();
    175         }
    176         switch (security) {
    177             case AccessPoint.SECURITY_NONE:
    178                 wifiConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
    179                 wifiConfig.allowedAuthAlgorithms.clear();
    180                 wifiConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
    181                 wifiConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
    182                 break;
    183             case AccessPoint.SECURITY_WEP:
    184                 wifiConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
    185                 wifiConfig.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
    186                 wifiConfig.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);
    187                 String password = mWifiPasswordInput.getInput();
    188                 wifiConfig.wepKeys[0] = isHexString(password) ? password
    189                         : "\"" + password + "\"";
    190                 wifiConfig.wepTxKeyIndex = 0;
    191                 break;
    192             case AccessPoint.SECURITY_PSK:
    193             case AccessPoint.SECURITY_EAP:
    194                 wifiConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
    195                 wifiConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
    196                 wifiConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
    197                 wifiConfig.preSharedKey = String.format(
    198                         "\"%s\"", mWifiPasswordInput.getInput());
    199                 break;
    200             default:
    201                 Log.w(TAG, "invalid security type: " + security);
    202                 break;
    203         }
    204         int netId = mWifiManager.addNetwork(wifiConfig);
    205         if (netId == -1) {
    206             Toast.makeText(getContext(),
    207                     R.string.wifi_failed_connect_message,
    208                     Toast.LENGTH_SHORT).show();
    209         } else {
    210             mWifiManager.enableNetwork(netId, true);
    211         }
    212     }
    213 
    214     private boolean isHexString(String password) {
    215         return HEX_PATTERN.matcher(password).matches();
    216     }
    217 
    218     // TODO: handle null case, show warning message etc.
    219     private String getSsId() {
    220         if (mAccessPoint == null) {
    221             return mWifiNameInput.getInput();
    222         } else {
    223             return mAccessPoint.getSsid().toString();
    224         }
    225     }
    226 }
    227