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