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.view.View;
     23 import android.widget.AdapterView;
     24 import android.widget.Button;
     25 import android.widget.Toast;
     26 
     27 import com.android.car.list.EditTextLineItem;
     28 import com.android.car.list.PasswordLineItem;
     29 import com.android.car.list.SpinnerLineItem;
     30 import com.android.car.list.TypedPagedListAdapter;
     31 import com.android.car.settings.R;
     32 import com.android.car.settings.common.ListSettingsFragment;
     33 import com.android.car.settings.common.Logger;
     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 Logger LOG = new Logger(AddWifiFragment.class);
     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
     54     private AccessPoint mAccessPoint;
     55     @Nullable
     56     private SpinnerLineItem<AccessPointSecurity> mSpinnerLineItem;
     57     private WifiManager mWifiManager;
     58     private Button mAddWifiButton;
     59     private final WifiManager.ActionListener mConnectionListener =
     60             new WifiManager.ActionListener() {
     61                 @Override
     62                 public void onSuccess() {
     63                 }
     64 
     65                 @Override
     66                 public void onFailure(int reason) {
     67                     Toast.makeText(getContext(),
     68                             R.string.wifi_failed_connect_message,
     69                             Toast.LENGTH_SHORT).show();
     70                 }
     71             };
     72     private EditTextLineItem mWifiNameInput;
     73     private EditTextLineItem mWifiPasswordInput;
     74 
     75     private int mSelectedPosition = AccessPointSecurity.SECURITY_NONE_POSITION;
     76 
     77     public static AddWifiFragment getInstance(AccessPoint accessPoint) {
     78         AddWifiFragment addWifiFragment = new AddWifiFragment();
     79         Bundle bundle = ListSettingsFragment.getBundle();
     80         bundle.putInt(EXTRA_TITLE_ID, R.string.wifi_setup_add_network);
     81         bundle.putInt(EXTRA_ACTION_BAR_LAYOUT, R.layout.action_bar_with_button);
     82         Bundle accessPointState = new Bundle();
     83         if (accessPoint != null) {
     84             accessPoint.saveWifiState(accessPointState);
     85             bundle.putBundle(EXTRA_AP_STATE, accessPointState);
     86         }
     87         addWifiFragment.setArguments(bundle);
     88         return addWifiFragment;
     89     }
     90 
     91     @Override
     92     public void onCreate(Bundle savedInstanceState) {
     93         super.onCreate(savedInstanceState);
     94         if (getArguments().keySet().contains(EXTRA_AP_STATE)) {
     95             mAccessPoint = new AccessPoint(getContext(), getArguments().getBundle(EXTRA_AP_STATE));
     96         }
     97         mWifiManager = getContext().getSystemService(WifiManager.class);
     98     }
     99 
    100     @Override
    101     public void onActivityCreated(Bundle savedInstanceState) {
    102         super.onActivityCreated(savedInstanceState);
    103 
    104         mAddWifiButton = getActivity().findViewById(R.id.action_button1);
    105         mAddWifiButton.setText(R.string.wifi_setup_connect);
    106         mAddWifiButton.setOnClickListener(v -> {
    107             connectToAccessPoint();
    108             getFragmentController().goBack();
    109         });
    110         mAddWifiButton.setEnabled(mAccessPoint != null);
    111     }
    112 
    113     @Override
    114     public ArrayList<TypedPagedListAdapter.LineItem> getLineItems() {
    115         ArrayList<TypedPagedListAdapter.LineItem> lineItems = new ArrayList<>();
    116         if (mAccessPoint != null) {
    117             mWifiNameInput = new EditTextLineItem(
    118                     getContext().getText(R.string.wifi_ssid), mAccessPoint.getSsid());
    119             mWifiNameInput.setTextType(EditTextLineItem.TextType.NONE);
    120         } else {
    121             mWifiNameInput = new EditTextLineItem(
    122                     getContext().getText(R.string.wifi_ssid));
    123             mWifiNameInput.setTextType(EditTextLineItem.TextType.TEXT);
    124             mWifiNameInput.setTextChangeListener(s ->
    125                     mAddWifiButton.setEnabled(VALID_SSID_PATTERN.matcher(s).matches()));
    126         }
    127         lineItems.add(mWifiNameInput);
    128 
    129         if (mAccessPoint == null) {
    130             List<AccessPointSecurity> securities =
    131                     AccessPointSecurity.getSecurityTypes(getContext());
    132             mSpinnerLineItem = new SpinnerLineItem<>(
    133                     getContext(),
    134                     this,
    135                     securities,
    136                     getContext().getText(R.string.wifi_security),
    137                     mSelectedPosition);
    138             lineItems.add(mSpinnerLineItem);
    139         }
    140 
    141         if (mAccessPoint != null
    142                 || mSelectedPosition != AccessPointSecurity.SECURITY_NONE_POSITION) {
    143             mWifiPasswordInput = new PasswordLineItem(getContext().getText(R.string.wifi_password));
    144             lineItems.add(mWifiPasswordInput);
    145         }
    146         return lineItems;
    147     }
    148 
    149     @Override
    150     public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
    151         if (position == mSelectedPosition) {
    152             return;
    153         }
    154         mSelectedPosition = position;
    155         mPagedListAdapter.setList(getLineItems());
    156     }
    157 
    158     @Override
    159     public void onNothingSelected(AdapterView<?> parent) {
    160     }
    161 
    162     private void connectToAccessPoint() {
    163         WifiConfiguration wifiConfig = new WifiConfiguration();
    164         wifiConfig.SSID = String.format("\"%s\"", getSsId());
    165         wifiConfig.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
    166         wifiConfig.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
    167         wifiConfig.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
    168         wifiConfig.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
    169         wifiConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
    170         wifiConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);
    171         int security;
    172         if (mAccessPoint == null) {
    173             security = mSpinnerLineItem.getItem(mSelectedPosition).getSecurityType();
    174             wifiConfig.hiddenSSID = true;
    175         } else {
    176             security = mAccessPoint.getSecurity();
    177         }
    178         switch (security) {
    179             case AccessPoint.SECURITY_NONE:
    180                 wifiConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
    181                 wifiConfig.allowedAuthAlgorithms.clear();
    182                 wifiConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
    183                 wifiConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
    184                 break;
    185             case AccessPoint.SECURITY_WEP:
    186                 wifiConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
    187                 wifiConfig.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
    188                 wifiConfig.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);
    189                 String password = mWifiPasswordInput.getInput();
    190                 wifiConfig.wepKeys[0] = isHexString(password) ? password
    191                         : "\"" + password + "\"";
    192                 wifiConfig.wepTxKeyIndex = 0;
    193                 break;
    194             case AccessPoint.SECURITY_PSK:
    195             case AccessPoint.SECURITY_EAP:
    196                 wifiConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
    197                 wifiConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
    198                 wifiConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
    199                 wifiConfig.preSharedKey = String.format(
    200                         "\"%s\"", mWifiPasswordInput.getInput());
    201                 break;
    202             default:
    203                 LOG.w("invalid security type: " + security);
    204                 break;
    205         }
    206         int netId = mWifiManager.addNetwork(wifiConfig);
    207         if (netId == -1) {
    208             Toast.makeText(getContext(),
    209                     R.string.wifi_failed_connect_message,
    210                     Toast.LENGTH_SHORT).show();
    211         } else {
    212             mWifiManager.enableNetwork(netId, true);
    213         }
    214     }
    215 
    216     private boolean isHexString(String password) {
    217         return HEX_PATTERN.matcher(password).matches();
    218     }
    219 
    220     // TODO: handle null case, show warning message etc.
    221     private String getSsId() {
    222         if (mAccessPoint == null) {
    223             return mWifiNameInput.getInput();
    224         } else {
    225             return mAccessPoint.getSsid().toString();
    226         }
    227     }
    228 }
    229