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