Files
packages_apps_Settings/src/com/android/settings/network/TetherPreferenceController.java
Juan Lang 777ed2535a Depend on SettingsLib's version of lifecycle and FooterMixin.
The implementations have been imported into SettingsLib. Setting's copy
can now be removed, which this change also does.

Test: Manually check battery status, which uses FooterMixin, looks OK.
make RunSettingsLibRobotTests && make RunSettingsRoboTests
     && make RunSettingsGoogleRoboTests
Change-Id: I6539605fdad80d156ff5ff249e68df4a1c412067
2017-05-12 11:10:46 -07:00

242 lines
9.2 KiB
Java

/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.network;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothPan;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.database.ContentObserver;
import android.net.ConnectivityManager;
import android.net.Uri;
import android.os.Handler;
import android.os.UserHandle;
import android.provider.Settings;
import android.support.annotation.VisibleForTesting;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settings.TetherSettings;
import com.android.settings.core.PreferenceController;
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnDestroy;
import com.android.settingslib.core.lifecycle.events.OnPause;
import com.android.settingslib.core.lifecycle.events.OnResume;
import java.util.concurrent.atomic.AtomicReference;
import static android.os.UserManager.DISALLOW_CONFIG_TETHERING;
import static com.android.settingslib.RestrictedLockUtils.checkIfRestrictionEnforced;
import static com.android.settingslib.RestrictedLockUtils.hasBaseUserRestriction;
public class TetherPreferenceController extends PreferenceController
implements LifecycleObserver, OnResume, OnPause, OnDestroy {
private static final String KEY_TETHER_SETTINGS = "tether_settings";
private final boolean mAdminDisallowedTetherConfig;
private final AtomicReference<BluetoothPan> mBluetoothPan;
private final ConnectivityManager mConnectivityManager;
private final BluetoothAdapter mBluetoothAdapter;
private final BluetoothProfile.ServiceListener mBtProfileServiceListener =
new android.bluetooth.BluetoothProfile.ServiceListener() {
public void onServiceConnected(int profile, BluetoothProfile proxy) {
mBluetoothPan.set((BluetoothPan) proxy);
updateSummary();
}
public void onServiceDisconnected(int profile) {
mBluetoothPan.set(null);
}
};
private SettingObserver mAirplaneModeObserver;
private Preference mPreference;
@VisibleForTesting(otherwise = VisibleForTesting.NONE)
TetherPreferenceController() {
super(null);
mAdminDisallowedTetherConfig = false;
mBluetoothPan = new AtomicReference<>();
mConnectivityManager = null;
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
}
public TetherPreferenceController(Context context, Lifecycle lifecycle) {
super(context);
mBluetoothPan = new AtomicReference<>();
mAdminDisallowedTetherConfig = checkIfRestrictionEnforced(
context, DISALLOW_CONFIG_TETHERING, UserHandle.myUserId()) != null;
mConnectivityManager =
(ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (lifecycle != null) {
lifecycle.addObserver(this);
}
if (mBluetoothAdapter != null) {
mBluetoothAdapter.getProfileProxy(context, mBtProfileServiceListener,
BluetoothProfile.PAN);
}
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mPreference = screen.findPreference(KEY_TETHER_SETTINGS);
if (mPreference != null && !mAdminDisallowedTetherConfig) {
mPreference.setTitle(
com.android.settingslib.Utils.getTetheringLabel(mConnectivityManager));
// Grey out if provisioning is not available.
mPreference.setEnabled(!TetherSettings.isProvisioningNeededButUnavailable(mContext));
}
}
@Override
public boolean isAvailable() {
final boolean isBlocked =
(!mConnectivityManager.isTetheringSupported() && !mAdminDisallowedTetherConfig)
|| hasBaseUserRestriction(mContext, DISALLOW_CONFIG_TETHERING,
UserHandle.myUserId());
return !isBlocked;
}
@Override
public void updateState(Preference preference) {
updateSummary();
}
@Override
public String getPreferenceKey() {
return KEY_TETHER_SETTINGS;
}
@Override
public void onResume() {
if (mAirplaneModeObserver == null) {
mAirplaneModeObserver = new SettingObserver();
}
mContext.getContentResolver()
.registerContentObserver(mAirplaneModeObserver.uri, false, mAirplaneModeObserver);
}
@Override
public void onPause() {
if (mAirplaneModeObserver != null) {
mContext.getContentResolver().unregisterContentObserver(mAirplaneModeObserver);
}
}
@Override
public void onDestroy() {
final BluetoothProfile profile = mBluetoothPan.getAndSet(null);
if (profile != null && mBluetoothAdapter != null) {
mBluetoothAdapter.closeProfileProxy(BluetoothProfile.PAN, profile);
}
}
@VisibleForTesting
void updateSummary() {
if (mPreference == null) {
// Preference is not ready yet.
return;
}
String[] allTethered = mConnectivityManager.getTetheredIfaces();
String[] wifiTetherRegex = mConnectivityManager.getTetherableWifiRegexs();
String[] bluetoothRegex = mConnectivityManager.getTetherableBluetoothRegexs();
boolean hotSpotOn = false;
boolean tetherOn = false;
if (allTethered != null) {
if (wifiTetherRegex != null) {
for (String tethered : allTethered) {
for (String regex : wifiTetherRegex) {
if (tethered.matches(regex)) {
hotSpotOn = true;
break;
}
}
}
}
if (allTethered.length > 1) {
// We have more than 1 tethered connection
tetherOn = true;
} else if (allTethered.length == 1) {
// We have more than 1 tethered, it's either wifiTether (hotspot), or other type of
// tether.
tetherOn = !hotSpotOn;
} else {
// No tethered connection.
tetherOn = false;
}
}
if (!tetherOn
&& bluetoothRegex != null && bluetoothRegex.length > 0
&& mBluetoothAdapter != null
&& mBluetoothAdapter.getState() == BluetoothAdapter.STATE_ON) {
// Check bluetooth state. It's not included in mConnectivityManager.getTetheredIfaces.
final BluetoothPan pan = mBluetoothPan.get();
tetherOn = pan != null && pan.isTetheringOn();
}
if (!hotSpotOn && !tetherOn) {
// Both off
mPreference.setSummary(R.string.switch_off_text);
} else if (hotSpotOn && tetherOn) {
// Both on
mPreference.setSummary(R.string.tether_settings_summary_hotspot_on_tether_on);
} else if (hotSpotOn) {
mPreference.setSummary(R.string.tether_settings_summary_hotspot_on_tether_off);
} else {
mPreference.setSummary(R.string.tether_settings_summary_hotspot_off_tether_on);
}
}
private void updateSummaryToOff() {
if (mPreference == null) {
// Preference is not ready yet.
return;
}
mPreference.setSummary(R.string.switch_off_text);
}
class SettingObserver extends ContentObserver {
public final Uri uri;
public SettingObserver() {
super(new Handler());
uri = Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON);
}
@Override
public void onChange(boolean selfChange, Uri uri) {
super.onChange(selfChange, uri);
if (this.uri.equals(uri)) {
boolean isAirplaneMode = Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.AIRPLANE_MODE_ON, 0) != 0;
if (isAirplaneMode) {
// Airplane mode is on. Update summary to say tether is OFF directly. We cannot
// go through updateSummary() because turning off tether takes time, and we
// might still get "ON" status when rerun updateSummary(). So, just say it's off
updateSummaryToOff();
}
}
}
}
}