• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 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.tv.settings.connectivity;
18 
19 import static com.android.tv.settings.util.InstrumentationUtils.logEntrySelected;
20 
21 import android.app.tvsettings.TvSettingsEnums;
22 import android.content.Context;
23 import android.net.IpConfiguration.IpAssignment;
24 import android.net.IpConfiguration.ProxySettings;
25 import android.net.wifi.WifiConfiguration;
26 import android.net.wifi.WifiInfo;
27 import android.net.wifi.WifiManager;
28 import android.os.Bundle;
29 import android.os.UserHandle;
30 import android.text.TextUtils;
31 
32 import androidx.annotation.NonNull;
33 import androidx.leanback.app.GuidedStepSupportFragment;
34 import androidx.leanback.widget.GuidanceStylist;
35 import androidx.leanback.widget.GuidedAction;
36 import androidx.preference.ListPreference;
37 import androidx.preference.Preference;
38 
39 import com.android.settingslib.RestrictedLockUtils;
40 import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
41 import com.android.settingslib.RestrictedPreference;
42 import com.android.settingslib.wifi.AccessPoint;
43 import com.android.tv.settings.R;
44 import com.android.tv.settings.SettingsPreferenceFragment;
45 
46 import java.util.List;
47 
48 /**
49  * Fragment for displaying the details of a single wifi network
50  */
51 public class WifiDetailsFragment extends SettingsPreferenceFragment
52         implements ConnectivityListener.Listener, ConnectivityListener.WifiNetworkListener {
53 
54     private static final String ARG_ACCESS_POINT_STATE = "apBundle";
55 
56     private static final String KEY_CONNECTION_STATUS = "connection_status";
57     private static final String KEY_IP_ADDRESS = "ip_address";
58     private static final String KEY_MAC_ADDRESS = "mac_address";
59     private static final String KEY_SIGNAL_STRENGTH = "signal_strength";
60     private static final String KEY_RANDOM_MAC = "random_mac";
61     private static final String KEY_PROXY_SETTINGS = "proxy_settings";
62     private static final String KEY_IP_SETTINGS = "ip_settings";
63     private static final String KEY_FORGET_NETWORK = "forget_network";
64 
65     private static final String VALUE_MAC_RANDOM = "random";
66     private static final String VALUE_MAC_DEVICE = "device";
67 
68     private Preference mConnectionStatusPref;
69     private Preference mIpAddressPref;
70     private Preference mMacAddressPref;
71     private Preference mSignalStrengthPref;
72     private ListPreference mRandomMacPref;
73     private RestrictedPreference mProxySettingsPref;
74     private RestrictedPreference mIpSettingsPref;
75     private RestrictedPreference mForgetNetworkPref;
76 
77     private ConnectivityListener mConnectivityListener;
78     private AccessPoint mAccessPoint;
79 
prepareArgs(@onNull Bundle args, AccessPoint accessPoint)80     public static void prepareArgs(@NonNull Bundle args, AccessPoint accessPoint) {
81         final Bundle apBundle = new Bundle();
82         accessPoint.saveWifiState(apBundle);
83         args.putParcelable(ARG_ACCESS_POINT_STATE, apBundle);
84     }
85 
86     @Override
onCreate(Bundle savedInstanceState)87     public void onCreate(Bundle savedInstanceState) {
88         mConnectivityListener = new ConnectivityListener(
89                 getContext(), this, getSettingsLifecycle());
90 
91         mAccessPoint = new AccessPoint(getContext(),
92                 getArguments().getBundle(ARG_ACCESS_POINT_STATE));
93         super.onCreate(savedInstanceState);
94     }
95 
96     @Override
onStart()97     public void onStart() {
98         super.onStart();
99         mConnectivityListener.setWifiListener(this);
100     }
101 
102     @Override
onResume()103     public void onResume() {
104         super.onResume();
105         update();
106     }
107 
108     @Override
onCreatePreferences(Bundle savedInstanceState, String rootKey)109     public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
110         setPreferencesFromResource(R.xml.wifi_details, null);
111 
112         getPreferenceScreen().setTitle(mAccessPoint.getSsid());
113 
114         mConnectionStatusPref = findPreference(KEY_CONNECTION_STATUS);
115         mIpAddressPref = findPreference(KEY_IP_ADDRESS);
116         mMacAddressPref = findPreference(KEY_MAC_ADDRESS);
117         mSignalStrengthPref = findPreference(KEY_SIGNAL_STRENGTH);
118         mRandomMacPref = (ListPreference) findPreference(KEY_RANDOM_MAC);
119         mProxySettingsPref = findPreference(KEY_PROXY_SETTINGS);
120         mIpSettingsPref = findPreference(KEY_IP_SETTINGS);
121         mForgetNetworkPref = findPreference(KEY_FORGET_NETWORK);
122     }
123 
124     @Override
onConnectivityChange()125     public void onConnectivityChange() {
126         update();
127     }
128 
129     @Override
onWifiListChanged()130     public void onWifiListChanged() {
131         final List<AccessPoint> accessPoints = mConnectivityListener.getAvailableNetworks();
132         for (final AccessPoint accessPoint : accessPoints) {
133             if (TextUtils.equals(mAccessPoint.getSsidStr(), accessPoint.getSsidStr())
134                     && mAccessPoint.getSecurity() == accessPoint.getSecurity()) {
135                 // Make sure we're not holding on to the one we inflated from the bundle, because
136                 // it won't be updated
137                 mAccessPoint = accessPoint;
138                 break;
139             }
140         }
141         update();
142     }
143 
update()144     private void update() {
145         if (!isAdded()) {
146             return;
147         }
148 
149         final boolean active = mAccessPoint.isActive();
150 
151         mConnectionStatusPref.setSummary(active ? R.string.connected : R.string.not_connected);
152         mIpAddressPref.setVisible(active);
153         mSignalStrengthPref.setVisible(active);
154 
155         if (active) {
156             mIpAddressPref.setSummary(mConnectivityListener.getWifiIpAddress());
157             mSignalStrengthPref.setSummary(getSignalStrength());
158         }
159 
160         // Mac address related Preferences (info entry and random mac setting entry)
161         String macAddress = mConnectivityListener.getWifiMacAddress(mAccessPoint);
162         if (active && !TextUtils.isEmpty(macAddress)) {
163             mMacAddressPref.setVisible(true);
164             updateMacAddressPref(macAddress);
165             updateRandomMacPref();
166         } else {
167             mMacAddressPref.setVisible(false);
168             mRandomMacPref.setVisible(false);
169         }
170 
171         WifiConfiguration wifiConfiguration = mAccessPoint.getConfig();
172         if (wifiConfiguration != null) {
173             final int networkId = wifiConfiguration.networkId;
174             ProxySettings proxySettings = wifiConfiguration.getIpConfiguration().getProxySettings();
175             mProxySettingsPref.setSummary(proxySettings == ProxySettings.NONE
176                     ? R.string.wifi_action_proxy_none : R.string.wifi_action_proxy_manual);
177             mProxySettingsPref.setIntent(EditProxySettingsActivity.createIntent(getContext(),
178                     networkId));
179 
180             IpAssignment ipAssignment = wifiConfiguration.getIpConfiguration().getIpAssignment();
181             mIpSettingsPref.setSummary(ipAssignment == IpAssignment.STATIC
182                             ? R.string.wifi_action_static : R.string.wifi_action_dhcp);
183             mIpSettingsPref.setIntent(EditIpSettingsActivity.createIntent(getContext(), networkId));
184 
185             mForgetNetworkPref.setFragment(ForgetNetworkConfirmFragment.class.getName());
186             ForgetNetworkConfirmFragment.prepareArgs(mForgetNetworkPref.getExtras(), mAccessPoint);
187         }
188 
189         mProxySettingsPref.setVisible(wifiConfiguration != null);
190         mProxySettingsPref.setOnPreferenceClickListener(
191                 preference -> {
192                     logEntrySelected(TvSettingsEnums.NETWORK_AP_INFO_PROXY_SETTINGS);
193                     return false;
194                 });
195         mIpSettingsPref.setVisible(wifiConfiguration != null);
196         mIpSettingsPref.setOnPreferenceClickListener(
197                 preference -> {
198                     logEntrySelected(TvSettingsEnums.NETWORK_AP_INFO_IP_SETTINGS);
199                     return false;
200                 });
201         mForgetNetworkPref.setVisible(wifiConfiguration != null);
202         mForgetNetworkPref.setOnPreferenceClickListener(
203                 preference -> {
204                     logEntrySelected(TvSettingsEnums.NETWORK_AP_INFO_FORGET_NETWORK);
205                     return false;
206                 });
207 
208         boolean canModifyNetwork = !WifiConfigHelper.isNetworkLockedDown(
209                 getContext(), wifiConfiguration);
210         if (canModifyNetwork) {
211             mProxySettingsPref.setDisabledByAdmin(null);
212             mIpSettingsPref.setDisabledByAdmin(null);
213             mForgetNetworkPref.setDisabledByAdmin(null);
214 
215             mProxySettingsPref.setEnabled(true);
216             mIpSettingsPref.setEnabled(true);
217             mForgetNetworkPref.setEnabled(true);
218         } else {
219             EnforcedAdmin admin = RestrictedLockUtils.getProfileOrDeviceOwner(getContext(),
220                     UserHandle.of(UserHandle.myUserId()));
221             mProxySettingsPref.setDisabledByAdmin(admin);
222             mIpSettingsPref.setDisabledByAdmin(admin);
223             mForgetNetworkPref.setDisabledByAdmin(admin);
224         }
225     }
226 
getSignalStrength()227     private String getSignalStrength() {
228         String[] signalLevels = getResources().getStringArray(R.array.wifi_signal_strength);
229         int strength = mConnectivityListener.getWifiSignalStrength(signalLevels.length);
230         return signalLevels[strength];
231     }
232 
updateMacAddressPref(String macAddress)233     private void updateMacAddressPref(String macAddress) {
234         if (WifiInfo.DEFAULT_MAC_ADDRESS.equals(macAddress)) {
235             mMacAddressPref.setSummary(R.string.mac_address_not_available);
236         } else {
237             mMacAddressPref.setSummary(macAddress);
238         }
239         if (mAccessPoint == null || mAccessPoint.getConfig() == null) {
240             return;
241         }
242         // For saved Passpoint network, framework doesn't have the field to keep the MAC choice
243         // persistently, so Passpoint network will always use the default value so far, which is
244         // randomized MAC address, so don't need to modify title.
245         if (mAccessPoint.isPasspoint() || mAccessPoint.isPasspointConfig()) {
246             return;
247         }
248         mMacAddressPref.setTitle(
249                 (mAccessPoint.getConfig().macRandomizationSetting
250                         == WifiConfiguration.RANDOMIZATION_PERSISTENT)
251                         ? R.string.title_randomized_mac_address
252                         : R.string.title_mac_address);
253     }
254 
updateRandomMacPref()255     private void updateRandomMacPref() {
256         mRandomMacPref.setVisible(mConnectivityListener.isMacAddressRandomizationSupported());
257         boolean isMacRandomized =
258                 (mConnectivityListener.getWifiMacRandomizationSetting(mAccessPoint)
259                         == WifiConfiguration.RANDOMIZATION_PERSISTENT);
260         mRandomMacPref.setValue(isMacRandomized ? VALUE_MAC_RANDOM : VALUE_MAC_DEVICE);
261         if (mAccessPoint.isEphemeral() || mAccessPoint.isPasspoint()
262                 || mAccessPoint.isPasspointConfig()) {
263             mRandomMacPref.setSelectable(false);
264             mRandomMacPref.setSummary(R.string.mac_address_ephemeral_summary);
265         } else {
266             mRandomMacPref.setSelectable(true);
267             mRandomMacPref.setSummary(mRandomMacPref.getEntries()[isMacRandomized ? 0 : 1]);
268         }
269         mRandomMacPref.setOnPreferenceChangeListener(
270                 (pref, newValue) -> {
271                     mConnectivityListener.applyMacRandomizationSetting(
272                             mAccessPoint,
273                             VALUE_MAC_RANDOM.equals(newValue));
274                     // The above call should trigger a connectivity change which will refresh
275                     // the UI.
276                     return true;
277                 });
278     }
279 
280     @Override
getPageId()281     protected int getPageId() {
282         return TvSettingsEnums.NETWORK_AP_INFO;
283     }
284 
285     public static class ForgetNetworkConfirmFragment extends GuidedStepSupportFragment {
286 
287         private AccessPoint mAccessPoint;
288 
prepareArgs(@onNull Bundle args, AccessPoint accessPoint)289         public static void prepareArgs(@NonNull Bundle args, AccessPoint accessPoint) {
290             final Bundle apBundle = new Bundle();
291             accessPoint.saveWifiState(apBundle);
292             args.putParcelable(ARG_ACCESS_POINT_STATE, apBundle);
293         }
294 
295         @Override
onCreate(Bundle savedInstanceState)296         public void onCreate(Bundle savedInstanceState) {
297             mAccessPoint = new AccessPoint(getContext(),
298                     getArguments().getBundle(ARG_ACCESS_POINT_STATE));
299             super.onCreate(savedInstanceState);
300         }
301 
302         @NonNull
303         @Override
onCreateGuidance(Bundle savedInstanceState)304         public GuidanceStylist.Guidance onCreateGuidance(Bundle savedInstanceState) {
305             return new GuidanceStylist.Guidance(
306                     getString(R.string.wifi_forget_network),
307                     getString(R.string.wifi_forget_network_description),
308                     mAccessPoint.getSsidStr(),
309                     getContext().getDrawable(R.drawable.ic_wifi_signal_4_white_132dp));
310         }
311 
312         @Override
onCreateActions(@onNull List<GuidedAction> actions, Bundle savedInstanceState)313         public void onCreateActions(@NonNull List<GuidedAction> actions,
314                 Bundle savedInstanceState) {
315             final Context context = getContext();
316             actions.add(new GuidedAction.Builder(context)
317                     .clickAction(GuidedAction.ACTION_ID_OK)
318                     .build());
319             actions.add(new GuidedAction.Builder(context)
320                     .clickAction(GuidedAction.ACTION_ID_CANCEL)
321                     .build());
322         }
323 
324         @Override
onGuidedActionClicked(GuidedAction action)325         public void onGuidedActionClicked(GuidedAction action) {
326             if (action.getId() == GuidedAction.ACTION_ID_OK) {
327                 WifiManager wifiManager =
328                         (WifiManager) getContext().getSystemService(Context.WIFI_SERVICE);
329                 wifiManager.forget(mAccessPoint.getConfig().networkId, null);
330             }
331             getFragmentManager().popBackStack();
332         }
333     }
334 }
335