Merge changes from topic "tc_change_22102807_16"
* changes:
[automerged blank] Import translations. DO NOT MERGE ANYWHERE 2p: bdaf53bb24
Import translations. DO NOT MERGE ANYWHERE
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index fd8a7ee..6cbc051 100644
--- a/res/values-pt/strings.xml
+++ b/res/values-pt/strings.xml
@@ -579,7 +579,7 @@
<string name="onscreenEndCallText" msgid="6138725377654842757">"Finalizar"</string>
<string name="onscreenShowDialpadText" msgid="658465753816164079">"Teclado"</string>
<string name="onscreenMuteText" msgid="5470306116733843621">"Desativar som"</string>
- <string name="onscreenAddCallText" msgid="9075675082903611677">"Adicionar chamada"</string>
+ <string name="onscreenAddCallText" msgid="9075675082903611677">"Adicionar ligação"</string>
<string name="onscreenMergeCallsText" msgid="3692389519611225407">"Juntar chamadas"</string>
<string name="onscreenSwapCallsText" msgid="2682542150803377991">"Trocar"</string>
<string name="onscreenManageCallsText" msgid="1162047856081836469">"Gerenciar chamadas"</string>
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index 88b4443..aa6f7f9 100755
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -385,6 +385,7 @@
private SharedPreferences mTelephonySharedPreferences;
private PhoneConfigurationManager mPhoneConfigurationManager;
private final RadioInterfaceCapabilityController mRadioInterfaceCapabilities;
+ private final Telephony2gUpdater mTelephony2gUpdater;
/** User Activity */
private AtomicBoolean mNotifyUserActivity;
@@ -2401,6 +2402,9 @@
mRadioInterfaceCapabilities = RadioInterfaceCapabilityController.getInstance();
mNotifyUserActivity = new AtomicBoolean(false);
PropertyInvalidatedCache.invalidateCache(TelephonyManager.CACHE_KEY_PHONE_ACCOUNT_TO_SUBID);
+ mTelephony2gUpdater = new Telephony2gUpdater(
+ Executors.newSingleThreadExecutor(), mApp);
+ mTelephony2gUpdater.init();
publish();
}
@@ -6804,8 +6808,7 @@
int phoneId = mSubscriptionController.getPhoneId(subId);
Phone phone = PhoneFactory.getPhone(phoneId);
if (phone != null) {
- boolean retVal;
- retVal = phone.getDataSettingsManager().isDataEnabled();
+ boolean retVal = phone.getDataSettingsManager().isDataEnabled();
if (DBG) log("isDataEnabled: " + retVal + ", subId=" + subId);
return retVal;
} else {
diff --git a/src/com/android/phone/Telephony2gUpdater.java b/src/com/android/phone/Telephony2gUpdater.java
new file mode 100644
index 0000000..0919385
--- /dev/null
+++ b/src/com/android/phone/Telephony2gUpdater.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2022 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.phone;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.UserManager;
+import android.telephony.RadioAccessFamily;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.RILConstants;
+
+import java.util.List;
+import java.util.concurrent.Executor;
+
+/**
+ * A {@link BroadcastReceiver} that ensures that user restrictions are correctly applied to
+ * telephony.
+ * This includes handling broadcasts from user restriction state changes, as well as ensuring that
+ * SIM-specific settings are correctly applied when new subscriptions become active.
+ *
+ * Callers are expected to call {@code init()} and keep an instance of this class alive.
+ */
+public class Telephony2gUpdater extends BroadcastReceiver {
+ private static final String TAG = "TelephonyUserManagerReceiver";
+
+ // We can't interact with the HAL on the main thread of the phone process (where
+ // receivers are run by default), so we execute our logic from a separate thread.
+ private final Executor mExecutor;
+ private final Context mContext;
+ private final long mBaseAllowedNetworks;
+
+ public Telephony2gUpdater(Executor executor, Context context) {
+ this(executor, context,
+ RadioAccessFamily.getRafFromNetworkType(RILConstants.PREFERRED_NETWORK_MODE));
+ }
+
+ public Telephony2gUpdater(Executor executor, Context context,
+ long baseAllowedNetworks) {
+ mExecutor = executor;
+ mContext = context;
+ mBaseAllowedNetworks = baseAllowedNetworks;
+ }
+
+ /**
+ * Register the given instance as a {@link BroadcastReceiver} and a {@link
+ * SubscriptionManager.OnSubscriptionsChangedListener}.
+ */
+ public void init() {
+ mContext.getSystemService(SubscriptionManager.class).addOnSubscriptionsChangedListener(
+ mExecutor, new SubscriptionListener());
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(UserManager.ACTION_USER_RESTRICTIONS_CHANGED);
+ mContext.registerReceiver(this, filter);
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (context == null || intent == null) return;
+ Log.i(TAG, "Received callback for action " + intent.getAction());
+ final PendingResult result = goAsync();
+ mExecutor.execute(() -> {
+ Log.i(TAG, "Running handler for action " + intent.getAction());
+ handleUserRestrictionsChanged(context);
+ result.finish();
+ });
+ }
+
+ /**
+ * Update all active subscriptions with allowed network types depending on the current state
+ * of the {@link UserManager.DISALLOW_2G}.
+ */
+ @VisibleForTesting
+ public void handleUserRestrictionsChanged(Context context) {
+ UserManager um = context.getSystemService(UserManager.class);
+ TelephonyManager tm = context.getSystemService(TelephonyManager.class);
+ SubscriptionManager sm = context.getSystemService(SubscriptionManager.class);
+ final long twoGBitmask = TelephonyManager.NETWORK_CLASS_BITMASK_2G;
+
+ boolean shouldDisable2g = um.hasUserRestriction(UserManager.DISALLOW_CELLULAR_2G);
+
+ // This is expected when subscription info cannot be determined. We'll get another
+ // callback in the future from our SubscriptionListener once we have valid subscriptions.
+ List<SubscriptionInfo> subscriptionInfoList = sm.getAvailableSubscriptionInfoList();
+ if (subscriptionInfoList == null) {
+ return;
+ }
+
+ long allowedNetworkTypes = mBaseAllowedNetworks;
+
+ // 2G device admin controls are global
+ for (SubscriptionInfo info : subscriptionInfoList) {
+ TelephonyManager telephonyManager = tm.createForSubscriptionId(
+ info.getSubscriptionId());
+ if (shouldDisable2g) {
+ allowedNetworkTypes &= ~twoGBitmask;
+ } else {
+ allowedNetworkTypes |= twoGBitmask;
+ }
+ telephonyManager.setAllowedNetworkTypesForReason(
+ TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER_RESTRICTIONS,
+ allowedNetworkTypes);
+ }
+ }
+
+ private class SubscriptionListener extends SubscriptionManager.OnSubscriptionsChangedListener {
+ @Override
+ public void onSubscriptionsChanged() {
+ Log.i(TAG, "Running handler for subscription change.");
+ handleUserRestrictionsChanged(mContext);
+ }
+ }
+
+}
diff --git a/src/com/android/phone/settings/RadioInfo.java b/src/com/android/phone/settings/RadioInfo.java
index 7c2c829..c6dbfc6 100644
--- a/src/com/android/phone/settings/RadioInfo.java
+++ b/src/com/android/phone/settings/RadioInfo.java
@@ -72,13 +72,6 @@
import android.telephony.TelephonyDisplayInfo;
import android.telephony.TelephonyManager;
import android.telephony.data.NetworkSlicingConfig;
-import android.telephony.ims.ImsException;
-import android.telephony.ims.ImsManager;
-import android.telephony.ims.ImsMmTelManager;
-import android.telephony.ims.ImsRcsManager;
-import android.telephony.ims.ProvisioningManager;
-import android.telephony.ims.feature.MmTelFeature;
-import android.telephony.ims.stub.ImsRegistrationImplBase;
import android.text.TextUtils;
import android.util.Log;
import android.view.Menu;
@@ -99,6 +92,9 @@
import androidx.appcompat.app.AlertDialog.Builder;
import androidx.appcompat.app.AppCompatActivity;
+import com.android.ims.ImsConfig;
+import com.android.ims.ImsException;
+import com.android.ims.ImsManager;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.euicc.EuiccConnector;
@@ -181,6 +177,18 @@
*/
private static final int ALWAYS_ON_DSDS_MODE = 1;
+ private static final int IMS_VOLTE_PROVISIONED_CONFIG_ID =
+ ImsConfig.ConfigConstants.VLT_SETTING_ENABLED;
+
+ private static final int IMS_VT_PROVISIONED_CONFIG_ID =
+ ImsConfig.ConfigConstants.LVC_SETTING_ENABLED;
+
+ private static final int IMS_WFC_PROVISIONED_CONFIG_ID =
+ ImsConfig.ConfigConstants.VOICE_OVER_WIFI_SETTING_ENABLED;
+
+ private static final int EAB_PROVISIONED_CONFIG_ID =
+ ImsConfig.ConfigConstants.EAB_SETTING_ENABLED;
+
//Values in must match CELL_INFO_REFRESH_RATES
private static final String[] CELL_INFO_REFRESH_RATE_LABELS = {
"Disabled",
@@ -285,7 +293,6 @@
private TelephonyManager mTelephonyManager;
private ImsManager mImsManager = null;
private Phone mPhone = null;
- private ProvisioningManager mProvisioningManager = null;
private String mPingHostnameResultV4;
private String mPingHostnameResultV6;
@@ -419,9 +426,8 @@
mTelephonyManager = mTelephonyManager.createForSubscriptionId(subId);
// update the phoneId
+ mImsManager = ImsManager.getInstance(getApplicationContext(), phoneIndex);
mPhone = PhoneFactory.getPhone(phoneIndex);
- mImsManager = new ImsManager(mPhone.getContext());
- mProvisioningManager = ProvisioningManager.createForSubscriptionId(mPhone.getSubId());
updateAllFields();
}
@@ -481,8 +487,7 @@
mTelephonyManager = ((TelephonyManager) getSystemService(TELEPHONY_SERVICE))
.createForSubscriptionId(mPhone.getSubId());
- mImsManager = new ImsManager(mPhone.getContext());
- mProvisioningManager = ProvisioningManager.createForSubscriptionId(mPhone.getSubId());
+ mImsManager = ImsManager.getInstance(getApplicationContext(), mPhone.getPhoneId());
sPhoneIndexLabels = getPhoneIndexLabels(mTelephonyManager);
@@ -550,7 +555,7 @@
mImsWfcProvisionedSwitch = (Switch) findViewById(R.id.wfc_provisioned_switch);
mEabProvisionedSwitch = (Switch) findViewById(R.id.eab_provisioned_switch);
- if (!isImsSupportedOnDevice(mPhone.getContext())) {
+ if (!ImsManager.isImsSupportedOnDevice(mPhone.getContext())) {
mImsVolteProvisionedSwitch.setVisibility(View.GONE);
mImsVtProvisionedSwitch.setVisibility(View.GONE);
mImsWfcProvisionedSwitch.setVisibility(View.GONE);
@@ -781,8 +786,7 @@
R.string.radioInfo_menu_viewFDN).setOnMenuItemClickListener(mViewFDNCallback);
menu.add(1, MENU_ITEM_VIEW_SDN, 0,
R.string.radioInfo_menu_viewSDN).setOnMenuItemClickListener(mViewSDNCallback);
-
- if (isImsSupportedOnDevice(mPhone.getContext())) {
+ if (ImsManager.isImsSupportedOnDevice(mPhone.getContext())) {
menu.add(1, MENU_ITEM_GET_IMS_STATUS,
0, R.string.radioInfo_menu_getIMS).setOnMenuItemClickListener(mGetImsStatus);
}
@@ -1510,38 +1514,34 @@
mRadioPowerOnSwitch.setOnCheckedChangeListener(mRadioPowerOnChangeListener);
}
- private void setImsVolteProvisionedState(boolean state) {
+ void setImsVolteProvisionedState(boolean state) {
Log.d(TAG, "setImsVolteProvisioned state: " + ((state) ? "on" : "off"));
- setImsConfigProvisionedState(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
- ImsRegistrationImplBase.REGISTRATION_TECH_LTE, state);
+ setImsConfigProvisionedState(IMS_VOLTE_PROVISIONED_CONFIG_ID, state);
}
- private void setImsVtProvisionedState(boolean state) {
+ void setImsVtProvisionedState(boolean state) {
Log.d(TAG, "setImsVtProvisioned() state: " + ((state) ? "on" : "off"));
- setImsConfigProvisionedState(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO,
- ImsRegistrationImplBase.REGISTRATION_TECH_LTE, state);
+ setImsConfigProvisionedState(IMS_VT_PROVISIONED_CONFIG_ID, state);
}
- private void setImsWfcProvisionedState(boolean state) {
+ void setImsWfcProvisionedState(boolean state) {
Log.d(TAG, "setImsWfcProvisioned() state: " + ((state) ? "on" : "off"));
- setImsConfigProvisionedState(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
- ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN, state);
+ setImsConfigProvisionedState(IMS_WFC_PROVISIONED_CONFIG_ID, state);
}
- private void setEabProvisionedState(boolean state) {
+ void setEabProvisionedState(boolean state) {
Log.d(TAG, "setEabProvisioned() state: " + ((state) ? "on" : "off"));
- setRcsConfigProvisionedState(ImsRcsManager.CAPABILITY_TYPE_PRESENCE_UCE,
- ImsRegistrationImplBase.REGISTRATION_TECH_LTE, state);
+ setImsConfigProvisionedState(EAB_PROVISIONED_CONFIG_ID, state);
}
- private void setImsConfigProvisionedState(int capability, int tech, boolean state) {
- if (mProvisioningManager != null) {
+ void setImsConfigProvisionedState(int configItem, boolean state) {
+ if (mPhone != null && mImsManager != null) {
mQueuedWork.execute(new Runnable() {
public void run() {
try {
- mProvisioningManager.setProvisioningStatusForCapability(
- capability, tech, state);
- } catch (RuntimeException e) {
+ mImsManager.getConfigInterface().setProvisionedValue(
+ configItem, state ? 1 : 0);
+ } catch (ImsException e) {
Log.e(TAG, "setImsConfigProvisioned() exception:", e);
}
}
@@ -1549,71 +1549,6 @@
}
}
- private void setRcsConfigProvisionedState(int capability, int tech, boolean state) {
- if (mProvisioningManager != null) {
- mQueuedWork.execute(new Runnable() {
- public void run() {
- try {
- mProvisioningManager.setRcsProvisioningStatusForCapability(
- capability, tech, state);
- } catch (RuntimeException e) {
- Log.e(TAG, "setRcsConfigProvisioned() exception:", e);
- }
- }
- });
- }
- }
-
- private boolean isImsVolteProvisioningRequired() {
- return isImsConfigProvisioningRequired(
- MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
- ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
- }
-
- private boolean isImsVtProvisioningRequired() {
- return isImsConfigProvisioningRequired(
- MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO,
- ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
- }
-
- private boolean isImsWfcProvisioningRequired() {
- return isImsConfigProvisioningRequired(
- MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
- ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN);
- }
-
- private boolean isEabProvisioningRequired() {
- return isRcsConfigProvisioningRequired(
- ImsRcsManager.CAPABILITY_TYPE_PRESENCE_UCE,
- ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
- }
-
- private boolean isImsConfigProvisioningRequired(int capability, int tech) {
- if (mProvisioningManager != null) {
- try {
- return mProvisioningManager.isProvisioningRequiredForCapability(
- capability, tech);
- } catch (RuntimeException e) {
- Log.e(TAG, "isImsConfigProvisioningRequired() exception:", e);
- }
- }
-
- return false;
- }
-
- private boolean isRcsConfigProvisioningRequired(int capability, int tech) {
- if (mProvisioningManager != null) {
- try {
- return mProvisioningManager.isRcsProvisioningRequiredForCapability(
- capability, tech);
- } catch (RuntimeException e) {
- Log.e(TAG, "isRcsConfigProvisioningRequired() exception:", e);
- }
- }
-
- return false;
- }
-
OnCheckedChangeListener mRadioPowerOnChangeListener = new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
@@ -1649,8 +1584,11 @@
};
private boolean isImsVolteProvisioned() {
- return getImsConfigProvisionedState(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
- ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
+ if (mImsManager != null) {
+ return mImsManager.isVolteEnabledByPlatform()
+ && mImsManager.isVolteProvisionedOnDevice();
+ }
+ return false;
}
OnCheckedChangeListener mImsVolteCheckedChangeListener = new OnCheckedChangeListener() {
@@ -1661,8 +1599,11 @@
};
private boolean isImsVtProvisioned() {
- return getImsConfigProvisionedState(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO,
- ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
+ if (mImsManager != null) {
+ return mImsManager.isVtEnabledByPlatform()
+ && mImsManager.isVtProvisionedOnDevice();
+ }
+ return false;
}
OnCheckedChangeListener mImsVtCheckedChangeListener = new OnCheckedChangeListener() {
@@ -1673,8 +1614,11 @@
};
private boolean isImsWfcProvisioned() {
- return getImsConfigProvisionedState(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
- ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN);
+ if (mImsManager != null) {
+ return mImsManager.isWfcEnabledByPlatform()
+ && mImsManager.isWfcProvisionedOnDevice();
+ }
+ return false;
}
OnCheckedChangeListener mImsWfcCheckedChangeListener = new OnCheckedChangeListener() {
@@ -1685,8 +1629,7 @@
};
private boolean isEabProvisioned() {
- return getRcsConfigProvisionedState(ImsRcsManager.CAPABILITY_TYPE_PRESENCE_UCE,
- ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
+ return isFeatureProvisioned(EAB_PROVISIONED_CONFIG_ID, false);
}
OnCheckedChangeListener mEabCheckedChangeListener = new OnCheckedChangeListener() {
@@ -1696,30 +1639,23 @@
}
};
- private boolean getImsConfigProvisionedState(int capability, int tech) {
- if (mProvisioningManager != null) {
+ private boolean isFeatureProvisioned(int featureId, boolean defaultValue) {
+ boolean provisioned = defaultValue;
+ if (mImsManager != null) {
try {
- return mProvisioningManager.getProvisioningStatusForCapability(
- capability, tech);
- } catch (RuntimeException e) {
- Log.e(TAG, "getImsConfigProvisionedState() exception:", e);
+ ImsConfig imsConfig = mImsManager.getConfigInterface();
+ if (imsConfig != null) {
+ provisioned =
+ (imsConfig.getProvisionedValue(featureId)
+ == ImsConfig.FeatureValueConstants.ON);
+ }
+ } catch (ImsException ex) {
+ Log.e(TAG, "isFeatureProvisioned() exception:", ex);
}
}
- return false;
- }
-
- private boolean getRcsConfigProvisionedState(int capability, int tech) {
- if (mProvisioningManager != null) {
- try {
- return mProvisioningManager.getRcsProvisioningStatusForCapability(
- capability, tech);
- } catch (RuntimeException e) {
- Log.e(TAG, "getRcsConfigProvisionedState() exception:", e);
- }
- }
-
- return false;
+ log("isFeatureProvisioned() featureId=" + featureId + " provisioned=" + provisioned);
+ return provisioned;
}
private boolean isEabEnabledByPlatform() {
@@ -1738,56 +1674,35 @@
}
private void updateImsProvisionedState() {
- if (!isImsSupportedOnDevice(mPhone.getContext())) {
+ if (!ImsManager.isImsSupportedOnDevice(mPhone.getContext())) {
return;
}
-
- updateServiceEnabledByPlatform();
-
- updateEabProvisionedSwitch(isEabEnabledByPlatform());
- }
-
- private void updateVolteProvisionedSwitch(boolean isEnabledByPlatform) {
- boolean isProvisioned = isEnabledByPlatform && isImsVolteProvisioned();
- log("updateImsProvisionedState isProvisioned" + isProvisioned);
-
+ log("updateImsProvisionedState isImsVolteProvisioned()=" + isImsVolteProvisioned());
+ //delightful hack to prevent on-checked-changed calls from
+ //actually forcing the ims provisioning to its transient/current value.
mImsVolteProvisionedSwitch.setOnCheckedChangeListener(null);
- mImsVolteProvisionedSwitch.setChecked(isProvisioned);
+ mImsVolteProvisionedSwitch.setChecked(isImsVolteProvisioned());
mImsVolteProvisionedSwitch.setOnCheckedChangeListener(mImsVolteCheckedChangeListener);
mImsVolteProvisionedSwitch.setEnabled(!IS_USER_BUILD
- && isEnabledByPlatform && isImsVolteProvisioningRequired());
- }
-
- private void updateVtProvisionedSwitch(boolean isEnabledByPlatform) {
- boolean isProvisioned = isEnabledByPlatform && isImsVtProvisioned();
- log("updateVtProvisionedSwitch isProvisioned" + isProvisioned);
+ && mImsManager.isVolteEnabledByPlatform());
mImsVtProvisionedSwitch.setOnCheckedChangeListener(null);
- mImsVtProvisionedSwitch.setChecked(isProvisioned);
+ mImsVtProvisionedSwitch.setChecked(isImsVtProvisioned());
mImsVtProvisionedSwitch.setOnCheckedChangeListener(mImsVtCheckedChangeListener);
mImsVtProvisionedSwitch.setEnabled(!IS_USER_BUILD
- && isEnabledByPlatform && isImsVtProvisioningRequired());
- }
-
- private void updateWfcProvisionedSwitch(boolean isEnabledByPlatform) {
- boolean isProvisioned = isEnabledByPlatform && isImsWfcProvisioned();
- log("updateWfcProvisionedSwitch isProvisioned" + isProvisioned);
+ && mImsManager.isVtEnabledByPlatform());
mImsWfcProvisionedSwitch.setOnCheckedChangeListener(null);
- mImsWfcProvisionedSwitch.setChecked(isProvisioned);
+ mImsWfcProvisionedSwitch.setChecked(isImsWfcProvisioned());
mImsWfcProvisionedSwitch.setOnCheckedChangeListener(mImsWfcCheckedChangeListener);
mImsWfcProvisionedSwitch.setEnabled(!IS_USER_BUILD
- && isEnabledByPlatform && isImsWfcProvisioningRequired());
- }
-
- private void updateEabProvisionedSwitch(boolean isEnabledByPlatform) {
- log("updateEabProvisionedSwitch isEabWfcProvisioned()=" + isEabProvisioned());
+ && mImsManager.isWfcEnabledByPlatform());
mEabProvisionedSwitch.setOnCheckedChangeListener(null);
mEabProvisionedSwitch.setChecked(isEabProvisioned());
mEabProvisionedSwitch.setOnCheckedChangeListener(mEabCheckedChangeListener);
mEabProvisionedSwitch.setEnabled(!IS_USER_BUILD
- && isEnabledByPlatform && isEabProvisioningRequired());
+ && isEabEnabledByPlatform());
}
OnClickListener mDnsCheckButtonHandler = new OnClickListener() {
@@ -2026,28 +1941,4 @@
intent.putExtra("isDefault", isChecked);
sendBroadcast(intent);
}
-
- private boolean isImsSupportedOnDevice(Context context) {
- return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY_IMS);
- }
-
- private void updateServiceEnabledByPlatform() {
- ImsMmTelManager imsMmTelManager = mImsManager.getImsMmTelManager(mPhone.getSubId());
- try {
- imsMmTelManager.isSupported(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
- AccessNetworkConstants.TRANSPORT_TYPE_WWAN, getMainExecutor(), (result) -> {
- updateVolteProvisionedSwitch(result);
- });
- imsMmTelManager.isSupported(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO,
- AccessNetworkConstants.TRANSPORT_TYPE_WWAN, getMainExecutor(), (result) -> {
- updateVtProvisionedSwitch(result);
- });
- imsMmTelManager.isSupported(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
- AccessNetworkConstants.TRANSPORT_TYPE_WLAN, getMainExecutor(), (result) -> {
- updateWfcProvisionedSwitch(result);
- });
- } catch (ImsException e) {
- e.printStackTrace();
- }
- }
}
diff --git a/src/com/android/phone/slicestore/SliceStore.java b/src/com/android/phone/slicestore/SliceStore.java
index 20245f6..bb66973 100644
--- a/src/com/android/phone/slicestore/SliceStore.java
+++ b/src/com/android/phone/slicestore/SliceStore.java
@@ -16,6 +16,7 @@
package com.android.phone.slicestore;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.PendingIntent;
@@ -27,7 +28,6 @@
import android.net.ConnectivityManager;
import android.os.AsyncResult;
import android.os.Handler;
-import android.os.Looper;
import android.os.Message;
import android.os.PersistableBundle;
import android.telephony.AnomalyReporter;
@@ -42,6 +42,8 @@
import com.android.internal.telephony.Phone;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Arrays;
@@ -68,6 +70,29 @@
public class SliceStore extends Handler {
@NonNull private static final String TAG = "SliceStore";
+ /** Unknown failure code. */
+ public static final int FAILURE_CODE_UNKNOWN = 0;
+ /** Network boost purchase failed because the carrier URL is unavailable. */
+ public static final int FAILURE_CODE_CARRIER_URL_UNAVAILABLE = 1;
+ /** Network boost purchase failed because the server is unreachable. */
+ public static final int FAILURE_CODE_SERVER_UNREACHABLE = 2;
+ /** Network boost purchase failed because user authentication failed. */
+ public static final int FAILURE_CODE_AUTHENTICATION_FAILED = 3;
+ /** Network boost purchase failed because the payment failed. */
+ public static final int FAILURE_CODE_PAYMENT_FAILED = 4;
+
+ /**
+ * Failure codes that the carrier website can return when a premium capability purchase fails.
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = { "FAILURE_CODE_" }, value = {
+ FAILURE_CODE_UNKNOWN,
+ FAILURE_CODE_CARRIER_URL_UNAVAILABLE,
+ FAILURE_CODE_SERVER_UNREACHABLE,
+ FAILURE_CODE_AUTHENTICATION_FAILED,
+ FAILURE_CODE_PAYMENT_FAILED})
+ public @interface FailureCode {}
+
/** Value for an invalid premium capability. */
public static final int PREMIUM_CAPABILITY_INVALID = -1;
@@ -77,8 +102,16 @@
private static final int EVENT_SLICING_CONFIG_CHANGED = 2;
/** Display booster notification. */
private static final int EVENT_DISPLAY_BOOSTER_NOTIFICATION = 3;
- /** Boost was not purchased within the timeout specified by carrier configs. */
+ /**
+ * Premium capability was not purchased within the timeout specified by
+ * {@link CarrierConfigManager#KEY_PREMIUM_CAPABILITY_NOTIFICATION_DISPLAY_TIMEOUT_MILLIS_LONG}.
+ */
private static final int EVENT_PURCHASE_TIMEOUT = 4;
+ /**
+ * Network did not set up the slicing configuration within the timeout specified by
+ * {@link CarrierConfigManager#KEY_PREMIUM_CAPABILITY_NETWORK_SETUP_TIME_MILLIS_LONG}.
+ */
+ private static final int EVENT_SETUP_TIMEOUT = 5;
/** UUID to report an anomaly when a premium capability is throttled twice in a row. */
private static final String UUID_CAPABILITY_THROTTLED_TWICE =
@@ -87,6 +120,13 @@
private static final String UUID_INVALID_PHONE_ID = "ced79f1a-8ac0-4260-8cf3-08b54c0494f3";
/** UUID to report an anomaly when receiving an unknown action. */
private static final String UUID_UNKNOWN_ACTION = "0197efb0-dab1-4b0a-abaf-ac9336ec7923";
+ /** UUID to report an anomaly when receiving an unknown failure code with a non-empty reason. */
+ private static final String UUID_UNKNOWN_FAILURE_CODE = "76943b23-4415-400c-9855-b534fc4fc62c";
+ /**
+ * UUID to report an anomaly when the network fails to set up a slicing configuration after
+ * the user purchases a premium capability.
+ */
+ private static final String UUID_NETWORK_SETUP_FAILED = "12eeffbf-08f8-40ed-9a00-d344199552fc";
/** Action to start the SliceStore application and display the network boost notification. */
public static final String ACTION_START_SLICE_STORE =
@@ -106,6 +146,9 @@
/** Action indicating the purchase request was not made on the default data subscription. */
private static final String ACTION_SLICE_STORE_RESPONSE_NOT_DEFAULT_DATA =
"com.android.phone.slicestore.action.SLICE_STORE_RESPONSE_NOT_DEFAULT_DATA";
+ /** Action indicating the purchase request was successful. */
+ private static final String ACTION_SLICE_STORE_RESPONSE_SUCCESS =
+ "com.android.phone.slicestore.action.SLICE_STORE_RESPONSE_SUCCESS";
/** Extra for the phone index to send to the SliceStore application. */
public static final String EXTRA_PHONE_ID = "com.android.phone.slicestore.extra.PHONE_ID";
@@ -114,6 +157,15 @@
/** Extra for the requested premium capability to purchase from the SliceStore application. */
public static final String EXTRA_PREMIUM_CAPABILITY =
"com.android.phone.slicestore.extra.PREMIUM_CAPABILITY";
+ /** Extra for the duration of the purchased premium capability. */
+ public static final String EXTRA_PURCHASE_DURATION =
+ "com.android.phone.slicestore.extra.PURCHASE_DURATION";
+ /** Extra for the {@link FailureCode} why the premium capability purchase failed. */
+ public static final String EXTRA_FAILURE_CODE =
+ "com.android.phone.slicestore.extra.FAILURE_CODE";
+ /** Extra for the human-readable reason why the premium capability purchase failed. */
+ public static final String EXTRA_FAILURE_REASON =
+ "com.android.phone.slicestore.extra.FAILURE_REASON";
/**
* Extra for the application name requesting to purchase the premium capability
* from the SliceStore application.
@@ -131,6 +183,8 @@
* Extra for the carrier error PendingIntent that the SliceStore application can send as a
* response if the premium capability purchase request failed due to a carrier error.
* Sends {@link #ACTION_SLICE_STORE_RESPONSE_CARRIER_ERROR}.
+ * Sender can modify the intent to specify the failure code and reason for failure with
+ * {@link #EXTRA_FAILURE_CODE} and {@link #EXTRA_FAILURE_REASON}.
*/
public static final String EXTRA_INTENT_CARRIER_ERROR =
"com.android.phone.slicestore.extra.INTENT_CARRIER_ERROR";
@@ -150,6 +204,15 @@
*/
public static final String EXTRA_INTENT_NOT_DEFAULT_DATA =
"com.android.phone.slicestore.extra.INTENT_NOT_DEFAULT_DATA";
+ /**
+ * Extra for the success PendingIntent that the SliceStore application can send as a response
+ * if the premium capability purchase request was successful.
+ * Sends {@link #ACTION_SLICE_STORE_RESPONSE_SUCCESS}.
+ * Sender can modify the intent to specify a purchase duration with
+ * {@link #EXTRA_PURCHASE_DURATION}.
+ */
+ public static final String EXTRA_INTENT_SUCCESS =
+ "com.android.phone.slicestore.extra.INTENT_SUCCESS";
/** Component name to send an explicit broadcast to SliceStoreBroadcastReceiver. */
private static final ComponentName SLICE_STORE_COMPONENT_NAME =
@@ -161,8 +224,8 @@
/** The Phone instance used to create the SliceStore */
@NonNull private final Phone mPhone;
- /** The set of purchased capabilities. */
- @NonNull private final Set<Integer> mPurchasedCapabilities = new HashSet<>();
+ /** The set of capabilities that are pending network setup. */
+ @NonNull private final Set<Integer> mPendingSetupCapabilities = new HashSet<>();
/** The set of throttled capabilities. */
@NonNull private final Set<Integer> mThrottledCapabilities = new HashSet<>();
/** A map of pending capabilities to the onComplete message for the purchase request. */
@@ -174,7 +237,7 @@
@Nullable private NetworkSlicingConfig mSlicingConfig;
private class SliceStoreBroadcastReceiver extends BroadcastReceiver {
- private final @TelephonyManager.PremiumCapability int mCapability;
+ @TelephonyManager.PremiumCapability private final int mCapability;
SliceStoreBroadcastReceiver(@TelephonyManager.PremiumCapability int capability) {
mCapability = capability;
@@ -191,11 +254,9 @@
int capability = intent.getIntExtra(EXTRA_PREMIUM_CAPABILITY,
PREMIUM_CAPABILITY_INVALID);
if (SliceStore.getInstance(phoneId) == null) {
- String logStr = "SliceStoreBroadcastReceiver( "
+ reportAnomaly(UUID_INVALID_PHONE_ID, "SliceStoreBroadcastReceiver( "
+ TelephonyManager.convertPremiumCapabilityToString(mCapability)
- + ") received invalid phoneId: " + phoneId;
- loge(logStr);
- AnomalyReporter.reportAnomaly(UUID.fromString(UUID_INVALID_PHONE_ID), logStr);
+ + ") received invalid phoneId: " + phoneId);
return;
} else if (capability != mCapability) {
logd("SliceStoreBroadcastReceiver("
@@ -214,11 +275,10 @@
break;
}
case ACTION_SLICE_STORE_RESPONSE_CARRIER_ERROR: {
- logd("Carrier error for capability: "
- + TelephonyManager.convertPremiumCapabilityToString(capability));
- SliceStore.getInstance(phoneId).sendPurchaseResultFromSliceStore(capability,
- TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_CARRIER_ERROR,
- true);
+ int failureCode = intent.getIntExtra(EXTRA_FAILURE_CODE, FAILURE_CODE_UNKNOWN);
+ String failureReason = intent.getStringExtra(EXTRA_FAILURE_REASON);
+ SliceStore.getInstance(phoneId).onCarrierError(
+ capability, failureCode, failureReason);
break;
}
case ACTION_SLICE_STORE_RESPONSE_REQUEST_FAILED: {
@@ -238,12 +298,15 @@
false);
break;
}
+ case ACTION_SLICE_STORE_RESPONSE_SUCCESS: {
+ long duration = intent.getLongExtra(EXTRA_PURCHASE_DURATION, 0);
+ SliceStore.getInstance(phoneId).onCarrierSuccess(capability, duration);
+ break;
+ }
default:
- String logStr = "SliceStoreBroadcastReceiver("
+ reportAnomaly(UUID_UNKNOWN_ACTION, "SliceStoreBroadcastReceiver("
+ TelephonyManager.convertPremiumCapabilityToString(mCapability)
- + ") received unknown action: " + action;
- loge(logStr);
- AnomalyReporter.reportAnomaly(UUID.fromString(UUID_UNKNOWN_ACTION), logStr);
+ + ") received unknown action: " + action);
break;
}
}
@@ -276,7 +339,7 @@
}
private SliceStore(@NonNull Phone phone) {
- super(Looper.myLooper());
+ super(phone.getLooper());
mPhone = phone;
// TODO: Create a cached value for slicing config in DataIndication and initialize here
mPhone.mCi.registerForSlicingConfigChanged(this, EVENT_SLICING_CONFIG_CHANGED, null);
@@ -297,6 +360,7 @@
NetworkSlicingConfig config = (NetworkSlicingConfig) ar.result;
logd("EVENT_SLICING_CONFIG_CHANGED: from " + mSlicingConfig + " to " + config);
mSlicingConfig = config;
+ onSlicingConfigChanged();
break;
}
case EVENT_DISPLAY_BOOSTER_NOTIFICATION: {
@@ -314,6 +378,12 @@
onTimeout(capability);
break;
}
+ case EVENT_SETUP_TIMEOUT:
+ int capability = (int) msg.obj;
+ logd("EVENT_SETUP_TIMEOUT: for capability "
+ + TelephonyManager.convertPremiumCapabilityToString(capability));
+ onSetupTimeout(capability);
+ break;
default:
loge("Unknown event: " + msg.obj);
}
@@ -380,13 +450,18 @@
onComplete);
return;
}
- if (mPurchasedCapabilities.contains(capability) || isSlicingConfigActive(capability)) {
- // TODO (b/245882601): Handle capability expiry
+ if (isSlicingConfigActive(capability)) {
sendPurchaseResult(capability,
TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_ALREADY_PURCHASED,
onComplete);
return;
}
+ if (mPendingSetupCapabilities.contains(capability)) {
+ sendPurchaseResult(capability,
+ TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_PENDING_NETWORK_SETUP,
+ onComplete);
+ return;
+ }
if (mThrottledCapabilities.contains(capability)) {
sendPurchaseResult(capability,
TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_THROTTLED,
@@ -456,10 +531,20 @@
throttleDuration);
}
} else {
- String logStr = TelephonyManager.convertPremiumCapabilityToString(capability)
- + " is already throttled.";
- loge(logStr);
- AnomalyReporter.reportAnomaly(UUID.fromString(UUID_CAPABILITY_THROTTLED_TWICE), logStr);
+ reportAnomaly(UUID_CAPABILITY_THROTTLED_TWICE,
+ TelephonyManager.convertPremiumCapabilityToString(capability)
+ + " is already throttled.");
+ }
+ }
+
+ private void onSlicingConfigChanged() {
+ for (int capability : new int[] {TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY}) {
+ if (isSlicingConfigActive(capability) && hasMessages(EVENT_SETUP_TIMEOUT, capability)) {
+ logd("Successfully set up slicing configuration for "
+ + TelephonyManager.convertPremiumCapabilityToString(capability));
+ mPendingSetupCapabilities.remove(capability);
+ removeMessages(EVENT_SETUP_TIMEOUT, capability);
+ }
}
}
@@ -481,13 +566,16 @@
intent.putExtra(EXTRA_PREMIUM_CAPABILITY, capability);
intent.putExtra(EXTRA_REQUESTING_APP_NAME, appName);
intent.putExtra(EXTRA_INTENT_CANCELED,
- createPendingIntent(ACTION_SLICE_STORE_RESPONSE_CANCELED, capability));
+ createPendingIntent(ACTION_SLICE_STORE_RESPONSE_CANCELED, capability, false));
intent.putExtra(EXTRA_INTENT_CARRIER_ERROR,
- createPendingIntent(ACTION_SLICE_STORE_RESPONSE_CARRIER_ERROR, capability));
+ createPendingIntent(ACTION_SLICE_STORE_RESPONSE_CARRIER_ERROR, capability, true));
intent.putExtra(EXTRA_INTENT_REQUEST_FAILED,
- createPendingIntent(ACTION_SLICE_STORE_RESPONSE_REQUEST_FAILED, capability));
+ createPendingIntent(ACTION_SLICE_STORE_RESPONSE_REQUEST_FAILED, capability, false));
intent.putExtra(EXTRA_INTENT_NOT_DEFAULT_DATA,
- createPendingIntent(ACTION_SLICE_STORE_RESPONSE_NOT_DEFAULT_DATA, capability));
+ createPendingIntent(ACTION_SLICE_STORE_RESPONSE_NOT_DEFAULT_DATA, capability,
+ false));
+ intent.putExtra(EXTRA_INTENT_SUCCESS,
+ createPendingIntent(ACTION_SLICE_STORE_RESPONSE_SUCCESS, capability, true));
logd("Broadcasting start intent to SliceStoreBroadcastReceiver.");
mPhone.getContext().sendBroadcast(intent);
@@ -498,6 +586,7 @@
filter.addAction(ACTION_SLICE_STORE_RESPONSE_CARRIER_ERROR);
filter.addAction(ACTION_SLICE_STORE_RESPONSE_REQUEST_FAILED);
filter.addAction(ACTION_SLICE_STORE_RESPONSE_NOT_DEFAULT_DATA);
+ filter.addAction(ACTION_SLICE_STORE_RESPONSE_SUCCESS);
mPhone.getContext().registerReceiver(mSliceStoreBroadcastReceivers.get(capability), filter);
}
@@ -506,15 +595,18 @@
*
* @param action The action that will be sent for this PendingIntent
* @param capability The premium capability that was requested.
+ * @param mutable {@code true} if the PendingIntent should be mutable and
+ * {@code false} if it should be immutable.
* @return The PendingIntent for the given action and capability.
*/
@NonNull private PendingIntent createPendingIntent(@NonNull String action,
- @TelephonyManager.PremiumCapability int capability) {
+ @TelephonyManager.PremiumCapability int capability, boolean mutable) {
Intent intent = new Intent(action);
intent.putExtra(EXTRA_PHONE_ID, mPhone.getPhoneId());
intent.putExtra(EXTRA_PREMIUM_CAPABILITY, capability);
- return PendingIntent.getBroadcast(mPhone.getContext(), 0, intent,
- PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_MUTABLE);
+ return PendingIntent.getBroadcast(mPhone.getContext(), capability, intent,
+ PendingIntent.FLAG_CANCEL_CURRENT
+ | (mutable ? PendingIntent.FLAG_MUTABLE : PendingIntent.FLAG_IMMUTABLE));
}
private void onTimeout(@TelephonyManager.PremiumCapability int capability) {
@@ -531,9 +623,43 @@
capability, TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_TIMEOUT, true);
}
- private void onCarrierSuccess(@TelephonyManager.PremiumCapability int capability) {
- // TODO(b/245882601): Process and return success.
- // Probably need to handle capability expiry as well
+ private void onCarrierError(@TelephonyManager.PremiumCapability int capability,
+ @FailureCode int failureCode, @Nullable String failureReason) {
+ logd("Carrier error for capability: "
+ + TelephonyManager.convertPremiumCapabilityToString(capability) + " with code: "
+ + convertFailureCodeToString(failureCode) + " and reason: " + failureReason);
+ if (failureCode == FAILURE_CODE_UNKNOWN && !TextUtils.isEmpty(failureReason)) {
+ reportAnomaly(UUID_UNKNOWN_FAILURE_CODE,
+ "Failure code needs to be added for: " + failureReason);
+ }
+ sendPurchaseResultFromSliceStore(capability,
+ TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_CARRIER_ERROR, true);
+ }
+
+ private void onCarrierSuccess(@TelephonyManager.PremiumCapability int capability,
+ long duration) {
+ logd("Successfully purchased premium capability "
+ + TelephonyManager.convertPremiumCapabilityToString(capability)
+ + " for " + TimeUnit.MILLISECONDS.toMinutes(duration) + " minutes.");
+ mPendingSetupCapabilities.add(capability);
+ long setupDuration = getCarrierConfigs().getLong(
+ CarrierConfigManager.KEY_PREMIUM_CAPABILITY_NETWORK_SETUP_TIME_MILLIS_LONG);
+ logd("Waiting " + TimeUnit.MILLISECONDS.toMinutes(setupDuration) + " minutes for the "
+ + "network to set up the slicing configuration.");
+ sendMessageDelayed(obtainMessage(EVENT_SETUP_TIMEOUT, capability), setupDuration);
+ sendPurchaseResultFromSliceStore(
+ capability, TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_SUCCESS, false);
+ }
+
+ private void onSetupTimeout(@TelephonyManager.PremiumCapability int capability) {
+ logd("onSetupTimeout: " + TelephonyManager.convertPremiumCapabilityToString(capability));
+ mPendingSetupCapabilities.remove(capability);
+ if (!isSlicingConfigActive(capability)) {
+ reportAnomaly(UUID_NETWORK_SETUP_FAILED,
+ "Failed to set up slicing configuration for capability "
+ + TelephonyManager.convertPremiumCapabilityToString(capability)
+ + " within the time specified.");
+ }
}
@Nullable private PersistableBundle getCarrierConfigs() {
@@ -628,6 +754,29 @@
return true;
}
+ /**
+ * Returns the failure code {@link FailureCode} as a String.
+ *
+ * @param failureCode The failure code.
+ * @return The failure code as a String.
+ */
+ @NonNull public static String convertFailureCodeToString(@FailureCode int failureCode) {
+ switch (failureCode) {
+ case FAILURE_CODE_UNKNOWN: return "UNKNOWN";
+ case FAILURE_CODE_CARRIER_URL_UNAVAILABLE: return "CARRIER_URL_UNAVAILABLE";
+ case FAILURE_CODE_SERVER_UNREACHABLE: return "SERVER_UNREACHABLE";
+ case FAILURE_CODE_AUTHENTICATION_FAILED: return "AUTHENTICATION_FAILED";
+ case FAILURE_CODE_PAYMENT_FAILED: return "PAYMENT_FAILED";
+ default:
+ return "UNKNOWN(" + failureCode + ")";
+ }
+ }
+
+ private void reportAnomaly(@NonNull String uuid, @NonNull String log) {
+ loge(log);
+ AnomalyReporter.reportAnomaly(UUID.fromString(uuid), log);
+ }
+
private void logd(String s) {
Log.d(TAG + "-" + mPhone.getPhoneId(), s);
}
diff --git a/tests/src/com/android/TelephonyTestBase.java b/tests/src/com/android/TelephonyTestBase.java
index ffda81b..d72d85e 100644
--- a/tests/src/com/android/TelephonyTestBase.java
+++ b/tests/src/com/android/TelephonyTestBase.java
@@ -24,10 +24,16 @@
import com.android.internal.telephony.PhoneConfigurationManager;
+import org.junit.After;
+import org.junit.Before;
import org.junit.Rule;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
+import java.lang.reflect.Field;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
@@ -40,6 +46,10 @@
protected TestContext mContext;
+ private final HashMap<InstanceKey, Object> mOldInstances = new HashMap<>();
+ private final LinkedList<InstanceKey> mInstanceKeys = new LinkedList<>();
+
+ @Before
public void setUp() throws Exception {
mContext = spy(new TestContext());
// Set up the looper if it does not exist on the test thread.
@@ -56,9 +66,11 @@
}
}
+ @After
public void tearDown() throws Exception {
// Ensure there are no static references to handlers after test completes.
PhoneConfigurationManager.unregisterAllMultiSimConfigChangeRegistrants();
+ restoreInstances();
}
protected final boolean waitForExecutorAction(Executor executor, long timeoutMillis) {
@@ -108,6 +120,61 @@
}
}
+ protected synchronized void replaceInstance(final Class c, final String instanceName,
+ final Object obj, final Object newValue)
+ throws Exception {
+ Field field = c.getDeclaredField(instanceName);
+ field.setAccessible(true);
+
+ InstanceKey key = new InstanceKey(c, instanceName, obj);
+ if (!mOldInstances.containsKey(key)) {
+ mOldInstances.put(key, field.get(obj));
+ mInstanceKeys.add(key);
+ }
+ field.set(obj, newValue);
+ }
+
+ private synchronized void restoreInstances() throws Exception {
+ Iterator<InstanceKey> it = mInstanceKeys.descendingIterator();
+
+ while (it.hasNext()) {
+ InstanceKey key = it.next();
+ Field field = key.mClass.getDeclaredField(key.mInstName);
+ field.setAccessible(true);
+ field.set(key.mObj, mOldInstances.get(key));
+ }
+
+ mInstanceKeys.clear();
+ mOldInstances.clear();
+ }
+
+ private static class InstanceKey {
+ public final Class mClass;
+ public final String mInstName;
+ public final Object mObj;
+ InstanceKey(final Class c, final String instName, final Object obj) {
+ mClass = c;
+ mInstName = instName;
+ mObj = obj;
+ }
+
+ @Override
+ public int hashCode() {
+ return (mClass.getName().hashCode() * 31 + mInstName.hashCode()) * 31;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null || obj.getClass() != getClass()) {
+ return false;
+ }
+
+ InstanceKey other = (InstanceKey) obj;
+ return (other.mClass == mClass && other.mInstName.equals(mInstName)
+ && other.mObj == mObj);
+ }
+ }
+
protected TestContext getTestContext() {
return mContext;
}
diff --git a/tests/src/com/android/TestContext.java b/tests/src/com/android/TestContext.java
index 7edbed9..7c3a842 100644
--- a/tests/src/com/android/TestContext.java
+++ b/tests/src/com/android/TestContext.java
@@ -31,6 +31,7 @@
import android.os.Looper;
import android.os.PersistableBundle;
import android.os.Process;
+import android.os.UserManager;
import android.telecom.TelecomManager;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
@@ -58,6 +59,7 @@
@Mock TelephonyManager mMockTelephonyManager;
@Mock SubscriptionManager mMockSubscriptionManager;
@Mock ImsManager mMockImsManager;
+ @Mock UserManager mMockUserManager;
private SparseArray<PersistableBundle> mCarrierConfigs = new SparseArray<>();
@@ -147,6 +149,9 @@
case(Context.TELEPHONY_IMS_SERVICE) : {
return mMockImsManager;
}
+ case(Context.USER_SERVICE) : {
+ return mMockUserManager;
+ }
}
return null;
}
@@ -165,6 +170,9 @@
if (serviceClass == SubscriptionManager.class) {
return Context.TELEPHONY_SUBSCRIPTION_SERVICE;
}
+ if (serviceClass == UserManager.class) {
+ return Context.USER_SERVICE;
+ }
return null;
}
diff --git a/tests/src/com/android/phone/ImsStateCallbackControllerTest.java b/tests/src/com/android/phone/ImsStateCallbackControllerTest.java
index 60374bc..2bd87be 100644
--- a/tests/src/com/android/phone/ImsStateCallbackControllerTest.java
+++ b/tests/src/com/android/phone/ImsStateCallbackControllerTest.java
@@ -52,6 +52,7 @@
import android.testing.TestableLooper;
import android.util.Log;
+import com.android.TelephonyTestBase;
import com.android.ims.FeatureConnector;
import com.android.ims.ImsManager;
import com.android.ims.RcsFeatureManager;
@@ -70,13 +71,12 @@
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
-import java.lang.reflect.Field;
import java.util.concurrent.Executor;
/**
* Unit tests for RcsProvisioningMonitor
*/
-public class ImsStateCallbackControllerTest {
+public class ImsStateCallbackControllerTest extends TelephonyTestBase {
private static final String TAG = "ImsStateCallbackControllerTest";
private static final int FAKE_SUB_ID_BASE = 0x0FFFFFF0;
@@ -189,6 +189,7 @@
mLooper.destroy();
mLooper = null;
}
+ super.tearDown();
}
@Test
@@ -952,13 +953,6 @@
}
}
- private static void replaceInstance(final Class c,
- final String instanceName, final Object obj, final Object newValue) throws Exception {
- Field field = c.getDeclaredField(instanceName);
- field.setAccessible(true);
- field.set(obj, newValue);
- }
-
private void makeFakeActiveSubIds(int count) {
final int[] subIds = new int[count];
for (int i = 0; i < count; i++) {
diff --git a/tests/src/com/android/phone/NotificationMgrTest.java b/tests/src/com/android/phone/NotificationMgrTest.java
index a6ee276..6d979d6 100644
--- a/tests/src/com/android/phone/NotificationMgrTest.java
+++ b/tests/src/com/android/phone/NotificationMgrTest.java
@@ -69,9 +69,13 @@
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import com.android.TelephonyTestBase;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.PhoneFactory;
+import com.android.internal.telephony.data.DataConfigManager;
+import com.android.internal.telephony.data.DataNetworkController;
+import com.android.internal.telephony.data.DataSettingsManager;
import com.android.internal.telephony.util.NotificationChannelController;
import org.junit.Before;
@@ -81,15 +85,14 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import java.lang.reflect.Field;
+import java.util.Collections;
/**
* Unit Test for NotificationMgr
*/
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
-public class NotificationMgrTest {
-
+public class NotificationMgrTest extends TelephonyTestBase {
private static final int TEST_SUB_ID = 1;
private static final long SERIAL_NUMBER_OF_USER = 1234567L;
private static final String TEST_LABEL_CF = "test_call_forwarding";
@@ -111,8 +114,12 @@
@Mock NotificationManager mNotificationManager;
@Mock SubscriptionInfo mSubscriptionInfo;
@Mock Resources mResources;
+ @Mock Context mMockedContext;
@Mock ServiceState mServiceState;
@Mock CarrierConfigManager mCarrierConfigManager;
+ @Mock DataNetworkController mDataNetworkController;
+ @Mock DataSettingsManager mDataSettingsManager;
+ @Mock DataConfigManager mDataConfigManager;
private Phone[] mPhones;
private NotificationMgr mNotificationMgr;
@@ -123,6 +130,15 @@
mPhones = new Phone[]{mPhone};
replaceInstance(PhoneFactory.class, "sPhones", null, mPhones);
when(mPhone.getPhoneType()).thenReturn(PhoneConstants.PHONE_TYPE_GSM);
+ when(mPhone.getContext()).thenReturn(mMockedContext);
+ when(mMockedContext.getResources()).thenReturn(mResources);
+ when(mPhone.getServiceState()).thenReturn(mServiceState);
+ when(mPhone.getDataNetworkController()).thenReturn(mDataNetworkController);
+ when(mDataNetworkController.getInternetDataDisallowedReasons()).thenReturn(
+ Collections.emptyList());
+ when(mDataNetworkController.getDataConfigManager()).thenReturn(mDataConfigManager);
+ when(mPhone.getDataSettingsManager()).thenReturn(mDataSettingsManager);
+ when(mDataSettingsManager.isDataEnabledForReason(anyInt())).thenReturn(true);
when(mApp.getSharedPreferences(anyString(), anyInt())).thenReturn(mSharedPreferences);
when(mApp.getPackageName()).thenReturn(TEST_PACKAGE_NAME);
@@ -157,8 +173,7 @@
}
@Test
- public void testUpdateCfi_visible_noActiveSubscription_notificationNeverSent()
- throws Exception {
+ public void testUpdateCfi_visible_noActiveSubscription_notificationNeverSent() {
// Given no active subscription available
when(mSubscriptionManager.getActiveSubscriptionInfo(eq(TEST_SUB_ID))).thenReturn(null);
@@ -170,7 +185,7 @@
}
@Test
- public void testUpdateCfi_visible_hasActiveSub_singleSIM_notificationSent() throws Exception {
+ public void testUpdateCfi_visible_hasActiveSub_singleSIM_notificationSent() {
when(mTelephonyManager.getPhoneCount()).thenReturn(1);
when(mSubscriptionManager.getActiveSubscriptionInfo(eq(TEST_SUB_ID))).thenReturn(
mSubscriptionInfo);
@@ -181,8 +196,7 @@
}
@Test
- public void testUpdateCfi_visible_hasActiveSub_multiSIM_notificationSentWithoutDisplayName()
- throws Exception {
+ public void testUpdateCfi_visible_hasActiveSub_multiSIM_notificationSentWithoutDisplayName() {
when(mTelephonyManager.getPhoneCount()).thenReturn(2);
when(mSubscriptionManager.getActiveSubscriptionInfo(eq(TEST_SUB_ID))).thenReturn(
mSubscriptionInfo);
@@ -194,8 +208,7 @@
}
@Test
- public void testUpdateCfi_visible_hasActiveSub_multiSIM_notificationSentWithDisplayName()
- throws Exception {
+ public void testUpdateCfi_visible_hasActiveSub_multiSIM_notificationSentWithDisplayName() {
when(mTelephonyManager.getPhoneCount()).thenReturn(2);
when(mSubscriptionManager.getActiveSubscriptionInfo(eq(TEST_SUB_ID))).thenReturn(
mSubscriptionInfo);
@@ -207,8 +220,7 @@
}
@Test
- public void testUpdateCfi_invisible_hasUnmanagedProfile_notificationCanceled()
- throws Exception {
+ public void testUpdateCfi_invisible_hasUnmanagedProfile_notificationCanceled() {
when(mUserManager.isManagedProfile(anyInt())).thenReturn(false);
mNotificationMgr.updateCfi(TEST_SUB_ID, /*visible=*/false, /*isFresh=*/false);
@@ -217,8 +229,7 @@
}
@Test
- public void testUpdateCfi_invisible_allProfilesAreManaged_notificationNeverCanceled()
- throws Exception {
+ public void testUpdateCfi_invisible_allProfilesAreManaged_notificationNeverCanceled() {
when(mUserManager.isManagedProfile(anyInt())).thenReturn(true);
mNotificationMgr.updateCfi(TEST_SUB_ID, /*visible=*/false, /*isFresh=*/false);
@@ -227,7 +238,7 @@
}
@Test
- public void testShowDataRoamingNotification_roamingOn() throws Exception {
+ public void testShowDataRoamingNotification_roamingOn() {
mNotificationMgr.showDataRoamingNotification(TEST_SUB_ID, /*roamingOn=*/true);
verifyNotificationSentWithChannelId(
@@ -235,7 +246,7 @@
}
@Test
- public void testShowDataRoamingNotification_roamingOff() throws Exception {
+ public void testShowDataRoamingNotification_roamingOff() {
mNotificationMgr.showDataRoamingNotification(TEST_SUB_ID, /*roamingOn=*/false);
verifyNotificationSentWithChannelId(
@@ -250,8 +261,7 @@
}
@Test
- public void testUpdateNetworkSelection_justOutOfService_notificationNeverSent()
- throws Exception {
+ public void testUpdateNetworkSelection_justOutOfService_notificationNeverSent() {
prepareResourcesForNetworkSelection();
mNotificationMgr.updateNetworkSelection(ServiceState.STATE_OUT_OF_SERVICE, TEST_SUB_ID);
@@ -265,8 +275,7 @@
}
@Test
- public void testUpdateNetworkSelection_oosEnoughTime_selectionVisibleToUser_notificationSent()
- throws Exception {
+ public void testUpdateNetworkSelection_oosEnoughTime_selectionVisibleToUser_notificationSent() {
prepareResourcesForNetworkSelection();
when(mTelephonyManager.isManualNetworkSelectionAllowed()).thenReturn(true);
PersistableBundle config = new PersistableBundle();
@@ -288,8 +297,7 @@
}
@Test
- public void testUpdateNetworkSelection_invalidSubscription_notificationNotSent()
- throws Exception {
+ public void testUpdateNetworkSelection_invalidSubscription_notificationNotSent() {
prepareResourcesForNetworkSelection();
when(mTelephonyManager.isManualNetworkSelectionAllowed()).thenReturn(true);
PersistableBundle config = new PersistableBundle();
@@ -312,8 +320,7 @@
}
@Test
- public void testUpdateNetworkSelection_nullCarrierConfig_notificationNotSent()
- throws Exception {
+ public void testUpdateNetworkSelection_nullCarrierConfig_notificationNotSent() {
prepareResourcesForNetworkSelection();
when(mCarrierConfigManager.getConfigForSubId(TEST_SUB_ID)).thenReturn(null);
@@ -329,8 +336,7 @@
}
@Test
- public void testUpdateNetworkSelection_userNotAllowedToChooseOperator_notificationNotSent()
- throws Exception {
+ public void testUpdateNetworkSelection_userNotAllowedToChooseOperator_notificationNotSent() {
prepareResourcesForNetworkSelection();
PersistableBundle config = new PersistableBundle();
@@ -353,8 +359,8 @@
}
@Test
- public void testUpdateNetworkSelection_OverrideHideCarrierNetworkSelection_notificationNotSent()
- throws Exception {
+ public void
+ testUpdateNetworkSelection_OverrideHideCarrierNetworkSelection_notificationNotSent() {
prepareResourcesForNetworkSelection();
PersistableBundle config = new PersistableBundle();
@@ -401,8 +407,7 @@
}
@Test
- public void testUpdateNetworkSelection_worldMode_userSetLTE_notificationNotSent()
- throws Exception {
+ public void testUpdateNetworkSelection_worldMode_userSetLTE_notificationNotSent() {
prepareResourcesForNetworkSelection();
PersistableBundle config = new PersistableBundle();
@@ -431,8 +436,7 @@
}
@Test
- public void testUpdateNetworkSelection_worldMode_userSetTDSCDMA_notSupported_notifNotSent()
- throws Exception {
+ public void testUpdateNetworkSelection_worldMode_userSetTDSCDMA_notSupported_notifNotSent() {
prepareResourcesForNetworkSelection();
PersistableBundle config = new PersistableBundle();
@@ -462,8 +466,7 @@
}
@Test
- public void testUpdateNetworkSelection_worldMode_userSetWCDMA_notificationSent()
- throws Exception {
+ public void testUpdateNetworkSelection_worldMode_userSetWCDMA_notificationSent() {
prepareResourcesForNetworkSelection();
PersistableBundle config = new PersistableBundle();
@@ -494,8 +497,7 @@
}
@Test
- public void testUpdateNetworkSelection_worldPhone_networkSelectionNotHide_notificationSent()
- throws Exception {
+ public void testUpdateNetworkSelection_worldPhone_networkSelectionNotHide_notificationSent() {
prepareResourcesForNetworkSelection();
PersistableBundle config = new PersistableBundle();
@@ -519,8 +521,7 @@
}
@Test
- public void testUpdateNetworkSelection_gsmBasicOptionOn_notificationSent()
- throws Exception {
+ public void testUpdateNetworkSelection_gsmBasicOptionOn_notificationSent() {
prepareResourcesForNetworkSelection();
PersistableBundle config = new PersistableBundle();
@@ -545,8 +546,7 @@
}
@Test
- public void testUpdateNetworkSelection_gsmBasicOptionOff_notificationNotSent()
- throws Exception {
+ public void testUpdateNetworkSelection_gsmBasicOptionOff_notificationNotSent() {
prepareResourcesForNetworkSelection();
PersistableBundle config = new PersistableBundle();
@@ -569,8 +569,7 @@
}
@Test
- public void testShowLimitedSimFunctionWarningNotification_forTheFirstTime_notificationSent()
- throws Exception {
+ public void testShowLimitedSimFunctionWarningNotification_forTheFirstTime_notificationSent() {
when(mResources.getText(R.string.limited_sim_function_notification_message)).thenReturn(
CARRIER_NAME);
when(mResources.getText(
@@ -584,8 +583,8 @@
}
@Test
- public void testShowLimitedSimFunctionWarningNotification_consecutiveCall_notificationSentOnce()
- throws Exception {
+ public void
+ testShowLimitedSimFunctionWarningNotification_consecutiveCall_notificationSentOnce() {
when(mResources.getText(R.string.limited_sim_function_notification_message)).thenReturn(
CARRIER_NAME);
when(mResources.getText(
@@ -602,8 +601,7 @@
}
@Test
- public void testDismissLimitedSimFunctionWarningNotification_noShowCalledBefore_noCancelSent()
- throws Exception {
+ public void testDismissLimitedSimFunctionWarningNotification_noShowCalledBefore_noCancelSent() {
// showLimitedSimFunctionWarningNotification was never called before
mNotificationMgr.dismissLimitedSimFunctionWarningNotification(TEST_SUB_ID);
@@ -612,8 +610,7 @@
}
@Test
- public void testDismissLimitedSimFunctionWarningNotification_showCalledBefore_cancelSent()
- throws Exception {
+ public void testDismissLimitedSimFunctionWarningNotification_showCalledBefore_cancelSent() {
when(mResources.getText(R.string.limited_sim_function_notification_message)).thenReturn(
CARRIER_NAME);
when(mResources.getText(
@@ -651,11 +648,4 @@
when(mApp.getString(R.string.mobile_network_settings_class)).thenReturn(
MOBILE_NETWORK_SELECTION_CLASS);
}
-
- private static void replaceInstance(final Class c,
- final String instanceName, final Object obj, final Object newValue) throws Exception {
- Field field = c.getDeclaredField(instanceName);
- field.setAccessible(true);
- field.set(obj, newValue);
- }
}
diff --git a/tests/src/com/android/phone/PhoneInterfaceManagerTest.java b/tests/src/com/android/phone/PhoneInterfaceManagerTest.java
index ffc0177..08bdb9b 100644
--- a/tests/src/com/android/phone/PhoneInterfaceManagerTest.java
+++ b/tests/src/com/android/phone/PhoneInterfaceManagerTest.java
@@ -33,6 +33,7 @@
import com.android.internal.telephony.RILConstants;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -90,6 +91,7 @@
}
@Test
+ @Ignore("b/254731907")
public void matchLocaleFromSupportedLocaleList_inputLocaleChangeToSupportedLocale() {
// Input zh-TW, then look up the matched supported locale, zh-Hant-TW, instead.
String result1 = mPhoneInterfaceManager.matchLocaleFromSupportedLocaleList(
diff --git a/tests/src/com/android/phone/PhoneUtilsTest.java b/tests/src/com/android/phone/PhoneUtilsTest.java
index eb4c248..521a0bb 100644
--- a/tests/src/com/android/phone/PhoneUtilsTest.java
+++ b/tests/src/com/android/phone/PhoneUtilsTest.java
@@ -28,23 +28,19 @@
import androidx.test.runner.AndroidJUnit4;
+import com.android.TelephonyTestBase;
import com.android.internal.telephony.GsmCdmaPhone;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneFactory;
-import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import java.lang.reflect.Field;
-import java.util.ArrayList;
-import java.util.HashMap;
-
@RunWith(AndroidJUnit4.class)
-public class PhoneUtilsTest {
+public class PhoneUtilsTest extends TelephonyTestBase {
@Mock
private SubscriptionManager mMockSubscriptionManager;
@Mock
@@ -59,37 +55,6 @@
private PhoneAccountHandle mPhoneAccountHandleTest = new PhoneAccountHandle(
PSTN_CONNECTION_SERVICE_COMPONENT, mPhoneAccountHandleIdString);
- private HashMap<InstanceKey, Object> mOldInstances = new HashMap<InstanceKey, Object>();
-
- private ArrayList<InstanceKey> mInstanceKeys = new ArrayList<InstanceKey>();
-
- private static class InstanceKey {
- public final Class mClass;
- public final String mInstName;
- public final Object mObj;
- InstanceKey(final Class c, final String instName, final Object obj) {
- mClass = c;
- mInstName = instName;
- mObj = obj;
- }
-
- @Override
- public int hashCode() {
- return (mClass.getName().hashCode() * 31 + mInstName.hashCode()) * 31;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (obj == null || !(obj instanceof InstanceKey)) {
- return false;
- }
-
- InstanceKey other = (InstanceKey) obj;
- return (other.mClass == mClass && other.mInstName.equals(mInstName)
- && other.mObj == mObj);
- }
- }
-
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
@@ -100,37 +65,6 @@
replaceInstance(PhoneFactory.class, "sPhones", null, mPhones);
}
- @After
- public void tearDown() throws Exception {
- restoreInstance(PhoneFactory.class, "sPhones", null);
- }
-
- protected synchronized void replaceInstance(final Class c, final String instanceName,
- final Object obj, final Object newValue)
- throws Exception {
- Field field = c.getDeclaredField(instanceName);
- field.setAccessible(true);
-
- InstanceKey key = new InstanceKey(c, instanceName, obj);
- if (!mOldInstances.containsKey(key)) {
- mOldInstances.put(key, field.get(obj));
- mInstanceKeys.add(key);
- }
- field.set(obj, newValue);
- }
-
- protected synchronized void restoreInstance(final Class c, final String instanceName,
- final Object obj) throws Exception {
- InstanceKey key = new InstanceKey(c, instanceName, obj);
- if (mOldInstances.containsKey(key)) {
- Field field = c.getDeclaredField(instanceName);
- field.setAccessible(true);
- field.set(obj, mOldInstances.get(key));
- mOldInstances.remove(key);
- mInstanceKeys.remove(key);
- }
- }
-
@Test
public void testIsPhoneAccountActive() throws Exception {
assertTrue(PhoneUtils.isPhoneAccountActive(
diff --git a/tests/src/com/android/phone/Telephony2gUpdaterTest.java b/tests/src/com/android/phone/Telephony2gUpdaterTest.java
new file mode 100644
index 0000000..3443767
--- /dev/null
+++ b/tests/src/com/android/phone/Telephony2gUpdaterTest.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2022 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.phone;
+
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.os.UserManager;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.android.TelephonyTestBase;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+
+@RunWith(AndroidJUnit4.class)
+public class Telephony2gUpdaterTest extends TelephonyTestBase {
+ private Telephony2gUpdater mTelephony2gUpdater;
+ private Executor mExecutor;
+
+ private UserManager mMockUserManager;
+ private TelephonyManager mMockTelephonyManager;
+ private SubscriptionManager mMockSubscriptionManager;
+
+ // 2G Bitmask is 0b10000000_01001011
+ private static final long BASE_NETWORK = 0b11111111_11111111;
+ private static final long EXPECTED_DISABLED = 0b01111111_10110100;
+ private static final long EXPECTED_ENABLED = 0b11111111_11111111;
+
+
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+
+ mMockTelephonyManager = mContext.getSystemService(TelephonyManager.class);
+ mMockUserManager = mContext.getSystemService(UserManager.class);
+ mMockSubscriptionManager = mContext.getSystemService(SubscriptionManager.class);
+
+ mExecutor = Executors.newSingleThreadExecutor();
+ mTelephony2gUpdater = new Telephony2gUpdater(mExecutor,
+ getTestContext(), BASE_NETWORK);
+ }
+
+ @Test
+ public void handleUserRestrictionsChanged_noSubscriptions_noAllowedNetworksChanged() {
+ when(mMockSubscriptionManager.getAvailableSubscriptionInfoList()).thenReturn(
+ new ArrayList<>());
+ mTelephony2gUpdater.handleUserRestrictionsChanged(getTestContext());
+ verify(mMockTelephonyManager, never()).setAllowedNetworkTypesForReason(anyInt(), anyInt());
+ }
+
+ @Test
+ public void handleUserRestrictionsChanged_nullSubscriptions_noAllowedNetworksChanged() {
+ when(mMockSubscriptionManager.getAvailableSubscriptionInfoList()).thenReturn(null);
+ mTelephony2gUpdater.handleUserRestrictionsChanged(getTestContext());
+ verify(mMockTelephonyManager, never()).setAllowedNetworkTypesForReason(anyInt(), anyInt());
+ }
+
+ @Test
+ public void handleUserRestrictionsChanged_oneSubscription_allowedNetworksUpdated() {
+ TelephonyManager tmSubscription1 = mock(TelephonyManager.class);
+ when(mMockSubscriptionManager.getAvailableSubscriptionInfoList()).thenReturn(
+ Collections.singletonList(getSubInfo(1)));
+ when(mMockTelephonyManager.createForSubscriptionId(1)).thenReturn(tmSubscription1);
+ when(mMockUserManager.hasUserRestriction(UserManager.DISALLOW_CELLULAR_2G)).thenReturn(
+ true);
+
+ mTelephony2gUpdater.handleUserRestrictionsChanged(getTestContext());
+
+ System.out.println(TelephonyManager.convertNetworkTypeBitmaskToString(11L));
+ verify(tmSubscription1, times(1)).setAllowedNetworkTypesForReason(
+ TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER_RESTRICTIONS, EXPECTED_DISABLED);
+ }
+
+ @Test
+ public void handleUserRestrictionsChanged_manySubscriptionsDisallow2g_allowedNetworkUpdated() {
+
+ // Two subscriptions are available
+ when(mMockSubscriptionManager.getAvailableSubscriptionInfoList()).thenReturn(
+ Arrays.asList(getSubInfo(1), getSubInfo(2)));
+ TelephonyManager tmSubscription1 = mock(TelephonyManager.class);
+ TelephonyManager tmSubscription2 = mock(TelephonyManager.class);
+ when(mMockTelephonyManager.createForSubscriptionId(1)).thenReturn(tmSubscription1);
+ when(mMockTelephonyManager.createForSubscriptionId(2)).thenReturn(tmSubscription2);
+ // 2g is disallowed
+ when(mMockUserManager.hasUserRestriction(UserManager.DISALLOW_CELLULAR_2G)).thenReturn(
+ true);
+
+ mTelephony2gUpdater.handleUserRestrictionsChanged(getTestContext());
+
+ verify(tmSubscription1, times(1)).setAllowedNetworkTypesForReason(
+ TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER_RESTRICTIONS, EXPECTED_DISABLED);
+ verify(tmSubscription1, times(1)).setAllowedNetworkTypesForReason(
+ TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER_RESTRICTIONS, EXPECTED_DISABLED);
+ }
+
+ @Test
+ public void handleUserRestrictionsChanged_manySubscriptionsAllow2g_allowedNetworkUpdated() {
+
+ // Two subscriptions are available
+ when(mMockSubscriptionManager.getAvailableSubscriptionInfoList()).thenReturn(
+ Arrays.asList(getSubInfo(1), getSubInfo(2)));
+ TelephonyManager tmSubscription1 = mock(TelephonyManager.class);
+ TelephonyManager tmSubscription2 = mock(TelephonyManager.class);
+ when(mMockTelephonyManager.createForSubscriptionId(1)).thenReturn(tmSubscription1);
+ when(mMockTelephonyManager.createForSubscriptionId(2)).thenReturn(tmSubscription2);
+
+ // 2g is allowed
+ when(mMockUserManager.hasUserRestriction(UserManager.DISALLOW_CELLULAR_2G)).thenReturn(
+ false);
+
+ mTelephony2gUpdater.handleUserRestrictionsChanged(getTestContext());
+
+ verify(tmSubscription1, times(1)).setAllowedNetworkTypesForReason(
+ TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER_RESTRICTIONS, EXPECTED_ENABLED);
+ verify(tmSubscription1, times(1)).setAllowedNetworkTypesForReason(
+ TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER_RESTRICTIONS, EXPECTED_ENABLED);
+ }
+
+ private SubscriptionInfo getSubInfo(int id) {
+ return new SubscriptionInfo(id, "890126042XXXXXXXXXXX", 0, "T-mobile", "T-mobile", 0, 255,
+ "12345", 0, null, "310", "260", "156", false, null, null);
+ }
+}
diff --git a/tests/src/com/android/services/telephony/DisconnectCauseUtilTest.java b/tests/src/com/android/services/telephony/DisconnectCauseUtilTest.java
index 28a7b02..969622a 100644
--- a/tests/src/com/android/services/telephony/DisconnectCauseUtilTest.java
+++ b/tests/src/com/android/services/telephony/DisconnectCauseUtilTest.java
@@ -38,19 +38,14 @@
import com.android.internal.telephony.PhoneFactory;
import com.android.phone.common.R;
-import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
-import java.lang.reflect.Field;
-import java.util.ArrayList;
-import java.util.HashMap;
import java.util.Locale;
-
@RunWith(AndroidJUnit4.class)
public class DisconnectCauseUtilTest extends TelephonyTestBase {
@@ -60,42 +55,11 @@
// dynamic
private Context mContext;
- private HashMap<InstanceKey, Object> mOldInstances = new HashMap<InstanceKey, Object>();
- private ArrayList<InstanceKey> mInstanceKeys = new ArrayList<InstanceKey>();
//Mocks
@Mock
private GsmCdmaPhone mMockPhone;
- // inner classes
- private static class InstanceKey {
- public final Class mClass;
- public final String mInstName;
- public final Object mObj;
-
- InstanceKey(final Class c, final String instName, final Object obj) {
- mClass = c;
- mInstName = instName;
- mObj = obj;
- }
-
- @Override
- public int hashCode() {
- return (mClass.getName().hashCode() * 31 + mInstName.hashCode()) * 31;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (obj == null || !(obj instanceof InstanceKey)) {
- return false;
- }
-
- InstanceKey other = (InstanceKey) obj;
- return (other.mClass == mClass && other.mInstName.equals(mInstName)
- && other.mObj == mObj);
- }
- }
-
@Before
public void setUp() throws Exception {
super.setUp();
@@ -106,15 +70,6 @@
setSinglePhone();
}
- @After
- public void tearDown() throws Exception {
- // restoreInstance.
- // Not doing so will potentially "confuse" other tests with the mocked instance
- restoreInstance(PhoneFactory.class, "sPhones", null);
- super.tearDown();
- }
-
-
/**
* Verifies that a call drop due to loss of WIFI results in a disconnect cause of error and that
* the label, description and tone are all present.
@@ -176,33 +131,6 @@
replaceInstance(PhoneFactory.class, "sPhones", null, mPhones);
}
-
- protected synchronized void replaceInstance(final Class c, final String instanceName,
- final Object obj, final Object newValue)
- throws Exception {
- Field field = c.getDeclaredField(instanceName);
- field.setAccessible(true);
-
- InstanceKey key = new InstanceKey(c, instanceName, obj);
- if (!mOldInstances.containsKey(key)) {
- mOldInstances.put(key, field.get(obj));
- mInstanceKeys.add(key);
- }
- field.set(obj, newValue);
- }
-
- protected synchronized void restoreInstance(final Class c, final String instanceName,
- final Object obj) throws Exception {
- InstanceKey key = new InstanceKey(c, instanceName, obj);
- if (mOldInstances.containsKey(key)) {
- Field field = c.getDeclaredField(instanceName);
- field.setAccessible(true);
- field.set(obj, mOldInstances.get(key));
- mOldInstances.remove(key);
- mInstanceKeys.remove(key);
- }
- }
-
private Resources getResourcesForLocale(Context context, Locale locale) {
Configuration config = new Configuration();
config.setToDefaults();