Merge "Add Test for missing absent SIM + PIN lock case"
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index fca8acf..8d84baf 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -15,6 +15,21 @@
-->
<resources>
+ <!-- Base attributes available to CheckBoxPreference. Copied from frameworks/base/core/res. -->
+ <declare-styleable name="CheckBoxPreference">
+ <!-- The summary for the Preference in a PreferenceActivity screen when the
+ CheckBoxPreference is checked. If separate on/off summaries are not
+ needed, the summary attribute can be used instead. -->
+ <attr name="android:summaryOn" />
+ <!-- The summary for the Preference in a PreferenceActivity screen when the
+ CheckBoxPreference is unchecked. If separate on/off summaries are not
+ needed, the summary attribute can be used instead. -->
+ <attr name="android:summaryOff" />
+ <!-- The state (true for on, or false for off) that causes dependents to be disabled. By default,
+ dependents will be disabled when this is unchecked, so the value of this preference is false. -->
+ <attr name="android:disableDependentsState" />
+ </declare-styleable>
+
<declare-styleable name="EditPhoneNumberPreference">
<!-- The enable button text. -->
<attr name="enableButtonText" format="string" />
diff --git a/src/com/android/phone/CallFeaturesSetting.java b/src/com/android/phone/CallFeaturesSetting.java
index 3858595..e5e02fa 100644
--- a/src/com/android/phone/CallFeaturesSetting.java
+++ b/src/com/android/phone/CallFeaturesSetting.java
@@ -26,6 +26,7 @@
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
+import android.content.res.Resources;
import android.os.Bundle;
import android.os.PersistableBundle;
import android.os.UserManager;
@@ -181,9 +182,9 @@
startActivity(intent);
}
};
- builder.setMessage(getResources().getString(
+ builder.setMessage(getResourcesForSubId().getString(
R.string.enable_video_calling_dialog_msg))
- .setNeutralButton(getResources().getString(
+ .setNeutralButton(getResourcesForSubId().getString(
R.string.enable_video_calling_dialog_settings),
networkSettingsClickListener)
.setPositiveButton(android.R.string.ok, null)
@@ -211,9 +212,9 @@
}
mSubscriptionInfoHelper = new SubscriptionInfoHelper(this, getIntent());
- mSubscriptionInfoHelper.setActionBarTitle(
- getActionBar(), getResources(), R.string.call_settings_with_label);
mPhone = mSubscriptionInfoHelper.getPhone();
+ mSubscriptionInfoHelper.setActionBarTitle(
+ getActionBar(), getResourcesForSubId(), R.string.call_settings_with_label);
mTelecomManager = getSystemService(TelecomManager.class);
}
@@ -315,7 +316,7 @@
mButtonAutoRetry = (SwitchPreference) findPreference(BUTTON_RETRY_KEY);
mEnableVideoCalling = (SwitchPreference) findPreference(ENABLE_VIDEO_CALLING_KEY);
- mButtonWifiCalling = findPreference(getResources().getString(
+ mButtonWifiCalling = findPreference(getResourcesForSubId().getString(
R.string.wifi_calling_settings_key));
PersistableBundle carrierConfig =
@@ -424,8 +425,7 @@
} else if (!mImsMgr.isWfcEnabledByPlatform() || !mImsMgr.isWfcProvisionedOnDevice()) {
prefSet.removePreference(mButtonWifiCalling);
} else {
- String title = SubscriptionManager.getResourcesForSubId(mPhone.getContext(),
- mPhone.getSubId()).getString(R.string.wifi_calling);
+ String title = getResourcesForSubId().getString(R.string.wifi_calling);
mButtonWifiCalling.setTitle(title);
int resId = com.android.internal.R.string.wifi_calling_off_summary;
@@ -447,7 +447,7 @@
if (DBG) log("Unexpected WFC mode value: " + wfcMode);
}
}
- mButtonWifiCalling.setSummary(resId);
+ mButtonWifiCalling.setSummary(getResourcesForSubId().getString(resId));
Intent intent = mButtonWifiCalling.getIntent();
if (intent != null) {
intent.putExtra(Settings.EXTRA_SUB_ID, mPhone.getSubId());
@@ -509,9 +509,9 @@
setIntent(newIntent);
mSubscriptionInfoHelper = new SubscriptionInfoHelper(this, getIntent());
- mSubscriptionInfoHelper.setActionBarTitle(
- getActionBar(), getResources(), R.string.call_settings_with_label);
mPhone = mSubscriptionInfoHelper.getPhone();
+ mSubscriptionInfoHelper.setActionBarTitle(
+ getActionBar(), getResourcesForSubId(), R.string.call_settings_with_label);
}
private static void log(String msg) {
@@ -540,4 +540,12 @@
activity.startActivity(intent);
activity.finish();
}
+
+ private Resources getResourcesForSubId() {
+ if (mPhone != null) {
+ return SubscriptionManager.getResourcesForSubId(mPhone.getContext(), mPhone.getSubId());
+ } else {
+ return getResources();
+ }
+ }
}
diff --git a/src/com/android/phone/EditPhoneNumberPreference.java b/src/com/android/phone/EditPhoneNumberPreference.java
index 74b8a45..35af20d 100644
--- a/src/com/android/phone/EditPhoneNumberPreference.java
+++ b/src/com/android/phone/EditPhoneNumberPreference.java
@@ -136,9 +136,9 @@
a.recycle();
//get the summary settings, use CheckBoxPreference as the standard.
- a = context.obtainStyledAttributes(attrs, android.R.styleable.CheckBoxPreference, 0, 0);
- mSummaryOn = a.getString(android.R.styleable.CheckBoxPreference_summaryOn);
- mSummaryOff = a.getString(android.R.styleable.CheckBoxPreference_summaryOff);
+ a = context.obtainStyledAttributes(attrs, R.styleable.CheckBoxPreference, 0, 0);
+ mSummaryOn = a.getString(R.styleable.CheckBoxPreference_summaryOn);
+ mSummaryOff = a.getString(R.styleable.CheckBoxPreference_summaryOff);
a.recycle();
}
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index 3ddb267..27c1a0b 100755
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -57,6 +57,7 @@
import android.os.UserManager;
import android.os.WorkSource;
import android.preference.PreferenceManager;
+import android.provider.DeviceConfig;
import android.provider.Settings;
import android.provider.Telephony;
import android.telecom.PhoneAccount;
@@ -262,6 +263,8 @@
private static final int EVENT_GET_MODEM_STATUS_DONE = 71;
private static final int CMD_SET_FORBIDDEN_PLMNS = 72;
private static final int EVENT_SET_FORBIDDEN_PLMNS_DONE = 73;
+ private static final int CMD_ERASE_MODEM_CONFIG = 74;
+ private static final int EVENT_ERASE_MODEM_CONFIG_DONE = 75;
// Parameters of select command.
private static final int SELECT_COMMAND = 0xA4;
@@ -302,6 +305,12 @@
private static final int MANUFACTURER_CODE_LENGTH = 8;
/**
+ * Experiment flag to enable erase modem config on reset network, default value is false
+ */
+ public static final String RESET_NETWORK_ERASE_MODEM_CONFIG_ENABLED =
+ "reset_network_erase_modem_config_enabled";
+
+ /**
* A request object to use for transmitting data to an ICC.
*/
private static final class IccAPDUArgument {
@@ -1214,6 +1223,13 @@
((SIMRecords) uiccApp.getIccRecords())
.setForbiddenPlmns(onCompleted, fplmns);
}
+ case CMD_ERASE_MODEM_CONFIG:
+ request = (MainThreadRequest) msg.obj;
+ onCompleted = obtainMessage(EVENT_ERASE_MODEM_CONFIG_DONE, request);
+ defaultPhone.eraseModemConfig(onCompleted);
+ break;
+ case EVENT_ERASE_MODEM_CONFIG_DONE:
+ handleNullReturnEvent(msg, "eraseModemConfig");
break;
default:
Log.w(LOG_TAG, "MainThreadHandler: unexpected message code: " + msg.what);
@@ -1423,6 +1439,20 @@
return PhoneFactory.getPhone(mSubscriptionController.getPhoneId(subId));
}
+ private void sendEraseModemConfig(Phone phone) {
+ if (phone != null) {
+ TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
+ mApp, phone.getSubId(), "eraseModemConfig");
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ Boolean success = (Boolean) sendRequest(CMD_ERASE_MODEM_CONFIG, null);
+ if (DBG) log("eraseModemConfig:" + ' ' + (success ? "ok" : "fail"));
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+ }
+
public void dial(String number) {
dialForSubscriber(getPreferredVoiceSubscription(), number);
}
@@ -4900,7 +4930,7 @@
* @hide
*/
@Override
- public boolean isTetherApnRequiredForSubscriber(int subId) {
+ public boolean isTetheringApnRequiredForSubscriber(int subId) {
enforceModifyPermission();
final long identity = Binder.clearCallingIdentity();
final Phone phone = getPhone(subId);
@@ -5836,6 +5866,13 @@
if (slotId > SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
ImsManager.getInstance(mApp, slotId).factoryReset();
}
+
+ // Erase modem config if erase modem on network setting is enabled.
+ String configValue = DeviceConfig.getProperty(DeviceConfig.NAMESPACE_TELEPHONY,
+ RESET_NETWORK_ERASE_MODEM_CONFIG_ENABLED);
+ if (configValue != null && Boolean.parseBoolean(configValue)) {
+ sendEraseModemConfig(getDefaultPhone());
+ }
} finally {
Binder.restoreCallingIdentity(identity);
}
diff --git a/src/com/android/phone/TelephonyShellCommand.java b/src/com/android/phone/TelephonyShellCommand.java
index 428c006..ebadf88 100644
--- a/src/com/android/phone/TelephonyShellCommand.java
+++ b/src/com/android/phone/TelephonyShellCommand.java
@@ -18,7 +18,6 @@
import android.content.Context;
import android.os.Binder;
-import android.os.Build;
import android.os.PersistableBundle;
import android.os.Process;
import android.os.RemoteException;
@@ -31,6 +30,7 @@
import com.android.internal.telephony.ITelephony;
import com.android.internal.telephony.emergency.EmergencyNumberTracker;
+import com.android.internal.telephony.util.TelephonyUtils;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -623,7 +623,7 @@
private int handleCcCommand() {
// Verify that the user is allowed to run the command. Only allowed in rooted device in a
// non user build.
- if (Binder.getCallingUid() != Process.ROOT_UID || Build.IS_USER) {
+ if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
getErrPrintWriter().println("cc: Permission denied.");
return -1;
}
diff --git a/src/com/android/services/telephony/TelephonyConnection.java b/src/com/android/services/telephony/TelephonyConnection.java
index d8e9c32..fdece42 100644
--- a/src/com/android/services/telephony/TelephonyConnection.java
+++ b/src/com/android/services/telephony/TelephonyConnection.java
@@ -19,6 +19,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
+import android.content.res.Resources;
import android.graphics.drawable.Icon;
import android.net.Uri;
import android.os.AsyncResult;
@@ -36,11 +37,13 @@
import android.telecom.StatusHints;
import android.telecom.TelecomManager;
import android.telecom.VideoProfile;
+import android.telephony.Annotation.RilRadioTechnology;
import android.telephony.CarrierConfigManager;
import android.telephony.DisconnectCause;
import android.telephony.PhoneNumberUtils;
import android.telephony.Rlog;
import android.telephony.ServiceState;
+import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.ims.ImsCallProfile;
import android.text.TextUtils;
@@ -136,7 +139,7 @@
if (connection != null &&
((connection.getAddress() != null &&
mOriginalConnection.getAddress() != null &&
- mOriginalConnection.getAddress().contains(connection.getAddress())) ||
+ mOriginalConnection.getAddress().equals(connection.getAddress())) ||
connection.getState() == mOriginalConnection.getStateBeforeHandover())) {
Log.d(TelephonyConnection.this,
"SettingOriginalConnection " + mOriginalConnection.toString()
@@ -404,7 +407,9 @@
}
}
if (messageId != -1 && getPhone() != null && getPhone().getContext() != null) {
- return getPhone().getContext().getText(messageId);
+ Resources res = SubscriptionManager.getResourcesForSubId(
+ getPhone().getContext(), getPhone().getSubId());
+ return res.getText(messageId);
} else {
return null;
}
@@ -502,7 +507,7 @@
* @param vrat the RIL Voice Radio Technology used for current connection.
*/
@Override
- public void onCallRadioTechChanged(@ServiceState.RilRadioTechnology int vrat) {
+ public void onCallRadioTechChanged(@RilRadioTechnology int vrat) {
mHandler.obtainMessage(MSG_SET_CALL_RADIO_TECH, vrat).sendToTarget();
}
@@ -645,6 +650,7 @@
@Override
public void onRttTerminated() {
updateConnectionProperties();
+ refreshConferenceSupported();
sendRttSessionRemotelyTerminated();
}
@@ -2198,8 +2204,10 @@
: R.string.status_hint_label_wifi_call;
Context context = getPhone().getContext();
+ Resources res =
+ SubscriptionManager.getResourcesForSubId(context, getPhone().getSubId());
setTelephonyStatusHints(new StatusHints(
- context.getString(labelId),
+ res.getString(labelId),
Icon.createWithResource(
context, R.drawable.ic_signal_wifi_4_bar_24dp),
null /* extras */));
@@ -2579,7 +2587,7 @@
* @param vrat the RIL Voice Radio Technology used for current connection,
* see {@code RIL_RADIO_TECHNOLOGY_*} in {@link android.telephony.ServiceState}.
*/
- public final void setCallRadioTech(@ServiceState.RilRadioTechnology int vrat) {
+ public final void setCallRadioTech(@RilRadioTechnology int vrat) {
Bundle extras = getExtras();
if (extras == null) {
extras = new Bundle();
@@ -2605,7 +2613,7 @@
* @return the RIL voice radio technology used for current connection,
* see {@code RIL_RADIO_TECHNOLOGY_*} in {@link android.telephony.ServiceState}.
*/
- public final @ServiceState.RilRadioTechnology int getCallRadioTech() {
+ public final @RilRadioTechnology int getCallRadioTech() {
int voiceNetworkType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
Bundle extras = getExtras();
if (extras != null) {
diff --git a/src/com/android/services/telephony/TelephonyConnectionService.java b/src/com/android/services/telephony/TelephonyConnectionService.java
index 61e06e9..2cfc8dc 100644
--- a/src/com/android/services/telephony/TelephonyConnectionService.java
+++ b/src/com/android/services/telephony/TelephonyConnectionService.java
@@ -182,6 +182,8 @@
public boolean isLocked = false;
// Is the emergency number associated with the slot
public boolean hasDialedEmergencyNumber = false;
+ //SimState
+ public int simState;
public SlotStatus(int slotId, int capabilities) {
this.slotId = slotId;
@@ -1663,6 +1665,8 @@
// 4)
// Report Slot's PIN/PUK lock status for sorting later.
int simState = mSubscriptionManagerProxy.getSimStateForSlotIdx(i);
+ // Record SimState.
+ status.simState = simState;
if (simState == TelephonyManager.SIM_STATE_PIN_REQUIRED ||
simState == TelephonyManager.SIM_STATE_PUK_REQUIRED) {
status.isLocked = true;
@@ -1708,6 +1712,15 @@
if (o1.hasDialedEmergencyNumber && !o2.hasDialedEmergencyNumber) {
return 1;
}
+ // Sort by non-absent SIM.
+ if (o1.simState == TelephonyManager.SIM_STATE_ABSENT
+ && o2.simState != TelephonyManager.SIM_STATE_ABSENT) {
+ return -1;
+ }
+ if (o2.simState == TelephonyManager.SIM_STATE_ABSENT
+ && o1.simState != TelephonyManager.SIM_STATE_ABSENT) {
+ return 1;
+ }
// First start by seeing if either of the phone slots are locked. If they
// are, then sort by non-locked SIM first. If they are both locked, sort
// by capability instead.
diff --git a/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java b/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
index 2dee0e1..bcc4fd3 100644
--- a/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
+++ b/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
@@ -23,11 +23,13 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.content.Context;
import android.net.Uri;
import android.os.AsyncResult;
import android.os.Bundle;
@@ -39,6 +41,7 @@
import android.telephony.TelephonyManager;
import android.test.suitebuilder.annotation.SmallTest;
+import androidx.test.InstrumentationRegistry;
import androidx.test.filters.FlakyTest;
import androidx.test.runner.AndroidJUnit4;
@@ -801,6 +804,11 @@
Phone phone = c.getPhone();
c.setOriginalConnection(c.getOriginalConnection());
+ // Use a real context since the method SubscriptionManager.getResourcesForSubId()
+ // needs to interact with a real context.
+ Context targetContext = InstrumentationRegistry.getTargetContext();
+ doReturn(targetContext).when(phone).getContext();
+
// When the registration occurs, we'll capture the handler and message so we can post our
// own messages to it.
ArgumentCaptor<Handler> handlerCaptor = ArgumentCaptor.forClass(Handler.class);