1 /*
2  * Copyright (C) 2021 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 
17 package com.android.settings.wifi.tether;
18 
19 import android.content.Context;
20 import android.net.wifi.SoftApConfiguration;
21 import android.util.Log;
22 
23 import androidx.annotation.VisibleForTesting;
24 import androidx.preference.Preference;
25 import androidx.preference.TwoStatePreference;
26 
27 import com.android.settings.R;
28 import com.android.settings.overlay.FeatureFactory;
29 
30 /**
31  * This controller helps to manage the state of maximize compatibility switch preference.
32  */
33 public class WifiTetherMaximizeCompatibilityPreferenceController extends
34         WifiTetherBasePreferenceController {
35 
36     private static final String TAG = "WifiTetherMaximizeCompatibilityPref";
37     public static final String PREF_KEY = "wifi_tether_maximize_compatibility";
38 
39     private boolean mIsChecked;
40     @VisibleForTesting
41     boolean mShouldHidePreference;
42 
WifiTetherMaximizeCompatibilityPreferenceController(Context context, WifiTetherBasePreferenceController.OnTetherConfigUpdateListener listener)43     public WifiTetherMaximizeCompatibilityPreferenceController(Context context,
44             WifiTetherBasePreferenceController.OnTetherConfigUpdateListener listener) {
45         super(context, listener);
46         // If the Wi-Fi Hotspot Speed Feature available, then hide this controller.
47         mShouldHidePreference = FeatureFactory.getFeatureFactory()
48                 .getWifiFeatureProvider().getWifiHotspotRepository().isSpeedFeatureAvailable();
49         Log.d(TAG, "mShouldHidePreference:" + mShouldHidePreference);
50         if (mShouldHidePreference) {
51             return;
52         }
53         mIsChecked = isMaximizeCompatibilityEnabled();
54     }
55 
56     @Override
isAvailable()57     public boolean isAvailable() {
58         if (mShouldHidePreference) {
59             return false;
60         }
61         return super.isAvailable();
62     }
63 
64     @Override
getPreferenceKey()65     public String getPreferenceKey() {
66         return PREF_KEY;
67     }
68 
69     @Override
updateDisplay()70     public void updateDisplay() {
71         if (mPreference == null) {
72             return;
73         }
74         mPreference.setEnabled(is5GhzBandSupported());
75         ((TwoStatePreference) mPreference).setChecked(mIsChecked);
76         mPreference.setSummary(mWifiManager.isBridgedApConcurrencySupported()
77                 ? R.string.wifi_hotspot_maximize_compatibility_dual_ap_summary
78                 : R.string.wifi_hotspot_maximize_compatibility_single_ap_summary);
79     }
80 
81     @Override
onPreferenceChange(Preference preference, Object newValue)82     public boolean onPreferenceChange(Preference preference, Object newValue) {
83         mIsChecked = (Boolean) newValue;
84         if (mListener != null) {
85             mListener.onTetherConfigUpdated(this);
86         }
87         return true;
88     }
89 
is5GhzBandSupported()90     private boolean is5GhzBandSupported() {
91         if (mWifiManager == null) {
92             return false;
93         }
94         if (!mWifiManager.is5GHzBandSupported() || mWifiManager.getCountryCode() == null) {
95             return false;
96         }
97         return true;
98     }
99 
100     @VisibleForTesting
isMaximizeCompatibilityEnabled()101     boolean isMaximizeCompatibilityEnabled() {
102         if (mWifiManager == null) {
103             return false;
104         }
105         final SoftApConfiguration config = mWifiManager.getSoftApConfiguration();
106         if (config == null) {
107             return false;
108         }
109         if (mWifiManager.isBridgedApConcurrencySupported()) {
110             final boolean isEnabled = config.isBridgedModeOpportunisticShutdownEnabled();
111             Log.d(TAG, "isBridgedModeOpportunisticShutdownEnabled:" + isEnabled);
112             // Because the return value defined by the Wi-Fi framework API is opposite to the UI.
113             //   Compatibility on:  isBridgedModeOpportunisticShutdownEnabled() = false
114             //   Compatibility off: isBridgedModeOpportunisticShutdownEnabled() = true
115             // Need to return the reverse value.
116             return !isEnabled;
117         }
118 
119         // If the BridgedAp Concurrency is not supported in early Pixel devices (e.g. Pixel 2~5),
120         // show toggle on when band is 2.4G only.
121         final int band = config.getBand();
122         Log.d(TAG, "getBand:" + band);
123         return band == SoftApConfiguration.BAND_2GHZ;
124     }
125 
126     /**
127      * Setup the Maximize Compatibility setting to the SoftAp Configuration
128      *
129      * @param builder The builder to build the SoftApConfiguration.
130      */
setupMaximizeCompatibility(SoftApConfiguration.Builder builder)131     public void setupMaximizeCompatibility(SoftApConfiguration.Builder builder) {
132         if (builder == null) {
133             return;
134         }
135         final boolean enabled = mIsChecked;
136         if (mWifiManager.isBridgedApConcurrencySupported()) {
137             int[] bands = {
138                     SoftApConfiguration.BAND_2GHZ,
139                     SoftApConfiguration.BAND_2GHZ | SoftApConfiguration.BAND_5GHZ};
140             builder.setBands(bands);
141             Log.d(TAG, "setBridgedModeOpportunisticShutdownEnabled:" + enabled);
142             // Because the defined value by the Wi-Fi framework API is opposite to the UI.
143             //   Compatibility on:  setBridgedModeOpportunisticShutdownEnabled(false)
144             //   Compatibility off: setBridgedModeOpportunisticShutdownEnabled(true)
145             // Need to set the reverse value.
146             builder.setBridgedModeOpportunisticShutdownEnabled(!enabled);
147         } else {
148             int band = enabled
149                     ? SoftApConfiguration.BAND_2GHZ
150                     : SoftApConfiguration.BAND_2GHZ | SoftApConfiguration.BAND_5GHZ;
151             Log.d(TAG, "setBand:" + band);
152             builder.setBand(band);
153         }
154     }
155 }
156