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.settings.wifi.details2;
18 
19 import android.content.Context;
20 import android.net.wifi.WifiManager;
21 
22 import androidx.annotation.NonNull;
23 import androidx.annotation.VisibleForTesting;
24 import androidx.preference.ListPreference;
25 import androidx.preference.Preference;
26 
27 import com.android.settings.R;
28 import com.android.settings.core.BasePreferenceController;
29 import com.android.wifi.flags.Flags;
30 import com.android.wifitrackerlib.WifiEntry;
31 
32 /**
33  * A controller that controls whether the Wi-Fi network is mac randomized or not.
34  */
35 public class WifiPrivacyPreferenceController2 extends BasePreferenceController implements
36         Preference.OnPreferenceChangeListener {
37 
38     private static final String KEY_WIFI_PRIVACY = "privacy";
39     private final WifiManager mWifiManager;
40     private WifiEntry mWifiEntry;
41 
WifiPrivacyPreferenceController2(Context context)42     public WifiPrivacyPreferenceController2(Context context) {
43         super(context, KEY_WIFI_PRIVACY);
44 
45         mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
46     }
47 
setWifiEntry(WifiEntry wifiEntry)48     public void setWifiEntry(WifiEntry wifiEntry) {
49         mWifiEntry = wifiEntry;
50     }
51 
52     @Override
getAvailabilityStatus()53     public int getAvailabilityStatus() {
54         return (!Flags.androidVWifiApi() && mWifiManager.isConnectedMacRandomizationSupported())
55                 ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
56     }
57 
58     @Override
updateState(Preference preference)59     public void updateState(Preference preference) {
60         final ListPreference listPreference = (ListPreference) preference;
61         final int randomizationLevel = getRandomizationValue();
62         final boolean isSelectable = mWifiEntry.canSetPrivacy();
63         preference.setSelectable(isSelectable);
64         listPreference.setValue(Integer.toString(randomizationLevel));
65         updateSummary(listPreference, randomizationLevel);
66 
67         // If the preference cannot be selectable, display a temporary network in the summary.
68         if (!isSelectable) {
69             listPreference.setSummary(R.string.wifi_privacy_settings_ephemeral_summary);
70         }
71     }
72 
73     @Override
onPreferenceChange(@onNull Preference preference, Object newValue)74     public boolean onPreferenceChange(@NonNull Preference preference, Object newValue) {
75         final int privacy = Integer.parseInt((String) newValue);
76         if (mWifiEntry.getPrivacy() == privacy) {
77             // Prevent disconnection + reconnection if settings not changed.
78             return true;
79         }
80         mWifiEntry.setPrivacy(privacy);
81 
82         // To activate changing, we need to reconnect network. WiFi will auto connect to
83         // current network after disconnect(). Only needed when this is connected network.
84         if (mWifiEntry.getConnectedState() == WifiEntry.CONNECTED_STATE_CONNECTED) {
85             mWifiEntry.disconnect(null /* callback */);
86             mWifiEntry.connect(null /* callback */);
87         }
88         updateSummary((ListPreference) preference, privacy);
89         return true;
90     }
91 
92     @VisibleForTesting
getRandomizationValue()93     int getRandomizationValue() {
94         return mWifiEntry.getPrivacy();
95     }
96 
97     private static final int PREF_RANDOMIZATION_PERSISTENT = 0;
98     private static final int PREF_RANDOMIZATION_NONE = 1;
99 
100     /**
101      * Returns preference index value.
102      *
103      * @param macRandomized is mac randomized value
104      * @return index value of preference
105      */
translateMacRandomizedValueToPrefValue(int macRandomized)106     public static int translateMacRandomizedValueToPrefValue(int macRandomized) {
107         return (macRandomized == WifiEntry.PRIVACY_RANDOMIZED_MAC)
108             ? PREF_RANDOMIZATION_PERSISTENT : PREF_RANDOMIZATION_NONE;
109     }
110 
111     /**
112      * Returns mac randomized value.
113      *
114      * @param prefMacRandomized is preference index value
115      * @return mac randomized value
116      */
translatePrefValueToMacRandomizedValue(int prefMacRandomized)117     public static int translatePrefValueToMacRandomizedValue(int prefMacRandomized) {
118         return (prefMacRandomized == PREF_RANDOMIZATION_PERSISTENT)
119             ? WifiEntry.PRIVACY_RANDOMIZED_MAC : WifiEntry.PRIVACY_DEVICE_MAC;
120     }
121 
updateSummary(ListPreference preference, int macRandomized)122     private void updateSummary(ListPreference preference, int macRandomized) {
123         // Translates value here to set RANDOMIZATION_PERSISTENT as first item in UI for better UX.
124         final int prefMacRandomized = translateMacRandomizedValueToPrefValue(macRandomized);
125         preference.setSummary(preference.getEntries()[prefMacRandomized]);
126     }
127 }
128