• 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     @Override
onStartInternal()82     protected void onStartInternal() {
83         int newSecurityType = mSharedPreferences.getInt(
84                 WifiTetherSecurityPreferenceController.KEY_SECURITY_TYPE,
85                 /* defaultValue= */ SHARED_SECURITY_TYPE_UNSET);
86         if (mSecurityType != newSecurityType && newSecurityType != SHARED_SECURITY_TYPE_UNSET) {
87             // Security type has been changed - update ap configuration
88             mSecurityType = newSecurityType;
89             syncPassword();
90             updateApSecurity(mPassword);
91         }
92     }
93 
94     @Override
handlePreferenceChanged(ValidatedEditTextPreference preference, Object newValue)95     protected boolean handlePreferenceChanged(ValidatedEditTextPreference preference,
96             Object newValue) {
97         if (!newValue.toString().equals(mPassword)) {
98             mPassword = newValue.toString();
99             updateApSecurity(mPassword);
100             refreshUi();
101         }
102         return true;
103     }
104 
105     @Override
updateState(ValidatedEditTextPreference preference)106     protected void updateState(ValidatedEditTextPreference preference) {
107         super.updateState(preference);
108         updatePasswordDisplay();
109         if (TextUtils.isEmpty(mPassword)) {
110             preference.setSummaryInputType(InputType.TYPE_CLASS_TEXT);
111         } else {
112             preference.setSummaryInputType(
113                     InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
114         }
115     }
116 
117     @Override
getSummary()118     protected String getSummary() {
119         return mPassword;
120     }
121 
122     @Override
getDefaultSummary()123     protected String getDefaultSummary() {
124         return getContext().getString(R.string.default_password_summary);
125     }
126 
syncPassword()127     private void syncPassword() {
128         mPassword = getSyncedPassword();
129         refreshUi();
130     }
131 
getSyncedPassword()132     private String getSyncedPassword() {
133         if (mSecurityType == SoftApConfiguration.SECURITY_TYPE_OPEN) {
134             return null;
135         }
136 
137         String passphrase = getCarSoftApConfig().getPassphrase();
138         if (!TextUtils.isEmpty(passphrase)) {
139             return passphrase;
140         }
141 
142         if (!TextUtils.isEmpty(
143                 mSharedPreferences.getString(KEY_SAVED_PASSWORD, /* defaultValue= */ null))) {
144             return mSharedPreferences.getString(KEY_SAVED_PASSWORD, /* defaultValue= */ null);
145         }
146 
147         return generateRandomPassword();
148     }
149 
generateRandomPassword()150     private static String generateRandomPassword() {
151         String randomUUID = UUID.randomUUID().toString();
152         // First 12 chars from xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
153         return randomUUID.substring(0, 8) + randomUUID.substring(9, 13);
154     }
155 
156     /**
157      * If the password and/or security type has changed, update the ap configuration
158      */
updateApSecurity(String password)159     private void updateApSecurity(String password) {
160         String passwordOrNullIfOpen;
161         if (mSecurityType == SoftApConfiguration.SECURITY_TYPE_OPEN) {
162             passwordOrNullIfOpen = null;
163             Log.w(TAG, "Setting password on an open network!");
164         } else {
165             passwordOrNullIfOpen = password;
166         }
167         SoftApConfiguration config = new SoftApConfiguration.Builder(getCarSoftApConfig())
168                 .setPassphrase(passwordOrNullIfOpen, mSecurityType)
169                 .build();
170         setCarSoftApConfig(config);
171 
172         if (!TextUtils.isEmpty(password)) {
173             mSharedPreferences.edit().putString(KEY_SAVED_PASSWORD, password).commit();
174         }
175     }
176 
updatePasswordDisplay()177     private void updatePasswordDisplay() {
178         getPreference().setText(mPassword);
179         getPreference().setVisible(mSecurityType != SoftApConfiguration.SECURITY_TYPE_OPEN);
180         getPreference().setSummary(getSummary());
181     }
182 
183 }
184