| /* |
| * Copyright (C) 2020 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 static android.os.UserManager.DISALLOW_CONFIG_TETHERING; |
| |
| import static com.android.settings.network.TetherEnabler.TETHERING_BLUETOOTH_ON; |
| import static com.android.settings.network.TetherEnabler.TETHERING_ETHERNET_ON; |
| import static com.android.settings.network.TetherEnabler.TETHERING_OFF; |
| import static com.android.settings.network.TetherEnabler.TETHERING_USB_ON; |
| import static com.android.settings.network.TetherEnabler.TETHERING_WIFI_ON; |
| import static com.android.settingslib.RestrictedLockUtilsInternal.checkIfRestrictionEnforced; |
| |
| import android.bluetooth.BluetoothAdapter; |
| import android.bluetooth.BluetoothPan; |
| import android.bluetooth.BluetoothProfile; |
| import android.content.Context; |
| import android.os.UserHandle; |
| import android.util.FeatureFlagUtils; |
| import android.util.Log; |
| |
| import androidx.annotation.VisibleForTesting; |
| import androidx.lifecycle.Lifecycle; |
| import androidx.lifecycle.Lifecycle.Event; |
| import androidx.lifecycle.LifecycleObserver; |
| import androidx.lifecycle.OnLifecycleEvent; |
| import androidx.preference.PreferenceScreen; |
| |
| import com.android.settings.R; |
| import com.android.settings.core.BasePreferenceController; |
| import com.android.settings.core.FeatureFlags; |
| import com.android.settings.widget.MasterSwitchController; |
| import com.android.settings.widget.MasterSwitchPreference; |
| import com.android.settingslib.TetherUtil; |
| |
| import java.util.concurrent.atomic.AtomicReference; |
| |
| /** |
| * This controller helps to manage the switch state and visibility of "Hotspot & tethering" switch |
| * preference. It updates the preference summary text based on tethering state. |
| */ |
| public class AllInOneTetherPreferenceController extends BasePreferenceController implements |
| LifecycleObserver, TetherEnabler.OnTetherStateUpdateListener { |
| private static final String TAG = "AllInOneTetherPreferenceController"; |
| |
| private int mTetheringState; |
| |
| private final boolean mAdminDisallowedTetherConfig; |
| private final AtomicReference<BluetoothPan> mBluetoothPan; |
| private final BluetoothAdapter mBluetoothAdapter; |
| @VisibleForTesting |
| final BluetoothProfile.ServiceListener mBtProfileServiceListener = |
| new BluetoothProfile.ServiceListener() { |
| @Override |
| public void onServiceConnected(int profile, BluetoothProfile proxy) { |
| mBluetoothPan.set((BluetoothPan) proxy); |
| } |
| |
| @Override |
| public void onServiceDisconnected(int profile) { |
| mBluetoothPan.set(null); |
| } |
| }; |
| |
| private MasterSwitchPreference mPreference; |
| private TetherEnabler mTetherEnabler; |
| |
| @VisibleForTesting(otherwise = VisibleForTesting.NONE) |
| AllInOneTetherPreferenceController() { |
| super(null /*context*/, "test"); |
| mAdminDisallowedTetherConfig = false; |
| mBluetoothPan = new AtomicReference<>(); |
| mBluetoothAdapter = null; |
| } |
| |
| public AllInOneTetherPreferenceController(Context context, String key) { |
| super(context, key); |
| mBluetoothPan = new AtomicReference<>(); |
| mAdminDisallowedTetherConfig = checkIfRestrictionEnforced( |
| context, DISALLOW_CONFIG_TETHERING, UserHandle.myUserId()) != null; |
| mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); |
| } |
| |
| @Override |
| public void displayPreference(PreferenceScreen screen) { |
| super.displayPreference(screen); |
| mPreference = screen.findPreference(mPreferenceKey); |
| } |
| |
| @Override |
| public int getAvailabilityStatus() { |
| if (!TetherUtil.isTetherAvailable(mContext) |
| || !FeatureFlagUtils.isEnabled(mContext, FeatureFlags.TETHER_ALL_IN_ONE)) { |
| return CONDITIONALLY_UNAVAILABLE; |
| } else { |
| return AVAILABLE; |
| } |
| } |
| |
| @Override |
| public CharSequence getSummary() { |
| switch (mTetheringState) { |
| case TETHERING_OFF: |
| return mContext.getString(R.string.tether_settings_summary_off); |
| case TETHERING_WIFI_ON: |
| return mContext.getString(R.string.tether_settings_summary_hotspot_only); |
| case TETHERING_USB_ON: |
| return mContext.getString(R.string.tether_settings_summary_usb_tethering_only); |
| case TETHERING_BLUETOOTH_ON: |
| return mContext.getString( |
| R.string.tether_settings_summary_bluetooth_tethering_only); |
| case TETHERING_ETHERNET_ON: |
| return mContext.getString(R.string.tether_settings_summary_ethernet_tethering_only); |
| case TETHERING_WIFI_ON | TETHERING_USB_ON: |
| return mContext.getString(R.string.tether_settings_summary_hotspot_and_usb); |
| case TETHERING_WIFI_ON | TETHERING_BLUETOOTH_ON: |
| return mContext.getString(R.string.tether_settings_summary_hotspot_and_bluetooth); |
| case TETHERING_WIFI_ON | TETHERING_ETHERNET_ON: |
| return mContext.getString(R.string.tether_settings_summary_hotspot_and_ethernet); |
| case TETHERING_USB_ON | TETHERING_BLUETOOTH_ON: |
| return mContext.getString(R.string.tether_settings_summary_usb_and_bluetooth); |
| case TETHERING_USB_ON | TETHERING_ETHERNET_ON: |
| return mContext.getString(R.string.tether_settings_summary_usb_and_ethernet); |
| case TETHERING_BLUETOOTH_ON | TETHERING_ETHERNET_ON: |
| return mContext.getString(R.string.tether_settings_summary_bluetooth_and_ethernet); |
| case TETHERING_WIFI_ON | TETHERING_USB_ON | TETHERING_BLUETOOTH_ON: |
| return mContext.getString( |
| R.string.tether_settings_summary_hotspot_and_usb_and_bluetooth); |
| case TETHERING_WIFI_ON | TETHERING_USB_ON | TETHERING_ETHERNET_ON: |
| return mContext.getString( |
| R.string.tether_settings_summary_hotspot_and_usb_and_ethernet); |
| case TETHERING_WIFI_ON | TETHERING_BLUETOOTH_ON | TETHERING_ETHERNET_ON: |
| return mContext.getString( |
| R.string.tether_settings_summary_hotspot_and_bluetooth_and_ethernet); |
| case TETHERING_USB_ON | TETHERING_BLUETOOTH_ON | TETHERING_ETHERNET_ON: |
| return mContext.getString( |
| R.string.tether_settings_summary_usb_and_bluetooth_and_ethernet); |
| case TETHERING_WIFI_ON | TETHERING_USB_ON | TETHERING_BLUETOOTH_ON |
| | TETHERING_ETHERNET_ON: |
| return mContext.getString(R.string.tether_settings_summary_all); |
| default: |
| Log.e(TAG, "Unknown tethering state"); |
| return mContext.getString(R.string.summary_placeholder); |
| } |
| } |
| |
| @OnLifecycleEvent(Event.ON_CREATE) |
| public void onCreate() { |
| if (mBluetoothAdapter != null |
| && mBluetoothAdapter.getState() == BluetoothAdapter.STATE_ON) { |
| mBluetoothAdapter.getProfileProxy(mContext, mBtProfileServiceListener, |
| BluetoothProfile.PAN); |
| } |
| } |
| |
| @OnLifecycleEvent(Event.ON_RESUME) |
| public void onResume() { |
| if (mTetherEnabler != null) { |
| mTetherEnabler.addListener(this); |
| } |
| } |
| |
| @OnLifecycleEvent(Event.ON_PAUSE) |
| public void onPause() { |
| if (mTetherEnabler != null) { |
| mTetherEnabler.removeListener(this); |
| } |
| } |
| |
| @OnLifecycleEvent(Event.ON_DESTROY) |
| public void onDestroy() { |
| final BluetoothProfile profile = mBluetoothPan.getAndSet(null); |
| if (profile != null && mBluetoothAdapter != null) { |
| mBluetoothAdapter.closeProfileProxy(BluetoothProfile.PAN, profile); |
| } |
| } |
| |
| void initEnabler(Lifecycle lifecycle) { |
| if (mPreference != null) { |
| mTetherEnabler = new TetherEnabler( |
| mContext, new MasterSwitchController(mPreference), mBluetoothPan); |
| if (lifecycle != null) { |
| lifecycle.addObserver(mTetherEnabler); |
| } |
| } else { |
| Log.e(TAG, "TetherEnabler is not initialized"); |
| } |
| } |
| |
| @Override |
| public void onTetherStateUpdated(@TetherEnabler.TetheringState int state) { |
| mTetheringState = state; |
| updateState(mPreference); |
| } |
| } |