blob: 22453a39725daaa4fe873e1ca9a7a465540b87be [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 Zhangb60e8ca2020-01-07 18:14:30 -080023import android.app.settings.SettingsEnums;
Zhen Zhang02dfed62020-01-13 14:57:23 -080024import android.bluetooth.BluetoothAdapter;
25import android.bluetooth.BluetoothPan;
26import android.bluetooth.BluetoothProfile;
Zhen Zhangb60e8ca2020-01-07 18:14:30 -080027import android.content.BroadcastReceiver;
28import android.content.Context;
29import android.content.Intent;
30import android.content.IntentFilter;
Zhen Zhangb60e8ca2020-01-07 18:14:30 -080031import android.net.wifi.SoftApConfiguration;
32import android.net.wifi.WifiManager;
33import android.os.Bundle;
Zhen Zhangb60e8ca2020-01-07 18:14:30 -080034import android.os.UserManager;
35import android.text.TextUtils;
Zhen Zhangd2a7f9a2020-01-30 15:12:50 -080036import android.util.FeatureFlagUtils;
Zhen Zhangb60e8ca2020-01-07 18:14:30 -080037import android.util.Log;
38
39import androidx.annotation.VisibleForTesting;
40import androidx.preference.Preference;
41import androidx.preference.PreferenceGroup;
42
Zhen Zhangd2a7f9a2020-01-30 15:12:50 -080043import com.android.settings.core.FeatureFlags;
Zhen Zhangb60e8ca2020-01-07 18:14:30 -080044import com.android.settings.dashboard.RestrictedDashboardFragment;
45import com.android.settings.datausage.DataSaverBackend;
Zhen Zhangaef1e8d2020-02-11 16:22:08 -080046import com.android.settings.network.BluetoothTetherPreferenceController;
Zhen Zhangb60e8ca2020-01-07 18:14:30 -080047import com.android.settings.network.TetherEnabler;
Zhen Zhangaef1e8d2020-02-11 16:22:08 -080048import com.android.settings.network.UsbTetherPreferenceController;
49import com.android.settings.network.WifiTetherDisablePreferenceController;
Zhen Zhangb60e8ca2020-01-07 18:14:30 -080050import com.android.settings.search.BaseSearchIndexProvider;
Zhen Zhang02dfed62020-01-13 14:57:23 -080051import com.android.settings.widget.SwitchBar;
52import com.android.settings.widget.SwitchBarController;
Zhen Zhangb60e8ca2020-01-07 18:14:30 -080053import com.android.settings.wifi.tether.WifiTetherApBandPreferenceController;
54import com.android.settings.wifi.tether.WifiTetherAutoOffPreferenceController;
55import com.android.settings.wifi.tether.WifiTetherBasePreferenceController;
Arc Wang005fe692020-03-04 21:03:54 +080056import com.android.settings.wifi.tether.WifiTetherFooterPreferenceController;
Zhen Zhangb60e8ca2020-01-07 18:14:30 -080057import com.android.settings.wifi.tether.WifiTetherPasswordPreferenceController;
58import com.android.settings.wifi.tether.WifiTetherSSIDPreferenceController;
59import com.android.settings.wifi.tether.WifiTetherSecurityPreferenceController;
60import com.android.settingslib.TetherUtil;
61import com.android.settingslib.core.AbstractPreferenceController;
62import com.android.settingslib.search.SearchIndexable;
63
64import java.util.ArrayList;
65import java.util.List;
Zhen Zhang02dfed62020-01-13 14:57:23 -080066import java.util.concurrent.atomic.AtomicReference;
Zhen Zhangb60e8ca2020-01-07 18:14:30 -080067
68/**
Zhen Zhang02dfed62020-01-13 14:57:23 -080069 * Displays preferences for all Tethering options.
Zhen Zhangb60e8ca2020-01-07 18:14:30 -080070 */
71@SearchIndexable
Arc Wang005fe692020-03-04 21:03:54 +080072public class AllInOneTetherSettings extends RestrictedDashboardFragment
Zhen Zhangb60e8ca2020-01-07 18:14:30 -080073 implements DataSaverBackend.Listener,
Zhen Zhang7f2d6ce2020-03-15 11:18:01 -070074 WifiTetherBasePreferenceController.OnTetherConfigUpdateListener {
Zhen Zhangb60e8ca2020-01-07 18:14:30 -080075
Zhen Zhangd2a7f9a2020-01-30 15:12:50 -080076 // TODO(b/148622133): Should clean up the postfix once this fragment replaced TetherSettings.
77 public static final String DEDUP_POSTFIX = "_2";
Zhen Zhangb60e8ca2020-01-07 18:14:30 -080078
Zhen Zhangd2a7f9a2020-01-30 15:12:50 -080079 @VisibleForTesting
80 static final String KEY_WIFI_TETHER_NETWORK_NAME = "wifi_tether_network_name" + DEDUP_POSTFIX;
81 @VisibleForTesting
82 static final String KEY_WIFI_TETHER_NETWORK_PASSWORD =
83 "wifi_tether_network_password" + DEDUP_POSTFIX;
84 @VisibleForTesting
85 static final String KEY_WIFI_TETHER_AUTO_OFF = "wifi_tether_auto_turn_off" + DEDUP_POSTFIX;
86 @VisibleForTesting
87 static final String KEY_WIFI_TETHER_NETWORK_AP_BAND =
88 "wifi_tether_network_ap_band" + DEDUP_POSTFIX;
89 @VisibleForTesting
90 static final String KEY_WIFI_TETHER_SECURITY = "wifi_tether_security" + DEDUP_POSTFIX;
91
92 private static final String KEY_DATA_SAVER_FOOTER = "disabled_on_data_saver" + DEDUP_POSTFIX;
Zhen Zhangb60e8ca2020-01-07 18:14:30 -080093 private static final String KEY_WIFI_TETHER_GROUP = "wifi_tether_settings_group";
Zhen Zhangb1d19a82020-03-25 13:33:45 -070094 @VisibleForTesting
95 static final int EXPANDED_CHILD_COUNT_DEFAULT = 3;
96 @VisibleForTesting
97 static final int EXPANDED_CHILD_COUNT_WITH_SECURITY_NON = 2;
98 @VisibleForTesting
99 static final int EXPANDED_CHILD_COUNT_WITHOUT_WIFI_CONFIG = 3;
Zhen Zhangb60e8ca2020-01-07 18:14:30 -0800100 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;
Zhen Zhang7f2d6ce2020-03-15 11:18:01 -0700117 private boolean mBluetoothTethering;
118 private boolean mUsbTethering;
119 private boolean mWifiTethering;
Zhen Zhang02dfed62020-01-13 14:57:23 -0800120 private TetherEnabler mTetherEnabler;
Zhen Zhang7f2d6ce2020-03-15 11:18:01 -0700121 private final TetherEnabler.OnTetherStateUpdateListener mStateUpdateListener =
122 state -> {
123 mBluetoothTethering = TetherEnabler.isBluetoothTethering(state);
124 mUsbTethering = TetherEnabler.isUsbTethering(state);
125 mWifiTethering = TetherEnabler.isWifiTethering(state);
126 mWifiTetherGroup.setVisible(shouldShowWifiConfig());
Zhen Zhang7f2d6ce2020-03-15 11:18:01 -0700127 };
Zhen Zhangb60e8ca2020-01-07 18:14:30 -0800128
129 private final BroadcastReceiver mTetherChangeReceiver = new BroadcastReceiver() {
130 @Override
131 public void onReceive(Context content, Intent intent) {
132 String action = intent.getAction();
133 if (Log.isLoggable(TAG, Log.DEBUG)) {
Zhen Zhangec966cb2020-02-05 12:52:35 -0800134 Log.d(TAG,
135 "updating display config due to receiving broadcast action " + action);
Zhen Zhangb60e8ca2020-01-07 18:14:30 -0800136 }
137 updateDisplayWithNewConfig();
138 if (TextUtils.equals(action, ACTION_TETHER_STATE_CHANGED)) {
Zhen Zhangec966cb2020-02-05 12:52:35 -0800139 restartWifiTetherIfNeed(mWifiManager.getWifiApState());
Zhen Zhangb60e8ca2020-01-07 18:14:30 -0800140 } else if (TextUtils.equals(action, WIFI_AP_STATE_CHANGED_ACTION)) {
Zhen Zhangec966cb2020-02-05 12:52:35 -0800141 restartWifiTetherIfNeed(intent.getIntExtra(WifiManager.EXTRA_WIFI_AP_STATE, 0));
142 }
143 }
144
145 private void restartWifiTetherIfNeed(int state) {
146 if (state == WifiManager.WIFI_AP_STATE_DISABLED
Zhen Zhangec966cb2020-02-05 12:52:35 -0800147 && mRestartWifiApAfterConfigChange) {
148 mRestartWifiApAfterConfigChange = false;
149 mTetherEnabler.startTethering(TETHERING_WIFI);
Zhen Zhangb60e8ca2020-01-07 18:14:30 -0800150 }
151 }
152 };
153
Zhen Zhang02dfed62020-01-13 14:57:23 -0800154 private final BluetoothProfile.ServiceListener mProfileServiceListener =
155 new BluetoothProfile.ServiceListener() {
156 public void onServiceConnected(int profile, BluetoothProfile proxy) {
157 mBluetoothPan.set((BluetoothPan) proxy);
158 }
159
160 public void onServiceDisconnected(int profile) {
161 mBluetoothPan.set(null);
162 }
163 };
164
Zhen Zhangb60e8ca2020-01-07 18:14:30 -0800165 @Override
166 public int getMetricsCategory() {
167 return SettingsEnums.TETHER;
168 }
169
170 public AllInOneTetherSettings() {
171 super(UserManager.DISALLOW_CONFIG_TETHERING);
172 }
173
174 @Override
175 public void onAttach(Context context) {
176 super.onAttach(context);
177 mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
Zhen Zhangb60e8ca2020-01-07 18:14:30 -0800178
179 mSSIDPreferenceController = use(WifiTetherSSIDPreferenceController.class);
180 mSecurityPreferenceController = use(WifiTetherSecurityPreferenceController.class);
181 mPasswordPreferenceController = use(WifiTetherPasswordPreferenceController.class);
182 mApBandPreferenceController = use(WifiTetherApBandPreferenceController.class);
Zhen Zhangaef1e8d2020-02-11 16:22:08 -0800183 getSettingsLifecycle().addObserver(use(UsbTetherPreferenceController.class));
184 getSettingsLifecycle().addObserver(use(BluetoothTetherPreferenceController.class));
185 getSettingsLifecycle().addObserver(use(WifiTetherDisablePreferenceController.class));
Zhen Zhangb60e8ca2020-01-07 18:14:30 -0800186 }
187
188 @Override
189 public void onCreate(Bundle icicle) {
190 super.onCreate(icicle);
191
192 mDataSaverBackend = new DataSaverBackend(getContext());
193 mDataSaverEnabled = mDataSaverBackend.isDataSaverEnabled();
194 mDataSaverFooter = findPreference(KEY_DATA_SAVER_FOOTER);
195 mWifiTetherGroup = findPreference(KEY_WIFI_TETHER_GROUP);
196
197 setIfOnlyAvailableForAdmins(true);
198 if (isUiRestricted()) {
199 mUnavailable = true;
200 return;
201 }
202
203 mDataSaverBackend.addListener(this);
204
205 // Set initial state based on Data Saver mode.
206 onDataSaverChanged(mDataSaverBackend.isDataSaverEnabled());
Zhen Zhangb60e8ca2020-01-07 18:14:30 -0800207 }
208
209 @Override
Zhen Zhang02dfed62020-01-13 14:57:23 -0800210 public void onActivityCreated(Bundle savedInstanceState) {
211 super.onActivityCreated(savedInstanceState);
212 if (mUnavailable) {
213 return;
214 }
215 // Assume we are in a SettingsActivity. This is only safe because we currently use
216 // SettingsActivity as base for all preference fragments.
217 final SettingsActivity activity = (SettingsActivity) getActivity();
Zhen Zhang0ccc8492020-01-17 15:23:40 -0800218 final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
Zhen Zhang02dfed62020-01-13 14:57:23 -0800219 if (adapter != null) {
220 adapter.getProfileProxy(activity.getApplicationContext(), mProfileServiceListener,
221 BluetoothProfile.PAN);
222 }
223 final SwitchBar switchBar = activity.getSwitchBar();
224 mTetherEnabler = new TetherEnabler(activity,
225 new SwitchBarController(switchBar), mBluetoothPan);
226 getSettingsLifecycle().addObserver(mTetherEnabler);
Zhen Zhang7f2d6ce2020-03-15 11:18:01 -0700227 use(UsbTetherPreferenceController.class).setTetherEnabler(mTetherEnabler);
228 use(BluetoothTetherPreferenceController.class).setTetherEnabler(mTetherEnabler);
229 use(WifiTetherDisablePreferenceController.class).setTetherEnabler(mTetherEnabler);
Zhen Zhang02dfed62020-01-13 14:57:23 -0800230 switchBar.show();
231 }
232
233 @Override
Zhen Zhangb60e8ca2020-01-07 18:14:30 -0800234 public void onStart() {
235 super.onStart();
236
237 if (mUnavailable) {
238 if (!isUiRestrictedByOnlyAdmin()) {
239 getEmptyTextView().setText(R.string.tethering_settings_not_available);
240 }
241 getPreferenceScreen().removeAll();
242 return;
243 }
244 final Context context = getContext();
245 if (context != null) {
246 IntentFilter filter = new IntentFilter(ACTION_TETHER_STATE_CHANGED);
247 filter.addAction(WIFI_AP_STATE_CHANGED_ACTION);
248 context.registerReceiver(mTetherChangeReceiver, filter);
249 }
250 }
251
252 @Override
253 public void onResume() {
254 super.onResume();
Zhen Zhang3b53b802020-03-23 12:18:14 -0700255 if (mUnavailable) {
256 return;
257 }
258 if (mTetherEnabler != null) {
259 mTetherEnabler.addListener(mStateUpdateListener);
260 }
Zhen Zhangb60e8ca2020-01-07 18:14:30 -0800261 }
262
263 @Override
264 public void onPause() {
265 super.onPause();
Zhen Zhang3b53b802020-03-23 12:18:14 -0700266 if (mUnavailable) {
267 return;
268 }
269 if (mTetherEnabler != null) {
270 mTetherEnabler.removeListener(mStateUpdateListener);
271 }
Zhen Zhangb60e8ca2020-01-07 18:14:30 -0800272 }
273
274 @Override
275 public void onStop() {
276 super.onStop();
Zhen Zhang3b53b802020-03-23 12:18:14 -0700277 if (mUnavailable) {
278 return;
279 }
Zhen Zhangb60e8ca2020-01-07 18:14:30 -0800280 final Context context = getContext();
281 if (context != null) {
282 context.unregisterReceiver(mTetherChangeReceiver);
283 }
284 }
285
286 @Override
287 public void onDestroy() {
288 mDataSaverBackend.remListener(this);
289 super.onDestroy();
290 }
291
292 @Override
293 public void onDataSaverChanged(boolean isDataSaving) {
294 mDataSaverEnabled = isDataSaving;
295 mDataSaverFooter.setVisible(mDataSaverEnabled);
296 }
297
298 @Override
299 public void onWhitelistStatusChanged(int uid, boolean isWhitelisted) {
300 // Do nothing
301 }
302
303 @Override
304 public void onBlacklistStatusChanged(int uid, boolean isBlacklisted) {
305 // Do nothing
306 }
307
308 @Override
309 protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
310 return buildPreferenceControllers(context, this);
311 }
312
313 private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
314 WifiTetherBasePreferenceController.OnTetherConfigUpdateListener listener) {
315 final List<AbstractPreferenceController> controllers = new ArrayList<>();
316 controllers.add(
317 new WifiTetherSSIDPreferenceController(context, listener));
318 controllers.add(
319 new WifiTetherPasswordPreferenceController(context, listener));
320 controllers.add(
321 new WifiTetherApBandPreferenceController(context, listener));
322 controllers.add(
323 new WifiTetherSecurityPreferenceController(context, listener));
324 controllers.add(
325 new WifiTetherAutoOffPreferenceController(context, KEY_WIFI_TETHER_AUTO_OFF));
Arc Wang005fe692020-03-04 21:03:54 +0800326 controllers.add(
327 new WifiTetherFooterPreferenceController(context));
Zhen Zhangb60e8ca2020-01-07 18:14:30 -0800328
329 return controllers;
330 }
331
332 @Override
333 protected int getPreferenceScreenResId() {
334 return R.xml.all_tether_prefs;
335 }
336
337 @Override
338 protected String getLogTag() {
339 return TAG;
340 }
341
342 @Override
Zhen Zhangb60e8ca2020-01-07 18:14:30 -0800343 public int getHelpResource() {
344 return R.string.help_url_tether;
345 }
346
347 @Override
348 public void onTetherConfigUpdated(AbstractPreferenceController controller) {
349 final SoftApConfiguration config = buildNewConfig();
350 mPasswordPreferenceController.updateVisibility(config.getSecurityType());
351 mWifiManager.setSoftApConfiguration(config);
352
353 if (mWifiManager.getWifiApState() == WifiManager.WIFI_AP_STATE_ENABLED) {
354 if (Log.isLoggable(TAG, Log.DEBUG)) {
355 Log.d(TAG, "Wifi AP config changed while enabled, stop and restart");
356 }
357 mRestartWifiApAfterConfigChange = true;
Zhen Zhang02dfed62020-01-13 14:57:23 -0800358 mTetherEnabler.stopTethering(TETHERING_WIFI);
Zhen Zhangb60e8ca2020-01-07 18:14:30 -0800359 }
Zhen Zhangb60e8ca2020-01-07 18:14:30 -0800360 }
361
362 private SoftApConfiguration buildNewConfig() {
363 final SoftApConfiguration.Builder configBuilder = new SoftApConfiguration.Builder();
364 final int securityType = mSecurityPreferenceController.getSecurityType();
365 configBuilder.setSsid(mSSIDPreferenceController.getSSID());
366 if (securityType == SoftApConfiguration.SECURITY_TYPE_WPA2_PSK) {
367 configBuilder.setPassphrase(
368 mPasswordPreferenceController.getPasswordValidated(securityType),
369 SoftApConfiguration.SECURITY_TYPE_WPA2_PSK);
370 }
371 configBuilder.setBand(mApBandPreferenceController.getBandIndex());
372 return configBuilder.build();
373 }
374
375 private void updateDisplayWithNewConfig() {
376 mSSIDPreferenceController.updateDisplay();
377 mSecurityPreferenceController.updateDisplay();
378 mPasswordPreferenceController.updateDisplay();
379 mApBandPreferenceController.updateDisplay();
380 }
381
Zhen Zhang7f2d6ce2020-03-15 11:18:01 -0700382 private boolean shouldShowWifiConfig() {
383 return mWifiTethering || (!mBluetoothTethering && !mUsbTethering);
Zhen Zhangb60e8ca2020-01-07 18:14:30 -0800384 }
385
Zhen Zhangb60e8ca2020-01-07 18:14:30 -0800386 @Override
387 public int getInitialExpandedChildCount() {
Zhen Zhang7f2d6ce2020-03-15 11:18:01 -0700388 if (!shouldShowWifiConfig()) {
Zhen Zhangb1d19a82020-03-25 13:33:45 -0700389 return EXPANDED_CHILD_COUNT_WITHOUT_WIFI_CONFIG;
Zhen Zhangb60e8ca2020-01-07 18:14:30 -0800390 }
391
392 if (mSecurityPreferenceController == null) {
393 return EXPANDED_CHILD_COUNT_DEFAULT;
394 }
395
396 return (mSecurityPreferenceController.getSecurityType()
397 == SoftApConfiguration.SECURITY_TYPE_OPEN)
398 ? EXPANDED_CHILD_COUNT_WITH_SECURITY_NON : EXPANDED_CHILD_COUNT_DEFAULT;
399 }
400
401 public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
402 new BaseSearchIndexProvider(R.xml.all_tether_prefs) {
403
404 @Override
405 public List<String> getNonIndexableKeys(Context context) {
406 final List<String> keys = super.getNonIndexableKeys(context);
407
408 if (!TetherUtil.isTetherAvailable(context)) {
Zhen Zhangb60e8ca2020-01-07 18:14:30 -0800409 keys.add(KEY_WIFI_TETHER_NETWORK_NAME);
410 keys.add(KEY_WIFI_TETHER_NETWORK_PASSWORD);
411 keys.add(KEY_WIFI_TETHER_AUTO_OFF);
412 keys.add(KEY_WIFI_TETHER_NETWORK_AP_BAND);
Zhen Zhangd2a7f9a2020-01-30 15:12:50 -0800413 keys.add(KEY_WIFI_TETHER_SECURITY);
Zhen Zhangb60e8ca2020-01-07 18:14:30 -0800414 }
Zhen Zhangb60e8ca2020-01-07 18:14:30 -0800415 return keys;
416 }
417
418 @Override
Zhen Zhang0ccc8492020-01-17 15:23:40 -0800419 protected boolean isPageSearchEnabled(Context context) {
Zhen Zhangd2a7f9a2020-01-30 15:12:50 -0800420 return FeatureFlagUtils.isEnabled(context, FeatureFlags.TETHER_ALL_IN_ONE);
Zhen Zhang0ccc8492020-01-17 15:23:40 -0800421 }
422
423 @Override
Zhen Zhangb60e8ca2020-01-07 18:14:30 -0800424 public List<AbstractPreferenceController> createPreferenceControllers(
425 Context context) {
Zhen Zhangec966cb2020-02-05 12:52:35 -0800426 return buildPreferenceControllers(context, null /*listener*/);
Zhen Zhangb60e8ca2020-01-07 18:14:30 -0800427 }
428 };
429}