• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 package com.android.settings.network.telephony;
17 
18 import android.app.settings.SettingsEnums;
19 import android.content.Context;
20 import android.os.PersistableBundle;
21 import android.telephony.CarrierConfigManager;
22 import android.telephony.SubscriptionInfo;
23 import android.telephony.SubscriptionManager;
24 import android.telephony.TelephonyManager;
25 import android.text.TextUtils;
26 import android.util.Log;
27 
28 import androidx.preference.Preference;
29 import androidx.preference.PreferenceScreen;
30 
31 import com.android.settings.R;
32 import com.android.settings.network.CarrierConfigCache;
33 import com.android.settings.network.SubscriptionUtil;
34 import com.android.settings.overlay.FeatureFactory;
35 import com.android.settingslib.RestrictedSwitchPreference;
36 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
37 
38 /**
39  * Preference controller for "Enable 2G"
40  *
41  * <p>
42  * This preference controller is invoked per subscription id, which means toggling 2g is a per-sim
43  * operation. The requested 2g preference is delegated to
44  * {@link TelephonyManager#setAllowedNetworkTypesForReason(int reason, long allowedNetworkTypes)}
45  * with:
46  * <ul>
47  *     <li>{@code reason} {@link TelephonyManager#ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G}.</li>
48  *     <li>{@code allowedNetworkTypes} with set or cleared 2g-related bits, depending on the
49  *     requested preference state. </li>
50  * </ul>
51  */
52 public class Enable2gPreferenceController extends TelephonyTogglePreferenceController {
53 
54     private static final String LOG_TAG = "Enable2gPreferenceController";
55     private static final long BITMASK_2G = TelephonyManager.NETWORK_TYPE_BITMASK_GSM
56             | TelephonyManager.NETWORK_TYPE_BITMASK_GPRS
57             | TelephonyManager.NETWORK_TYPE_BITMASK_EDGE
58             | TelephonyManager.NETWORK_TYPE_BITMASK_CDMA
59             | TelephonyManager.NETWORK_TYPE_BITMASK_1xRTT;
60 
61     private final MetricsFeatureProvider mMetricsFeatureProvider;
62 
63     private CarrierConfigCache mCarrierConfigCache;
64     private SubscriptionManager mSubscriptionManager;
65     private TelephonyManager mTelephonyManager;
66     private RestrictedSwitchPreference mRestrictedPreference;
67 
68     /**
69      * Class constructor of "Enable 2G" toggle.
70      *
71      * @param context of settings
72      * @param key     assigned within UI entry of XML file
73      */
Enable2gPreferenceController(Context context, String key)74     public Enable2gPreferenceController(Context context, String key) {
75         super(context, key);
76         mCarrierConfigCache = CarrierConfigCache.getInstance(context);
77         mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
78         mSubscriptionManager = context.getSystemService(SubscriptionManager.class);
79         mRestrictedPreference = null;
80     }
81 
82     /**
83      * Initialization based on a given subscription id.
84      *
85      * @param subId is the subscription id
86      * @return this instance after initialization
87      */
init(int subId)88     public Enable2gPreferenceController init(int subId) {
89         mSubId = subId;
90         mTelephonyManager = mContext.getSystemService(TelephonyManager.class)
91                 .createForSubscriptionId(mSubId);
92         return this;
93     }
94 
95     @Override
displayPreference(PreferenceScreen screen)96     public void displayPreference(PreferenceScreen screen) {
97         super.displayPreference(screen);
98         mRestrictedPreference = screen.findPreference(getPreferenceKey());
99     }
100 
101     @Override
updateState(Preference preference)102     public void updateState(Preference preference) {
103         super.updateState(preference);
104 
105         // The device admin decision overrides any carrier preferences
106         if (isDisabledByAdmin()) {
107             return;
108         }
109 
110         if (preference == null || !SubscriptionManager.isUsableSubscriptionId(mSubId)) {
111             return;
112         }
113 
114         final PersistableBundle carrierConfig = mCarrierConfigCache.getConfigForSubId(mSubId);
115         boolean isDisabledByCarrier =
116                 carrierConfig != null
117                         && carrierConfig.getBoolean(CarrierConfigManager.KEY_HIDE_ENABLE_2G);
118         preference.setEnabled(!isDisabledByCarrier);
119         String summary;
120         if (isDisabledByCarrier) {
121             summary = mContext.getString(R.string.enable_2g_summary_disabled_carrier,
122                     getSimCardName());
123         } else {
124             summary = mContext.getString(R.string.enable_2g_summary);
125         }
126         preference.setSummary(summary);
127     }
128 
getSimCardName()129     private String getSimCardName() {
130         SubscriptionInfo subInfo = SubscriptionUtil.getSubById(mSubscriptionManager, mSubId);
131         if (subInfo == null) {
132             return "";
133         }
134         // It is the sim card name, and it should be the same name as the sim page.
135         CharSequence simCardName = subInfo.getDisplayName();
136         return TextUtils.isEmpty(simCardName) ? "" : simCardName.toString();
137     }
138 
139     /**
140      * Get the {@link com.android.settings.core.BasePreferenceController.AvailabilityStatus} for
141      * this preference given a {@code subId}.
142      * <p>
143      * A return value of {@link #AVAILABLE} denotes that the 2g status can be updated for this
144      * particular subscription.
145      * We return {@link #AVAILABLE} if the following conditions are met and {@link
146      * #CONDITIONALLY_UNAVAILABLE} otherwise.
147      * <ul>
148      *     <li>The subscription is usable {@link SubscriptionManager#isUsableSubscriptionId}</li>
149      *     <li>The carrier has not opted to disable this preference
150      *     {@link CarrierConfigManager#KEY_HIDE_ENABLE_2G}</li>
151      *     <li>The device supports
152      *     <a href="https://cs.android.com/android/platform/superproject/+/master:hardware/interfaces/radio/1.6/IRadio.hal">Radio HAL version 1.6 or greater</a> </li>
153      * </ul>
154      */
155     @Override
getAvailabilityStatus(int subId)156     public int getAvailabilityStatus(int subId) {
157         final PersistableBundle carrierConfig = mCarrierConfigCache.getConfigForSubId(subId);
158         if (mTelephonyManager == null) {
159             Log.w(LOG_TAG, "Telephony manager not yet initialized");
160             mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
161         }
162         boolean visible =
163                 SubscriptionManager.isUsableSubscriptionId(subId)
164                         && carrierConfig != null
165                         && mTelephonyManager.isRadioInterfaceCapabilitySupported(
166                         mTelephonyManager.CAPABILITY_USES_ALLOWED_NETWORK_TYPES_BITMASK);
167         return visible ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
168     }
169 
170     /**
171      * Return {@code true} if 2g is currently enabled.
172      *
173      * <p><b>NOTE:</b> This method returns the active state of the preference controller and is not
174      * the parameter passed into {@link #setChecked(boolean)}, which is instead the requested future
175      * state.</p>
176      */
177     @Override
isChecked()178     public boolean isChecked() {
179         // If an enterprise admin has disabled 2g, we show the toggle as not checked to avoid
180         // user confusion of seeing a checked toggle, but having 2g actually disabled.
181         // The RestrictedSwitchPreference will take care of transparently informing the user that
182         // the setting was disabled by their admin
183         if (isDisabledByAdmin()) {
184             return false;
185         }
186 
187         long currentlyAllowedNetworkTypes = mTelephonyManager.getAllowedNetworkTypesForReason(
188                 mTelephonyManager.ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G);
189         return (currentlyAllowedNetworkTypes & BITMASK_2G) != 0;
190     }
191 
192     /**
193      * Ensure that the modem's allowed network types are configured according to the user's
194      * preference.
195      * <p>
196      * See {@link com.android.settings.core.TogglePreferenceController#setChecked(boolean)} for
197      * details.
198      *
199      * @param isChecked The toggle value that we're being requested to enforce. A value of {@code
200      *                  false} denotes that 2g will be disabled by the modem after this function
201      *                  completes, if it is not already.
202      */
203     @Override
setChecked(boolean isChecked)204     public boolean setChecked(boolean isChecked) {
205         if (isDisabledByAdmin()) {
206             return false;
207         }
208 
209         if (!SubscriptionManager.isUsableSubscriptionId(mSubId)) {
210             return false;
211         }
212         long currentlyAllowedNetworkTypes = mTelephonyManager.getAllowedNetworkTypesForReason(
213                 mTelephonyManager.ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G);
214         boolean enabled = (currentlyAllowedNetworkTypes & BITMASK_2G) != 0;
215         if (enabled == isChecked) {
216             return false;
217         }
218         long newAllowedNetworkTypes = currentlyAllowedNetworkTypes;
219         if (isChecked) {
220             newAllowedNetworkTypes = currentlyAllowedNetworkTypes | BITMASK_2G;
221             Log.i(LOG_TAG, "Enabling 2g. Allowed network types: " + newAllowedNetworkTypes);
222         } else {
223             newAllowedNetworkTypes = currentlyAllowedNetworkTypes & ~BITMASK_2G;
224             Log.i(LOG_TAG, "Disabling 2g. Allowed network types: " + newAllowedNetworkTypes);
225         }
226         mTelephonyManager.setAllowedNetworkTypesForReason(
227                 mTelephonyManager.ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G, newAllowedNetworkTypes);
228         mMetricsFeatureProvider.action(
229                 mContext, SettingsEnums.ACTION_2G_ENABLED, isChecked);
230         return true;
231     }
232 
isDisabledByAdmin()233     private boolean isDisabledByAdmin() {
234         return (mRestrictedPreference != null && mRestrictedPreference.isDisabledByAdmin());
235     }
236 }
237