blob: 72b5eeb18ccdd7d51b7bece0d567df67bc117bc2 [file] [log] [blame]
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.car.settings.wifi;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.Toast;
import androidx.annotation.Nullable;
import com.android.car.list.EditTextLineItem;
import com.android.car.list.PasswordLineItem;
import com.android.car.list.SpinnerLineItem;
import com.android.car.list.TypedPagedListAdapter;
import com.android.car.settings.R;
import com.android.car.settings.common.ListSettingsFragment;
import com.android.car.settings.common.Logger;
import com.android.settingslib.wifi.AccessPoint;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
/**
* Adds a wifi network, the network can be public or private. If ADD_NETWORK_MODE is not specified
* in the intent, then it needs to contain AccessPoint information, which is be use that to
* render UI, e.g. show SSID etc.
*/
public class AddWifiFragment extends ListSettingsFragment implements
AdapterView.OnItemSelectedListener {
public static final String EXTRA_AP_STATE = "extra_ap_state";
private static final Logger LOG = new Logger(AddWifiFragment.class);
private static final Pattern HEX_PATTERN = Pattern.compile("^[0-9A-F]+$");
private static final Pattern VALID_SSID_PATTERN =
Pattern.compile("^[A-Za-z]+[\\w\\-\\:\\.]*$");
@Nullable
private AccessPoint mAccessPoint;
@Nullable
private SpinnerLineItem<AccessPointSecurity> mSpinnerLineItem;
private WifiManager mWifiManager;
private Button mAddWifiButton;
private final WifiManager.ActionListener mConnectionListener =
new WifiManager.ActionListener() {
@Override
public void onSuccess() {
}
@Override
public void onFailure(int reason) {
Toast.makeText(getContext(),
R.string.wifi_failed_connect_message,
Toast.LENGTH_SHORT).show();
}
};
private EditTextLineItem mWifiNameInput;
private EditTextLineItem mWifiPasswordInput;
private int mSelectedPosition = AccessPointSecurity.SECURITY_NONE_POSITION;
public static AddWifiFragment getInstance(AccessPoint accessPoint) {
AddWifiFragment addWifiFragment = new AddWifiFragment();
Bundle bundle = ListSettingsFragment.getBundle();
bundle.putInt(EXTRA_TITLE_ID, R.string.wifi_setup_add_network);
bundle.putInt(EXTRA_ACTION_BAR_LAYOUT, R.layout.action_bar_with_button);
Bundle accessPointState = new Bundle();
if (accessPoint != null) {
accessPoint.saveWifiState(accessPointState);
bundle.putBundle(EXTRA_AP_STATE, accessPointState);
}
addWifiFragment.setArguments(bundle);
return addWifiFragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments().keySet().contains(EXTRA_AP_STATE)) {
mAccessPoint = new AccessPoint(getContext(), getArguments().getBundle(EXTRA_AP_STATE));
}
mWifiManager = getContext().getSystemService(WifiManager.class);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mAddWifiButton = getActivity().findViewById(R.id.action_button1);
mAddWifiButton.setText(R.string.wifi_setup_connect);
mAddWifiButton.setOnClickListener(v -> {
connectToAccessPoint();
getFragmentController().goBack();
});
mAddWifiButton.setEnabled(mAccessPoint != null);
}
@Override
public ArrayList<TypedPagedListAdapter.LineItem> getLineItems() {
ArrayList<TypedPagedListAdapter.LineItem> lineItems = new ArrayList<>();
if (mAccessPoint != null) {
mWifiNameInput = new EditTextLineItem(
getContext().getText(R.string.wifi_ssid), mAccessPoint.getSsid());
mWifiNameInput.setTextType(EditTextLineItem.TextType.NONE);
} else {
mWifiNameInput = new EditTextLineItem(
getContext().getText(R.string.wifi_ssid));
mWifiNameInput.setTextType(EditTextLineItem.TextType.TEXT);
mWifiNameInput.setTextChangeListener(s ->
mAddWifiButton.setEnabled(VALID_SSID_PATTERN.matcher(s).matches()));
}
lineItems.add(mWifiNameInput);
if (mAccessPoint == null) {
List<AccessPointSecurity> securities =
AccessPointSecurity.getSecurityTypes(getContext());
mSpinnerLineItem = new SpinnerLineItem<>(
getContext(),
this,
securities,
getContext().getText(R.string.wifi_security),
mSelectedPosition);
lineItems.add(mSpinnerLineItem);
}
if (mAccessPoint != null
|| mSelectedPosition != AccessPointSecurity.SECURITY_NONE_POSITION) {
mWifiPasswordInput = new PasswordLineItem(getContext().getText(R.string.wifi_password));
lineItems.add(mWifiPasswordInput);
}
return lineItems;
}
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
if (position == mSelectedPosition) {
return;
}
mSelectedPosition = position;
mPagedListAdapter.setList(getLineItems());
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
private void connectToAccessPoint() {
WifiConfiguration wifiConfig = new WifiConfiguration();
wifiConfig.SSID = String.format("\"%s\"", getSsId());
wifiConfig.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
wifiConfig.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
wifiConfig.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
wifiConfig.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
wifiConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
wifiConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);
int security;
if (mAccessPoint == null) {
security = mSpinnerLineItem.getItem(mSelectedPosition).getSecurityType();
wifiConfig.hiddenSSID = true;
} else {
security = mAccessPoint.getSecurity();
}
switch (security) {
case AccessPoint.SECURITY_NONE:
wifiConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
wifiConfig.allowedAuthAlgorithms.clear();
wifiConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
wifiConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
break;
case AccessPoint.SECURITY_WEP:
wifiConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
wifiConfig.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
wifiConfig.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);
String password = mWifiPasswordInput.getInput();
wifiConfig.wepKeys[0] = isHexString(password) ? password
: "\"" + password + "\"";
wifiConfig.wepTxKeyIndex = 0;
break;
case AccessPoint.SECURITY_PSK:
case AccessPoint.SECURITY_EAP:
wifiConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
wifiConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
wifiConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
wifiConfig.preSharedKey = String.format(
"\"%s\"", mWifiPasswordInput.getInput());
break;
default:
LOG.w("invalid security type: " + security);
break;
}
int netId = mWifiManager.addNetwork(wifiConfig);
if (netId == -1) {
Toast.makeText(getContext(),
R.string.wifi_failed_connect_message,
Toast.LENGTH_SHORT).show();
} else {
mWifiManager.enableNetwork(netId, true);
}
}
private boolean isHexString(String password) {
return HEX_PATTERN.matcher(password).matches();
}
// TODO: handle null case, show warning message etc.
private String getSsId() {
if (mAccessPoint == null) {
return mWifiNameInput.getInput();
} else {
return mAccessPoint.getSsid().toString();
}
}
}