blob: 251d1357b255809da67fe12c8fef25faaf31ad0d [file] [log] [blame]
Zhen Zhangb60e8ca2020-01-07 18:14:30 -08001/*
2 * Copyright (C) 2020 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
17package com.android.settings;
18
19import static android.net.ConnectivityManager.ACTION_TETHER_STATE_CHANGED;
20import static android.net.ConnectivityManager.TETHERING_WIFI;
21import static android.net.wifi.WifiManager.WIFI_AP_STATE_CHANGED_ACTION;
22
Zhen Zhang258fb7f2020-02-05 10:09:27 -080023import static com.android.settings.network.TetherEnabler.KEY_ENABLE_WIFI_TETHERING;
Zhen Zhangb60e8ca2020-01-07 18:14:30 -080024
25import android.app.settings.SettingsEnums;
Zhen Zhang02dfed62020-01-13 14:57:23 -080026import android.bluetooth.BluetoothAdapter;
27import android.bluetooth.BluetoothPan;
28import android.bluetooth.BluetoothProfile;
Zhen Zhangb60e8ca2020-01-07 18:14:30 -080029import android.content.BroadcastReceiver;
30import android.content.Context;
31import android.content.Intent;
32import android.content.IntentFilter;
33import android.content.SharedPreferences;
Zhen Zhangb60e8ca2020-01-07 18:14:30 -080034import android.net.wifi.SoftApConfiguration;
35import android.net.wifi.WifiManager;
36import android.os.Bundle;
Zhen Zhangb60e8ca2020-01-07 18:14:30 -080037import android.os.UserManager;
38import android.text.TextUtils;
Zhen Zhangd2a7f9a2020-01-30 15:12:50 -080039import android.util.FeatureFlagUtils;
Zhen Zhangb60e8ca2020-01-07 18:14:30 -080040import android.util.Log;
41
42import androidx.annotation.VisibleForTesting;
43import androidx.preference.Preference;
44import androidx.preference.PreferenceGroup;
45
Zhen Zhangd2a7f9a2020-01-30 15:12:50 -080046import com.android.settings.core.FeatureFlags;
Zhen Zhangb60e8ca2020-01-07 18:14:30 -080047import com.android.settings.dashboard.RestrictedDashboardFragment;
48import com.android.settings.datausage.DataSaverBackend;
Zhen Zhangaef1e8d2020-02-11 16:22:08 -080049import com.android.settings.network.BluetoothTetherPreferenceController;
Zhen Zhangb60e8ca2020-01-07 18:14:30 -080050import com.android.settings.network.TetherEnabler;
Zhen Zhangaef1e8d2020-02-11 16:22:08 -080051import com.android.settings.network.UsbTetherPreferenceController;
52import com.android.settings.network.WifiTetherDisablePreferenceController;
Zhen Zhangb60e8ca2020-01-07 18:14:30 -080053import com.android.settings.search.BaseSearchIndexProvider;
Zhen Zhang02dfed62020-01-13 14:57:23 -080054import com.android.settings.widget.SwitchBar;
55import com.android.settings.widget.SwitchBarController;
Zhen Zhangb60e8ca2020-01-07 18:14:30 -080056import com.android.settings.wifi.tether.WifiTetherApBandPreferenceController;
57import com.android.settings.wifi.tether.WifiTetherAutoOffPreferenceController;
58import com.android.settings.wifi.tether.WifiTetherBasePreferenceController;
Arc Wang005fe692020-03-04 21:03:54 +080059import com.android.settings.wifi.tether.WifiTetherFooterPreferenceController;
Zhen Zhangb60e8ca2020-01-07 18:14:30 -080060import com.android.settings.wifi.tether.WifiTetherPasswordPreferenceController;
61import com.android.settings.wifi.tether.WifiTetherSSIDPreferenceController;
62import com.android.settings.wifi.tether.WifiTetherSecurityPreferenceController;
63import com.android.settingslib.TetherUtil;
64import com.android.settingslib.core.AbstractPreferenceController;
65import com.android.settingslib.search.SearchIndexable;
66
67import java.util.ArrayList;
68import java.util.List;
Zhen Zhang02dfed62020-01-13 14:57:23 -080069import java.util.concurrent.atomic.AtomicReference;
Zhen Zhangb60e8ca2020-01-07 18:14:30 -080070
71/**
Zhen Zhang02dfed62020-01-13 14:57:23 -080072 * Displays preferences for all Tethering options.
Zhen Zhangb60e8ca2020-01-07 18:14:30 -080073 */
74@SearchIndexable
Arc Wang005fe692020-03-04 21:03:54 +080075public class AllInOneTetherSettings extends RestrictedDashboardFragment
Zhen Zhangb60e8ca2020-01-07 18:14:30 -080076 implements DataSaverBackend.Listener,
77 WifiTetherBasePreferenceController.OnTetherConfigUpdateListener,
78 SharedPreferences.OnSharedPreferenceChangeListener {
79
Zhen Zhangd2a7f9a2020-01-30 15:12:50 -080080 // TODO(b/148622133): Should clean up the postfix once this fragment replaced TetherSettings.
81 public static final String DEDUP_POSTFIX = "_2";
Zhen Zhangb60e8ca2020-01-07 18:14:30 -080082
Zhen Zhangd2a7f9a2020-01-30 15:12:50 -080083 @VisibleForTesting
84 static final String KEY_WIFI_TETHER_NETWORK_NAME = "wifi_tether_network_name" + DEDUP_POSTFIX;
85 @VisibleForTesting
86 static final String KEY_WIFI_TETHER_NETWORK_PASSWORD =
87 "wifi_tether_network_password" + DEDUP_POSTFIX;
88 @VisibleForTesting
89 static final String KEY_WIFI_TETHER_AUTO_OFF = "wifi_tether_auto_turn_off" + DEDUP_POSTFIX;
90 @VisibleForTesting
91 static final String KEY_WIFI_TETHER_NETWORK_AP_BAND =
92 "wifi_tether_network_ap_band" + DEDUP_POSTFIX;
93 @VisibleForTesting
94 static final String KEY_WIFI_TETHER_SECURITY = "wifi_tether_security" + DEDUP_POSTFIX;
95
96 private static final String KEY_DATA_SAVER_FOOTER = "disabled_on_data_saver" + DEDUP_POSTFIX;
Zhen Zhangb60e8ca2020-01-07 18:14:30 -080097 private static final String KEY_WIFI_TETHER_GROUP = "wifi_tether_settings_group";
Zhen Zhangb60e8ca2020-01-07 18:14:30 -080098 private static final int EXPANDED_CHILD_COUNT_WITH_SECURITY_NON = 2;
99 private static final int EXPANDED_CHILD_COUNT_DEFAULT = 3;
100 private static final String TAG = "AllInOneTetherSettings";
101
102 private boolean mUnavailable;
103
104 private DataSaverBackend mDataSaverBackend;
105 private boolean mDataSaverEnabled;
106 private Preference mDataSaverFooter;
107
108 private WifiManager mWifiManager;
109 private boolean mRestartWifiApAfterConfigChange;
Zhen Zhang02dfed62020-01-13 14:57:23 -0800110 private final AtomicReference<BluetoothPan> mBluetoothPan = new AtomicReference<>();
Zhen Zhangb60e8ca2020-01-07 18:14:30 -0800111
112 private WifiTetherSSIDPreferenceController mSSIDPreferenceController;
113 private WifiTetherPasswordPreferenceController mPasswordPreferenceController;
114 private WifiTetherApBandPreferenceController mApBandPreferenceController;
115 private WifiTetherSecurityPreferenceController mSecurityPreferenceController;
116 private PreferenceGroup mWifiTetherGroup;
117 private SharedPreferences mSharedPreferences;
Zhen Zhangb60e8ca2020-01-07 18:14:30 -0800118 private boolean mWifiTetherChosen;
Zhen Zhang02dfed62020-01-13 14:57:23 -0800119 private TetherEnabler mTetherEnabler;
Zhen Zhangb60e8ca2020-01-07 18:14:30 -0800120
121 private final BroadcastReceiver mTetherChangeReceiver = new BroadcastReceiver() {
122 @Override
123 public void onReceive(Context content, Intent intent) {
124 String action = intent.getAction();
125 if (Log.isLoggable(TAG, Log.DEBUG)) {
Zhen Zhangec966cb2020-02-05 12:52:35 -0800126 Log.d(TAG,
127 "updating display config due to receiving broadcast action " + action);
Zhen Zhangb60e8ca2020-01-07 18:14:30 -0800128 }
129 updateDisplayWithNewConfig();
130 if (TextUtils.equals(action, ACTION_TETHER_STATE_CHANGED)) {
Zhen Zhangec966cb2020-02-05 12:52:35 -0800131 restartWifiTetherIfNeed(mWifiManager.getWifiApState());
Zhen Zhangb60e8ca2020-01-07 18:14:30 -0800132 } else if (TextUtils.equals(action, WIFI_AP_STATE_CHANGED_ACTION)) {
Zhen Zhangec966cb2020-02-05 12:52:35 -0800133 restartWifiTetherIfNeed(intent.getIntExtra(WifiManager.EXTRA_WIFI_AP_STATE, 0));
134 }
135 }
136
137 private void restartWifiTetherIfNeed(int state) {
138 if (state == WifiManager.WIFI_AP_STATE_DISABLED
139 && mWifiTetherChosen
140 && mRestartWifiApAfterConfigChange) {
141 mRestartWifiApAfterConfigChange = false;
142 mTetherEnabler.startTethering(TETHERING_WIFI);
Zhen Zhangb60e8ca2020-01-07 18:14:30 -0800143 }
144 }
145 };
146
Zhen Zhang02dfed62020-01-13 14:57:23 -0800147 private final BluetoothProfile.ServiceListener mProfileServiceListener =
148 new BluetoothProfile.ServiceListener() {
149 public void onServiceConnected(int profile, BluetoothProfile proxy) {
150 mBluetoothPan.set((BluetoothPan) proxy);
151 }
152
153 public void onServiceDisconnected(int profile) {
154 mBluetoothPan.set(null);
155 }
156 };
157
Zhen Zhangb60e8ca2020-01-07 18:14:30 -0800158 @Override
159 public int getMetricsCategory() {
160 return SettingsEnums.TETHER;
161 }
162
163 public AllInOneTetherSettings() {
164 super(UserManager.DISALLOW_CONFIG_TETHERING);
165 }
166
167 @Override
168 public void onAttach(Context context) {
169 super.onAttach(context);
170 mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
Zhen Zhangb60e8ca2020-01-07 18:14:30 -0800171 mSharedPreferences =
172 context.getSharedPreferences(TetherEnabler.SHARED_PREF, Context.MODE_PRIVATE);
173
174 mSSIDPreferenceController = use(WifiTetherSSIDPreferenceController.class);
175 mSecurityPreferenceController = use(WifiTetherSecurityPreferenceController.class);
176 mPasswordPreferenceController = use(WifiTetherPasswordPreferenceController.class);
177 mApBandPreferenceController = use(WifiTetherApBandPreferenceController.class);
Zhen Zhangaef1e8d2020-02-11 16:22:08 -0800178 getSettingsLifecycle().addObserver(use(UsbTetherPreferenceController.class));
179 getSettingsLifecycle().addObserver(use(BluetoothTetherPreferenceController.class));
180 getSettingsLifecycle().addObserver(use(WifiTetherDisablePreferenceController.class));
Zhen Zhangb60e8ca2020-01-07 18:14:30 -0800181 }
182
183 @Override
184 public void onCreate(Bundle icicle) {
185 super.onCreate(icicle);
186
187 mDataSaverBackend = new DataSaverBackend(getContext());
188 mDataSaverEnabled = mDataSaverBackend.isDataSaverEnabled();
189 mDataSaverFooter = findPreference(KEY_DATA_SAVER_FOOTER);
190 mWifiTetherGroup = findPreference(KEY_WIFI_TETHER_GROUP);
191
192 setIfOnlyAvailableForAdmins(true);
193 if (isUiRestricted()) {
194 mUnavailable = true;
195 return;
196 }
197
198 mDataSaverBackend.addListener(this);
199
200 // Set initial state based on Data Saver mode.
201 onDataSaverChanged(mDataSaverBackend.isDataSaverEnabled());
202
203 // Set initial state based on SharedPreferences value.
204 onSharedPreferenceChanged(mSharedPreferences, KEY_ENABLE_WIFI_TETHERING);
Zhen Zhangb60e8ca2020-01-07 18:14:30 -0800205 }
206
207 @Override
Zhen Zhang02dfed62020-01-13 14:57:23 -0800208 public void onActivityCreated(Bundle savedInstanceState) {
209 super.onActivityCreated(savedInstanceState);
210 if (mUnavailable) {
211 return;
212 }
213 // Assume we are in a SettingsActivity. This is only safe because we currently use
214 // SettingsActivity as base for all preference fragments.
215 final SettingsActivity activity = (SettingsActivity) getActivity();
Zhen Zhang0ccc8492020-01-17 15:23:40 -0800216 final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
Zhen Zhang02dfed62020-01-13 14:57:23 -0800217 if (adapter != null) {
218 adapter.getProfileProxy(activity.getApplicationContext(), mProfileServiceListener,
219 BluetoothProfile.PAN);
220 }
221 final SwitchBar switchBar = activity.getSwitchBar();
222 mTetherEnabler = new TetherEnabler(activity,
223 new SwitchBarController(switchBar), mBluetoothPan);
224 getSettingsLifecycle().addObserver(mTetherEnabler);
225 switchBar.show();
226 }
227
228 @Override
Zhen Zhangb60e8ca2020-01-07 18:14:30 -0800229 public void onStart() {
230 super.onStart();
231
232 if (mUnavailable) {
233 if (!isUiRestrictedByOnlyAdmin()) {
234 getEmptyTextView().setText(R.string.tethering_settings_not_available);
235 }
236 getPreferenceScreen().removeAll();
237 return;
238 }
239 final Context context = getContext();
240 if (context != null) {
241 IntentFilter filter = new IntentFilter(ACTION_TETHER_STATE_CHANGED);
242 filter.addAction(WIFI_AP_STATE_CHANGED_ACTION);
243 context.registerReceiver(mTetherChangeReceiver, filter);
244 }
245 }
246
247 @Override
248 public void onResume() {
249 super.onResume();
250 mSharedPreferences.registerOnSharedPreferenceChangeListener(this);
251 }
252
253 @Override
254 public void onPause() {
255 super.onPause();
256 mSharedPreferences.unregisterOnSharedPreferenceChangeListener(this);
257 }
258
259 @Override
260 public void onStop() {
261 super.onStop();
262 final Context context = getContext();
263 if (context != null) {
264 context.unregisterReceiver(mTetherChangeReceiver);
265 }
266 }
267
268 @Override
269 public void onDestroy() {
270 mDataSaverBackend.remListener(this);
271 super.onDestroy();
272 }
273
274 @Override
275 public void onDataSaverChanged(boolean isDataSaving) {
276 mDataSaverEnabled = isDataSaving;
277 mDataSaverFooter.setVisible(mDataSaverEnabled);
278 }
279
280 @Override
281 public void onWhitelistStatusChanged(int uid, boolean isWhitelisted) {
282 // Do nothing
283 }
284
285 @Override
286 public void onBlacklistStatusChanged(int uid, boolean isBlacklisted) {
287 // Do nothing
288 }
289
290 @Override
291 protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
292 return buildPreferenceControllers(context, this);
293 }
294
295 private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
296 WifiTetherBasePreferenceController.OnTetherConfigUpdateListener listener) {
297 final List<AbstractPreferenceController> controllers = new ArrayList<>();
298 controllers.add(
299 new WifiTetherSSIDPreferenceController(context, listener));
300 controllers.add(
301 new WifiTetherPasswordPreferenceController(context, listener));
302 controllers.add(
303 new WifiTetherApBandPreferenceController(context, listener));
304 controllers.add(
305 new WifiTetherSecurityPreferenceController(context, listener));
306 controllers.add(
307 new WifiTetherAutoOffPreferenceController(context, KEY_WIFI_TETHER_AUTO_OFF));
Arc Wang005fe692020-03-04 21:03:54 +0800308 controllers.add(
309 new WifiTetherFooterPreferenceController(context));
Zhen Zhangb60e8ca2020-01-07 18:14:30 -0800310
311 return controllers;
312 }
313
314 @Override
315 protected int getPreferenceScreenResId() {
316 return R.xml.all_tether_prefs;
317 }
318
319 @Override
320 protected String getLogTag() {
321 return TAG;
322 }
323
324 @Override
Zhen Zhangb60e8ca2020-01-07 18:14:30 -0800325 public int getHelpResource() {
326 return R.string.help_url_tether;
327 }
328
329 @Override
330 public void onTetherConfigUpdated(AbstractPreferenceController controller) {
331 final SoftApConfiguration config = buildNewConfig();
332 mPasswordPreferenceController.updateVisibility(config.getSecurityType());
333 mWifiManager.setSoftApConfiguration(config);
334
335 if (mWifiManager.getWifiApState() == WifiManager.WIFI_AP_STATE_ENABLED) {
336 if (Log.isLoggable(TAG, Log.DEBUG)) {
337 Log.d(TAG, "Wifi AP config changed while enabled, stop and restart");
338 }
339 mRestartWifiApAfterConfigChange = true;
Zhen Zhang02dfed62020-01-13 14:57:23 -0800340 mTetherEnabler.stopTethering(TETHERING_WIFI);
Zhen Zhangb60e8ca2020-01-07 18:14:30 -0800341 }
342
343 if (controller instanceof WifiTetherSecurityPreferenceController) {
344 reConfigInitialExpandedChildCount();
345 }
346 }
347
348 private SoftApConfiguration buildNewConfig() {
349 final SoftApConfiguration.Builder configBuilder = new SoftApConfiguration.Builder();
350 final int securityType = mSecurityPreferenceController.getSecurityType();
351 configBuilder.setSsid(mSSIDPreferenceController.getSSID());
352 if (securityType == SoftApConfiguration.SECURITY_TYPE_WPA2_PSK) {
353 configBuilder.setPassphrase(
354 mPasswordPreferenceController.getPasswordValidated(securityType),
355 SoftApConfiguration.SECURITY_TYPE_WPA2_PSK);
356 }
357 configBuilder.setBand(mApBandPreferenceController.getBandIndex());
358 return configBuilder.build();
359 }
360
361 private void updateDisplayWithNewConfig() {
362 mSSIDPreferenceController.updateDisplay();
363 mSecurityPreferenceController.updateDisplay();
364 mPasswordPreferenceController.updateDisplay();
365 mApBandPreferenceController.updateDisplay();
366 }
367
368 @Override
369 public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
370 if (TextUtils.equals(key, KEY_ENABLE_WIFI_TETHERING)) {
371 mWifiTetherChosen = sharedPreferences.getBoolean(KEY_ENABLE_WIFI_TETHERING, true);
372 mWifiTetherGroup.setVisible(mWifiTetherChosen);
373 reConfigInitialExpandedChildCount();
374 }
375 }
376
Zhen Zhangb60e8ca2020-01-07 18:14:30 -0800377 private void reConfigInitialExpandedChildCount() {
378 getPreferenceScreen().setInitialExpandedChildrenCount(getInitialExpandedChildCount());
379 }
380
381 @Override
382 public int getInitialExpandedChildCount() {
383 if (!mWifiTetherChosen) {
384 // Expand all preferences in the screen.
385 return getPreferenceScreen().getPreferenceCount();
386 }
387
388 if (mSecurityPreferenceController == null) {
389 return EXPANDED_CHILD_COUNT_DEFAULT;
390 }
391
392 return (mSecurityPreferenceController.getSecurityType()
393 == SoftApConfiguration.SECURITY_TYPE_OPEN)
394 ? EXPANDED_CHILD_COUNT_WITH_SECURITY_NON : EXPANDED_CHILD_COUNT_DEFAULT;
395 }
396
397 public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
398 new BaseSearchIndexProvider(R.xml.all_tether_prefs) {
399
400 @Override
401 public List<String> getNonIndexableKeys(Context context) {
402 final List<String> keys = super.getNonIndexableKeys(context);
403
404 if (!TetherUtil.isTetherAvailable(context)) {
Zhen Zhangb60e8ca2020-01-07 18:14:30 -0800405 keys.add(KEY_WIFI_TETHER_NETWORK_NAME);
406 keys.add(KEY_WIFI_TETHER_NETWORK_PASSWORD);
407 keys.add(KEY_WIFI_TETHER_AUTO_OFF);
408 keys.add(KEY_WIFI_TETHER_NETWORK_AP_BAND);
Zhen Zhangd2a7f9a2020-01-30 15:12:50 -0800409 keys.add(KEY_WIFI_TETHER_SECURITY);
Zhen Zhangb60e8ca2020-01-07 18:14:30 -0800410 }
Zhen Zhangb60e8ca2020-01-07 18:14:30 -0800411 return keys;
412 }
413
414 @Override
Zhen Zhang0ccc8492020-01-17 15:23:40 -0800415 protected boolean isPageSearchEnabled(Context context) {
Zhen Zhangd2a7f9a2020-01-30 15:12:50 -0800416 return FeatureFlagUtils.isEnabled(context, FeatureFlags.TETHER_ALL_IN_ONE);
Zhen Zhang0ccc8492020-01-17 15:23:40 -0800417 }
418
419 @Override
Zhen Zhangb60e8ca2020-01-07 18:14:30 -0800420 public List<AbstractPreferenceController> createPreferenceControllers(
421 Context context) {
Zhen Zhangec966cb2020-02-05 12:52:35 -0800422 return buildPreferenceControllers(context, null /*listener*/);
Zhen Zhangb60e8ca2020-01-07 18:14:30 -0800423 }
424 };
425}