blob: 4576fb762b6ffc7ea3a5fd7afa0d1e0f62af665f [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;
59import com.android.settings.wifi.tether.WifiTetherPasswordPreferenceController;
60import com.android.settings.wifi.tether.WifiTetherSSIDPreferenceController;
61import com.android.settings.wifi.tether.WifiTetherSecurityPreferenceController;
62import com.android.settingslib.TetherUtil;
63import com.android.settingslib.core.AbstractPreferenceController;
64import com.android.settingslib.search.SearchIndexable;
65
66import java.util.ArrayList;
67import java.util.List;
Zhen Zhang02dfed62020-01-13 14:57:23 -080068import java.util.concurrent.atomic.AtomicReference;
Zhen Zhangb60e8ca2020-01-07 18:14:30 -080069
70/**
Zhen Zhang02dfed62020-01-13 14:57:23 -080071 * Displays preferences for all Tethering options.
Zhen Zhangb60e8ca2020-01-07 18:14:30 -080072 */
73@SearchIndexable
74public final class AllInOneTetherSettings extends RestrictedDashboardFragment
75 implements DataSaverBackend.Listener,
76 WifiTetherBasePreferenceController.OnTetherConfigUpdateListener,
77 SharedPreferences.OnSharedPreferenceChangeListener {
78
Zhen Zhangd2a7f9a2020-01-30 15:12:50 -080079 // TODO(b/148622133): Should clean up the postfix once this fragment replaced TetherSettings.
80 public static final String DEDUP_POSTFIX = "_2";
Zhen Zhangb60e8ca2020-01-07 18:14:30 -080081
Zhen Zhangd2a7f9a2020-01-30 15:12:50 -080082 @VisibleForTesting
83 static final String KEY_WIFI_TETHER_NETWORK_NAME = "wifi_tether_network_name" + DEDUP_POSTFIX;
84 @VisibleForTesting
85 static final String KEY_WIFI_TETHER_NETWORK_PASSWORD =
86 "wifi_tether_network_password" + DEDUP_POSTFIX;
87 @VisibleForTesting
88 static final String KEY_WIFI_TETHER_AUTO_OFF = "wifi_tether_auto_turn_off" + DEDUP_POSTFIX;
89 @VisibleForTesting
90 static final String KEY_WIFI_TETHER_NETWORK_AP_BAND =
91 "wifi_tether_network_ap_band" + DEDUP_POSTFIX;
92 @VisibleForTesting
93 static final String KEY_WIFI_TETHER_SECURITY = "wifi_tether_security" + DEDUP_POSTFIX;
94
95 private static final String KEY_DATA_SAVER_FOOTER = "disabled_on_data_saver" + DEDUP_POSTFIX;
Zhen Zhangb60e8ca2020-01-07 18:14:30 -080096 private static final String KEY_WIFI_TETHER_GROUP = "wifi_tether_settings_group";
Zhen Zhangb60e8ca2020-01-07 18:14:30 -080097 private static final int EXPANDED_CHILD_COUNT_WITH_SECURITY_NON = 2;
98 private static final int EXPANDED_CHILD_COUNT_DEFAULT = 3;
99 private static final String TAG = "AllInOneTetherSettings";
100
101 private boolean mUnavailable;
102
103 private DataSaverBackend mDataSaverBackend;
104 private boolean mDataSaverEnabled;
105 private Preference mDataSaverFooter;
106
107 private WifiManager mWifiManager;
108 private boolean mRestartWifiApAfterConfigChange;
Zhen Zhang02dfed62020-01-13 14:57:23 -0800109 private final AtomicReference<BluetoothPan> mBluetoothPan = new AtomicReference<>();
Zhen Zhangb60e8ca2020-01-07 18:14:30 -0800110
111 private WifiTetherSSIDPreferenceController mSSIDPreferenceController;
112 private WifiTetherPasswordPreferenceController mPasswordPreferenceController;
113 private WifiTetherApBandPreferenceController mApBandPreferenceController;
114 private WifiTetherSecurityPreferenceController mSecurityPreferenceController;
115 private PreferenceGroup mWifiTetherGroup;
116 private SharedPreferences mSharedPreferences;
Zhen Zhangb60e8ca2020-01-07 18:14:30 -0800117 private boolean mWifiTetherChosen;
Zhen Zhang02dfed62020-01-13 14:57:23 -0800118 private TetherEnabler mTetherEnabler;
Zhen Zhangb60e8ca2020-01-07 18:14:30 -0800119
120 private final BroadcastReceiver mTetherChangeReceiver = new BroadcastReceiver() {
121 @Override
122 public void onReceive(Context content, Intent intent) {
123 String action = intent.getAction();
124 if (Log.isLoggable(TAG, Log.DEBUG)) {
Zhen Zhangec966cb2020-02-05 12:52:35 -0800125 Log.d(TAG,
126 "updating display config due to receiving broadcast action " + action);
Zhen Zhangb60e8ca2020-01-07 18:14:30 -0800127 }
128 updateDisplayWithNewConfig();
129 if (TextUtils.equals(action, ACTION_TETHER_STATE_CHANGED)) {
Zhen Zhangec966cb2020-02-05 12:52:35 -0800130 restartWifiTetherIfNeed(mWifiManager.getWifiApState());
Zhen Zhangb60e8ca2020-01-07 18:14:30 -0800131 } else if (TextUtils.equals(action, WIFI_AP_STATE_CHANGED_ACTION)) {
Zhen Zhangec966cb2020-02-05 12:52:35 -0800132 restartWifiTetherIfNeed(intent.getIntExtra(WifiManager.EXTRA_WIFI_AP_STATE, 0));
133 }
134 }
135
136 private void restartWifiTetherIfNeed(int state) {
137 if (state == WifiManager.WIFI_AP_STATE_DISABLED
138 && mWifiTetherChosen
139 && mRestartWifiApAfterConfigChange) {
140 mRestartWifiApAfterConfigChange = false;
141 mTetherEnabler.startTethering(TETHERING_WIFI);
Zhen Zhangb60e8ca2020-01-07 18:14:30 -0800142 }
143 }
144 };
145
Zhen Zhang02dfed62020-01-13 14:57:23 -0800146 private final BluetoothProfile.ServiceListener mProfileServiceListener =
147 new BluetoothProfile.ServiceListener() {
148 public void onServiceConnected(int profile, BluetoothProfile proxy) {
149 mBluetoothPan.set((BluetoothPan) proxy);
150 }
151
152 public void onServiceDisconnected(int profile) {
153 mBluetoothPan.set(null);
154 }
155 };
156
Zhen Zhangb60e8ca2020-01-07 18:14:30 -0800157 @Override
158 public int getMetricsCategory() {
159 return SettingsEnums.TETHER;
160 }
161
162 public AllInOneTetherSettings() {
163 super(UserManager.DISALLOW_CONFIG_TETHERING);
164 }
165
166 @Override
167 public void onAttach(Context context) {
168 super.onAttach(context);
169 mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
Zhen Zhangb60e8ca2020-01-07 18:14:30 -0800170 mSharedPreferences =
171 context.getSharedPreferences(TetherEnabler.SHARED_PREF, Context.MODE_PRIVATE);
172
173 mSSIDPreferenceController = use(WifiTetherSSIDPreferenceController.class);
174 mSecurityPreferenceController = use(WifiTetherSecurityPreferenceController.class);
175 mPasswordPreferenceController = use(WifiTetherPasswordPreferenceController.class);
176 mApBandPreferenceController = use(WifiTetherApBandPreferenceController.class);
Zhen Zhangaef1e8d2020-02-11 16:22:08 -0800177 getSettingsLifecycle().addObserver(use(UsbTetherPreferenceController.class));
178 getSettingsLifecycle().addObserver(use(BluetoothTetherPreferenceController.class));
179 getSettingsLifecycle().addObserver(use(WifiTetherDisablePreferenceController.class));
Zhen Zhangb60e8ca2020-01-07 18:14:30 -0800180 }
181
182 @Override
183 public void onCreate(Bundle icicle) {
184 super.onCreate(icicle);
185
186 mDataSaverBackend = new DataSaverBackend(getContext());
187 mDataSaverEnabled = mDataSaverBackend.isDataSaverEnabled();
188 mDataSaverFooter = findPreference(KEY_DATA_SAVER_FOOTER);
189 mWifiTetherGroup = findPreference(KEY_WIFI_TETHER_GROUP);
190
191 setIfOnlyAvailableForAdmins(true);
192 if (isUiRestricted()) {
193 mUnavailable = true;
194 return;
195 }
196
197 mDataSaverBackend.addListener(this);
198
199 // Set initial state based on Data Saver mode.
200 onDataSaverChanged(mDataSaverBackend.isDataSaverEnabled());
201
202 // Set initial state based on SharedPreferences value.
203 onSharedPreferenceChanged(mSharedPreferences, KEY_ENABLE_WIFI_TETHERING);
204
205 // TODO(b/147325229): Hide advanced settings like security and ap band.
206 }
207
208 @Override
Zhen Zhang02dfed62020-01-13 14:57:23 -0800209 public void onActivityCreated(Bundle savedInstanceState) {
210 super.onActivityCreated(savedInstanceState);
211 if (mUnavailable) {
212 return;
213 }
214 // Assume we are in a SettingsActivity. This is only safe because we currently use
215 // SettingsActivity as base for all preference fragments.
216 final SettingsActivity activity = (SettingsActivity) getActivity();
Zhen Zhang0ccc8492020-01-17 15:23:40 -0800217 final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
Zhen Zhang02dfed62020-01-13 14:57:23 -0800218 if (adapter != null) {
219 adapter.getProfileProxy(activity.getApplicationContext(), mProfileServiceListener,
220 BluetoothProfile.PAN);
221 }
222 final SwitchBar switchBar = activity.getSwitchBar();
223 mTetherEnabler = new TetherEnabler(activity,
224 new SwitchBarController(switchBar), mBluetoothPan);
225 getSettingsLifecycle().addObserver(mTetherEnabler);
226 switchBar.show();
227 }
228
229 @Override
Zhen Zhangb60e8ca2020-01-07 18:14:30 -0800230 public void onStart() {
231 super.onStart();
232
233 if (mUnavailable) {
234 if (!isUiRestrictedByOnlyAdmin()) {
235 getEmptyTextView().setText(R.string.tethering_settings_not_available);
236 }
237 getPreferenceScreen().removeAll();
238 return;
239 }
240 final Context context = getContext();
241 if (context != null) {
242 IntentFilter filter = new IntentFilter(ACTION_TETHER_STATE_CHANGED);
243 filter.addAction(WIFI_AP_STATE_CHANGED_ACTION);
244 context.registerReceiver(mTetherChangeReceiver, filter);
245 }
246 }
247
248 @Override
249 public void onResume() {
250 super.onResume();
251 mSharedPreferences.registerOnSharedPreferenceChangeListener(this);
252 }
253
254 @Override
255 public void onPause() {
256 super.onPause();
257 mSharedPreferences.unregisterOnSharedPreferenceChangeListener(this);
258 }
259
260 @Override
261 public void onStop() {
262 super.onStop();
263 final Context context = getContext();
264 if (context != null) {
265 context.unregisterReceiver(mTetherChangeReceiver);
266 }
267 }
268
269 @Override
270 public void onDestroy() {
271 mDataSaverBackend.remListener(this);
272 super.onDestroy();
273 }
274
275 @Override
276 public void onDataSaverChanged(boolean isDataSaving) {
277 mDataSaverEnabled = isDataSaving;
278 mDataSaverFooter.setVisible(mDataSaverEnabled);
279 }
280
281 @Override
282 public void onWhitelistStatusChanged(int uid, boolean isWhitelisted) {
283 // Do nothing
284 }
285
286 @Override
287 public void onBlacklistStatusChanged(int uid, boolean isBlacklisted) {
288 // Do nothing
289 }
290
291 @Override
292 protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
293 return buildPreferenceControllers(context, this);
294 }
295
296 private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
297 WifiTetherBasePreferenceController.OnTetherConfigUpdateListener listener) {
298 final List<AbstractPreferenceController> controllers = new ArrayList<>();
299 controllers.add(
300 new WifiTetherSSIDPreferenceController(context, listener));
301 controllers.add(
302 new WifiTetherPasswordPreferenceController(context, listener));
303 controllers.add(
304 new WifiTetherApBandPreferenceController(context, listener));
305 controllers.add(
306 new WifiTetherSecurityPreferenceController(context, listener));
307 controllers.add(
308 new WifiTetherAutoOffPreferenceController(context, KEY_WIFI_TETHER_AUTO_OFF));
309
310 return controllers;
311 }
312
313 @Override
314 protected int getPreferenceScreenResId() {
315 return R.xml.all_tether_prefs;
316 }
317
318 @Override
319 protected String getLogTag() {
320 return TAG;
321 }
322
323 @Override
324 public void onExpandButtonClick() {
325 super.onExpandButtonClick();
326 // TODO(b/147325229): Display hidden advanced settings like security and ap band.
327 }
328
329 @Override
330 public int getHelpResource() {
331 return R.string.help_url_tether;
332 }
333
334 @Override
335 public void onTetherConfigUpdated(AbstractPreferenceController controller) {
336 final SoftApConfiguration config = buildNewConfig();
337 mPasswordPreferenceController.updateVisibility(config.getSecurityType());
338 mWifiManager.setSoftApConfiguration(config);
339
340 if (mWifiManager.getWifiApState() == WifiManager.WIFI_AP_STATE_ENABLED) {
341 if (Log.isLoggable(TAG, Log.DEBUG)) {
342 Log.d(TAG, "Wifi AP config changed while enabled, stop and restart");
343 }
344 mRestartWifiApAfterConfigChange = true;
Zhen Zhang02dfed62020-01-13 14:57:23 -0800345 mTetherEnabler.stopTethering(TETHERING_WIFI);
Zhen Zhangb60e8ca2020-01-07 18:14:30 -0800346 }
347
348 if (controller instanceof WifiTetherSecurityPreferenceController) {
349 reConfigInitialExpandedChildCount();
350 }
351 }
352
353 private SoftApConfiguration buildNewConfig() {
354 final SoftApConfiguration.Builder configBuilder = new SoftApConfiguration.Builder();
355 final int securityType = mSecurityPreferenceController.getSecurityType();
356 configBuilder.setSsid(mSSIDPreferenceController.getSSID());
357 if (securityType == SoftApConfiguration.SECURITY_TYPE_WPA2_PSK) {
358 configBuilder.setPassphrase(
359 mPasswordPreferenceController.getPasswordValidated(securityType),
360 SoftApConfiguration.SECURITY_TYPE_WPA2_PSK);
361 }
362 configBuilder.setBand(mApBandPreferenceController.getBandIndex());
363 return configBuilder.build();
364 }
365
366 private void updateDisplayWithNewConfig() {
367 mSSIDPreferenceController.updateDisplay();
368 mSecurityPreferenceController.updateDisplay();
369 mPasswordPreferenceController.updateDisplay();
370 mApBandPreferenceController.updateDisplay();
371 }
372
373 @Override
374 public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
375 if (TextUtils.equals(key, KEY_ENABLE_WIFI_TETHERING)) {
376 mWifiTetherChosen = sharedPreferences.getBoolean(KEY_ENABLE_WIFI_TETHERING, true);
377 mWifiTetherGroup.setVisible(mWifiTetherChosen);
378 reConfigInitialExpandedChildCount();
379 }
380 }
381
Zhen Zhangb60e8ca2020-01-07 18:14:30 -0800382 private void reConfigInitialExpandedChildCount() {
383 getPreferenceScreen().setInitialExpandedChildrenCount(getInitialExpandedChildCount());
384 }
385
386 @Override
387 public int getInitialExpandedChildCount() {
388 if (!mWifiTetherChosen) {
389 // Expand all preferences in the screen.
390 return getPreferenceScreen().getPreferenceCount();
391 }
392
393 if (mSecurityPreferenceController == null) {
394 return EXPANDED_CHILD_COUNT_DEFAULT;
395 }
396
397 return (mSecurityPreferenceController.getSecurityType()
398 == SoftApConfiguration.SECURITY_TYPE_OPEN)
399 ? EXPANDED_CHILD_COUNT_WITH_SECURITY_NON : EXPANDED_CHILD_COUNT_DEFAULT;
400 }
401
402 public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
403 new BaseSearchIndexProvider(R.xml.all_tether_prefs) {
404
405 @Override
406 public List<String> getNonIndexableKeys(Context context) {
407 final List<String> keys = super.getNonIndexableKeys(context);
408
409 if (!TetherUtil.isTetherAvailable(context)) {
Zhen Zhangb60e8ca2020-01-07 18:14:30 -0800410 keys.add(KEY_WIFI_TETHER_NETWORK_NAME);
411 keys.add(KEY_WIFI_TETHER_NETWORK_PASSWORD);
412 keys.add(KEY_WIFI_TETHER_AUTO_OFF);
413 keys.add(KEY_WIFI_TETHER_NETWORK_AP_BAND);
Zhen Zhangd2a7f9a2020-01-30 15:12:50 -0800414 keys.add(KEY_WIFI_TETHER_SECURITY);
Zhen Zhangb60e8ca2020-01-07 18:14:30 -0800415 }
Zhen Zhangb60e8ca2020-01-07 18:14:30 -0800416 return keys;
417 }
418
419 @Override
Zhen Zhang0ccc8492020-01-17 15:23:40 -0800420 protected boolean isPageSearchEnabled(Context context) {
Zhen Zhangd2a7f9a2020-01-30 15:12:50 -0800421 return FeatureFlagUtils.isEnabled(context, FeatureFlags.TETHER_ALL_IN_ONE);
Zhen Zhang0ccc8492020-01-17 15:23:40 -0800422 }
423
424 @Override
Zhen Zhangb60e8ca2020-01-07 18:14:30 -0800425 public List<AbstractPreferenceController> createPreferenceControllers(
426 Context context) {
Zhen Zhangec966cb2020-02-05 12:52:35 -0800427 return buildPreferenceControllers(context, null /*listener*/);
Zhen Zhangb60e8ca2020-01-07 18:14:30 -0800428 }
429 };
430}