Bug:391709444 Test: atest Enable2gPreferenceControllerTest Flag: EXEMPT bugfix Change-Id: I66bd05441e29b4976343d145ebecaf11fa924b0c
252 lines
10 KiB
Java
252 lines
10 KiB
Java
/*
|
|
* 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.telephony;
|
|
|
|
import android.app.settings.SettingsEnums;
|
|
import android.content.Context;
|
|
import android.os.PersistableBundle;
|
|
import android.telephony.CarrierConfigManager;
|
|
import android.telephony.SubscriptionInfo;
|
|
import android.telephony.SubscriptionManager;
|
|
import android.telephony.TelephonyManager;
|
|
import android.text.TextUtils;
|
|
import android.util.Log;
|
|
|
|
import androidx.preference.Preference;
|
|
import androidx.preference.PreferenceScreen;
|
|
|
|
import com.android.settings.R;
|
|
import com.android.settings.flags.Flags;
|
|
import com.android.settings.network.CarrierConfigCache;
|
|
import com.android.settings.network.SubscriptionUtil;
|
|
import com.android.settings.overlay.FeatureFactory;
|
|
import com.android.settingslib.RestrictedSwitchPreference;
|
|
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
|
|
|
/**
|
|
* Preference controller for "Enable 2G"
|
|
*
|
|
* <p>
|
|
* This preference controller is invoked per subscription id, which means toggling 2g is a per-sim
|
|
* operation. The requested 2g preference is delegated to
|
|
* {@link TelephonyManager#setAllowedNetworkTypesForReason(int reason, long allowedNetworkTypes)}
|
|
* with:
|
|
* <ul>
|
|
* <li>{@code reason} {@link TelephonyManager#ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G}.</li>
|
|
* <li>{@code allowedNetworkTypes} with set or cleared 2g-related bits, depending on the
|
|
* requested preference state. </li>
|
|
* </ul>
|
|
*/
|
|
public class Enable2gPreferenceController extends TelephonyTogglePreferenceController {
|
|
|
|
private static final String LOG_TAG = "Enable2gPreferenceController";
|
|
private static final long BITMASK_2G = TelephonyManager.NETWORK_TYPE_BITMASK_GSM
|
|
| TelephonyManager.NETWORK_TYPE_BITMASK_GPRS
|
|
| TelephonyManager.NETWORK_TYPE_BITMASK_EDGE
|
|
| TelephonyManager.NETWORK_TYPE_BITMASK_CDMA
|
|
| TelephonyManager.NETWORK_TYPE_BITMASK_1xRTT;
|
|
|
|
private final MetricsFeatureProvider mMetricsFeatureProvider;
|
|
|
|
private CarrierConfigCache mCarrierConfigCache;
|
|
private SubscriptionManager mSubscriptionManager;
|
|
private TelephonyManager mTelephonyManager;
|
|
private RestrictedSwitchPreference mRestrictedPreference;
|
|
|
|
/**
|
|
* Class constructor of "Enable 2G" toggle.
|
|
*
|
|
* @param context of settings
|
|
* @param key assigned within UI entry of XML file
|
|
*/
|
|
public Enable2gPreferenceController(Context context, String key) {
|
|
super(context, key);
|
|
mCarrierConfigCache = CarrierConfigCache.getInstance(context);
|
|
mMetricsFeatureProvider = FeatureFactory.getFeatureFactory().getMetricsFeatureProvider();
|
|
mSubscriptionManager = context.getSystemService(SubscriptionManager.class);
|
|
mRestrictedPreference = null;
|
|
}
|
|
|
|
/**
|
|
* Initialization based on a given subscription id.
|
|
*
|
|
* @param subId is the subscription id
|
|
* @return this instance after initialization
|
|
*/
|
|
public Enable2gPreferenceController init(int subId) {
|
|
mSubId = subId;
|
|
mTelephonyManager = mContext.getSystemService(TelephonyManager.class)
|
|
.createForSubscriptionId(mSubId);
|
|
return this;
|
|
}
|
|
|
|
@Override
|
|
public void displayPreference(PreferenceScreen screen) {
|
|
super.displayPreference(screen);
|
|
mRestrictedPreference = screen.findPreference(getPreferenceKey());
|
|
}
|
|
|
|
@Override
|
|
public void updateState(Preference preference) {
|
|
super.updateState(preference);
|
|
|
|
// The device admin decision overrides any carrier preferences
|
|
if (isDisabledByAdmin()) {
|
|
return;
|
|
}
|
|
|
|
if (preference == null || !SubscriptionManager.isUsableSubscriptionId(mSubId)) {
|
|
return;
|
|
}
|
|
|
|
// TODO: b/303411083 remove all dynamic logic and rely on summary in resource file once flag
|
|
// is no longer needed
|
|
if (Flags.removeKeyHideEnable2g()) {
|
|
preference.setSummary(mContext.getString(R.string.enable_2g_summary));
|
|
} else {
|
|
final PersistableBundle carrierConfig = mCarrierConfigCache.getConfigForSubId(mSubId);
|
|
boolean isDisabledByCarrier =
|
|
carrierConfig != null
|
|
&& carrierConfig.getBoolean(CarrierConfigManager.KEY_HIDE_ENABLE_2G);
|
|
preference.setEnabled(!isDisabledByCarrier);
|
|
String summary;
|
|
if (isDisabledByCarrier) {
|
|
summary = mContext.getString(R.string.enable_2g_summary_disabled_carrier,
|
|
getSimCardName());
|
|
} else {
|
|
summary = mContext.getString(R.string.enable_2g_summary);
|
|
}
|
|
preference.setSummary(summary);
|
|
}
|
|
}
|
|
|
|
private String getSimCardName() {
|
|
SubscriptionInfo subInfo = SubscriptionUtil.getSubById(mSubscriptionManager, mSubId);
|
|
if (subInfo == null) {
|
|
return "";
|
|
}
|
|
// It is the sim card name, and it should be the same name as the sim page.
|
|
CharSequence simCardName = subInfo.getDisplayName();
|
|
return TextUtils.isEmpty(simCardName) ? "" : simCardName.toString();
|
|
}
|
|
|
|
/**
|
|
* Get the {@link com.android.settings.core.BasePreferenceController.AvailabilityStatus} for
|
|
* this preference given a {@code subId}.
|
|
* <p>
|
|
* A return value of {@link #AVAILABLE} denotes that the 2g status can be updated for this
|
|
* particular subscription.
|
|
* We return {@link #AVAILABLE} if the following conditions are met and {@link
|
|
* #CONDITIONALLY_UNAVAILABLE} otherwise.
|
|
* <ul>
|
|
* <li>The subscription is usable {@link SubscriptionManager#isUsableSubscriptionId}</li>
|
|
* <li>The carrier has not opted to disable this preference
|
|
* {@link CarrierConfigManager#KEY_HIDE_ENABLE_2G}</li>
|
|
* <li>The device supports
|
|
* <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>
|
|
* </ul>
|
|
*/
|
|
@Override
|
|
public int getAvailabilityStatus(int subId) {
|
|
if (mTelephonyManager == null) {
|
|
Log.w(LOG_TAG, "getAvailabilityStatus: Telephony manager not yet initialized");
|
|
return CONDITIONALLY_UNAVAILABLE;
|
|
}
|
|
boolean visible =
|
|
SubscriptionManager.isUsableSubscriptionId(subId)
|
|
&& mTelephonyManager.isRadioInterfaceCapabilitySupported(
|
|
mTelephonyManager.CAPABILITY_USES_ALLOWED_NETWORK_TYPES_BITMASK);
|
|
return visible ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
|
|
}
|
|
|
|
/**
|
|
* Return {@code true} if only 3G and higher is currently enabled.
|
|
*
|
|
* <p><b>NOTE:</b> This method returns the active state of the preference controller and is not
|
|
* the parameter passed into {@link #setChecked(boolean)}, which is instead the requested future
|
|
* state.</p>
|
|
*/
|
|
@Override
|
|
public boolean isChecked() {
|
|
// If an enterprise admin has disabled 2g, we show the toggle as checked to avoid
|
|
// user confusion of seeing a unchecked toggle, but having 3G and higher actually enable.
|
|
// The RestrictedSwitchPreference will take care of transparently informing the user that
|
|
// the setting was disabled by their admin
|
|
if (isDisabledByAdmin()) {
|
|
return true;
|
|
}
|
|
|
|
if (mTelephonyManager == null) {
|
|
Log.w(LOG_TAG, "isChecked: Telephony manager not yet initialized");
|
|
return false;
|
|
}
|
|
long currentlyAllowedNetworkTypes = mTelephonyManager.getAllowedNetworkTypesForReason(
|
|
mTelephonyManager.ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G);
|
|
return (currentlyAllowedNetworkTypes & BITMASK_2G) == 0;
|
|
}
|
|
|
|
/**
|
|
* Ensure that the modem's allowed network types are configured according to the user's
|
|
* preference.
|
|
* <p>
|
|
* See {@link com.android.settings.core.TogglePreferenceController#setChecked(boolean)} for
|
|
* details.
|
|
*
|
|
* @param isChecked The toggle value that we're being requested to enforce. A value of {@code
|
|
* true} denotes that 2g will be disabled by the modem after this function
|
|
* completes, if it is not already.
|
|
*/
|
|
@Override
|
|
public boolean setChecked(boolean isChecked) {
|
|
if (isDisabledByAdmin()) {
|
|
return false;
|
|
}
|
|
|
|
if (!SubscriptionManager.isUsableSubscriptionId(mSubId)) {
|
|
return false;
|
|
}
|
|
|
|
if (mTelephonyManager == null) {
|
|
Log.w(LOG_TAG, "setChecked: Telephony manager not yet initialized");
|
|
return false;
|
|
}
|
|
|
|
long currentlyAllowedNetworkTypes = mTelephonyManager.getAllowedNetworkTypesForReason(
|
|
mTelephonyManager.ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G);
|
|
boolean enabled = (currentlyAllowedNetworkTypes & BITMASK_2G) != 0;
|
|
if (enabled != isChecked) {
|
|
return false;
|
|
}
|
|
long newAllowedNetworkTypes = currentlyAllowedNetworkTypes;
|
|
if (isChecked) {
|
|
newAllowedNetworkTypes = currentlyAllowedNetworkTypes & ~BITMASK_2G;
|
|
Log.i(LOG_TAG, "Disabling 2g. Allowed network types: " + newAllowedNetworkTypes);
|
|
} else {
|
|
newAllowedNetworkTypes = currentlyAllowedNetworkTypes | BITMASK_2G;
|
|
Log.i(LOG_TAG, "Enabling 2g. Allowed network types: " + newAllowedNetworkTypes);
|
|
}
|
|
mTelephonyManager.setAllowedNetworkTypesForReason(
|
|
mTelephonyManager.ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G, newAllowedNetworkTypes);
|
|
mMetricsFeatureProvider.action(
|
|
mContext, SettingsEnums.ACTION_2G_ENABLED, !isChecked);
|
|
return true;
|
|
}
|
|
|
|
private boolean isDisabledByAdmin() {
|
|
return (mRestrictedPreference != null && mRestrictedPreference.isDisabledByAdmin());
|
|
}
|
|
}
|