• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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 
17 package com.android.car.settings.wifi;
18 
19 import android.car.drivingstate.CarUxRestrictions;
20 import android.content.Context;
21 import android.content.SharedPreferences;
22 import android.net.wifi.SoftApConfiguration;
23 import android.text.InputType;
24 import android.text.TextUtils;
25 import android.util.Log;
26 
27 import com.android.car.settings.R;
28 import com.android.car.settings.common.FragmentController;
29 import com.android.car.settings.common.ValidatedEditTextPreference;
30 
31 import java.util.UUID;
32 
33 /**
34  * Controls Wifi Hotspot password configuration.
35  *
36  * <p>Note: This controller uses {@link ValidatedEditTextPreference} as opposed to
37  * PasswordEditTextPreference because the input is not obscured by default, and the user is setting
38  * their own password, as opposed to entering password for authentication.
39  */
40 public class WifiTetherPasswordPreferenceController extends
41         WifiTetherBasePreferenceController<ValidatedEditTextPreference> {
42     private static final String TAG = "CarWifiTetherApPwdPref";
43 
44     protected static final String SHARED_PREFERENCE_PATH =
45             "com.android.car.settings.wifi.WifiTetherPreferenceController";
46     protected static final String KEY_SAVED_PASSWORD =
47             "com.android.car.settings.wifi.SAVED_PASSWORD";
48 
49     private static final int SHARED_SECURITY_TYPE_UNSET = -1;
50 
51     private static final int HOTSPOT_PASSWORD_MIN_LENGTH = 8;
52     private static final int HOTSPOT_PASSWORD_MAX_LENGTH = 63;
53     private static final ValidatedEditTextPreference.Validator PASSWORD_VALIDATOR =
54             value -> value.length() >= HOTSPOT_PASSWORD_MIN_LENGTH
55                     && value.length() <= HOTSPOT_PASSWORD_MAX_LENGTH;
56 
57     private final SharedPreferences mSharedPreferences =
58             getContext().getSharedPreferences(SHARED_PREFERENCE_PATH, Context.MODE_PRIVATE);
59 
60     private String mPassword;
61     private int mSecurityType;
62 
WifiTetherPasswordPreferenceController(Context context, String preferenceKey, FragmentController fragmentController, CarUxRestrictions uxRestrictions)63     public WifiTetherPasswordPreferenceController(Context context, String preferenceKey,
64             FragmentController fragmentController, CarUxRestrictions uxRestrictions) {
65         super(context, preferenceKey, fragmentController, uxRestrictions);
66     }
67 
68     @Override
getPreferenceType()69     protected Class<ValidatedEditTextPreference> getPreferenceType() {
70         return ValidatedEditTextPreference.class;
71     }
72 
73     @Override
onCreateInternal()74     protected void onCreateInternal() {
75         super.onCreateInternal();
76         getPreference().setValidator(PASSWORD_VALIDATOR);
77         mSecurityType = getCarSoftApConfig().getSecurityType();
78         syncPassword();
79     }
80 
81     @SuppressWarnings("MissingSuperCall") // TODO: Fix me
82     @Override
onStartInternal()83     protected void onStartInternal() {
84         int newSecurityType = mSharedPreferences.getInt(
85                 WifiTetherSecurityPreferenceController.KEY_SECURITY_TYPE,
86                 /* defaultValue= */ SHARED_SECURITY_TYPE_UNSET);
87         if (mSecurityType != newSecurityType && newSecurityType != SHARED_SECURITY_TYPE_UNSET) {
88             // Security type has been changed - update ap configuration
89             mSecurityType = newSecurityType;
90             syncPassword();
91             updateApSecurity(mPassword);
92         }
93     }
94 
95     @Override
handlePreferenceChanged(ValidatedEditTextPreference preference, Object newValue)96     protected boolean handlePreferenceChanged(ValidatedEditTextPreference preference,
97             Object newValue) {
98         if (!newValue.toString().equals(mPassword)) {
99             mPassword = newValue.toString();
100             updateApSecurity(mPassword);
101             refreshUi();
102         }
103         return true;
104     }
105 
106     @Override
updateState(ValidatedEditTextPreference preference)107     protected void updateState(ValidatedEditTextPreference preference) {
108         super.updateState(preference);
109         updatePasswordDisplay();
110         if (TextUtils.isEmpty(mPassword)) {
111             preference.setSummaryInputType(InputType.TYPE_CLASS_TEXT);
112         } else {
113             preference.setSummaryInputType(
114                     InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
115         }
116     }
117 
118     @Override
getSummary()119     protected String getSummary() {
120         return mPassword;
121     }
122 
123     @Override
getDefaultSummary()124     protected String getDefaultSummary() {
125         return getContext().getString(R.string.default_password_summary);
126     }
127 
syncPassword()128     private void syncPassword() {
129         mPassword = getSyncedPassword();
130         refreshUi();
131     }
132 
getSyncedPassword()133     private String getSyncedPassword() {
134         if (mSecurityType == SoftApConfiguration.SECURITY_TYPE_OPEN) {
135             return null;
136         }
137 
138         String passphrase = getCarSoftApConfig().getPassphrase();
139         if (!TextUtils.isEmpty(passphrase)) {
140             return passphrase;
141         }
142 
143         if (!TextUtils.isEmpty(
144                 mSharedPreferences.getString(KEY_SAVED_PASSWORD, /* defaultValue= */ null))) {
145             return mSharedPreferences.getString(KEY_SAVED_PASSWORD, /* defaultValue= */ null);
146         }
147 
148         return generateRandomPassword();
149     }
150 
generateRandomPassword()151     private static String generateRandomPassword() {
152         String randomUUID = UUID.randomUUID().toString();
153         // First 12 chars from xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
154         return randomUUID.substring(0, 8) + randomUUID.substring(9, 13);
155     }
156 
157     /**
158      * If the password and/or security type has changed, update the ap configuration
159      */
updateApSecurity(String password)160     private void updateApSecurity(String password) {
161         String passwordOrNullIfOpen;
162         if (mSecurityType == SoftApConfiguration.SECURITY_TYPE_OPEN) {
163             passwordOrNullIfOpen = null;
164             Log.w(TAG, "Setting password on an open network!");
165         } else {
166             passwordOrNullIfOpen = password;
167         }
168         SoftApConfiguration config = new SoftApConfiguration.Builder(getCarSoftApConfig())
169                 .setPassphrase(passwordOrNullIfOpen, mSecurityType)
170                 .build();
171         setCarSoftApConfig(config);
172 
173         if (!TextUtils.isEmpty(password)) {
174             mSharedPreferences.edit().putString(KEY_SAVED_PASSWORD, password).commit();
175         }
176     }
177 
updatePasswordDisplay()178     private void updatePasswordDisplay() {
179         getPreference().setText(mPassword);
180         getPreference().setVisible(mSecurityType != SoftApConfiguration.SECURITY_TYPE_OPEN);
181         getPreference().setSummary(getSummary());
182     }
183 
184 }
185