blob: 1e6b8a0134280399d7cef898739a7e195b40e682 [file] [log] [blame]
/*
* Copyright (C) 2019 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.car.drivingstate.CarUxRestrictions;
import android.content.Context;
import android.content.SharedPreferences;
import android.net.wifi.SoftApConfiguration;
import android.text.InputType;
import android.text.TextUtils;
import android.util.Log;
import com.android.car.settings.R;
import com.android.car.settings.common.FragmentController;
import com.android.car.settings.common.ValidatedEditTextPreference;
import java.util.UUID;
/**
* Controls Wifi Hotspot password configuration.
*
* <p>Note: This controller uses {@link ValidatedEditTextPreference} as opposed to
* PasswordEditTextPreference because the input is not obscured by default, and the user is setting
* their own password, as opposed to entering password for authentication.
*/
public class WifiTetherPasswordPreferenceController extends
WifiTetherBasePreferenceController<ValidatedEditTextPreference> {
private static final String TAG = "CarWifiTetherApPwdPref";
protected static final String SHARED_PREFERENCE_PATH =
"com.android.car.settings.wifi.WifiTetherPreferenceController";
protected static final String KEY_SAVED_PASSWORD =
"com.android.car.settings.wifi.SAVED_PASSWORD";
private static final int SHARED_SECURITY_TYPE_UNSET = -1;
private static final int HOTSPOT_PASSWORD_MIN_LENGTH = 8;
private static final int HOTSPOT_PASSWORD_MAX_LENGTH = 63;
private static final ValidatedEditTextPreference.Validator PASSWORD_VALIDATOR =
value -> value.length() >= HOTSPOT_PASSWORD_MIN_LENGTH
&& value.length() <= HOTSPOT_PASSWORD_MAX_LENGTH;
private final SharedPreferences mSharedPreferences =
getContext().getSharedPreferences(SHARED_PREFERENCE_PATH, Context.MODE_PRIVATE);
private String mPassword;
private int mSecurityType;
public WifiTetherPasswordPreferenceController(Context context, String preferenceKey,
FragmentController fragmentController, CarUxRestrictions uxRestrictions) {
super(context, preferenceKey, fragmentController, uxRestrictions);
}
@Override
protected Class<ValidatedEditTextPreference> getPreferenceType() {
return ValidatedEditTextPreference.class;
}
@Override
protected void onCreateInternal() {
super.onCreateInternal();
getPreference().setValidator(PASSWORD_VALIDATOR);
mSecurityType = getCarSoftApConfig().getSecurityType();
syncPassword();
}
@Override
protected void onStartInternal() {
int newSecurityType = mSharedPreferences.getInt(
WifiTetherSecurityPreferenceController.KEY_SECURITY_TYPE,
/* defaultValue= */ SHARED_SECURITY_TYPE_UNSET);
if (mSecurityType != newSecurityType && newSecurityType != SHARED_SECURITY_TYPE_UNSET) {
// Security type has been changed - update ap configuration
mSecurityType = newSecurityType;
syncPassword();
updateApSecurity(mPassword);
}
}
@Override
protected boolean handlePreferenceChanged(ValidatedEditTextPreference preference,
Object newValue) {
if (!newValue.toString().equals(mPassword)) {
mPassword = newValue.toString();
updateApSecurity(mPassword);
refreshUi();
}
return true;
}
@Override
protected void updateState(ValidatedEditTextPreference preference) {
super.updateState(preference);
updatePasswordDisplay();
if (TextUtils.isEmpty(mPassword)) {
preference.setSummaryInputType(InputType.TYPE_CLASS_TEXT);
} else {
preference.setSummaryInputType(
InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
}
}
@Override
protected String getSummary() {
return mPassword;
}
@Override
protected String getDefaultSummary() {
return getContext().getString(R.string.default_password_summary);
}
private void syncPassword() {
mPassword = getSyncedPassword();
refreshUi();
}
private String getSyncedPassword() {
if (mSecurityType == SoftApConfiguration.SECURITY_TYPE_OPEN) {
return null;
}
String passphrase = getCarSoftApConfig().getPassphrase();
if (!TextUtils.isEmpty(passphrase)) {
return passphrase;
}
if (!TextUtils.isEmpty(
mSharedPreferences.getString(KEY_SAVED_PASSWORD, /* defaultValue= */ null))) {
return mSharedPreferences.getString(KEY_SAVED_PASSWORD, /* defaultValue= */ null);
}
return generateRandomPassword();
}
private static String generateRandomPassword() {
String randomUUID = UUID.randomUUID().toString();
// First 12 chars from xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
return randomUUID.substring(0, 8) + randomUUID.substring(9, 13);
}
/**
* If the password and/or security type has changed, update the ap configuration
*/
private void updateApSecurity(String password) {
String passwordOrNullIfOpen;
if (mSecurityType == SoftApConfiguration.SECURITY_TYPE_OPEN) {
passwordOrNullIfOpen = null;
Log.w(TAG, "Setting password on an open network!");
} else {
passwordOrNullIfOpen = password;
}
SoftApConfiguration config = new SoftApConfiguration.Builder(getCarSoftApConfig())
.setPassphrase(passwordOrNullIfOpen, mSecurityType)
.build();
setCarSoftApConfig(config);
if (!TextUtils.isEmpty(password)) {
mSharedPreferences.edit().putString(KEY_SAVED_PASSWORD, password).commit();
}
}
private void updatePasswordDisplay() {
getPreference().setText(mPassword);
getPreference().setVisible(mSecurityType != SoftApConfiguration.SECURITY_TYPE_OPEN);
getPreference().setSummary(getSummary());
}
}