1 /*
2  * Copyright (C) 2017 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.settings.wifi.tether;
18 
19 import static com.android.settings.AllInOneTetherSettings.DEDUP_POSTFIX;
20 
21 import android.app.settings.SettingsEnums;
22 import android.content.Context;
23 import android.net.wifi.SoftApConfiguration;
24 import android.text.TextUtils;
25 import android.util.FeatureFlagUtils;
26 
27 import androidx.annotation.VisibleForTesting;
28 import androidx.preference.EditTextPreference;
29 import androidx.preference.Preference;
30 
31 import com.android.settings.R;
32 import com.android.settings.core.FeatureFlags;
33 import com.android.settings.overlay.FeatureFactory;
34 import com.android.settings.widget.ValidatedEditTextPreference;
35 import com.android.settings.wifi.WifiUtils;
36 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
37 
38 import java.util.UUID;
39 
40 /**
41  * Controller for logic pertaining to the password of Wi-Fi tethering.
42  */
43 public class WifiTetherPasswordPreferenceController extends WifiTetherBasePreferenceController
44         implements ValidatedEditTextPreference.Validator {
45 
46     private static final String PREF_KEY = "wifi_tether_network_password";
47 
48     private String mPassword;
49     private int mSecurityType;
50 
51     private final MetricsFeatureProvider mMetricsFeatureProvider;
52 
53     @VisibleForTesting
WifiTetherPasswordPreferenceController(Context context, OnTetherConfigUpdateListener listener, MetricsFeatureProvider provider)54     WifiTetherPasswordPreferenceController(Context context, OnTetherConfigUpdateListener listener,
55             MetricsFeatureProvider provider) {
56         super(context, listener);
57         mMetricsFeatureProvider = provider;
58     }
59 
WifiTetherPasswordPreferenceController(Context context, OnTetherConfigUpdateListener listener)60     public WifiTetherPasswordPreferenceController(Context context,
61             OnTetherConfigUpdateListener listener) {
62         super(context, listener);
63         mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
64     }
65 
66     @Override
getPreferenceKey()67     public String getPreferenceKey() {
68         return FeatureFlagUtils.isEnabled(mContext, FeatureFlags.TETHER_ALL_IN_ONE)
69                 ? PREF_KEY + DEDUP_POSTFIX : PREF_KEY;
70     }
71 
72     @Override
updateDisplay()73     public void updateDisplay() {
74         final SoftApConfiguration config = mWifiManager.getSoftApConfiguration();
75         if (config.getSecurityType() != SoftApConfiguration.SECURITY_TYPE_OPEN
76                 && TextUtils.isEmpty(config.getPassphrase())) {
77             mPassword = generateRandomPassword();
78         } else {
79             mPassword = config.getPassphrase();
80         }
81         mSecurityType = config.getSecurityType();
82         ((ValidatedEditTextPreference) mPreference).setValidator(this);
83         ((ValidatedEditTextPreference) mPreference).setIsPassword(true);
84         ((ValidatedEditTextPreference) mPreference).setIsSummaryPassword(true);
85         updatePasswordDisplay((EditTextPreference) mPreference);
86     }
87 
88     @Override
onPreferenceChange(Preference preference, Object newValue)89     public boolean onPreferenceChange(Preference preference, Object newValue) {
90         if (!TextUtils.equals(mPassword, (String) newValue)) {
91             mMetricsFeatureProvider.action(mContext,
92                     SettingsEnums.ACTION_SETTINGS_CHANGE_WIFI_HOTSPOT_PASSWORD);
93         }
94         mPassword = (String) newValue;
95         updatePasswordDisplay((EditTextPreference) mPreference);
96         mListener.onTetherConfigUpdated(this);
97         return true;
98     }
99 
100     /**
101      * This method returns the current password if it is valid for the indicated security type. If
102      * the password currently set is invalid it will forcefully set a random password that is valid.
103      *
104      * @param securityType The security type for the password.
105      * @return The current password if it is valid for the indicated security type. A new randomly
106      * generated password if it is not.
107      */
getPasswordValidated(int securityType)108     public String getPasswordValidated(int securityType) {
109         // don't actually overwrite unless we get a new config in case it was accidentally toggled.
110         if (securityType == SoftApConfiguration.SECURITY_TYPE_OPEN) {
111             return "";
112         } else if (!WifiUtils.isHotspotPasswordValid(mPassword, securityType)) {
113             mPassword = generateRandomPassword();
114             updatePasswordDisplay((EditTextPreference) mPreference);
115         }
116         return mPassword;
117     }
118 
119     /**
120      * This method set the security type of user selection. Then the controller will based on the
121      * security type changed to update the password changed on the preference.
122      *
123      * @param securityType The security type of SoftApConfiguration.
124      */
setSecurityType(int securityType)125     public void setSecurityType(int securityType) {
126         mSecurityType = securityType;
127         mPreference.setVisible(securityType != SoftApConfiguration.SECURITY_TYPE_OPEN);
128     }
129 
130     @Override
isTextValid(String value)131     public boolean isTextValid(String value) {
132         return WifiUtils.isHotspotPasswordValid(value, mSecurityType);
133     }
134 
generateRandomPassword()135     private static String generateRandomPassword() {
136         String randomUUID = UUID.randomUUID().toString();
137         //first 12 chars from xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
138         return randomUUID.substring(0, 8) + randomUUID.substring(9, 13);
139     }
140 
updatePasswordDisplay(EditTextPreference preference)141     private void updatePasswordDisplay(EditTextPreference preference) {
142         ValidatedEditTextPreference pref = (ValidatedEditTextPreference) preference;
143         pref.setText(mPassword);
144         if (!TextUtils.isEmpty(mPassword)) {
145             pref.setIsSummaryPassword(true);
146             pref.setSummary(mPassword);
147             pref.setVisible(true);
148         } else {
149             pref.setIsSummaryPassword(false);
150             pref.setSummary(R.string.wifi_hotspot_no_password_subtext);
151             pref.setVisible(false);
152         }
153     }
154 }
155