Merge "Do not set brandOverride if opNames are invalid"
diff --git a/Android.bp b/Android.bp
index c567b99..5c79cf9 100644
--- a/Android.bp
+++ b/Android.bp
@@ -62,6 +62,7 @@
"android.hardware.radio-V1.2-java",
"android.hardware.radio-V1.3-java",
"android.hardware.radio-V1.4-java",
+ "android.hardware.radio-V1.5-java",
"voip-common",
"ims-common",
"services",
diff --git a/TEST_MAPPING b/TEST_MAPPING
new file mode 100644
index 0000000..e75dcb0
--- /dev/null
+++ b/TEST_MAPPING
@@ -0,0 +1,12 @@
+{
+ "presubmit": [
+ {
+ "name": "TeleServiceTests",
+ "options": [
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ }
+ ]
+ }
+ ]
+}
diff --git a/proto/src/carrierId.proto b/proto/src/carrierId.proto
deleted file mode 100644
index 0f5eba8..0000000
--- a/proto/src/carrierId.proto
+++ /dev/null
@@ -1,92 +0,0 @@
-//
-// Copyright (C) 2017 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.
-//
-
-syntax = "proto2";
-
-package carrierIdentification;
-
-option java_package = "com.android.internal.telephony";
-option java_outer_classname = "CarrierIdProto";
-
-// A complete list of carriers
-message CarrierList {
- // A collection of carriers. one entry for one carrier.
- repeated CarrierId carrier_id = 1;
- // Version number of current carrier list
- optional int32 version = 2;
-};
-
-// CarrierId is the unique representation of a carrier in CID table.
-message CarrierId {
- // [Optional] A unique canonical number designated to a carrier.
- optional int32 canonical_id = 1;
-
- // [Optional] A user-friendly carrier name (not localized).
- optional string carrier_name = 2;
-
- // [Optional] Carrier attributes to match a carrier. At least one value is required.
- repeated CarrierAttribute carrier_attribute = 3;
-
- // [Optional] A unique canonical number to represent its parent carrier. The parent-child
- // relationship can be used to differentiate a single carrier by different networks,
- // by prepaid v.s. postpaid or even by 4G v.s. 3G plan.
- optional int32 parent_canonical_id = 4;
-};
-
-// Attributes used to match a carrier.
-// For each field within this message:
-// - if not set, the attribute is ignored;
-// - if set, the device must have one of the specified values to match.
-// Match is based on AND between any field that is set and OR for values within a repeated field.
-message CarrierAttribute {
- // [Optional] The MCC and MNC that map to this carrier. At least one value is required.
- repeated string mccmnc_tuple = 1;
-
- // [Optional] Prefix of IMSI (International Mobile Subscriber Identity) in
- // decimal format. Some digits can be replaced with "x" symbols matching any digit.
- // Sample values: 20404794, 21670xx2xxx.
- repeated string imsi_prefix_xpattern = 2;
-
- // [Optional] The Service Provider Name. Read from subscription EF_SPN.
- // Sample values: C Spire, LeclercMobile
- repeated string spn = 3;
-
- // [Optional] PLMN network name. Read from subscription EF_PNN.
- // Sample values:
- repeated string plmn = 4;
-
- // [Optional] Group Identifier Level1 for a GSM phone. Read from subscription EF_GID1.
- // Sample values: 6D, BAE0000000000000
- repeated string gid1 = 5;
-
- // [Optional] Group Identifier Level2 for a GSM phone. Read from subscription EF_GID2.
- // Sample values: 6D, BAE0000000000000
- repeated string gid2 = 6;
-
- // [Optional] The Access Point Name, corresponding to "apn" field returned by
- // "content://telephony/carriers/preferapn" on device.
- // Sample values: fast.t-mobile.com, internet
- repeated string preferred_apn = 7;
-
- // [Optional] Prefix of Integrated Circuit Card Identifier. Read from subscription EF_ICCID.
- // Sample values: 894430, 894410
- repeated string iccid_prefix = 8;
-
- // [Optional] Carrier Privilege Access Rule in hex string.
- // Sample values: 61ed377e85d386a8dfee6b864bd85b0bfaa5af88
- repeated string privilege_access_rule = 9;
-};
-
diff --git a/src/java/com/android/internal/telephony/AsyncEmergencyContactNotifier.java b/src/java/com/android/internal/telephony/AsyncEmergencyContactNotifier.java
index 820a052..fd6ccd4 100644
--- a/src/java/com/android/internal/telephony/AsyncEmergencyContactNotifier.java
+++ b/src/java/com/android/internal/telephony/AsyncEmergencyContactNotifier.java
@@ -23,8 +23,7 @@
/**
* An {@link AsyncTask} that notifies the Blocked number provider that emergency services were
- * contacted. See {@link BlockedNumberContract.SystemContract#notifyEmergencyContact(Context)}
- * for details.
+ * contacted.
* {@hide}
*/
public class AsyncEmergencyContactNotifier extends AsyncTask<Void, Void, Void> {
@@ -39,10 +38,27 @@
@Override
protected Void doInBackground(Void... params) {
try {
- BlockedNumberContract.SystemContract.notifyEmergencyContact(mContext);
+ notifyEmergencyContact(mContext);
} catch (Exception e) {
Rlog.e(TAG, "Exception notifying emergency contact: " + e);
}
return null;
}
+
+ /**
+ * Notifies the provider that emergency services were contacted by the user.
+ */
+ private void notifyEmergencyContact(Context context) {
+ try {
+ Rlog.i("notifyEmergencyContact; caller=%s", context.getOpPackageName());
+ context.getContentResolver().call(
+ BlockedNumberContract.AUTHORITY_URI,
+ BlockedNumberContract.METHOD_NOTIFY_EMERGENCY_CONTACT,
+ null, null);
+ } catch (NullPointerException | IllegalArgumentException ex) {
+ // The content resolver can throw an NPE or IAE; we don't want to crash Telecom if
+ // either of these happen.
+ Rlog.w(null, "notifyEmergencyContact: provider not ready.");
+ }
+ }
}
diff --git a/src/java/com/android/internal/telephony/BlockChecker.java b/src/java/com/android/internal/telephony/BlockChecker.java
index 1a63db6..19981eb 100644
--- a/src/java/com/android/internal/telephony/BlockChecker.java
+++ b/src/java/com/android/internal/telephony/BlockChecker.java
@@ -67,19 +67,76 @@
long startTimeNano = System.nanoTime();
try {
- blockStatus = BlockedNumberContract.SystemContract.shouldSystemBlockNumber(
- context, phoneNumber, extras);
+ blockStatus = shouldSystemBlockNumber(context, phoneNumber, extras);
if (blockStatus != BlockedNumberContract.STATUS_NOT_BLOCKED) {
Rlog.d(TAG, phoneNumber + " is blocked.");
}
} catch (Exception e) {
Rlog.e(TAG, "Exception checking for blocked number: " + e);
}
-
int durationMillis = (int) ((System.nanoTime() - startTimeNano) / 1000000);
if (durationMillis > 500 || VDBG) {
Rlog.d(TAG, "Blocked number lookup took: " + durationMillis + " ms.");
}
return blockStatus;
}
+
+ /**
+ * Returns {@code true} if {@code phoneNumber} is blocked taking
+ * {@link #notifyEmergencyContact(Context)} into consideration. If emergency services
+ * have not been contacted recently and enhanced call blocking not been enabled, this
+ * method is equivalent to {@link #isBlocked(Context, String)}.
+ *
+ * @param context the context of the caller.
+ * @param phoneNumber the number to check.
+ * @param extras the extra attribute of the number.
+ * @return result code indicating if the number should be blocked, and if so why.
+ * Valid values are: {@link #STATUS_NOT_BLOCKED}, {@link #STATUS_BLOCKED_IN_LIST},
+ * {@link #STATUS_BLOCKED_NOT_IN_CONTACTS}, {@link #STATUS_BLOCKED_PAYPHONE},
+ * {@link #STATUS_BLOCKED_RESTRICTED}, {@link #STATUS_BLOCKED_UNKNOWN_NUMBER}.
+ */
+ private static int shouldSystemBlockNumber(Context context, String phoneNumber,
+ Bundle extras) {
+ try {
+ String caller = context.getOpPackageName();
+ final Bundle res = context.getContentResolver().call(
+ BlockedNumberContract.AUTHORITY_URI,
+ BlockedNumberContract.METHOD_SHOULD_SYSTEM_BLOCK_NUMBER,
+ phoneNumber, extras);
+ int blockResult = res != null ? res.getInt(BlockedNumberContract.RES_BLOCK_STATUS,
+ BlockedNumberContract.STATUS_NOT_BLOCKED) :
+ BlockedNumberContract.STATUS_NOT_BLOCKED;
+ Rlog.d(TAG, "shouldSystemBlockNumber: number=" + Rlog.pii(TAG, phoneNumber)
+ + "caller=" + caller + "result=" + blockStatusToString(blockResult));
+ return blockResult;
+ } catch (NullPointerException | IllegalArgumentException ex) {
+ // The content resolver can throw an NPE or IAE; we don't want to crash Telecom if
+ // either of these happen.
+ Rlog.w(null, "shouldSystemBlockNumber: provider not ready.");
+ return BlockedNumberContract.STATUS_NOT_BLOCKED;
+ }
+ }
+
+ /**
+ * Converts a block status constant to a string equivalent for logging.
+ * @hide
+ */
+ private static String blockStatusToString(int blockStatus) {
+ switch (blockStatus) {
+ case BlockedNumberContract.STATUS_NOT_BLOCKED:
+ return "not blocked";
+ case BlockedNumberContract.STATUS_BLOCKED_IN_LIST:
+ return "blocked - in list";
+ case BlockedNumberContract.STATUS_BLOCKED_RESTRICTED:
+ return "blocked - restricted";
+ case BlockedNumberContract.STATUS_BLOCKED_UNKNOWN_NUMBER:
+ return "blocked - unknown";
+ case BlockedNumberContract.STATUS_BLOCKED_PAYPHONE:
+ return "blocked - payphone";
+ case BlockedNumberContract.STATUS_BLOCKED_NOT_IN_CONTACTS:
+ return "blocked - not in contacts";
+ }
+ return "unknown";
+ }
+
}
diff --git a/src/java/com/android/internal/telephony/CarrierServiceBindHelper.java b/src/java/com/android/internal/telephony/CarrierServiceBindHelper.java
index 5eb0456..4cdfd26 100644
--- a/src/java/com/android/internal/telephony/CarrierServiceBindHelper.java
+++ b/src/java/com/android/internal/telephony/CarrierServiceBindHelper.java
@@ -34,6 +34,7 @@
import android.os.SystemClock;
import android.os.UserHandle;
import android.service.carrier.CarrierService;
+import android.telephony.PackageChangeReceiver;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
@@ -41,9 +42,8 @@
import android.util.SparseArray;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.content.PackageMonitor;
-
import com.android.internal.telephony.util.TelephonyUtils;
+
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.List;
@@ -67,7 +67,7 @@
public SparseArray<AppBinding> mBindings = new SparseArray();
@VisibleForTesting
public SparseArray<String> mLastSimState = new SparseArray<>();
- private final PackageMonitor mPackageMonitor = new CarrierServicePackageMonitor();
+ private final PackageChangeReceiver mPackageMonitor = new CarrierServicePackageMonitor();
private BroadcastReceiver mUserUnlockedReceiver = new BroadcastReceiver() {
@Override
@@ -124,11 +124,11 @@
updateBindingsAndSimStates();
- PhoneConfigurationManager.getInstance().registerForMultiSimConfigChange(
+ PhoneConfigurationManager.registerForMultiSimConfigChange(
mHandler, EVENT_MULTI_SIM_CONFIG_CHANGED, null);
mPackageMonitor.register(
- context, mHandler.getLooper(), UserHandle.ALL, false /* externalStorage */);
+ context, mHandler.getLooper(), UserHandle.ALL);
try {
Context contextAsUser = mContext.createPackageContextAsUser(mContext.getPackageName(),
0, UserHandle.SYSTEM);
@@ -373,19 +373,19 @@
}
}
- private class CarrierServicePackageMonitor extends PackageMonitor {
+ private class CarrierServicePackageMonitor extends PackageChangeReceiver {
@Override
- public void onPackageAdded(String packageName, int reason) {
+ public void onPackageAdded(String packageName) {
evaluateBinding(packageName, true /* forceUnbind */);
}
@Override
- public void onPackageRemoved(String packageName, int reason) {
+ public void onPackageRemoved(String packageName) {
evaluateBinding(packageName, true /* forceUnbind */);
}
@Override
- public void onPackageUpdateFinished(String packageName, int uid) {
+ public void onPackageUpdateFinished(String packageName) {
evaluateBinding(packageName, true /* forceUnbind */);
}
@@ -395,13 +395,12 @@
}
@Override
- public boolean onHandleForceStop(Intent intent, String[] packages, int uid, boolean doit) {
+ public void onHandleForceStop(String[] packages, boolean doit) {
if (doit) {
for (String packageName : packages) {
evaluateBinding(packageName, true /* forceUnbind */);
}
}
- return super.onHandleForceStop(intent, packages, uid, doit);
}
private void evaluateBinding(String carrierPackageName, boolean forceUnbind) {
diff --git a/src/java/com/android/internal/telephony/CarrierServiceStateTracker.java b/src/java/com/android/internal/telephony/CarrierServiceStateTracker.java
index e112068..a61cc37 100644
--- a/src/java/com/android/internal/telephony/CarrierServiceStateTracker.java
+++ b/src/java/com/android/internal/telephony/CarrierServiceStateTracker.java
@@ -170,13 +170,6 @@
|| mSST.mSS.getDataRegState() == ServiceState.STATE_IN_SERVICE);
}
- private boolean isPhoneVoiceRegistered() {
- if (mSST.mSS == null) {
- return true; //something has gone wrong, return true and not show the notification.
- }
- return (mSST.mSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE);
- }
-
private boolean isPhoneRegisteredForWifiCalling() {
Rlog.d(LOG_TAG, "isPhoneRegisteredForWifiCalling: " + mPhone.isWifiCallingEnabled());
return mPhone.isWifiCallingEnabled();
@@ -456,8 +449,8 @@
}
/**
- * Class that defines the emergency notification, which is shown when the user is out of cell
- * connectivity, but has wifi enabled.
+ * Class that defines the emergency notification, which is shown when Wi-Fi Calling is
+ * available.
*/
public class EmergencyNetworkNotification implements NotificationType {
@@ -502,10 +495,9 @@
*/
public boolean sendMessage() {
Rlog.i(LOG_TAG, "EmergencyNetworkNotification: sendMessage() w/values: "
- + "," + isPhoneVoiceRegistered() + "," + mDelay + ","
- + isPhoneRegisteredForWifiCalling() + "," + mSST.isRadioOn());
- if (mDelay == UNINITIALIZED_DELAY_VALUE || isPhoneVoiceRegistered()
- || !isPhoneRegisteredForWifiCalling()) {
+ + "," + mDelay + "," + isPhoneRegisteredForWifiCalling() + ","
+ + mSST.isRadioOn());
+ if (mDelay == UNINITIALIZED_DELAY_VALUE || !isPhoneRegisteredForWifiCalling()) {
return false;
}
return true;
@@ -525,6 +517,7 @@
.setContentTitle(title)
.setStyle(new Notification.BigTextStyle().bigText(details))
.setContentText(details)
+ .setFlag(Notification.FLAG_NO_CLEAR, true)
.setChannelId(NotificationChannelController.CHANNEL_ID_WFC);
}
}
diff --git a/src/java/com/android/internal/telephony/CommandsInterface.java b/src/java/com/android/internal/telephony/CommandsInterface.java
index 0c60bc6..273de72 100644
--- a/src/java/com/android/internal/telephony/CommandsInterface.java
+++ b/src/java/com/android/internal/telephony/CommandsInterface.java
@@ -26,6 +26,7 @@
import android.telephony.ClientRequestStats;
import android.telephony.ImsiEncryptionInfo;
import android.telephony.NetworkScanRequest;
+import android.telephony.SignalThresholdInfo;
import android.telephony.data.DataProfile;
import android.telephony.emergency.EmergencyNumber;
@@ -2230,17 +2231,30 @@
void setUnsolResponseFilter(int filter, Message result);
/**
- * Send the signal strength reporting criteria to the modem.
+ * Sets the signal strength reporting criteria.
*
- * @param hysteresisMs A hysteresis time in milliseconds. A value of 0 disables hysteresis.
- * @param hysteresisDb An interval in dB defining the required magnitude change between reports.
- * A value of 0 disables hysteresis.
- * @param thresholdsDbm An array of trigger thresholds in dBm. A size of 0 disables thresholds.
- * @param ran RadioAccessNetwork for which to apply criteria.
+ * The resulting reporting rules are the AND of all the supplied criteria. For each RAN
+ * The hysteresisDb and thresholds apply to only the following measured quantities:
+ * -GERAN - RSSI
+ * -CDMA2000 - RSSI
+ * -UTRAN - RSCP
+ * -EUTRAN - RSRP/RSRQ/RSSNR
+ * -NGRAN - SSRSRP/SSRSRQ/SSSINR
+ *
+ * Note: Reporting criteria must be individually set for each RAN. For any unset reporting
+ * criteria, the value is implementation-defined.
+ *
+ * Response callback is
+ * IRadioResponse.setSignalStrengthReportingCriteriaResponse_1_5()
+ *
+ * @param signalThresholdInfo Signal threshold info including the threshold values,
+ * hysteresisDb, and hysteresisMs. See @1.5::SignalThresholdInfo
+ * for details.
+ * @param ran The type of network for which to apply these thresholds.
* @param result callback message contains the information of SUCCESS/FAILURE
*/
- void setSignalStrengthReportingCriteria(int hysteresisMs, int hysteresisDb, int[] thresholdsDbm,
- int ran, Message result);
+ void setSignalStrengthReportingCriteria(SignalThresholdInfo signalThresholdInfo, int ran,
+ Message result);
/**
* Send the link capacity reporting criteria to the modem
diff --git a/src/java/com/android/internal/telephony/Connection.java b/src/java/com/android/internal/telephony/Connection.java
index 6cc9e63..36de488 100755
--- a/src/java/com/android/internal/telephony/Connection.java
+++ b/src/java/com/android/internal/telephony/Connection.java
@@ -217,6 +217,9 @@
protected int mCause = DisconnectCause.NOT_DISCONNECTED;
protected PostDialState mPostDialState = PostDialState.NOT_STARTED;
+ // Store the current audio code
+ protected int mAudioCodec;
+
@UnsupportedAppUsage
private static String LOG_TAG = "Connection";
@@ -1355,4 +1358,12 @@
.append(" post dial state: " + getPostDialState());
return str.toString();
}
+
+ /**
+ * Get current audio codec.
+ * @return current audio codec.
+ */
+ public int getAudioCodec() {
+ return mAudioCodec;
+ }
}
diff --git a/src/java/com/android/internal/telephony/DeviceStateMonitor.java b/src/java/com/android/internal/telephony/DeviceStateMonitor.java
index f4d782c..bf033d8 100644
--- a/src/java/com/android/internal/telephony/DeviceStateMonitor.java
+++ b/src/java/com/android/internal/telephony/DeviceStateMonitor.java
@@ -37,6 +37,7 @@
import android.telephony.AccessNetworkConstants.AccessNetworkType;
import android.telephony.CarrierConfigManager;
import android.telephony.Rlog;
+import android.telephony.SignalThresholdInfo;
import android.telephony.TelephonyManager;
import android.util.LocalLog;
import android.util.SparseIntArray;
@@ -587,14 +588,23 @@
}
private void setSignalStrengthReportingCriteria() {
- mPhone.setSignalStrengthReportingCriteria(
- AccessNetworkThresholds.GERAN, AccessNetworkType.GERAN);
- mPhone.setSignalStrengthReportingCriteria(
- AccessNetworkThresholds.UTRAN, AccessNetworkType.UTRAN);
- mPhone.setSignalStrengthReportingCriteria(
- AccessNetworkThresholds.EUTRAN, AccessNetworkType.EUTRAN);
- mPhone.setSignalStrengthReportingCriteria(
- AccessNetworkThresholds.CDMA2000, AccessNetworkType.CDMA2000);
+ mPhone.setSignalStrengthReportingCriteria(SignalThresholdInfo.SIGNAL_RSSI,
+ AccessNetworkThresholds.GERAN, AccessNetworkType.GERAN, true);
+ mPhone.setSignalStrengthReportingCriteria(SignalThresholdInfo.SIGNAL_RSCP,
+ AccessNetworkThresholds.UTRAN, AccessNetworkType.UTRAN, true);
+ mPhone.setSignalStrengthReportingCriteria(SignalThresholdInfo.SIGNAL_RSRP,
+ AccessNetworkThresholds.EUTRAN_RSRP, AccessNetworkType.EUTRAN, true);
+ mPhone.setSignalStrengthReportingCriteria(SignalThresholdInfo.SIGNAL_RSSI,
+ AccessNetworkThresholds.CDMA2000, AccessNetworkType.CDMA2000, true);
+ if (mPhone.getHalVersion().greaterOrEqual(RIL.RADIO_HAL_VERSION_1_5)) {
+ // Defaultly we only need SSRSRP for NGRAN signal criterial reporting
+ mPhone.setSignalStrengthReportingCriteria(SignalThresholdInfo.SIGNAL_SSRSRP,
+ AccessNetworkThresholds.NGRAN_RSRSRP, AccessNetworkType.NGRAN, true);
+ mPhone.setSignalStrengthReportingCriteria(SignalThresholdInfo.SIGNAL_SSRSRQ,
+ AccessNetworkThresholds.NGRAN_RSRSRQ, AccessNetworkType.NGRAN, false);
+ mPhone.setSignalStrengthReportingCriteria(SignalThresholdInfo.SIGNAL_SSSINR,
+ AccessNetworkThresholds.NGRAN_SSSINR, AccessNetworkType.NGRAN, false);
+ }
}
private void setLinkCapacityReportingCriteria() {
@@ -730,17 +740,19 @@
};
/**
- * List of default dBm thresholds for EUTRAN {@link AccessNetworkType}.
+ * List of default dBm RSRP thresholds for EUTRAN {@link AccessNetworkType}.
*
* These thresholds are taken from the LTE RSRP defaults in {@link CarrierConfigManager}.
*/
- public static final int[] EUTRAN = new int[] {
+ public static final int[] EUTRAN_RSRP = new int[] {
-128, /* SIGNAL_STRENGTH_POOR */
-118, /* SIGNAL_STRENGTH_MODERATE */
-108, /* SIGNAL_STRENGTH_GOOD */
-98, /* SIGNAL_STRENGTH_GREAT */
};
+ // TODO Add EUTRAN_RSRQ and EUTRAN_RSSNI
+
/**
* List of dBm thresholds for CDMA2000 {@link AccessNetworkType}.
*
@@ -752,6 +764,36 @@
-75,
-65
};
+
+ /**
+ * List of dB thresholds for NGRAN {@link AccessNetworkType} RSRSRP
+ */
+ public static final int[] NGRAN_RSRSRP = new int[] {
+ -125, /* SIGNAL_STRENGTH_POOR */
+ -115, /* SIGNAL_STRENGTH_MODERATE */
+ -105, /* SIGNAL_STRENGTH_GOOD */
+ -95, /* SIGNAL_STRENGTH_GREAT */
+ };
+
+ /**
+ * List of dB thresholds for NGRAN {@link AccessNetworkType} RSRSRP
+ */
+ public static final int[] NGRAN_RSRSRQ = new int[] {
+ -14, /* SIGNAL_STRENGTH_POOR */
+ -12, /* SIGNAL_STRENGTH_MODERATE */
+ -10, /* SIGNAL_STRENGTH_GOOD */
+ -8 /* SIGNAL_STRENGTH_GREAT */
+ };
+
+ /**
+ * List of dB thresholds for NGRAN {@link AccessNetworkType} SSSINR
+ */
+ public static final int[] NGRAN_SSSINR = new int[] {
+ -8, /* SIGNAL_STRENGTH_POOR */
+ 0, /* SIGNAL_STRENGTH_MODERATE */
+ 8, /* SIGNAL_STRENGTH_GOOD */
+ 16 /* SIGNAL_STRENGTH_GREAT */
+ };
}
/**
diff --git a/src/java/com/android/internal/telephony/GsmCdmaConnection.java b/src/java/com/android/internal/telephony/GsmCdmaConnection.java
index e74c176..4f695e6 100644
--- a/src/java/com/android/internal/telephony/GsmCdmaConnection.java
+++ b/src/java/com/android/internal/telephony/GsmCdmaConnection.java
@@ -76,9 +76,6 @@
// The cached delay to be used between DTMF tones fetched from carrier config.
private int mDtmfToneDelay = 0;
- // Store the current audio codec
- private int mAudioCodec = DriverCall.AUDIO_QUALITY_UNSPECIFIED;
-
private TelephonyMetrics mMetrics = TelephonyMetrics.getInstance();
//***** Event Constants
diff --git a/src/java/com/android/internal/telephony/GsmCdmaPhone.java b/src/java/com/android/internal/telephony/GsmCdmaPhone.java
index e8c988d..41e0053 100644
--- a/src/java/com/android/internal/telephony/GsmCdmaPhone.java
+++ b/src/java/com/android/internal/telephony/GsmCdmaPhone.java
@@ -66,6 +66,7 @@
import android.telephony.PhoneNumberUtils;
import android.telephony.Rlog;
import android.telephony.ServiceState;
+import android.telephony.SignalThresholdInfo;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
@@ -3658,9 +3659,11 @@
}
@Override
- public void setSignalStrengthReportingCriteria(int[] thresholds, int ran) {
- mCi.setSignalStrengthReportingCriteria(REPORTING_HYSTERESIS_MILLIS, REPORTING_HYSTERESIS_DB,
- thresholds, ran, null);
+ public void setSignalStrengthReportingCriteria(
+ int signalStrengthMeasure, int[] thresholds, int ran, boolean isEnabled) {
+ mCi.setSignalStrengthReportingCriteria(new SignalThresholdInfo(signalStrengthMeasure,
+ REPORTING_HYSTERESIS_MILLIS, REPORTING_HYSTERESIS_DB, thresholds, isEnabled),
+ ran, null);
}
@Override
diff --git a/src/java/com/android/internal/telephony/NitzStateMachineImpl.java b/src/java/com/android/internal/telephony/NitzStateMachineImpl.java
index 7760394..cc96cba 100644
--- a/src/java/com/android/internal/telephony/NitzStateMachineImpl.java
+++ b/src/java/com/android/internal/telephony/NitzStateMachineImpl.java
@@ -89,8 +89,8 @@
private boolean mNitzTimeZoneDetectionSuccessful = false;
// Miscellaneous dependencies and helpers not related to detection state.
- private final LocalLog mTimeLog = new LocalLog(30);
- private final LocalLog mTimeZoneLog = new LocalLog(30);
+ private final LocalLog mTimeLog = new LocalLog(30, false /* useLocalTimestamps */);
+ private final LocalLog mTimeZoneLog = new LocalLog(30, false /* useLocalTimestamps */);
private final Phone mPhone;
private final DeviceState mDeviceState;
private final TimeServiceHelper mTimeServiceHelper;
@@ -253,7 +253,7 @@
// Set state as needed.
if (zoneId != null) {
if (mTimeServiceHelper.isTimeZoneDetectionEnabled()) {
- setAndBroadcastNetworkSetTimeZone(zoneId, logMsg);
+ setTimeZone(zoneId, logMsg);
} else {
if (DBG) {
logMsg += " [Not setting device time zone]";
@@ -402,7 +402,8 @@
}
private void sendEmptyTimeSuggestion(String reason) {
- PhoneTimeSuggestion timeSuggestion = new PhoneTimeSuggestion(mPhone.getPhoneId());
+ PhoneTimeSuggestion timeSuggestion =
+ new PhoneTimeSuggestion.Builder(mPhone.getPhoneId()).build();
timeSuggestion.addDebugInfo("Empty suggestion, reason=" + reason);
mTimeServiceHelper.suggestDeviceTime(timeSuggestion);
}
@@ -484,9 +485,11 @@
Rlog.d(LOG_TAG, logMsg);
}
mTimeLog.log(logMsg);
- PhoneTimeSuggestion phoneTimeSuggestion = new PhoneTimeSuggestion(mPhone.getPhoneId());
- phoneTimeSuggestion.setUtcTime(newNitzTime);
- phoneTimeSuggestion.addDebugInfo(logMsg);
+ PhoneTimeSuggestion phoneTimeSuggestion =
+ new PhoneTimeSuggestion.Builder(mPhone.getPhoneId())
+ .setUtcTime(newNitzTime)
+ .addDebugInfo(logMsg)
+ .build();
mTimeServiceHelper.suggestDeviceTime(phoneTimeSuggestion);
TelephonyMetrics.getInstance().writeNITZEvent(
@@ -501,7 +504,7 @@
}
}
- private void setAndBroadcastNetworkSetTimeZone(String zoneId, String logMessage) {
+ private void setTimeZone(String zoneId, String logMessage) {
logMessage += " [Setting device time zone to zoneId=" + zoneId + "]";
if (DBG) {
Rlog.d(LOG_TAG, logMessage);
@@ -528,7 +531,7 @@
String logMsg = "handleAutoTimeZoneEnabled: "
+ " mSavedTimeZoneId=" + mSavedTimeZoneId;
if (mSavedTimeZoneId != null) {
- setAndBroadcastNetworkSetTimeZone(mSavedTimeZoneId, logMsg);
+ setTimeZone(mSavedTimeZoneId, logMsg);
} else {
if (DBG) {
logMsg += " [Not setting device time zone]";
@@ -587,7 +590,7 @@
String zoneId = lookupResult.zoneId;
if (mTimeServiceHelper.isTimeZoneDetectionEnabled()) {
- setAndBroadcastNetworkSetTimeZone(zoneId, logMsg);
+ setTimeZone(zoneId, logMsg);
} else {
if (DBG) {
logMsg += " [Not setting device time zone]";
diff --git a/src/java/com/android/internal/telephony/Phone.java b/src/java/com/android/internal/telephony/Phone.java
index efa3954..db76e84 100644
--- a/src/java/com/android/internal/telephony/Phone.java
+++ b/src/java/com/android/internal/telephony/Phone.java
@@ -19,10 +19,8 @@
import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
import android.app.BroadcastOptions;
-import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
-import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.net.LinkProperties;
import android.net.NetworkCapabilities;
@@ -116,33 +114,6 @@
protected final int USSD_MAX_QUEUE = 10;
- private BroadcastReceiver mImsIntentReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- Rlog.d(LOG_TAG, "mImsIntentReceiver: action " + intent.getAction());
- if (intent.hasExtra(ImsManager.EXTRA_PHONE_ID)) {
- int extraPhoneId = intent.getIntExtra(ImsManager.EXTRA_PHONE_ID,
- SubscriptionManager.INVALID_PHONE_INDEX);
- Rlog.d(LOG_TAG, "mImsIntentReceiver: extraPhoneId = " + extraPhoneId);
- if (extraPhoneId == SubscriptionManager.INVALID_PHONE_INDEX ||
- extraPhoneId != getPhoneId()) {
- return;
- }
- }
-
- synchronized (Phone.lockForRadioTechnologyChange) {
- if (intent.getAction().equals(ImsManager.ACTION_IMS_SERVICE_UP)) {
- mImsServiceReady = true;
- updateImsPhone();
- ImsManager.getInstance(mContext, mPhoneId).updateImsServiceConfig(false);
- } else if (intent.getAction().equals(ImsManager.ACTION_IMS_SERVICE_DOWN)) {
- mImsServiceReady = false;
- updateImsPhone();
- }
- }
- }
- };
-
// Key used to read and write the saved network selection numeric value
public static final String NETWORK_SELECTION_KEY = "network_selection_key";
// Key used to read and write the saved network selection operator name
@@ -323,7 +294,6 @@
@UnsupportedAppUsage
protected int mPhoneId;
- private boolean mImsServiceReady = false;
@UnsupportedAppUsage
protected Phone mImsPhone = null;
@@ -586,34 +556,20 @@
}
/**
- * Start listening for IMS service UP/DOWN events. If using the new ImsResolver APIs, we should
- * always be setting up ImsPhones.
+ * Start setup of ImsPhone, which will start trying to connect to the ImsResolver. Will not be
+ * called if this device does not support FEATURE_IMS_TELEPHONY.
*/
- public void startMonitoringImsService() {
+ public void createImsPhone() {
if (getPhoneType() == PhoneConstants.PHONE_TYPE_SIP) {
return;
}
synchronized(Phone.lockForRadioTechnologyChange) {
- IntentFilter filter = new IntentFilter();
- ImsManager imsManager = ImsManager.getInstance(mContext, getPhoneId());
- // Don't listen to deprecated intents using the new dynamic binding.
- if (imsManager != null && !imsManager.isDynamicBinding()) {
- filter.addAction(ImsManager.ACTION_IMS_SERVICE_UP);
- filter.addAction(ImsManager.ACTION_IMS_SERVICE_DOWN);
- mContext.registerReceiver(mImsIntentReceiver, filter);
- }
-
- // Monitor IMS service - but first poll to see if already up (could miss
- // intent). Also, when using new ImsResolver APIs, the service will be available soon,
- // so start trying to bind.
- if (imsManager != null) {
- // If it is dynamic binding, kick off ImsPhone creation now instead of waiting for
- // the service to be available.
- if (imsManager.isDynamicBinding() || imsManager.isServiceAvailable()) {
- mImsServiceReady = true;
- updateImsPhone();
- }
+ if (mImsPhone == null) {
+ mImsPhone = PhoneFactory.makeImsPhone(mNotifier, this);
+ CallManager.getInstance().registerPhone(mImsPhone);
+ mImsPhone.registerForSilentRedial(
+ this, EVENT_INITIATE_SILENT_REDIAL, null);
}
}
}
@@ -3461,28 +3417,6 @@
public void dispose() {
}
- private void updateImsPhone() {
- Rlog.d(LOG_TAG, "updateImsPhone"
- + " mImsServiceReady=" + mImsServiceReady);
-
- if (mImsServiceReady && (mImsPhone == null)) {
- mImsPhone = PhoneFactory.makeImsPhone(mNotifier, this);
- CallManager.getInstance().registerPhone(mImsPhone);
- mImsPhone.registerForSilentRedial(
- this, EVENT_INITIATE_SILENT_REDIAL, null);
- } else if (!mImsServiceReady && (mImsPhone != null)) {
- CallManager.getInstance().unregisterPhone(mImsPhone);
- mImsPhone.unregisterForSilentRedial(this);
-
- mImsPhone.dispose();
- // Potential GC issue if someone keeps a reference to ImsPhone.
- // However: this change will make sure that such a reference does
- // not access functions through NULL pointer.
- //mImsPhone.removeReferences();
- mImsPhone = null;
- }
- }
-
/**
* Dials a number.
*
@@ -3913,7 +3847,8 @@
}
/** Sets the SignalStrength reporting criteria. */
- public void setSignalStrengthReportingCriteria(int[] thresholds, int ran) {
+ public void setSignalStrengthReportingCriteria(
+ int signalStrengthMeasure, int[] thresholds, int ran, boolean isEnabled) {
// no-op default implementation
}
diff --git a/src/java/com/android/internal/telephony/PhoneFactory.java b/src/java/com/android/internal/telephony/PhoneFactory.java
index a5b6437..3ed44d6 100644
--- a/src/java/com/android/internal/telephony/PhoneFactory.java
+++ b/src/java/com/android/internal/telephony/PhoneFactory.java
@@ -28,6 +28,7 @@
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.net.LocalServerSocket;
+import android.os.HandlerThread;
import android.os.Looper;
import android.preference.PreferenceManager;
import android.provider.Settings;
@@ -38,7 +39,6 @@
import android.telephony.TelephonyManager;
import android.util.LocalLog;
-import com.android.internal.os.BackgroundThread;
import com.android.internal.telephony.cdma.CdmaSubscriptionSourceManager;
import com.android.internal.telephony.dataconnection.TelephonyNetworkFactory;
import com.android.internal.telephony.euicc.EuiccCardController;
@@ -205,30 +205,27 @@
sMadeDefaults = true;
Rlog.i(LOG_TAG, "Creating SubInfoRecordUpdater ");
+ HandlerThread pfhandlerThread = new HandlerThread("PhoneFactoryHandlerThread");
+ pfhandlerThread.start();
sSubInfoRecordUpdater = new SubscriptionInfoUpdater(
- BackgroundThread.get().getLooper(), context, sCommandsInterfaces);
+ pfhandlerThread.getLooper(), context, sCommandsInterfaces);
// Only bring up IMS if the device supports having an IMS stack.
if (context.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_TELEPHONY_IMS)) {
- // Return whether or not the device should use dynamic binding or the static
- // implementation (deprecated)
- boolean isDynamicBinding = sContext.getResources().getBoolean(
- com.android.internal.R.bool.config_dynamic_bind_ims);
// Get the package name of the default IMS implementation.
String defaultImsPackage = sContext.getResources().getString(
com.android.internal.R.string.config_ims_package);
// Start ImsResolver and bind to ImsServices.
Rlog.i(LOG_TAG, "ImsResolver: defaultImsPackage: " + defaultImsPackage);
- sImsResolver = new ImsResolver(sContext, defaultImsPackage, numPhones,
- isDynamicBinding);
+ sImsResolver = new ImsResolver(sContext, defaultImsPackage, numPhones);
sImsResolver.initialize();
// Start monitoring after defaults have been made.
// Default phone must be ready before ImsPhone is created because ImsService
// might need it when it is being opened. This should initialize multiple
// ImsPhones for ImsResolver implementations of ImsService.
for (int i = 0; i < numPhones; i++) {
- sPhones[i].startMonitoringImsService();
+ sPhones[i].createImsPhone();
}
} else {
Rlog.i(LOG_TAG, "IMS is not supported on this device, skipping ImsResolver.");
@@ -284,7 +281,7 @@
sPhones[i] = createPhone(context, i);
if (context.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_TELEPHONY_IMS)) {
- sPhones[i].startMonitoringImsService();
+ sPhones[i].createImsPhone();
}
sTelephonyNetworkFactories[i] = new TelephonyNetworkFactory(
Looper.myLooper(), sPhones[i]);
diff --git a/src/java/com/android/internal/telephony/PhoneSwitcher.java b/src/java/com/android/internal/telephony/PhoneSwitcher.java
index ae514d9..3981eb6 100644
--- a/src/java/com/android/internal/telephony/PhoneSwitcher.java
+++ b/src/java/com/android/internal/telephony/PhoneSwitcher.java
@@ -1110,6 +1110,8 @@
@VisibleForTesting
protected boolean isPhoneActive(int phoneId) {
+ if (phoneId >= mActiveModemCount)
+ return false;
return mPhoneStates[phoneId].active;
}
diff --git a/src/java/com/android/internal/telephony/RIL.java b/src/java/com/android/internal/telephony/RIL.java
index 195da41..a0be155 100644
--- a/src/java/com/android/internal/telephony/RIL.java
+++ b/src/java/com/android/internal/telephony/RIL.java
@@ -48,9 +48,9 @@
import android.hardware.radio.V1_0.SimApdu;
import android.hardware.radio.V1_0.SmsWriteArgs;
import android.hardware.radio.V1_0.UusInfo;
-import android.hardware.radio.V1_2.AccessNetwork;
import android.hardware.radio.V1_4.CarrierRestrictionsWithPriority;
import android.hardware.radio.V1_4.SimLockMultiSimPolicy;
+import android.hardware.radio.V1_5.AccessNetwork;
import android.hardware.radio.deprecated.V1_0.IOemHook;
import android.net.ConnectivityManager;
import android.net.KeepalivePacketData;
@@ -90,6 +90,7 @@
import android.telephony.Rlog;
import android.telephony.ServiceState;
import android.telephony.SignalStrength;
+import android.telephony.SignalThresholdInfo;
import android.telephony.SmsManager;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyHistogram;
@@ -180,6 +181,9 @@
/** @hide */
public static final HalVersion RADIO_HAL_VERSION_1_4 = new HalVersion(1, 4);
+ /** @hide */
+ public static final HalVersion RADIO_HAL_VERSION_1_5 = new HalVersion(1, 5);
+
// IRadio version
private HalVersion mRadioVersion = RADIO_HAL_VERSION_UNKNOWN;
@@ -435,14 +439,23 @@
+ " is disabled");
} else {
try {
- mRadioProxy = android.hardware.radio.V1_4.IRadio.getService(
+ mRadioProxy = android.hardware.radio.V1_5.IRadio.getService(
HIDL_SERVICE_NAME[mPhoneId], true);
- mRadioVersion = RADIO_HAL_VERSION_1_4;
+ mRadioVersion = RADIO_HAL_VERSION_1_5;
} catch (NoSuchElementException e) {
}
if (mRadioProxy == null) {
try {
+ mRadioProxy = android.hardware.radio.V1_4.IRadio.getService(
+ HIDL_SERVICE_NAME[mPhoneId], true);
+ mRadioVersion = RADIO_HAL_VERSION_1_4;
+ } catch (NoSuchElementException e) {
+ }
+ }
+
+ if (mRadioProxy == null) {
+ try {
mRadioProxy = android.hardware.radio.V1_3.IRadio.getService(
HIDL_SERVICE_NAME[mPhoneId], true);
mRadioVersion = RADIO_HAL_VERSION_1_3;
@@ -2080,12 +2093,83 @@
return rasInHalFormat;
}
+ private android.hardware.radio.V1_5.RadioAccessSpecifier
+ convertRadioAccessSpecifierToRadioHAL_1_5(RadioAccessSpecifier ras) {
+ android.hardware.radio.V1_5.RadioAccessSpecifier rasInHalFormat =
+ new android.hardware.radio.V1_5.RadioAccessSpecifier();
+ rasInHalFormat.radioAccessNetwork = ras.getRadioAccessNetwork();
+ List<Integer> bands = null;
+ switch (ras.getRadioAccessNetwork()) {
+ case AccessNetworkType.GERAN:
+ bands = rasInHalFormat.bands.geranBands();
+ break;
+ case AccessNetworkType.UTRAN:
+ bands = rasInHalFormat.bands.utranBands();
+ break;
+ case AccessNetworkType.EUTRAN:
+ bands = rasInHalFormat.bands.eutranBands();
+ break;
+ case AccessNetworkType.NGRAN:
+ bands = rasInHalFormat.bands.ngranBands();
+ break;
+ default:
+ Log.wtf(RILJ_LOG_TAG, "radioAccessNetwork " + ras.getRadioAccessNetwork()
+ + " not supported!");
+ return null;
+ }
+
+ if (ras.getBands() != null) {
+ for (int band : ras.getBands()) {
+ bands.add(band);
+ }
+ }
+ if (ras.getChannels() != null) {
+ for (int channel : ras.getChannels()) {
+ rasInHalFormat.channels.add(channel);
+ }
+ }
+
+ return rasInHalFormat;
+ }
+
@Override
public void startNetworkScan(NetworkScanRequest nsr, Message result) {
IRadio radioProxy = getRadioProxy(result);
if (radioProxy != null) {
- if (mRadioVersion.greaterOrEqual(RADIO_HAL_VERSION_1_2)) {
+ if (mRadioVersion.greaterOrEqual(RADIO_HAL_VERSION_1_5)) {
+ android.hardware.radio.V1_5.NetworkScanRequest request =
+ new android.hardware.radio.V1_5.NetworkScanRequest();
+ request.type = nsr.getScanType();
+ request.interval = nsr.getSearchPeriodicity();
+ request.maxSearchTime = nsr.getMaxSearchTime();
+ request.incrementalResultsPeriodicity = nsr.getIncrementalResultsPeriodicity();
+ request.incrementalResults = nsr.getIncrementalResults();
+ for (RadioAccessSpecifier ras : nsr.getSpecifiers()) {
+ android.hardware.radio.V1_5.RadioAccessSpecifier rasInHalFormat =
+ convertRadioAccessSpecifierToRadioHAL_1_5(ras);
+ if (rasInHalFormat == null) {
+ return;
+ }
+ request.specifiers.add(rasInHalFormat);
+ }
+
+ request.mccMncs.addAll(nsr.getPlmns());
+ RILRequest rr = obtainRequest(RIL_REQUEST_START_NETWORK_SCAN, result,
+ mRILDefaultWorkSource);
+
+ if (RILJ_LOGD) {
+ riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+ }
+
+ try {
+ android.hardware.radio.V1_5.IRadio radioProxy15 =
+ (android.hardware.radio.V1_5.IRadio) radioProxy;
+ radioProxy15.startNetworkScan_1_5(rr.mSerial, request);
+ } catch (RemoteException | RuntimeException e) {
+ handleRadioProxyExceptionForRR(rr, "startNetworkScan", e);
+ }
+ } else if (mRadioVersion.greaterOrEqual(RADIO_HAL_VERSION_1_2)) {
android.hardware.radio.V1_2.NetworkScanRequest request =
new android.hardware.radio.V1_2.NetworkScanRequest();
request.type = nsr.getScanType();
@@ -4358,8 +4442,8 @@
}
@Override
- public void setSignalStrengthReportingCriteria(int hysteresisMs, int hysteresisDb,
- int[] thresholdsDbm, int ran, Message result) {
+ public void setSignalStrengthReportingCriteria(SignalThresholdInfo signalThresholdInfo,
+ int ran, Message result) {
IRadio radioProxy = getRadioProxy(result);
if (radioProxy != null) {
if (mRadioVersion.less(RADIO_HAL_VERSION_1_2)) {
@@ -4367,26 +4451,57 @@
+ "than 1.2");
return;
}
-
- RILRequest rr = obtainRequest(RIL_REQUEST_SET_SIGNAL_STRENGTH_REPORTING_CRITERIA,
- result, mRILDefaultWorkSource);
-
- if (RILJ_LOGD) {
- riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
- }
-
- try {
- android.hardware.radio.V1_2.IRadio radioProxy12 =
+ if (mRadioVersion.greaterOrEqual(RADIO_HAL_VERSION_1_2)
+ && mRadioVersion.less(RADIO_HAL_VERSION_1_5)) {
+ RILRequest rr = obtainRequest(RIL_REQUEST_SET_SIGNAL_STRENGTH_REPORTING_CRITERIA,
+ result, mRILDefaultWorkSource);
+ if (RILJ_LOGD) {
+ riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+ }
+ try {
+ android.hardware.radio.V1_2.IRadio radioProxy12 =
(android.hardware.radio.V1_2.IRadio) radioProxy;
- radioProxy12.setSignalStrengthReportingCriteria(rr.mSerial, hysteresisMs,
- hysteresisDb, primitiveArrayToArrayList(thresholdsDbm),
- convertRanToHalRan(ran));
- } catch (RemoteException | RuntimeException e) {
- handleRadioProxyExceptionForRR(rr, "setSignalStrengthReportingCriteria", e);
+ radioProxy12.setSignalStrengthReportingCriteria(rr.mSerial,
+ signalThresholdInfo.getHysteresisMs(),
+ signalThresholdInfo.getHysteresisDb(),
+ primitiveArrayToArrayList(signalThresholdInfo.getThresholds()),
+ convertRanToHalRan(ran));
+ } catch (RemoteException | RuntimeException e) {
+ handleRadioProxyExceptionForRR(rr, "setSignalStrengthReportingCriteria", e);
+ }
+ }
+ if (mRadioVersion.greaterOrEqual(RADIO_HAL_VERSION_1_5)) {
+ RILRequest rr = obtainRequest(RIL_REQUEST_SET_SIGNAL_STRENGTH_REPORTING_CRITERIA,
+ result, mRILDefaultWorkSource);
+ if (RILJ_LOGD) {
+ riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+ }
+ try {
+ android.hardware.radio.V1_5.IRadio radioProxy15 =
+ (android.hardware.radio.V1_5.IRadio) radioProxy;
+ radioProxy15.setSignalStrengthReportingCriteria_1_5(rr.mSerial,
+ convertToHalSignalThresholdInfo(signalThresholdInfo),
+ convertRanToHalRan(ran));
+ } catch (RemoteException | RuntimeException e) {
+ handleRadioProxyExceptionForRR(
+ rr, "setSignalStrengthReportingCriteria_1_5", e);
+ }
}
}
}
+ private static android.hardware.radio.V1_5.SignalThresholdInfo convertToHalSignalThresholdInfo(
+ SignalThresholdInfo signalThresholdInfo) {
+ android.hardware.radio.V1_5.SignalThresholdInfo signalThresholdInfoHal =
+ new android.hardware.radio.V1_5.SignalThresholdInfo();
+ signalThresholdInfoHal.signalMeasurement = signalThresholdInfo.getSignalMeasurement();
+ signalThresholdInfoHal.hysteresisMs = signalThresholdInfo.getHysteresisMs();
+ signalThresholdInfoHal.hysteresisDb = signalThresholdInfo.getHysteresisDb();
+ signalThresholdInfoHal.thresholds = primitiveArrayToArrayList(
+ signalThresholdInfo.getThresholds());
+ return signalThresholdInfoHal;
+ }
+
@Override
public void setLinkCapacityReportingCriteria(int hysteresisMs, int hysteresisDlKbps,
int hysteresisUlKbps, int[] thresholdsDlKbps, int[] thresholdsUlKbps, int ran,
@@ -4431,6 +4546,8 @@
return AccessNetwork.CDMA2000;
case AccessNetworkType.IWLAN:
return AccessNetwork.IWLAN;
+ case AccessNetworkType.NGRAN:
+ return AccessNetwork.NGRAN;
case AccessNetworkType.UNKNOWN:
default:
return 0;
diff --git a/src/java/com/android/internal/telephony/RadioResponse.java b/src/java/com/android/internal/telephony/RadioResponse.java
index a36b7a6..da68b69 100644
--- a/src/java/com/android/internal/telephony/RadioResponse.java
+++ b/src/java/com/android/internal/telephony/RadioResponse.java
@@ -1452,6 +1452,13 @@
/**
* @param responseInfo Response info struct containing response type, serial no. and error
*/
+ public void setSignalStrengthReportingCriteriaResponse_1_5(RadioResponseInfo responseInfo) {
+ responseVoid(responseInfo);
+ }
+
+ /**
+ * @param responseInfo Response info struct containing response type, serial no. and error
+ */
public void setLinkCapacityReportingCriteriaResponse(RadioResponseInfo responseInfo) {
responseVoid(responseInfo);
}
diff --git a/src/java/com/android/internal/telephony/ServiceStateTracker.java b/src/java/com/android/internal/telephony/ServiceStateTracker.java
index d790a3e..b3149c2 100755
--- a/src/java/com/android/internal/telephony/ServiceStateTracker.java
+++ b/src/java/com/android/internal/telephony/ServiceStateTracker.java
@@ -67,12 +67,14 @@
import android.telephony.CellIdentityWcdma;
import android.telephony.CellInfo;
import android.telephony.CellLocation;
+import android.telephony.CellSignalStrengthNr;
import android.telephony.DataSpecificRegistrationInfo;
import android.telephony.NetworkRegistrationInfo;
import android.telephony.PhysicalChannelConfig;
import android.telephony.Rlog;
import android.telephony.ServiceState;
import android.telephony.SignalStrength;
+import android.telephony.SignalThresholdInfo;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
@@ -4715,15 +4717,32 @@
}
private void updateReportingCriteria(PersistableBundle config) {
- mPhone.setSignalStrengthReportingCriteria(
+ mPhone.setSignalStrengthReportingCriteria(SignalThresholdInfo.SIGNAL_RSRP,
config.getIntArray(CarrierConfigManager.KEY_LTE_RSRP_THRESHOLDS_INT_ARRAY),
- AccessNetworkType.EUTRAN);
- mPhone.setSignalStrengthReportingCriteria(
+ AccessNetworkType.EUTRAN, true);
+ mPhone.setSignalStrengthReportingCriteria(SignalThresholdInfo.SIGNAL_RSCP,
config.getIntArray(CarrierConfigManager.KEY_WCDMA_RSCP_THRESHOLDS_INT_ARRAY),
- AccessNetworkType.UTRAN);
- mPhone.setSignalStrengthReportingCriteria(
+ AccessNetworkType.UTRAN, true);
+ mPhone.setSignalStrengthReportingCriteria(SignalThresholdInfo.SIGNAL_RSSI,
config.getIntArray(CarrierConfigManager.KEY_GSM_RSSI_THRESHOLDS_INT_ARRAY),
- AccessNetworkType.GERAN);
+ AccessNetworkType.GERAN, true);
+
+ if (mPhone.getHalVersion().greaterOrEqual(RIL.RADIO_HAL_VERSION_1_5)) {
+ int measurementEnabled = config.getInt(CarrierConfigManager
+ .KEY_PARAMETERS_USE_FOR_5G_NR_SIGNAL_BAR_INT, CellSignalStrengthNr.USE_SSRSRP);
+ mPhone.setSignalStrengthReportingCriteria(SignalThresholdInfo.SIGNAL_SSRSRP,
+ config.getIntArray(CarrierConfigManager.KEY_5G_NR_SSRSRP_THRESHOLDS_INT_ARRAY),
+ AccessNetworkType.NGRAN,
+ (measurementEnabled & CellSignalStrengthNr.USE_SSRSRP) != 0);
+ mPhone.setSignalStrengthReportingCriteria(SignalThresholdInfo.SIGNAL_SSRSRQ,
+ config.getIntArray(CarrierConfigManager.KEY_5G_NR_SSRSRQ_THRESHOLDS_INT_ARRAY),
+ AccessNetworkType.NGRAN,
+ (measurementEnabled & CellSignalStrengthNr.USE_SSRSRQ) != 0);
+ mPhone.setSignalStrengthReportingCriteria(SignalThresholdInfo.SIGNAL_SSSINR,
+ config.getIntArray(CarrierConfigManager.KEY_5G_NR_SSSINR_THRESHOLDS_INT_ARRAY),
+ AccessNetworkType.NGRAN,
+ (measurementEnabled & CellSignalStrengthNr.USE_SSSINR) != 0);
+ }
}
private void updateServiceStateLteEarfcnBoost(ServiceState serviceState, int lteEarfcn) {
diff --git a/src/java/com/android/internal/telephony/TimeServiceHelperImpl.java b/src/java/com/android/internal/telephony/TimeServiceHelperImpl.java
index 5064d50..e5ffdad 100644
--- a/src/java/com/android/internal/telephony/TimeServiceHelperImpl.java
+++ b/src/java/com/android/internal/telephony/TimeServiceHelperImpl.java
@@ -21,11 +21,9 @@
import android.app.timedetector.TimeDetector;
import android.content.ContentResolver;
import android.content.Context;
-import android.content.Intent;
import android.database.ContentObserver;
import android.os.Handler;
import android.os.SystemProperties;
-import android.os.UserHandle;
import android.provider.Settings;
/**
@@ -95,10 +93,6 @@
public void setDeviceTimeZone(String zoneId) {
AlarmManager alarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
alarmManager.setTimeZone(zoneId);
- Intent intent = new Intent(TelephonyIntents.ACTION_NETWORK_SET_TIMEZONE);
- intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
- intent.putExtra("time-zone", zoneId);
- mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
}
@Override
diff --git a/src/java/com/android/internal/telephony/cat/CatService.java b/src/java/com/android/internal/telephony/cat/CatService.java
index f149c6f..50ceaac 100644
--- a/src/java/com/android/internal/telephony/cat/CatService.java
+++ b/src/java/com/android/internal/telephony/cat/CatService.java
@@ -21,6 +21,7 @@
import static com.android.internal.telephony.cat.CatCmdMessage.SetupEventListConstants.USER_ACTIVITY_EVENT;
import android.annotation.UnsupportedAppUsage;
+import android.app.ActivityManager;
import android.app.ActivityManagerNative;
import android.app.IActivityManager;
import android.app.backup.BackupManager;
@@ -1182,8 +1183,7 @@
for (int i = 0; i < defaultLocaleList.size(); i++) {
locales[i+1] = defaultLocaleList.get(i);
}
- config.setLocales(new LocaleList(locales));
- config.userSetLocale = true;
+ mContext.getSystemService(ActivityManager.class).setDeviceLocales(new LocaleList(locales));
am.updatePersistentConfiguration(config);
BackupManager.dataChanged("com.android.providers.settings");
}
diff --git a/src/java/com/android/internal/telephony/dataconnection/DataConnection.java b/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
index 822d249..cb4853e 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
@@ -82,7 +82,6 @@
import com.android.internal.telephony.metrics.TelephonyMetrics;
import com.android.internal.telephony.nano.TelephonyProto.RilDataCall;
import com.android.internal.util.AsyncChannel;
-import com.android.internal.util.CollectionUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Protocol;
import com.android.internal.util.State;
@@ -709,8 +708,7 @@
}
linkProperties = dc.getLinkProperties();
- if (linkProperties == null || CollectionUtils.isEmpty(
- linkProperties.getLinkAddresses())) {
+ if (linkProperties == null || linkProperties.getLinkAddresses().isEmpty()) {
loge("connect: Can't find link properties of handover data connection. dc="
+ dc);
return DataFailCause.HANDOVER_FAILED;
@@ -1612,9 +1610,7 @@
AsyncResult ar = (AsyncResult)msg.obj;
Pair<Integer, Integer> drsRatPair = (Pair<Integer, Integer>)ar.result;
mDataRegState = drsRatPair.first;
- if (mRilRat != drsRatPair.second) {
- updateTcpBufferSizes(drsRatPair.second);
- }
+ updateTcpBufferSizes(drsRatPair.second);
mRilRat = drsRatPair.second;
if (DBG) {
log("DcDefaultState: EVENT_DATA_CONNECTION_DRS_OR_RAT_CHANGED"
diff --git a/src/java/com/android/internal/telephony/euicc/EuiccConnector.java b/src/java/com/android/internal/telephony/euicc/EuiccConnector.java
index 874bd51..8b1bd33 100644
--- a/src/java/com/android/internal/telephony/euicc/EuiccConnector.java
+++ b/src/java/com/android/internal/telephony/euicc/EuiccConnector.java
@@ -56,6 +56,7 @@
import android.service.euicc.IRetainSubscriptionsForFactoryResetCallback;
import android.service.euicc.ISwitchToSubscriptionCallback;
import android.service.euicc.IUpdateSubscriptionNicknameCallback;
+import android.telephony.PackageChangeReceiver;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.UiccCardInfo;
@@ -68,7 +69,6 @@
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.content.PackageMonitor;
import com.android.internal.telephony.util.TelephonyUtils;
import com.android.internal.util.IState;
import com.android.internal.util.State;
@@ -327,7 +327,7 @@
private TelephonyManager mTm;
private SubscriptionManager mSm;
- private final PackageMonitor mPackageMonitor = new EuiccPackageMonitor();
+ private final PackageChangeReceiver mPackageMonitor = new EuiccPackageMonitor();
private final BroadcastReceiver mUserUnlockedReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -393,7 +393,7 @@
mSelectedComponent = findBestComponent();
setInitialState(mSelectedComponent != null ? mAvailableState : mUnavailableState);
- mPackageMonitor.register(mContext, null /* thread */, false /* externalStorage */);
+ mPackageMonitor.register(mContext, null /* thread */, null /* user */);
mContext.registerReceiver(
mUserUnlockedReceiver, new IntentFilter(Intent.ACTION_USER_UNLOCKED));
@@ -1124,19 +1124,19 @@
sendMessage(CMD_SERVICE_DISCONNECTED);
}
- private class EuiccPackageMonitor extends PackageMonitor {
+ private class EuiccPackageMonitor extends PackageChangeReceiver {
@Override
- public void onPackageAdded(String packageName, int reason) {
+ public void onPackageAdded(String packageName) {
sendPackageChange(packageName, true /* forceUnbindForThisPackage */);
}
@Override
- public void onPackageRemoved(String packageName, int reason) {
+ public void onPackageRemoved(String packageName) {
sendPackageChange(packageName, true /* forceUnbindForThisPackage */);
}
@Override
- public void onPackageUpdateFinished(String packageName, int uid) {
+ public void onPackageUpdateFinished(String packageName) {
sendPackageChange(packageName, true /* forceUnbindForThisPackage */);
}
@@ -1146,13 +1146,12 @@
}
@Override
- public boolean onHandleForceStop(Intent intent, String[] packages, int uid, boolean doit) {
+ public void onHandleForceStop(String[] packages, boolean doit) {
if (doit) {
for (String packageName : packages) {
sendPackageChange(packageName, true /* forceUnbindForThisPackage */);
}
}
- return super.onHandleForceStop(intent, packages, uid, doit);
}
private void sendPackageChange(String packageName, boolean forceUnbindForThisPackage) {
diff --git a/src/java/com/android/internal/telephony/ims/ImsResolver.java b/src/java/com/android/internal/telephony/ims/ImsResolver.java
index cee0c8a..9131a0e 100644
--- a/src/java/com/android/internal/telephony/ims/ImsResolver.java
+++ b/src/java/com/android/internal/telephony/ims/ImsResolver.java
@@ -17,6 +17,7 @@
package com.android.internal.telephony.ims;
import android.Manifest;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
@@ -44,6 +45,7 @@
import android.telephony.ims.feature.MmTelFeature;
import android.telephony.ims.stub.ImsFeatureConfiguration;
import android.text.TextUtils;
+import android.util.ArrayMap;
import android.util.LocalLog;
import android.util.Log;
import android.util.SparseArray;
@@ -56,20 +58,23 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
+import java.util.concurrent.LinkedBlockingQueue;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* Creates a list of ImsServices that are available to bind to based on the Device configuration
- * overlay value "config_ims_package" and Carrier Configuration value
- * "config_ims_package_override_string".
- * These ImsServices are then bound to in the following order:
+ * overlay values "config_ims_rcs_package" and "config_ims_mmtel_package" as well as Carrier
+ * Configuration value "config_ims_rcs_package_override_string" and
+ * "config_ims_mmtel_package_override_string".
+ * These ImsServices are then bound to in the following order for each mmtel and rcs feature:
*
* 1. Carrier Config defined override value per SIM.
* 2. Device overlay default value (including no SIM case).
@@ -82,9 +87,12 @@
private static final String TAG = "ImsResolver";
+ @VisibleForTesting
public static final String METADATA_EMERGENCY_MMTEL_FEATURE =
"android.telephony.ims.EMERGENCY_MMTEL_FEATURE";
+ @VisibleForTesting
public static final String METADATA_MMTEL_FEATURE = "android.telephony.ims.MMTEL_FEATURE";
+ @VisibleForTesting
public static final String METADATA_RCS_FEATURE = "android.telephony.ims.RCS_FEATURE";
// Overrides the sanity permission check of android.permission.BIND_IMS_SERVICE for any
// ImsService that is connecting to the platform.
@@ -99,7 +107,7 @@
private static final int HANDLER_CONFIG_CHANGED = 2;
// A query has been started for an ImsService to relay the features they support.
private static final int HANDLER_START_DYNAMIC_FEATURE_QUERY = 3;
- // A query to request ImsService features has completed or the ImsService has updated features.
+ // A dynamic query to request ImsService features has completed.
private static final int HANDLER_DYNAMIC_FEATURE_CHANGE = 4;
// Testing: Overrides the current configuration for ImsService binding
private static final int HANDLER_OVERRIDE_IMS_SERVICE_CONFIG = 5;
@@ -144,7 +152,7 @@
}
@VisibleForTesting
- public HashSet<ImsFeatureConfiguration.FeatureSlotPair> getSupportedFeatures() {
+ public Set<ImsFeatureConfiguration.FeatureSlotPair> getSupportedFeatures() {
return mSupportedFeatures;
}
@@ -359,21 +367,6 @@
}
};
- private ImsServiceControllerFactory mImsServiceControllerFactoryStaticBindingCompat =
- new ImsServiceControllerFactory() {
- @Override
- public String getServiceInterface() {
- // The static method of binding does not use service interfaces.
- return null;
- }
-
- @Override
- public ImsServiceController create(Context context, ComponentName componentName,
- ImsServiceController.ImsServiceControllerCallbacks callbacks) {
- return new ImsServiceControllerStaticCompat(context, componentName, callbacks);
- }
- };
-
private ImsDynamicQueryManagerFactory mDynamicQueryManagerFactory =
ImsServiceFeatureQueryManager::new;
@@ -388,13 +381,13 @@
// ImsServiceController callbacks.
private final Object mBoundServicesLock = new Object();
private final int mNumSlots;
- private final boolean mIsDynamicBinding;
- // Package name of the default device service.
- private String mDeviceService;
+ private SparseArray<Map<Integer, String>> mCarrierServices;
+ // Package name of the default device services, Maps ImsFeature -> packageName.
+ private Map<Integer, String> mDeviceServices;
// Persistent Logging
private final LocalLog mEventLog = new LocalLog(50);
- // Synchronize all messages on a handler to ensure that the cache includes the most recent
+ // Synchronize all events on a handler to ensure that the cache includes the most recent
// version of the installed ImsServices.
private Handler mHandler = new Handler(Looper.getMainLooper(), (msg) -> {
switch (msg.what) {
@@ -411,7 +404,7 @@
case HANDLER_BOOT_COMPLETE: {
mEventLog.log("handling BOOT_COMPLETE");
// Re-evaluate bound services for all slots after requerying packagemanager
- maybeAddedImsService(null);
+ maybeAddedImsService(null /*packageName*/);
break;
}
case HANDLER_CONFIG_CHANGED: {
@@ -438,33 +431,7 @@
// arg2 will be equal to 1 if it is a carrier service.
boolean isCarrierImsService = (msg.arg2 == 1);
String packageName = (String) msg.obj;
- if (isCarrierImsService) {
- Log.i(TAG, "overriding carrier ImsService - slot=" + slotId + " packageName="
- + packageName);
- overrideService(slotId, packageName);
- } else {
- Log.i(TAG, "overriding device ImsService - packageName=" + packageName);
- mEventLog.log("overriding device ImsService with " + packageName);
- if (TextUtils.equals(mDeviceService, packageName)) {
- // No change in device service.
- break;
- }
- // Unbind from the previous ImsService before binding to the new one.
- unbindImsService(getImsServiceInfoFromCache(mDeviceService));
- mDeviceService = packageName;
- ImsServiceInfo deviceInfo = getImsServiceInfoFromCache(mDeviceService);
- if (deviceInfo == null) {
- // The package name is either "" or does not exist on the device.
- break;
- }
- if (deviceInfo.featureFromMetadata) {
- bindImsService(deviceInfo);
- } else {
- // newly added ImsServiceInfo that has not had features queried yet. Start
- // async bind and query features.
- scheduleQueryForFeatures(deviceInfo);
- }
- }
+ overrideService(isCarrierImsService, slotId, packageName);
break;
}
default:
@@ -503,51 +470,44 @@
// Used during testing, overrides the carrier services while non-empty.
// Array index corresponds to slot Id associated with the service package name.
private String[] mOverrideServices;
- // Array index corresponds to slot Id associated with the service package name.
- private String[] mCarrierServices;
// List index corresponds to Slot Id, Maps ImsFeature.FEATURE->bound ImsServiceController
// Locked on mBoundServicesLock
private List<SparseArray<ImsServiceController>> mBoundImsServicesByFeature;
// not locked, only accessed on a handler thread.
+ // Tracks list of all installed ImsServices
private Map<ComponentName, ImsServiceInfo> mInstalledServicesCache = new HashMap<>();
// not locked, only accessed on a handler thread.
+ // Active ImsServiceControllers, which are bound to ImsServices.
private Map<ComponentName, ImsServiceController> mActiveControllers = new HashMap<>();
- // Only used as the Component name for legacy ImsServices that did not use dynamic binding.
- private final ComponentName mStaticComponent;
private ImsServiceFeatureQueryManager mFeatureQueryManager;
- public ImsResolver(Context context, String defaultImsPackageName, int numSlots,
- boolean isDynamicBinding) {
+ public ImsResolver(Context context, String defaultImsPackageName, int numSlots) {
mContext = context;
mReceiverContext = context.createContextAsUser(UserHandle.ALL, 0 /*flags*/);
- mDeviceService = defaultImsPackageName;
+
+ mCarrierServices = new SparseArray<>(numSlots);
+ mDeviceServices = new ArrayMap<>();
+ // TODO: create separate device configurations for MMTEL and RCS
+ setDeviceConfiguration(defaultImsPackageName, ImsFeature.FEATURE_EMERGENCY_MMTEL);
+ setDeviceConfiguration(defaultImsPackageName, ImsFeature.FEATURE_MMTEL);
+ setDeviceConfiguration(defaultImsPackageName, ImsFeature.FEATURE_RCS);
mNumSlots = numSlots;
- mIsDynamicBinding = isDynamicBinding;
- mStaticComponent = new ComponentName(mContext, ImsResolver.class);
- if (!mIsDynamicBinding) {
- Log.i(TAG, "ImsResolver initialized with static binding.");
- mDeviceService = mStaticComponent.getPackageName();
- }
mCarrierConfigManager = (CarrierConfigManager) mContext.getSystemService(
Context.CARRIER_CONFIG_SERVICE);
- mCarrierServices = new String[numSlots];
mOverrideServices = new String[numSlots];
mBoundImsServicesByFeature = Stream.generate(SparseArray<ImsServiceController>::new)
.limit(mNumSlots).collect(Collectors.toList());
- // Only register for Package/CarrierConfig updates if dynamic binding.
- if(mIsDynamicBinding) {
- IntentFilter appChangedFilter = new IntentFilter();
- appChangedFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
- appChangedFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
- appChangedFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
- appChangedFilter.addDataScheme("package");
- mReceiverContext.registerReceiver(mAppChangedReceiver, appChangedFilter);
- mReceiverContext.registerReceiver(mConfigChangedReceiver, new IntentFilter(
- CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED));
- mReceiverContext.registerReceiver(mBootCompleted, new IntentFilter(
- Intent.ACTION_BOOT_COMPLETED));
- }
+ IntentFilter appChangedFilter = new IntentFilter();
+ appChangedFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
+ appChangedFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+ appChangedFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
+ appChangedFilter.addDataScheme("package");
+ mReceiverContext.registerReceiver(mAppChangedReceiver, appChangedFilter);
+ mReceiverContext.registerReceiver(mConfigChangedReceiver, new IntentFilter(
+ CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED));
+ mReceiverContext.registerReceiver(mBootCompleted, new IntentFilter(
+ Intent.ACTION_BOOT_COMPLETED));
}
@VisibleForTesting
@@ -593,20 +553,34 @@
// Update the package names of the carrier ImsServices if they do not exist already and
// possibly bind if carrier configs exist. Otherwise wait for CarrierConfigChanged
// indication.
- for (int i = 0; i < mNumSlots; i++) {
- int subId = mSubscriptionManagerProxy.getSubId(i);
- PersistableBundle config = mCarrierConfigManager.getConfigForSubId(subId);
- if (config != null && mCarrierServices[i] == null) {
- String newPackageName = config.getString(
- CarrierConfigManager.KEY_CONFIG_IMS_PACKAGE_OVERRIDE_STRING, null);
+ bindCarrierServicesIfAvailable();
+ }
+
+ // Only start the bind if there is an existing Carrier Configuration. Otherwise, wait for
+ // carrier config changed.
+ private void bindCarrierServicesIfAvailable() {
+ boolean hasConfigChanged = false;
+ for (int slotId = 0; slotId < mNumSlots; slotId++) {
+ Map<Integer, String> featureMap = getImsPackageOverrideConfig(slotId);
+ for (int f = ImsFeature.FEATURE_EMERGENCY_MMTEL; f < ImsFeature.FEATURE_MAX; f++) {
+ String newPackageName = featureMap.getOrDefault(f, "");
if (!TextUtils.isEmpty(newPackageName)) {
- mEventLog.log("Initializing: found carrier package.");
- updateBoundCarrierServices(i, newPackageName);
- Log.i(TAG, "Initializing, found package " + newPackageName + " on slot "
- + i);
+ mEventLog.log("bindCarrierServicesIfAvailable - carrier package found: "
+ + newPackageName + " on slot " + slotId);
+ setCarrierConfiguration(newPackageName, slotId, f);
+ ImsServiceInfo info = getImsServiceInfoFromCache(newPackageName);
+ // We do not want to trigger feature configuration changes unless there is
+ // already a valid carrier config change.
+ if (info != null && info.featureFromMetadata) {
+ hasConfigChanged = true;
+ } else {
+ // Config will change when this query completes
+ scheduleQueryForFeatures(info);
+ }
}
}
}
+ if (hasConfigChanged) calculateFeatureConfigurationChange();
}
/**
@@ -754,14 +728,73 @@
return true;
}
- // used for testing only.
- public String getImsServiceConfiguration(int slotId, boolean isCarrierService) {
+ // not synchronized, access through handler ONLY.
+ private String getDeviceConfiguration(@ImsFeature.FeatureType int featureType) {
+ return mDeviceServices.getOrDefault(featureType, "");
+ }
+
+ // not synchronized, access in handler ONLY.
+ private void setDeviceConfiguration(String name, @ImsFeature.FeatureType int featureType) {
+ mDeviceServices.put(featureType, name);
+ }
+
+ // not synchronized, access in handler ONLY.
+ private void setCarrierConfiguration(@NonNull String packageName, int slotId,
+ @ImsFeature.FeatureType int featureType) {
+ getCarrierConfigurations(slotId).put(featureType, packageName);
+ }
+
+ // not synchronized, access in handler ONLY.
+ private @NonNull String getCarrierConfiguration(int slotId,
+ @ImsFeature.FeatureType int featureType) {
+ return getCarrierConfigurations(slotId).getOrDefault(featureType, "");
+ }
+
+ // not synchronized, access in handler ONLY.
+ private @NonNull Map<Integer, String> getCarrierConfigurations(int slotId) {
+ Map<Integer, String> carrierConfig = mCarrierServices.get(slotId);
+ if (carrierConfig == null) {
+ carrierConfig = new ArrayMap<>();
+ mCarrierServices.put(slotId, carrierConfig);
+ }
+ return carrierConfig;
+ }
+
+ /**
+ * @return true if there is a carrier configuration that exists for the slot & featureType pair
+ * and the cached carrier ImsService associated with the configuration also supports the
+ * requested ImsFeature type.
+ */
+ // not synchronized, access in handler ONLY.
+ private boolean doesCarrierConfigurationExist(int slotId,
+ @ImsFeature.FeatureType int featureType) {
+ String carrierPackage = getCarrierConfiguration(slotId, featureType);
+ if (TextUtils.isEmpty(carrierPackage)) {
+ return false;
+ }
+ // Config exists, but the carrier ImsService also needs to support this feature
+ ImsServiceInfo info = getImsServiceInfoFromCache(carrierPackage);
+ return info != null && info.getSupportedFeatures().stream().anyMatch(
+ feature -> feature.slotId == slotId && feature.featureType == featureType);
+ }
+
+ /**
+ * @return the package name of the ImsService with the requested configuration.
+ */
+ // used in shell commands queries during testing only.
+ public String getImsServiceConfiguration(int slotId, boolean isCarrierService,
+ @ImsFeature.FeatureType int featureType) {
if (slotId < 0 || slotId >= mNumSlots) {
Log.w(TAG, "getImsServiceConfiguration: invalid slotId!");
return "";
}
- return isCarrierService ? mCarrierServices[slotId] : mDeviceService;
+ LinkedBlockingQueue<String> result = new LinkedBlockingQueue<>(1);
+ // access the configuration on the handler.
+ mHandler.post(() -> result.offer(isCarrierService
+ ? getCarrierConfiguration(slotId, featureType) :
+ getDeviceConfiguration(featureType)));
+ return result.poll();
}
private void putImsController(int slotId, int feature, ImsServiceController controller) {
@@ -817,7 +850,9 @@
private void maybeAddedImsService(String packageName) {
Log.d(TAG, "maybeAddedImsService, packageName: " + packageName);
List<ImsServiceInfo> infos = getImsServiceInfo(packageName);
- List<ImsServiceInfo> newlyAddedInfos = new ArrayList<>();
+ // Wait until all ImsServiceInfo is cached before calling
+ // calculateFeatureConfigurationChange to reduce churn.
+ boolean requiresCalculation = false;
for (ImsServiceInfo info : infos) {
// Checking to see if the ComponentName is the same, so we can update the supported
// features. Will only be one (if it exists), since it is a set.
@@ -835,7 +870,7 @@
+ info);
// update features in the cache
match.replaceFeatures(info.getSupportedFeatures());
- updateImsServiceFeatures(info);
+ requiresCalculation = true;
} else {
mEventLog.log("maybeAddedImsService - scheduling query for " + info);
// start a query to get ImsService features
@@ -846,7 +881,7 @@
mEventLog.log("maybeAddedImsService - adding new ImsService: " + info);
mInstalledServicesCache.put(info.name, info);
if (info.featureFromMetadata) {
- newlyAddedInfos.add(info);
+ requiresCalculation = true;
} else {
// newly added ImsServiceInfo that has not had features queried yet. Start async
// bind and query features.
@@ -854,20 +889,7 @@
}
}
}
- // Loop through the newly created ServiceInfos in a separate loop to make sure the cache
- // is fully updated.
- for (ImsServiceInfo info : newlyAddedInfos) {
- if (isActiveCarrierService(info)) {
- // New ImsService is registered to active carrier services and must be newly
- // bound.
- bindImsService(info);
- // Update existing device service features
- updateImsServiceFeatures(getImsServiceInfoFromCache(mDeviceService));
- } else if (isDeviceService(info)) {
- // New ImsService is registered as device default and must be newly bound.
- bindImsService(info);
- }
- }
+ if (requiresCalculation) calculateFeatureConfigurationChange();
}
// Remove the ImsService from the cache. This may have been due to the ImsService being removed
@@ -880,35 +902,27 @@
mEventLog.log("maybeRemovedImsService - removing ImsService: " + match);
Log.i(TAG, "Removing ImsService: " + match.name);
unbindImsService(match);
- updateImsServiceFeatures(getImsServiceInfoFromCache(mDeviceService));
+ calculateFeatureConfigurationChange();
return true;
}
return false;
}
- // Returns true if the CarrierConfig that has been loaded includes this ImsServiceInfo
- // package name.
- // Called from Handler ONLY
- private boolean isActiveCarrierService(ImsServiceInfo info) {
- for (int i = 0; i < mNumSlots; i++) {
- if (TextUtils.equals(mCarrierServices[i], info.name.getPackageName())) {
- return true;
- }
- }
- return false;
- }
-
private boolean isDeviceService(ImsServiceInfo info) {
- return TextUtils.equals(mDeviceService, info.name.getPackageName());
+ if (info == null) return false;
+ return mDeviceServices.containsValue(info.name.getPackageName());
}
- private int getSlotForActiveCarrierService(ImsServiceInfo info) {
+ private List<Integer> getSlotsForActiveCarrierService(ImsServiceInfo info) {
+ if (info == null) return Collections.emptyList();
+ List<Integer> slots = new ArrayList<>(mNumSlots);
for (int i = 0; i < mNumSlots; i++) {
- if (TextUtils.equals(mCarrierServices[i], info.name.getPackageName())) {
- return i;
+ if (!TextUtils.isEmpty(getCarrierConfigurations(i).values().stream()
+ .filter(e -> e.equals(info.name.getPackageName())).findAny().orElse(""))) {
+ slots.add(i);
}
}
- return SubscriptionManager.INVALID_SIM_SLOT_INDEX;
+ return slots;
}
private ImsServiceController getControllerByServiceInfo(
@@ -930,58 +944,8 @@
return searchMap.get(matchValue);
}
- // Creates new features in active ImsServices and removes obsolete cached features. If
- // cachedInfo == null, then newInfo is assumed to be a new ImsService and will have all features
- // created.
- private void updateImsServiceFeatures(ImsServiceInfo newInfo) {
- if (newInfo == null) {
- return;
- }
- ImsServiceController controller = getControllerByServiceInfo(mActiveControllers, newInfo);
- // Will return zero if these features are overridden or it should not currently have any
- // features because it is not carrier/device.
- HashSet<ImsFeatureConfiguration.FeatureSlotPair> features =
- calculateFeaturesToCreate(newInfo);
- if (shouldFeaturesCauseBind(features)) {
- try {
- if (controller != null) {
- Log.i(TAG, "Updating features for ImsService: "
- + controller.getComponentName());
- Log.d(TAG, "Updating Features - New Features: " + features);
- controller.changeImsServiceFeatures(features);
- } else {
- Log.i(TAG, "updateImsServiceFeatures: unbound with active features, binding");
- bindImsServiceWithFeatures(newInfo, features);
- }
- // If the carrier service features have changed, the device features will also
- // need to be recalculated.
- if (isActiveCarrierService(newInfo)
- // Prevent infinite recursion from bad behavior
- && !TextUtils.equals(newInfo.name.getPackageName(), mDeviceService)) {
- Log.i(TAG, "Updating device default");
- updateImsServiceFeatures(getImsServiceInfoFromCache(mDeviceService));
- }
- } catch (RemoteException e) {
- Log.e(TAG, "updateImsServiceFeatures: Remote Exception: " + e.getMessage());
- }
- // Don't stay bound if the ImsService is providing no features.
- } else if (controller != null) {
- Log.i(TAG, "Unbinding: features = 0 for ImsService: " + controller.getComponentName());
- unbindImsService(newInfo);
- }
- }
-
- // Bind to an ImsService and wait for the service to be connected to create ImsFeatures.
- private void bindImsService(ImsServiceInfo info) {
- if (info == null) {
- return;
- }
- HashSet<ImsFeatureConfiguration.FeatureSlotPair> features = calculateFeaturesToCreate(info);
- bindImsServiceWithFeatures(info, features);
- }
-
private void bindImsServiceWithFeatures(ImsServiceInfo info,
- HashSet<ImsFeatureConfiguration.FeatureSlotPair> features) {
+ Set<ImsFeatureConfiguration.FeatureSlotPair> features) {
// Only bind if there are features that will be created by the service.
if (shouldFeaturesCauseBind(features)) {
// Check to see if an active controller already exists
@@ -1033,36 +997,27 @@
private HashSet<ImsFeatureConfiguration.FeatureSlotPair> calculateFeaturesToCreate(
ImsServiceInfo info) {
HashSet<ImsFeatureConfiguration.FeatureSlotPair> imsFeaturesBySlot = new HashSet<>();
- // Check if the info is a carrier service
- int slotId = getSlotForActiveCarrierService(info);
- if (slotId != SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
+ List<Integer> slots = getSlotsForActiveCarrierService(info);
+ if (!slots.isEmpty()) {
+ // There is an active carrier config associated with this. Return with the ImsService's
+ // supported features that are also within the carrier configuration
imsFeaturesBySlot.addAll(info.getSupportedFeatures().stream()
- // Match slotId with feature slotId.
- .filter(feature -> slotId == feature.slotId)
+ .filter(feature -> info.name.getPackageName().equals(
+ getCarrierConfiguration(feature.slotId, feature.featureType)))
.collect(Collectors.toList()));
- } else if (isDeviceService(info)) {
- // For all slots that are not currently using a carrier ImsService, enable all features
- // for the device default.
- for (int i = 0; i < mNumSlots; i++) {
- final int currSlotId = i;
- ImsServiceInfo carrierImsInfo = getImsServiceInfoFromCache(mCarrierServices[i]);
- if (carrierImsInfo == null) {
- // No Carrier override, add all features for this slot
- imsFeaturesBySlot.addAll(info.getSupportedFeatures().stream()
- .filter(feature -> currSlotId == feature.slotId)
- .collect(Collectors.toList()));
- } else {
- // Add all features to the device service that are not currently covered by
- // the carrier ImsService.
- HashSet<ImsFeatureConfiguration.FeatureSlotPair> deviceFeatures =
- new HashSet<>(info.getSupportedFeatures());
- deviceFeatures.removeAll(carrierImsInfo.getSupportedFeatures());
- // only add features for current slot
- imsFeaturesBySlot.addAll(deviceFeatures.stream()
- .filter(feature -> currSlotId == feature.slotId).collect(
- Collectors.toList()));
- }
- }
+ return imsFeaturesBySlot;
+ }
+ if (isDeviceService(info)) {
+ imsFeaturesBySlot.addAll(info.getSupportedFeatures().stream()
+ // only allow supported features that are also set for this package as the
+ // device configuration.
+ .filter(feature -> info.name.getPackageName().equals(
+ getDeviceConfiguration(feature.featureType)))
+ // filter out any separate carrier configuration, since that feature is handled
+ // by the carrier ImsService.
+ .filter(feature -> !doesCarrierConfigurationExist(feature.slotId,
+ feature.featureType))
+ .collect(Collectors.toList()));
}
return imsFeaturesBySlot;
}
@@ -1118,8 +1073,7 @@
* @return true if MMTEL or RCS features are present, false if they are not or only
* EMERGENCY_MMTEL is specified.
*/
- private boolean shouldFeaturesCauseBind(
- HashSet<ImsFeatureConfiguration.FeatureSlotPair> features) {
+ private boolean shouldFeaturesCauseBind(Set<ImsFeatureConfiguration.FeatureSlotPair> features) {
long bindableFeatures = features.stream()
// remove all emergency features
.filter(f -> f.featureType != ImsFeature.FEATURE_EMERGENCY_MMTEL).count();
@@ -1128,20 +1082,26 @@
// Possibly rebind to another ImsService for testing.
// Called from the handler ONLY
- private void overrideService(int slotId, String newPackageName) {
+ private void overrideService(boolean isCarrierService, int slotId, String newPackageName) {
mEventLog.log("overriding carrier ImsService to " + newPackageName
+ " on slot " + slotId);
- if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
- // not specified, replace package on all slots.
- for (int i = 0; i < mNumSlots; i++) {
- mOverrideServices[i] = newPackageName;
- updateBoundCarrierServices(i, newPackageName);
+ Map<Integer, String> overrideMap = new ArrayMap<>();
+ overrideMap.put(ImsFeature.FEATURE_MMTEL, newPackageName);
+ overrideMap.put(ImsFeature.FEATURE_RCS, newPackageName);
+ if (isCarrierService) {
+ if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
+ // not specified, replace package on all slots.
+ for (int i = 0; i < mNumSlots; i++) {
+ mOverrideServices[i] = newPackageName;
+ updateBoundServices(i, overrideMap);
+ }
+ } else {
+ mOverrideServices[slotId] = newPackageName;
+ updateBoundServices(slotId, overrideMap);
}
} else {
- mOverrideServices[slotId] = newPackageName;
- updateBoundCarrierServices(slotId, newPackageName);
+ overrideBoundDeviceServices(overrideMap);
}
-
}
// Called from handler ONLY.
@@ -1149,62 +1109,79 @@
if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
// not specified, update carrier override cache and possibly rebind on all slots.
for (int i = 0; i < mNumSlots; i++) {
- updateBoundCarrierServices(i, getImsPackageOverrideConfig(i));
+ updateBoundServices(i, getImsPackageOverrideConfig(i));
}
}
- updateBoundCarrierServices(slotId, getImsPackageOverrideConfig(slotId));
+ updateBoundServices(slotId, getImsPackageOverrideConfig(slotId));
}
- private String getImsPackageOverrideConfig(int slotId) {
- int subId = mSubscriptionManagerProxy.getSubId(slotId);
- PersistableBundle config = mCarrierConfigManager.getConfigForSubId(subId);
- if (config == null) return null;
- return config.getString(CarrierConfigManager.KEY_CONFIG_IMS_PACKAGE_OVERRIDE_STRING, null);
- }
-
- /**
- * Use the slotId specified to update the carrier override cache with the new package name.
- * If it has changed, trigger an unbind from the old service kick off the process to recalculate
- * features supported on the new service.
- */
- private void updateBoundCarrierServices(int slotId, String newPackageName) {
- if (slotId > SubscriptionManager.INVALID_SIM_SLOT_INDEX && slotId < mNumSlots) {
- String overridePackageName = mOverrideServices[slotId];
- String oldPackageName = mCarrierServices[slotId];
+ private void updateBoundServices(int slotId, Map<Integer, String> featureMap) {
+ if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX || slotId >= mNumSlots) {
+ return;
+ }
+ boolean hasConfigChanged = false;
+ String overridePackageName = mOverrideServices[slotId];
+ for (int f = ImsFeature.FEATURE_EMERGENCY_MMTEL; f < ImsFeature.FEATURE_MAX; f++) {
+ String oldPackageName = getCarrierConfiguration(slotId, f);
+ String newPackageName = featureMap.getOrDefault(f, "");
if (!TextUtils.isEmpty(overridePackageName)) {
- // Do not allow carrier config changes to change the override package while it is
- // in effect.
- Log.i(TAG, "CarrierConfig change ignored for " + newPackageName + " while override"
- + " is in effect for " + overridePackageName);
+ // Do not allow carrier config changes to change the override package while it
+ // is in effect.
+ Log.i(TAG, "CarrierConfig change ignored for " + newPackageName + " while "
+ + "override is in effect for " + overridePackageName);
newPackageName = overridePackageName;
}
- mCarrierServices[slotId] = newPackageName;
- if (!TextUtils.equals(newPackageName, oldPackageName)) {
- Log.i(TAG, "Carrier Config updated, binding new ImsService");
- mEventLog.log("updateBoundCarrierServices - carrier package changed: "
- + oldPackageName + " -> " + newPackageName + " on slot " + slotId);
- // Unbind old ImsService, not needed anymore
- // ImsService is retrieved from the cache. If the cache hasn't been populated yet,
- // the calls to unbind/bind will fail (intended during initial start up).
- unbindImsService(getImsServiceInfoFromCache(oldPackageName));
- }
- ImsServiceInfo newInfo = getImsServiceInfoFromCache(newPackageName);
- // if there is no carrier ImsService, newInfo is null. This we still want to update
- // bindings for device ImsService to pick up the missing features.
- if (newInfo == null || newInfo.featureFromMetadata) {
- mEventLog.log("updateBoundCarrierServices - recalculating bindings "
- + (newInfo != null ? newInfo : "for device"));
- bindImsService(newInfo);
- // Recalculate the device ImsService features to reflect changes.
- updateImsServiceFeatures(getImsServiceInfoFromCache(mDeviceService));
+ mEventLog.log("updateBoundServices - carrier package changed: "
+ + oldPackageName + " -> " + newPackageName + " on slot " + slotId);
+ setCarrierConfiguration(newPackageName, slotId, f);
+ // Carrier config may have not changed, but we still want to kick off a recalculation
+ // in case there has been a change to the supported device features.
+ ImsServiceInfo info = getImsServiceInfoFromCache(newPackageName);
+ if (info == null || info.featureFromMetadata) {
+ hasConfigChanged = true;
} else {
- // ImsServiceInfo that has not had features queried yet. Start async
- // bind and query features.
- mEventLog.log("updateBoundCarrierServices - scheduling feature query for "
- + newInfo);
- scheduleQueryForFeatures(newInfo);
+ // Config will change when this query completes
+ scheduleQueryForFeatures(info);
}
}
+ if (hasConfigChanged) calculateFeatureConfigurationChange();
+ }
+
+ private @NonNull Map<Integer, String> getImsPackageOverrideConfig(int slotId) {
+ int subId = mSubscriptionManagerProxy.getSubId(slotId);
+ PersistableBundle config = mCarrierConfigManager.getConfigForSubId(subId);
+ if (config == null) return Collections.emptyMap();
+ // TODO: Create carrier configs for all feature types
+ String packageName = config.getString(
+ CarrierConfigManager.KEY_CONFIG_IMS_PACKAGE_OVERRIDE_STRING, null);
+ Map<Integer, String> result = new ArrayMap<>();
+ if (!TextUtils.isEmpty(packageName)) {
+ result.put(ImsFeature.FEATURE_EMERGENCY_MMTEL, packageName);
+ result.put(ImsFeature.FEATURE_MMTEL, packageName);
+ result.put(ImsFeature.FEATURE_RCS, packageName);
+ }
+ return result;
+ }
+
+ private void overrideBoundDeviceServices(Map<Integer, String> overrideMap) {
+ boolean hasConfigChanged = false;
+ for (int f = ImsFeature.FEATURE_EMERGENCY_MMTEL; f < ImsFeature.FEATURE_MAX; f++) {
+ String oldPackageName = getDeviceConfiguration(f);
+ String overridePackageName = overrideMap.getOrDefault(f, "");
+ if (!TextUtils.equals(oldPackageName, overridePackageName)) {
+ mEventLog.log("overrideBoundDeviceServices - device package changed: "
+ + oldPackageName + " -> " + overridePackageName);
+ setDeviceConfiguration(overridePackageName, f);
+ ImsServiceInfo info = getImsServiceInfoFromCache(overridePackageName);
+ if (info == null || info.featureFromMetadata) {
+ hasConfigChanged = true;
+ } else {
+ // Config will change when this query completes
+ scheduleQueryForFeatures(info);
+ }
+ }
+ }
+ if (hasConfigChanged) calculateFeatureConfigurationChange();
}
/**
@@ -1213,8 +1190,7 @@
private void scheduleQueryForFeatures(ImsServiceInfo service, int delayMs) {
// if not current device/carrier service, don't perform query. If this changes, this method
// will be called again.
- if (!isDeviceService(service) && getSlotForActiveCarrierService(service)
- == SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
+ if (!isDeviceService(service) && getSlotsForActiveCarrierService(service).isEmpty()) {
Log.i(TAG, "scheduleQueryForFeatures: skipping query for ImsService that is not"
+ " set as carrier/device ImsService.");
return;
@@ -1274,23 +1250,43 @@
Set<ImsFeatureConfiguration.FeatureSlotPair> features) {
ImsServiceInfo service = getImsServiceInfoFromCache(name.getPackageName());
if (service == null) {
- Log.w(TAG, "handleFeaturesChanged: Couldn't find cached info for name: "
+ Log.w(TAG, "dynamicQueryComplete: Couldn't find cached info for name: "
+ name);
return;
}
- mEventLog.log("dynamicQueryComplete for package " + name + ", features: "
+ mEventLog.log("dynamicQueryComplete: for package " + name + ", features: "
+ printFeatures(service.getSupportedFeatures()) + " -> " + printFeatures(features));
+ sanitizeFeatureConfig(features);
// Add features to service
service.replaceFeatures(features);
- if (isActiveCarrierService(service)) {
- // New ImsService is registered to active carrier services and must be newly
- // bound.
- bindImsService(service);
- // Update existing device service features
- updateImsServiceFeatures(getImsServiceInfoFromCache(mDeviceService));
- } else if (isDeviceService(service)) {
- // New ImsService is registered as device default and must be newly bound.
- bindImsService(service);
+ calculateFeatureConfigurationChange();
+ }
+
+ /**
+ * Ensure the feature includes MMTEL when it supports EMERGENCY_MMTEL, if not, remove.
+ */
+ private void sanitizeFeatureConfig(Set<ImsFeatureConfiguration.FeatureSlotPair> features) {
+ Set<ImsFeatureConfiguration.FeatureSlotPair> emergencyMmtelFeatures = features.stream()
+ .filter(feature -> feature.featureType == ImsFeature.FEATURE_EMERGENCY_MMTEL)
+ .collect(Collectors.toSet());
+ for (ImsFeatureConfiguration.FeatureSlotPair feature : emergencyMmtelFeatures) {
+ if (!features.contains(new ImsFeatureConfiguration.FeatureSlotPair(feature.slotId,
+ ImsFeature.FEATURE_MMTEL))) {
+ features.remove(feature);
+ }
+ }
+ }
+
+ // Calculate the new configuration for the bound ImsServices.
+ // Should ONLY be called from the handler.
+ private void calculateFeatureConfigurationChange() {
+ for (ImsServiceInfo info : mInstalledServicesCache.values()) {
+ Set<ImsFeatureConfiguration.FeatureSlotPair> features = calculateFeaturesToCreate(info);
+ if (shouldFeaturesCauseBind(features)) {
+ bindImsServiceWithFeatures(info, features);
+ } else {
+ unbindImsService(info);
+ }
}
}
@@ -1331,27 +1327,10 @@
// get all packages that support ImsServices.
private List<ImsServiceInfo> getImsServiceInfo(String packageName) {
List<ImsServiceInfo> infos = new ArrayList<>();
- if (!mIsDynamicBinding) {
- // always return the same ImsService info.
- infos.addAll(getStaticImsService());
- } else {
- // Search for Current ImsService implementations
- infos.addAll(searchForImsServices(packageName, mImsServiceControllerFactory));
- // Search for compat ImsService Implementations
- infos.addAll(searchForImsServices(packageName, mImsServiceControllerFactoryCompat));
- }
- return infos;
- }
-
- private List<ImsServiceInfo> getStaticImsService() {
- List<ImsServiceInfo> infos = new ArrayList<>();
-
- ImsServiceInfo info = new ImsServiceInfo(mNumSlots);
- info.name = mStaticComponent;
- info.controllerFactory = mImsServiceControllerFactoryStaticBindingCompat;
- info.addFeatureForAllSlots(ImsFeature.FEATURE_EMERGENCY_MMTEL);
- info.addFeatureForAllSlots(ImsFeature.FEATURE_MMTEL);
- infos.add(info);
+ // Search for Current ImsService implementations
+ infos.addAll(searchForImsServices(packageName, mImsServiceControllerFactory));
+ // Search for compat ImsService Implementations
+ infos.addAll(searchForImsServices(packageName, mImsServiceControllerFactoryCompat));
return infos;
}
@@ -1382,12 +1361,13 @@
if (isDeviceService(info)
|| mImsServiceControllerFactoryCompat == controllerFactory) {
if (serviceInfo.metaData != null) {
- if (serviceInfo.metaData.getBoolean(METADATA_EMERGENCY_MMTEL_FEATURE,
- false)) {
- info.addFeatureForAllSlots(ImsFeature.FEATURE_EMERGENCY_MMTEL);
- }
if (serviceInfo.metaData.getBoolean(METADATA_MMTEL_FEATURE, false)) {
info.addFeatureForAllSlots(ImsFeature.FEATURE_MMTEL);
+ // only allow FEATURE_EMERGENCY_MMTEL if FEATURE_MMTEL is defined.
+ if (serviceInfo.metaData.getBoolean(METADATA_EMERGENCY_MMTEL_FEATURE,
+ false)) {
+ info.addFeatureForAllSlots(ImsFeature.FEATURE_EMERGENCY_MMTEL);
+ }
}
if (serviceInfo.metaData.getBoolean(METADATA_RCS_FEATURE, false)) {
info.addFeatureForAllSlots(ImsFeature.FEATURE_RCS);
@@ -1428,14 +1408,31 @@
IndentingPrintWriter pw = new IndentingPrintWriter(printWriter, " ");
pw.println("ImsResolver:");
pw.increaseIndent();
- pw.println("mIsDynamicBinding = " + mIsDynamicBinding);
- pw.println("mDeviceService = " + mDeviceService);
- pw.println("mCarrierServices: ");
+ pw.println("Configurations:");
pw.increaseIndent();
- for (String s : mCarrierServices) {
- pw.println(s);
+ pw.println("Device:");
+ pw.increaseIndent();
+ for (Integer i : mDeviceServices.keySet()) {
+ pw.println(ImsFeature.FEATURE_LOG_MAP.get(i) + " -> " + mDeviceServices.get(i));
}
pw.decreaseIndent();
+ pw.println("Carrier: ");
+ pw.increaseIndent();
+ for (int i = 0; i < mNumSlots; i++) {
+ for (int j = 0; j < MmTelFeature.FEATURE_MAX; j++) {
+ pw.print("slot=");
+ pw.print(i);
+ pw.print(", feature=");
+ pw.print(ImsFeature.FEATURE_LOG_MAP.getOrDefault(j, "?"));
+ pw.println(": ");
+ pw.increaseIndent();
+ String name = getCarrierConfiguration(i, j);
+ pw.println(TextUtils.isEmpty(name) ? "none" : name);
+ pw.decreaseIndent();
+ }
+ }
+ pw.decreaseIndent();
+ pw.decreaseIndent();
pw.println("Bound Features:");
pw.increaseIndent();
for (int i = 0; i < mNumSlots; i++) {
@@ -1443,7 +1440,7 @@
pw.print("slot=");
pw.print(i);
pw.print(", feature=");
- pw.print(MmTelFeature.FEATURE_LOG_MAP.getOrDefault(j, "?"));
+ pw.print(ImsFeature.FEATURE_LOG_MAP.getOrDefault(j, "?"));
pw.println(": ");
pw.increaseIndent();
ImsServiceController c = getImsServiceController(i, j);
diff --git a/src/java/com/android/internal/telephony/ims/ImsServiceController.java b/src/java/com/android/internal/telephony/ims/ImsServiceController.java
index c4b7399..967152d 100644
--- a/src/java/com/android/internal/telephony/ims/ImsServiceController.java
+++ b/src/java/com/android/internal/telephony/ims/ImsServiceController.java
@@ -49,6 +49,7 @@
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.stream.Collectors;
/**
* Manages the Binding lifecycle of one ImsService as well as the relevant ImsFeatures that the
@@ -205,7 +206,7 @@
private boolean mIsBound = false;
private boolean mIsBinding = false;
// Set of a pair of slotId->feature
- private HashSet<ImsFeatureConfiguration.FeatureSlotPair> mImsFeatures;
+ private Set<ImsFeatureConfiguration.FeatureSlotPair> mImsFeatures;
// Binder interfaces to the features set in mImsFeatures;
private HashSet<ImsFeatureContainer> mImsFeatureBinders = new HashSet<>();
private IImsServiceController mIImsServiceController;
@@ -362,10 +363,11 @@
* @return {@link true} if the service is in the process of being bound, {@link false} if it
* has failed.
*/
- public boolean bind(HashSet<ImsFeatureConfiguration.FeatureSlotPair> imsFeatureSet) {
+ public boolean bind(Set<ImsFeatureConfiguration.FeatureSlotPair> imsFeatureSet) {
synchronized (mLock) {
if (!mIsBound && !mIsBinding) {
mIsBinding = true;
+ sanitizeFeatureConfig(imsFeatureSet);
mImsFeatures = imsFeatureSet;
grantPermissionsToService();
Intent imsServiceIntent = new Intent(getServiceInterface()).setComponent(
@@ -376,7 +378,7 @@
mLocalLog.log("binding " + imsFeatureSet);
Log.i(LOG_TAG, "Binding ImsService:" + mComponentName);
try {
- boolean bindSucceeded = startBindToService(imsServiceIntent,
+ boolean bindSucceeded = mContext.bindService(imsServiceIntent,
mImsServiceConnection, serviceFlags);
if (!bindSucceeded) {
mLocalLog.log(" binding failed, retrying in "
@@ -401,12 +403,18 @@
}
/**
- * Starts the bind to the ImsService. Overridden by subclasses that need to access the service
- * in a different fashion.
+ * Ensure the feature includes MMTEL when it supports EMERGENCY_MMTEL, if not, remove.
*/
- protected boolean startBindToService(Intent intent, ImsServiceConnection connection,
- int flags) {
- return mContext.bindService(intent, connection, flags);
+ private void sanitizeFeatureConfig(Set<ImsFeatureConfiguration.FeatureSlotPair> features) {
+ Set<ImsFeatureConfiguration.FeatureSlotPair> emergencyMmtelFeatures = features.stream()
+ .filter(feature -> feature.featureType == ImsFeature.FEATURE_EMERGENCY_MMTEL)
+ .collect(Collectors.toSet());
+ for (ImsFeatureConfiguration.FeatureSlotPair feature : emergencyMmtelFeatures) {
+ if (!features.contains(new ImsFeatureConfiguration.FeatureSlotPair(feature.slotId,
+ ImsFeature.FEATURE_MMTEL))) {
+ features.remove(feature);
+ }
+ }
}
/**
@@ -436,8 +444,9 @@
* ImsFeature that is removed, {@link IImsServiceController#removeImsFeature} is called.
*/
public void changeImsServiceFeatures(
- HashSet<ImsFeatureConfiguration.FeatureSlotPair> newImsFeatures)
+ Set<ImsFeatureConfiguration.FeatureSlotPair> newImsFeatures)
throws RemoteException {
+ sanitizeFeatureConfig(newImsFeatures);
synchronized (mLock) {
if (mImsFeatures.equals(newImsFeatures)) {
return;
@@ -706,12 +715,12 @@
IInterface f = createImsFeature(featurePair.slotId, featurePair.featureType,
c.getCallback());
addImsFeatureBinder(featurePair.slotId, featurePair.featureType, f);
- // Signal ImsResolver to change supported ImsFeatures for this ImsServiceController
- mCallbacks.imsServiceFeatureCreated(featurePair.slotId, featurePair.featureType, this);
} else {
// Don't update ImsService for emergency MMTEL feature.
Log.i(LOG_TAG, "supports emergency calling on slot " + featurePair.slotId);
}
+ // Signal ImsResolver to change supported ImsFeatures for this ImsServiceController
+ mCallbacks.imsServiceFeatureCreated(featurePair.slotId, featurePair.featureType, this);
// Send callback to ImsServiceProxy to change supported ImsFeatures including emergency
// MMTEL state.
sendImsFeatureCreatedCallback(featurePair.slotId, featurePair.featureType);
@@ -723,6 +732,8 @@
Log.w(LOG_TAG, "removeImsServiceFeature called with null values.");
return;
}
+ // Signal ImsResolver to change supported ImsFeatures for this ImsServiceController
+ mCallbacks.imsServiceFeatureRemoved(featurePair.slotId, featurePair.featureType, this);
if (featurePair.featureType != ImsFeature.FEATURE_EMERGENCY_MMTEL) {
ImsFeatureStatusCallback callbackToRemove = mFeatureStatusCallbacks.stream().filter(c ->
c.mSlotId == featurePair.slotId && c.mFeatureType == featurePair.featureType)
@@ -732,8 +743,6 @@
mFeatureStatusCallbacks.remove(callbackToRemove);
}
removeImsFeatureBinder(featurePair.slotId, featurePair.featureType);
- // Signal ImsResolver to change supported ImsFeatures for this ImsServiceController
- mCallbacks.imsServiceFeatureRemoved(featurePair.slotId, featurePair.featureType, this);
try {
removeImsFeature(featurePair.slotId, featurePair.featureType,
(callbackToRemove != null ? callbackToRemove.getCallback() : null));
diff --git a/src/java/com/android/internal/telephony/ims/ImsServiceControllerCompat.java b/src/java/com/android/internal/telephony/ims/ImsServiceControllerCompat.java
index 11cae27..835d780 100644
--- a/src/java/com/android/internal/telephony/ims/ImsServiceControllerCompat.java
+++ b/src/java/com/android/internal/telephony/ims/ImsServiceControllerCompat.java
@@ -171,7 +171,7 @@
return mServiceController != null;
}
- protected MmTelInterfaceAdapter getInterface(int slotId, IImsFeatureStatusCallback c)
+ private MmTelInterfaceAdapter getInterface(int slotId, IImsFeatureStatusCallback c)
throws RemoteException {
IImsMMTelFeature feature = mServiceController.createMMTelFeature(slotId, c);
if (feature == null) {
diff --git a/src/java/com/android/internal/telephony/ims/ImsServiceControllerStaticCompat.java b/src/java/com/android/internal/telephony/ims/ImsServiceControllerStaticCompat.java
deleted file mode 100644
index bd033db..0000000
--- a/src/java/com/android/internal/telephony/ims/ImsServiceControllerStaticCompat.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (C) 2018 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.internal.telephony.ims;
-
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.util.Log;
-
-import com.android.ims.internal.IImsFeatureStatusCallback;
-import com.android.ims.internal.IImsService;
-
-/**
- * A compat layer for communicating with older devices that still used the ServiceManager to get
- * the ImsService.
- */
-
-public class ImsServiceControllerStaticCompat extends ImsServiceControllerCompat {
-
- private static final String TAG = "ImsSCStaticCompat";
-
- private static final String IMS_SERVICE_NAME = "ims";
-
- private class ImsDeathRecipient implements IBinder.DeathRecipient {
-
- private ComponentName mComponentName;
- private ServiceConnection mServiceConnection;
-
- ImsDeathRecipient(ComponentName name, ServiceConnection conn) {
- mComponentName = name;
- mServiceConnection = conn;
- }
-
- @Override
- public void binderDied() {
- Log.e(TAG, "ImsService(" + mComponentName + ") died. Restarting...");
- // This is hacky... ImsServiceController uses the traditional service binding procedure,
- // so we have to emulate it when using a persistent service.
- mServiceConnection.onBindingDied(mComponentName);
- }
- }
-
- private IImsService mImsServiceCompat = null;
- private ImsDeathRecipient mImsDeathRecipient = null;
-
- public ImsServiceControllerStaticCompat(Context context, ComponentName componentName,
- ImsServiceController.ImsServiceControllerCallbacks callbacks) {
- super(context, componentName, callbacks);
- }
-
- @Override
- public boolean startBindToService(Intent intent, ImsServiceConnection connection, int flags) {
- IBinder binder = ServiceManager.checkService(IMS_SERVICE_NAME);
-
- if (binder == null) {
- return false;
- }
- // This is a little hacky, but we are going to call the onServiceConnected to "pretend" like
- // bindService has completed here, which will pass the binder to setServiceController and
- // set up all supporting structures.
- ComponentName name = new ComponentName(mContext, ImsServiceControllerStaticCompat.class);
- connection.onServiceConnected(name, binder);
- try {
- mImsDeathRecipient = new ImsDeathRecipient(name, connection);
- binder.linkToDeath(mImsDeathRecipient, 0);
- } catch (RemoteException e) {
- // The binder connection is already dead.. signal to the ImsServiceController to retry.
- mImsDeathRecipient.binderDied();
- mImsDeathRecipient = null;
- }
- return true;
- }
-
- @Override
- protected void setServiceController(IBinder serviceController) {
- if (serviceController == null) {
- // The service controller has been set to null, meaning it has been unbound or died.
- // Unlink if needed.
- if (mImsServiceCompat != null) {
- mImsServiceCompat.asBinder().unlinkToDeath(mImsDeathRecipient, 0);
- }
- mImsDeathRecipient = null;
- }
- mImsServiceCompat = IImsService.Stub.asInterface(serviceController);
- }
-
- @Override
- // used for add/remove features and cleanup in ImsServiceController.
- protected boolean isServiceControllerAvailable() {
- return mImsServiceCompat != null;
- }
-
- @Override
- protected MmTelInterfaceAdapter getInterface(int slotId, IImsFeatureStatusCallback c) {
- if (mImsServiceCompat == null) {
- Log.w(TAG, "getInterface: IImsService returned null.");
- return null;
- }
- return new ImsServiceInterfaceAdapter(slotId, mImsServiceCompat.asBinder());
- }
-}
diff --git a/src/java/com/android/internal/telephony/ims/ImsServiceInterfaceAdapter.java b/src/java/com/android/internal/telephony/ims/ImsServiceInterfaceAdapter.java
deleted file mode 100644
index f554e6f..0000000
--- a/src/java/com/android/internal/telephony/ims/ImsServiceInterfaceAdapter.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (C) 2018 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.internal.telephony.ims;
-
-import android.app.PendingIntent;
-import android.os.IBinder;
-import android.os.Message;
-import android.os.RemoteException;
-import android.telephony.ims.ImsCallProfile;
-import android.telephony.ims.compat.feature.ImsFeature;
-
-import com.android.ims.internal.IImsCallSession;
-import com.android.ims.internal.IImsConfig;
-import com.android.ims.internal.IImsEcbm;
-import com.android.ims.internal.IImsMultiEndpoint;
-import com.android.ims.internal.IImsRegistrationListener;
-import com.android.ims.internal.IImsService;
-import com.android.ims.internal.IImsUt;
-
-/**
- * Compatibility layer for IImsService implementations of IMS. Converts "generic" MMTel commands
- * to implementation.
- */
-
-public class ImsServiceInterfaceAdapter extends MmTelInterfaceAdapter {
-
- private static final int SERVICE_ID = ImsFeature.MMTEL;
-
- public ImsServiceInterfaceAdapter(int slotId, IBinder binder) {
- super(slotId, binder);
- }
-
- public int startSession(PendingIntent incomingCallIntent, IImsRegistrationListener listener)
- throws RemoteException {
- return getInterface().open(mSlotId, ImsFeature.MMTEL, incomingCallIntent, listener);
- }
-
- public void endSession(int sessionId) throws RemoteException {
- getInterface().close(sessionId);
- }
-
- public boolean isConnected(int callSessionType, int callType) throws RemoteException {
- return getInterface().isConnected(SERVICE_ID, callSessionType, callType);
- }
-
- public boolean isOpened() throws RemoteException {
- return getInterface().isOpened(SERVICE_ID);
- }
-
- public int getFeatureState() throws RemoteException {
- return ImsFeature.STATE_READY;
- }
-
- public void addRegistrationListener(IImsRegistrationListener listener) throws RemoteException {
- getInterface().addRegistrationListener(mSlotId, ImsFeature.MMTEL, listener);
- }
-
- public void removeRegistrationListener(IImsRegistrationListener listener)
- throws RemoteException {
- // Not Implemented in the old ImsService. If the registration listener becomes invalid, the
- // ImsService will remove it.
- }
-
- public ImsCallProfile createCallProfile(int sessionId, int callSessionType, int callType)
- throws RemoteException {
- return getInterface().createCallProfile(sessionId, callSessionType, callType);
- }
-
- public IImsCallSession createCallSession(int sessionId, ImsCallProfile profile)
- throws RemoteException {
- return getInterface().createCallSession(sessionId, profile, null);
- }
-
- public IImsCallSession getPendingCallSession(int sessionId, String callId)
- throws RemoteException {
- return getInterface().getPendingCallSession(sessionId, callId);
- }
-
- public IImsUt getUtInterface() throws RemoteException {
- return getInterface().getUtInterface(SERVICE_ID);
- }
-
- public IImsConfig getConfigInterface() throws RemoteException {
- return getInterface().getConfigInterface(mSlotId);
- }
-
- public void turnOnIms() throws RemoteException {
- getInterface().turnOnIms(mSlotId);
- }
-
- public void turnOffIms() throws RemoteException {
- getInterface().turnOffIms(mSlotId);
- }
-
- public IImsEcbm getEcbmInterface() throws RemoteException {
- return getInterface().getEcbmInterface(SERVICE_ID);
- }
-
- public void setUiTTYMode(int uiTtyMode, Message onComplete) throws RemoteException {
- getInterface().setUiTTYMode(SERVICE_ID, uiTtyMode, onComplete);
- }
-
- public IImsMultiEndpoint getMultiEndpointInterface() throws RemoteException {
- return getInterface().getMultiEndpointInterface(SERVICE_ID);
- }
-
- private IImsService getInterface() throws RemoteException {
- IImsService feature = IImsService.Stub.asInterface(mBinder);
- if (feature == null) {
- throw new RemoteException("Binder not Available");
- }
- return feature;
- }
-}
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhone.java b/src/java/com/android/internal/telephony/imsphone/ImsPhone.java
index 7f2e70d..d1adee5 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhone.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhone.java
@@ -681,8 +681,18 @@
if (getRingingCall().getState() != ImsPhoneCall.State.IDLE) {
if (DBG) logd("MmiCode 2: accept ringing call");
mCT.acceptCall(ImsCallProfile.CALL_TYPE_VOICE);
- } else {
- if (DBG) logd("MmiCode 2: holdActiveCall");
+ } else if (getBackgroundCall().getState() == ImsPhoneCall.State.HOLDING) {
+ // If there's an active ongoing call as well, hold it and the background one
+ // should automatically unhold. Otherwise just unhold the background call.
+ if (getForegroundCall().getState() != ImsPhoneCall.State.IDLE) {
+ if (DBG) logd("MmiCode 2: switch holding and active");
+ mCT.holdActiveCall();
+ } else {
+ if (DBG) logd("MmiCode 2: unhold held call");
+ mCT.unholdHeldCall();
+ }
+ } else if (getForegroundCall().getState() != ImsPhoneCall.State.IDLE) {
+ if (DBG) logd("MmiCode 2: hold active call");
mCT.holdActiveCall();
}
} catch (CallStateException e) {
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
index 0fbc3d4..34b4f3b 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
@@ -1345,7 +1345,7 @@
/**
* Unhold the currently held call.
*/
- void unholdHeldCall() throws CallStateException {
+ public void unholdHeldCall() throws CallStateException {
ImsCall imsCall = mBackgroundCall.getImsCall();
if (mHoldSwitchingState == HoldSwapState.PENDING_SINGLE_CALL_UNHOLD
|| mHoldSwitchingState == HoldSwapState.SWAPPING_ACTIVE_AND_HELD) {
@@ -3252,6 +3252,14 @@
@Override
public void onProvisioningIntChanged(int item, int value) {
sendConfigChangedIntent(item, Integer.toString(value));
+ if ((mImsManager != null)
+ && (item == ImsConfig.ConfigConstants.VOICE_OVER_WIFI_SETTING_ENABLED
+ || item == ImsConfig.ConfigConstants.VLT_SETTING_ENABLED
+ || item == ImsConfig.ConfigConstants.LVC_SETTING_ENABLED)) {
+ // Update Ims Service state to make sure updated provisioning values take effect
+ // immediately.
+ mImsManager.updateImsServiceConfig(true);
+ }
}
@Override
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCommandInterface.java b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCommandInterface.java
index 0eba486..28143f4 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCommandInterface.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCommandInterface.java
@@ -23,6 +23,7 @@
import android.os.Message;
import android.telephony.ImsiEncryptionInfo;
import android.telephony.NetworkScanRequest;
+import android.telephony.SignalThresholdInfo;
import android.telephony.data.DataProfile;
import android.telephony.emergency.EmergencyNumber;
@@ -635,8 +636,8 @@
}
@Override
- public void setSignalStrengthReportingCriteria(int hysteresisMs, int hysteresisDb,
- int[] thresholdsDbm, int ran, Message result) {
+ public void setSignalStrengthReportingCriteria(
+ SignalThresholdInfo signalThresholdInfo, int ran, Message result) {
}
@Override
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhoneConnection.java b/src/java/com/android/internal/telephony/imsphone/ImsPhoneConnection.java
index c7dbf4e..e1216c2 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhoneConnection.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhoneConnection.java
@@ -132,9 +132,6 @@
*/
private boolean mIsLocalVideoCapable = true;
- // Store the current audio codec
- private int mAudioCodec = ImsStreamMediaProfile.AUDIO_QUALITY_NONE;
-
//***** Event Constants
private static final int EVENT_DTMF_DONE = 1;
private static final int EVENT_PAUSE_DONE = 2;
diff --git a/src/java/com/android/internal/telephony/nitz/NewNitzStateMachineImpl.java b/src/java/com/android/internal/telephony/nitz/NewNitzStateMachineImpl.java
index 27d23e3..ce6d1ce 100644
--- a/src/java/com/android/internal/telephony/nitz/NewNitzStateMachineImpl.java
+++ b/src/java/com/android/internal/telephony/nitz/NewNitzStateMachineImpl.java
@@ -312,20 +312,20 @@
try {
Objects.requireNonNull(reason);
- PhoneTimeSuggestion timeSuggestion = new PhoneTimeSuggestion(mPhoneId);
+ PhoneTimeSuggestion.Builder builder = new PhoneTimeSuggestion.Builder(mPhoneId);
if (nitzSignal == null) {
- timeSuggestion.addDebugInfo("Clearing time zone suggestion"
+ builder.addDebugInfo("Clearing time zone suggestion"
+ " reason=" + reason);
} else {
TimestampedValue<Long> newNitzTime = new TimestampedValue<>(
nitzSignal.getReferenceTimeMillis(),
nitzSignal.getValue().getCurrentTimeInMillis());
- timeSuggestion.setUtcTime(newNitzTime);
- timeSuggestion.addDebugInfo("Sending new time zone suggestion"
+ builder.setUtcTime(newNitzTime);
+ builder.addDebugInfo("Sending new time zone suggestion"
+ " nitzSignal=" + nitzSignal
+ ", reason=" + reason);
}
- mNewTimeServiceHelper.suggestDeviceTime(timeSuggestion);
+ mNewTimeServiceHelper.suggestDeviceTime(builder.build());
} catch (RuntimeException ex) {
Rlog.e(LOG_TAG, "doTimeDetection: Exception thrown"
+ " mPhoneId=" + mPhoneId
diff --git a/src/java/com/android/internal/telephony/nitz/NewTimeServiceHelperImpl.java b/src/java/com/android/internal/telephony/nitz/NewTimeServiceHelperImpl.java
index 36d38f6..bb0c9cf 100644
--- a/src/java/com/android/internal/telephony/nitz/NewTimeServiceHelperImpl.java
+++ b/src/java/com/android/internal/telephony/nitz/NewTimeServiceHelperImpl.java
@@ -42,8 +42,8 @@
private final TimeDetector mTimeDetector;
private final TimeZoneDetector mTimeZoneDetector;
- private final LocalLog mTimeZoneLog = new LocalLog(30);
- private final LocalLog mTimeLog = new LocalLog(30);
+ private final LocalLog mTimeZoneLog = new LocalLog(30, false /* mUseLocalTimestamps */);
+ private final LocalLog mTimeLog = new LocalLog(30, false /* mUseLocalTimestamps */);
/**
* Records the last time zone suggestion made. Used to avoid sending duplicate suggestions to
diff --git a/src/java/com/android/internal/telephony/sip/SipCommandInterface.java b/src/java/com/android/internal/telephony/sip/SipCommandInterface.java
index d904caf..4762979 100644
--- a/src/java/com/android/internal/telephony/sip/SipCommandInterface.java
+++ b/src/java/com/android/internal/telephony/sip/SipCommandInterface.java
@@ -23,6 +23,7 @@
import android.os.Message;
import android.telephony.ImsiEncryptionInfo;
import android.telephony.NetworkScanRequest;
+import android.telephony.SignalThresholdInfo;
import android.telephony.data.DataProfile;
import android.telephony.emergency.EmergencyNumber;
@@ -635,8 +636,8 @@
}
@Override
- public void setSignalStrengthReportingCriteria(int hysteresisMs, int hysteresisDb,
- int[] thresholdsDbm, int ran, Message result) {
+ public void setSignalStrengthReportingCriteria(
+ SignalThresholdInfo signalThresholdInfo, int ran, Message result) {
}
@Override
diff --git a/src/java/com/android/internal/telephony/uicc/UiccCarrierPrivilegeRules.java b/src/java/com/android/internal/telephony/uicc/UiccCarrierPrivilegeRules.java
index 2585e26..114447f 100644
--- a/src/java/com/android/internal/telephony/uicc/UiccCarrierPrivilegeRules.java
+++ b/src/java/com/android/internal/telephony/uicc/UiccCarrierPrivilegeRules.java
@@ -114,6 +114,8 @@
// Max number of retries for open logical channel, interval is 10s.
private static final int MAX_RETRY = 1;
private static final int RETRY_INTERVAL_MS = 10000;
+ private static final int STATUS_CODE_CONDITION_NOT_SATISFIED = 0x6985;
+ private static final int STATUS_CODE_APPLET_SELECT_FAILED = 0x6999;
// Used for parsing the data from the UICC.
public static class TLV {
@@ -426,6 +428,30 @@
return null;
}
+ /**
+ * The following three situations could be due to logical channels temporarily unavailable, so
+ * we retry up to MAX_RETRY times, with an interval of RETRY_INTERVAL_MS: 1. MISSING_RESOURCE,
+ * 2. NO_SUCH_ELEMENT and the status code is 6985, 3. INTERNAL_ERR and the status code is 6999.
+ */
+ public static boolean shouldRetry(AsyncResult ar, int retryCount) {
+ if (ar.exception instanceof CommandException && retryCount < MAX_RETRY) {
+ CommandException.Error error = ((CommandException) (ar.exception)).getCommandError();
+ int[] results = (int[]) ar.result;
+ int statusCode = 0;
+ if (results.length == 3) {
+ byte[] bytes = new byte[]{(byte) results[1], (byte) results[2]};
+ statusCode = Integer.parseInt(IccUtils.bytesToHexString(bytes), 16);
+ log("status code: " + String.valueOf(statusCode));
+ }
+ return (error == CommandException.Error.MISSING_RESOURCE)
+ || (error == CommandException.Error.NO_SUCH_ELEMENT
+ && statusCode == STATUS_CODE_CONDITION_NOT_SATISFIED)
+ || (error == CommandException.Error.INTERNAL_ERR
+ && statusCode == STATUS_CODE_APPLET_SELECT_FAILED);
+ }
+ return false;
+ }
+
@Override
public void handleMessage(Message msg) {
AsyncResult ar;
@@ -442,11 +468,8 @@
DATA, obtainMessage(EVENT_TRANSMIT_LOGICAL_CHANNEL_DONE, mChannelId,
mAIDInUse));
} else {
- // MISSING_RESOURCE could be due to logical channels temporarily unavailable,
- // so we retry up to MAX_RETRY times, with an interval of RETRY_INTERVAL_MS.
- if (ar.exception instanceof CommandException && mRetryCount < MAX_RETRY
- && ((CommandException) (ar.exception)).getCommandError()
- == CommandException.Error.MISSING_RESOURCE) {
+ if (shouldRetry(ar, mRetryCount)) {
+ log("should retry");
mRetryCount++;
removeCallbacks(mRetryRunnable);
postDelayed(mRetryRunnable, RETRY_INTERVAL_MS);
@@ -745,4 +768,4 @@
return "UNKNOWN";
}
}
-}
+}
\ No newline at end of file
diff --git a/tests/telephonytests/src/com/android/internal/telephony/CarrierServiceStateTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/CarrierServiceStateTrackerTest.java
index bf36e73..9736f47 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/CarrierServiceStateTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/CarrierServiceStateTrackerTest.java
@@ -187,7 +187,6 @@
notificationTypeMap.put(CarrierServiceStateTracker.NOTIFICATION_EMERGENCY_NETWORK,
spyEmergencyNetworkNotification);
Notification.Builder mNotificationBuilder = new Notification.Builder(mContext);
- doReturn(ServiceState.STATE_OUT_OF_SERVICE).when(mSST.mSS).getVoiceRegState();
doReturn(mNotificationBuilder).when(spyEmergencyNetworkNotification)
.getNotificationBuilder();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/CellSignalStrengthNrTest.java b/tests/telephonytests/src/com/android/internal/telephony/CellSignalStrengthNrTest.java
index d967bf6..f0a22ff 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/CellSignalStrengthNrTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/CellSignalStrengthNrTest.java
@@ -109,11 +109,9 @@
CSIRSRP, CSIRSRQ, CSISINR, ssRsrp, SSRSRQ, SSSINR);
// THEN the signal level is valid
- assertThat(css.getLevel()).isAnyOf(
- CellSignalStrength.SIGNAL_STRENGTH_GREAT,
- CellSignalStrength.SIGNAL_STRENGTH_GOOD,
- CellSignalStrength.SIGNAL_STRENGTH_MODERATE,
- CellSignalStrength.SIGNAL_STRENGTH_POOR);
+ assertThat(css.getLevel()).isIn(Range.range(
+ CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN, BoundType.CLOSED,
+ CellSignalStrength.SIGNAL_STRENGTH_GREAT, BoundType.CLOSED));
}
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/NitzStateMachineTestSupport.java b/tests/telephonytests/src/com/android/internal/telephony/NitzStateMachineTestSupport.java
index b9215ed..e4db62d 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/NitzStateMachineTestSupport.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/NitzStateMachineTestSupport.java
@@ -278,17 +278,17 @@
}
public static PhoneTimeSuggestion createEmptyTimeSuggestion(int phoneId) {
- PhoneTimeSuggestion timeSuggestion = new PhoneTimeSuggestion(phoneId);
- timeSuggestion.addDebugInfo("Test");
- return timeSuggestion;
+ return new PhoneTimeSuggestion.Builder(phoneId)
+ .addDebugInfo("Test")
+ .build();
}
public static PhoneTimeSuggestion createTimeSuggestionFromNitzSignal(
int phoneId, TimestampedValue<NitzData> nitzSignal) {
- PhoneTimeSuggestion timeSuggestion = new PhoneTimeSuggestion(phoneId);
- timeSuggestion.setUtcTime(createTimeSignalFromNitzSignal(nitzSignal));
- timeSuggestion.addDebugInfo("Test");
- return timeSuggestion;
+ return new PhoneTimeSuggestion.Builder(phoneId)
+ .setUtcTime(createTimeSignalFromNitzSignal(nitzSignal))
+ .addDebugInfo("Test")
+ .build();
}
public static TimestampedValue<Long> createTimeSignalFromNitzSignal(
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java
index cb6a5e6..36850a7 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java
@@ -302,6 +302,27 @@
com.android.internal.R.array.config_display_no_service_when_sim_unready,
new String[0]);
+ mBundle.putIntArray(CarrierConfigManager.KEY_5G_NR_SSRSRP_THRESHOLDS_INT_ARRAY,
+ new int[] {
+ -125, /* SIGNAL_STRENGTH_POOR */
+ -115, /* SIGNAL_STRENGTH_MODERATE */
+ -105, /* SIGNAL_STRENGTH_GOOD */
+ -95, /* SIGNAL_STRENGTH_GREAT */
+ });
+ mBundle.putIntArray(CarrierConfigManager.KEY_5G_NR_SSRSRQ_THRESHOLDS_INT_ARRAY,
+ new int[] {
+ -14, /* SIGNAL_STRENGTH_POOR */
+ -12, /* SIGNAL_STRENGTH_MODERATE */
+ -10, /* SIGNAL_STRENGTH_GOOD */
+ -8 /* SIGNAL_STRENGTH_GREAT */
+ });
+ mBundle.putIntArray(CarrierConfigManager.KEY_5G_NR_SSSINR_THRESHOLDS_INT_ARRAY,
+ new int[] {
+ -8, /* SIGNAL_STRENGTH_POOR */
+ 0, /* SIGNAL_STRENGTH_MODERATE */
+ 8, /* SIGNAL_STRENGTH_GOOD */
+ 16 /* SIGNAL_STRENGTH_GREAT */
+ });
logd("ServiceStateTrackerTest -Setup!");
}
@@ -682,6 +703,105 @@
}
@Test
+ public void test5gNrSignalStrengthReportingCriteria_UseSsRsrp() {
+ SignalStrength ss = new SignalStrength(
+ new CellSignalStrengthCdma(),
+ new CellSignalStrengthGsm(),
+ new CellSignalStrengthWcdma(),
+ new CellSignalStrengthTdscdma(),
+ new CellSignalStrengthLte(),
+ new CellSignalStrengthNr(
+ -139, /** csiRsrp NONE */
+ -20, /** csiRsrq NONE */
+ -23, /** CsiSinr NONE */
+ -44, /** SsRsrp SIGNAL_STRENGTH_GREAT */
+ -20, /** SsRsrq NONE */
+ -23) /** SsSinr NONE */
+ );
+
+ // SSRSRP = 1 << 0
+ mBundle.putInt(CarrierConfigManager.KEY_PARAMETERS_USE_FOR_5G_NR_SIGNAL_BAR_INT,
+ CellSignalStrengthNr.USE_SSRSRP);
+ sendCarrierConfigUpdate();
+ mSimulatedCommands.setSignalStrength(ss);
+ mSimulatedCommands.notifySignalStrength();
+ waitForLastHandlerAction(mSSTTestHandler.getThreadHandler());
+ assertEquals(CellSignalStrength.SIGNAL_STRENGTH_GREAT, sst.getSignalStrength().getLevel());
+ }
+
+ @Test
+ public void test5gNrSignalStrengthReportingCriteria_UseSsRsrpAndSsRsrq() {
+ SignalStrength ss = new SignalStrength(
+ new CellSignalStrengthCdma(),
+ new CellSignalStrengthGsm(),
+ new CellSignalStrengthWcdma(),
+ new CellSignalStrengthTdscdma(),
+ new CellSignalStrengthLte(),
+ new CellSignalStrengthNr(
+ -139, /** csiRsrp NONE */
+ -20, /** csiRsrq NONE */
+ -23, /** CsiSinr NONE */
+ -44, /** SsRsrp SIGNAL_STRENGTH_GREAT */
+ -20, /** SsRsrq NONE */
+ -23) /** SsSinr NONE */
+ );
+
+ // SSRSRP = 1 << 0 | SSSINR = 1 << 2
+ mBundle.putInt(CarrierConfigManager.KEY_PARAMETERS_USE_FOR_5G_NR_SIGNAL_BAR_INT,
+ CellSignalStrengthNr.USE_SSRSRP | CellSignalStrengthNr.USE_SSRSRQ);
+ sendCarrierConfigUpdate();
+ mSimulatedCommands.setSignalStrength(ss);
+ mSimulatedCommands.notifySignalStrength();
+ waitForLastHandlerAction(mSSTTestHandler.getThreadHandler());
+ assertEquals(CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN,
+ sst.getSignalStrength().getLevel());
+ }
+
+ @Test
+ public void test5gNrSignalStrengthReportingCriteria_ConfiguredThresholds() {
+ SignalStrength ss = new SignalStrength(
+ new CellSignalStrengthCdma(),
+ new CellSignalStrengthGsm(),
+ new CellSignalStrengthWcdma(),
+ new CellSignalStrengthTdscdma(),
+ new CellSignalStrengthLte(),
+ new CellSignalStrengthNr(
+ -139, /** csiRsrp NONE */
+ -20, /** csiRsrq NONE */
+ -23, /** CsiSinr NONE */
+ -44, /** SsRsrp SIGNAL_STRENGTH_GREAT */
+ -20, /** SsRsrq NONE */
+ -23) /** SsSinr NONE */
+ );
+
+ // SSRSRP = 1 << 0
+ mBundle.putInt(CarrierConfigManager.KEY_PARAMETERS_USE_FOR_5G_NR_SIGNAL_BAR_INT,
+ CellSignalStrengthNr.USE_SSRSRP);
+ sendCarrierConfigUpdate();
+ mSimulatedCommands.setSignalStrength(ss);
+ mSimulatedCommands.notifySignalStrength();
+ waitForLastHandlerAction(mSSTTestHandler.getThreadHandler());
+ assertEquals(CellSignalStrength.SIGNAL_STRENGTH_GREAT, sst.getSignalStrength().getLevel());
+
+ int[] nrSsRsrpThresholds = {
+ -45, // SIGNAL_STRENGTH_POOR
+ -40, // SIGNAL_STRENGTH_MODERATE
+ -37, // SIGNAL_STRENGTH_GOOD
+ -34, // SIGNAL_STRENGTH_GREAT
+ };
+ mBundle.putIntArray(CarrierConfigManager.KEY_5G_NR_SSRSRP_THRESHOLDS_INT_ARRAY,
+ nrSsRsrpThresholds);
+ mBundle.putInt(CarrierConfigManager.KEY_PARAMETERS_USE_FOR_5G_NR_SIGNAL_BAR_INT,
+ CellSignalStrengthNr.USE_SSRSRP);
+ sendCarrierConfigUpdate();
+ mSimulatedCommands.setSignalStrength(ss);
+ mSimulatedCommands.notifySignalStrength();
+ waitForLastHandlerAction(mSSTTestHandler.getThreadHandler());
+ assertEquals(CellSignalStrength.SIGNAL_STRENGTH_POOR,
+ sst.getSignalStrength().getLevel());
+ }
+
+ @Test
public void testWcdmaSignalStrengthReportingCriteria() {
SignalStrength ss = new SignalStrength(
new CellSignalStrengthCdma(),
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SignalThresholdInfoTest.java b/tests/telephonytests/src/com/android/internal/telephony/SignalThresholdInfoTest.java
new file mode 100644
index 0000000..1574a06
--- /dev/null
+++ b/tests/telephonytests/src/com/android/internal/telephony/SignalThresholdInfoTest.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2019 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.internal.telephony;
+
+import android.telephony.SignalThresholdInfo;
+
+import junit.framework.TestCase;
+
+import java.util.Arrays;
+
+public class SignalThresholdInfoTest extends TestCase {
+ private static final int HYSTERESIS_DB = 2;
+ private static final int HYSTERESIS_MS = 30;
+ private static final int[] SSRSRP_THRESHOLDS = new int[] {-30, 10, 45, 130};
+
+ public void testSignalThresholdInfo() throws Exception {
+ SignalThresholdInfo signalThresholdInfo = new SignalThresholdInfo(
+ SignalThresholdInfo.SIGNAL_SSRSRP,
+ HYSTERESIS_MS,
+ HYSTERESIS_DB,
+ SSRSRP_THRESHOLDS,
+ false);
+
+ assertEquals(SignalThresholdInfo.SIGNAL_SSRSRP,
+ signalThresholdInfo.getSignalMeasurement());
+ assertEquals(HYSTERESIS_MS, signalThresholdInfo.getHysteresisMs());
+ assertEquals(HYSTERESIS_DB, signalThresholdInfo.getHysteresisDb());
+ assertEquals(Arrays.toString(SSRSRP_THRESHOLDS), Arrays.toString(
+ signalThresholdInfo.getThresholds()));
+ assertFalse(signalThresholdInfo.isEnabled());
+ }
+}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SimulatedCommands.java b/tests/telephonytests/src/com/android/internal/telephony/SimulatedCommands.java
index 261b60e..009f71c 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/SimulatedCommands.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SimulatedCommands.java
@@ -45,6 +45,7 @@
import android.telephony.Rlog;
import android.telephony.ServiceState;
import android.telephony.SignalStrength;
+import android.telephony.SignalThresholdInfo;
import android.telephony.TelephonyManager;
import android.telephony.data.ApnSetting;
import android.telephony.data.DataCallResponse;
@@ -2248,8 +2249,8 @@
}
@Override
- public void setSignalStrengthReportingCriteria(int hysteresisMs, int hysteresisDb,
- int[] thresholdsDbm, int ran, Message result) {
+ public void setSignalStrengthReportingCriteria(SignalThresholdInfo signalThresholdInfo,
+ int ran, Message result) {
}
@Override
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SimulatedCommandsVerifier.java b/tests/telephonytests/src/com/android/internal/telephony/SimulatedCommandsVerifier.java
index f030a40..64b0c38 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/SimulatedCommandsVerifier.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SimulatedCommandsVerifier.java
@@ -22,6 +22,7 @@
import android.os.Message;
import android.telephony.ImsiEncryptionInfo;
import android.telephony.NetworkScanRequest;
+import android.telephony.SignalThresholdInfo;
import android.telephony.TelephonyManager;
import android.telephony.data.DataProfile;
import android.telephony.emergency.EmergencyNumber;
@@ -1393,8 +1394,8 @@
}
@Override
- public void setSignalStrengthReportingCriteria(int hysteresisMs, int hysteresisDb,
- int[] thresholdsDbm, int ran, Message result) {
+ public void setSignalStrengthReportingCriteria(SignalThresholdInfo signalThresholdInfo,
+ int ran, Message result) {
}
@Override
diff --git a/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java b/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java
index 6c2faf0..743fcaf 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java
@@ -661,14 +661,14 @@
@Override
public Bundle call(String method, String arg, Bundle extras) {
switch (method) {
- case BlockedNumberContract.SystemContract.METHOD_SHOULD_SYSTEM_BLOCK_NUMBER:
+ case BlockedNumberContract.METHOD_SHOULD_SYSTEM_BLOCK_NUMBER:
Bundle bundle = new Bundle();
int blockStatus = mBlockedNumbers.contains(arg)
? BlockedNumberContract.STATUS_BLOCKED_IN_LIST
: BlockedNumberContract.STATUS_NOT_BLOCKED;
bundle.putInt(BlockedNumberContract.RES_BLOCK_STATUS, blockStatus);
return bundle;
- case BlockedNumberContract.SystemContract.METHOD_NOTIFY_EMERGENCY_CONTACT:
+ case BlockedNumberContract.METHOD_NOTIFY_EMERGENCY_CONTACT:
mNumEmergencyContactNotifications++;
return new Bundle();
default:
diff --git a/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DataFailCauseTest.java b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DataFailCauseTest.java
index e881cc9..24d9bd6 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DataFailCauseTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DataFailCauseTest.java
@@ -138,9 +138,7 @@
mFailCauseDataList.add(new DcFailCauseData(0x10000, false, false));
mFailCauseDataList.add(new DcFailCauseData(0x10001, true, false));
mFailCauseDataList.add(new DcFailCauseData(0x10002, true, true));
- mFailCauseDataList.add(new DcFailCauseData(0x10003, false, false));
mFailCauseDataList.add(new DcFailCauseData(0x10004, false, false));
- mFailCauseDataList.add(new DcFailCauseData(0x10005, false, false));
CarrierConfigManager configManager = (CarrierConfigManager)
mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ims/ImsResolverTest.java b/tests/telephonytests/src/com/android/internal/telephony/ims/ImsResolverTest.java
index 84e1dce..e1f984f 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ims/ImsResolverTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ims/ImsResolverTest.java
@@ -212,6 +212,8 @@
// Set CarrierConfig default package name and make it available to the package manager
setConfigCarrierString(0, TEST_CARRIER_DEFAULT_NAME.getPackageName());
HashSet<ImsFeatureConfiguration.FeatureSlotPair> features = new HashSet<>();
+ features.add(new ImsFeatureConfiguration.FeatureSlotPair(0,
+ ImsFeature.FEATURE_EMERGENCY_MMTEL));
features.add(new ImsFeatureConfiguration.FeatureSlotPair(0, ImsFeature.FEATURE_MMTEL));
features.add(new ImsFeatureConfiguration.FeatureSlotPair(0, ImsFeature.FEATURE_RCS));
setupPackageQuery(TEST_CARRIER_DEFAULT_NAME, new HashSet<>(), true);
@@ -226,6 +228,34 @@
}
/**
+ * Creates a carrier ImsService that defines FEATURE_EMERGENCY_MMTEL but not FEATURE_MMTEL and
+ * ensure that the controller doesn't set FEATURE_EMERGENCY_MMTEL.
+ */
+ @Test
+ @SmallTest
+ public void testCarrierPackageBindWithEmergencyButNotMmtel() throws RemoteException {
+ setupResolver(1/*numSlots*/);
+ // Set CarrierConfig default package name and make it available to the package manager
+ setConfigCarrierString(0, TEST_CARRIER_DEFAULT_NAME.getPackageName());
+ HashSet<ImsFeatureConfiguration.FeatureSlotPair> features = new HashSet<>();
+ features.add(new ImsFeatureConfiguration.FeatureSlotPair(0,
+ ImsFeature.FEATURE_EMERGENCY_MMTEL));
+ features.add(new ImsFeatureConfiguration.FeatureSlotPair(0, ImsFeature.FEATURE_RCS));
+ setupPackageQuery(TEST_CARRIER_DEFAULT_NAME, new HashSet<>(), true);
+ ImsServiceController controller = setupController();
+
+ startBindCarrierConfigAlreadySet();
+ setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, features, 1);
+
+ // We will not bind with FEATURE_EMERGENCY_MMTEL
+ features.remove(new ImsFeatureConfiguration.FeatureSlotPair(0,
+ ImsFeature.FEATURE_EMERGENCY_MMTEL));
+ verify(controller).bind(features);
+ verify(controller, never()).unbind();
+ assertEquals(TEST_CARRIER_DEFAULT_NAME, controller.getComponentName());
+ }
+
+ /**
* Creates a carrier ImsService that does not report FEATURE_EMERGENCY_MMTEL and then update the
* ImsService to define it. Ensure that the controller sets this capability once enabled.
*/
@@ -313,6 +343,37 @@
}
/**
+ * Test that the ImsService corresponding to the default device ImsService package name is
+ * bound to only RCS if METADATA_EMERGENCY_MMTEL_FEATURE but not METADATA_MMTEL_FEATURE.
+ */
+ @Test
+ @SmallTest
+ public void testDevicePackageInvalidMmTelBind() throws RemoteException {
+ setupResolver(1/*numSlots*/);
+ List<ResolveInfo> info = new ArrayList<>();
+ Set<String> features = new HashSet<>();
+ features.add(ImsResolver.METADATA_EMERGENCY_MMTEL_FEATURE);
+ features.add(ImsResolver.METADATA_RCS_FEATURE);
+ // Use device default package, which will load the ImsService that the device provides
+ info.add(getResolveInfo(TEST_DEVICE_DEFAULT_NAME, features, true));
+ info.add(getResolveInfo(TEST_CARRIER_DEFAULT_NAME, new HashSet<>(), true));
+ setupPackageQuery(info);
+ ImsServiceController controller = setupController();
+
+
+ startBindNoCarrierConfig(1);
+ mLooper.processAllMessages();
+
+ // There is no carrier override set, so make sure that the ImsServiceController binds
+ // to all SIMs.
+ HashSet<ImsFeatureConfiguration.FeatureSlotPair> featureSet = convertToHashSet(features, 0);
+ verify(controller).bind(featureSet);
+ verify(controller, never()).unbind();
+ verify(mMockQueryManager, never()).startQuery(any(), any());
+ assertEquals(TEST_DEVICE_DEFAULT_NAME, controller.getComponentName());
+ }
+
+ /**
* Test that when a device and carrier override package are set, both ImsServices are bound.
* Verify that the carrier ImsService features are created and the device default features
* are created for all features that are not covered by the carrier ImsService.
@@ -484,7 +545,9 @@
// remove carrier overrides for slot 0
newDeviceFeatureSet.removeAll(carrierFeatures);
verify(deviceController).changeImsServiceFeatures(newDeviceFeatureSet);
- verify(carrierController, never()).changeImsServiceFeatures(any());
+ // features should be the same as before, ImsServiceController will disregard change if it
+ // is the same feature set anyway.
+ verify(carrierController).changeImsServiceFeatures(carrierFeatures);
}
/**
@@ -941,7 +1004,7 @@
}
mTestImsResolver = new ImsResolver(mMockContext, TEST_DEVICE_DEFAULT_NAME.getPackageName(),
- numSlots, true);
+ numSlots);
try {
mLooper = new TestableLooper(mTestImsResolver.getHandler().getLooper());
} catch (Exception e) {
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ims/ImsServiceControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/ims/ImsServiceControllerTest.java
index 85a83ce..ff17216 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ims/ImsServiceControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ims/ImsServiceControllerTest.java
@@ -38,6 +38,7 @@
import android.os.RemoteException;
import android.telephony.ims.ImsService;
import android.telephony.ims.aidl.IImsServiceController;
+import android.telephony.ims.feature.ImsFeature;
import android.telephony.ims.stub.ImsFeatureConfiguration;
import android.test.suitebuilder.annotation.SmallTest;
@@ -60,6 +61,9 @@
@RunWith(AndroidJUnit4.class)
public class ImsServiceControllerTest extends ImsTestBase {
+ private static final int SLOT_0 = 0;
+ private static final int SLOT_1 = 1;
+
private static final ImsServiceController.RebindRetry REBIND_RETRY =
new ImsServiceController.RebindRetry() {
@Override
@@ -110,10 +114,10 @@
@Test
public void testBindService() {
HashSet<ImsFeatureConfiguration.FeatureSlotPair> testFeatures = new HashSet<>();
- // Slot 1, MMTel
- testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(1, 1));
- // Slot 1, RCS
- testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(1, 2));
+ testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(SLOT_0,
+ ImsFeature.FEATURE_MMTEL));
+ testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(SLOT_0,
+ ImsFeature.FEATURE_RCS));
ArgumentCaptor<Intent> intentCaptor =
ArgumentCaptor.forClass(Intent.class);
@@ -134,8 +138,8 @@
@Test
public void testBindFailureWhenBound() {
HashSet<ImsFeatureConfiguration.FeatureSlotPair> testFeatures = new HashSet<>();
- // Slot 1, MMTel
- testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(1, 1));
+ testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(SLOT_0,
+ ImsFeature.FEATURE_MMTEL));
bindAndConnectService(testFeatures);
// already bound, should return false
@@ -152,21 +156,21 @@
@Test
public void testBindServiceAndConnected() throws RemoteException {
HashSet<ImsFeatureConfiguration.FeatureSlotPair> testFeatures = new HashSet<>();
- // Slot 1, MMTel
- testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(1, 1));
- // Slot 1, RCS
- testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(1, 2));
+ testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(SLOT_0,
+ ImsFeature.FEATURE_MMTEL));
+ testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(SLOT_0,
+ ImsFeature.FEATURE_RCS));
bindAndConnectService(testFeatures);
- verify(mMockServiceControllerBinder).createMmTelFeature(eq(1), any());
- verify(mMockServiceControllerBinder).createRcsFeature(eq(1), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(1), eq(1),
+ verify(mMockServiceControllerBinder).createMmTelFeature(eq(SLOT_0), any());
+ verify(mMockServiceControllerBinder).createRcsFeature(eq(SLOT_0), any());
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_MMTEL),
eq(mTestImsServiceController));
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(1), eq(2),
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_RCS),
eq(mTestImsServiceController));
- verify(mMockProxyCallbacks).imsFeatureCreated(eq(1), eq(1));
- verify(mMockProxyCallbacks).imsFeatureCreated(eq(1), eq(2));
+ verify(mMockProxyCallbacks).imsFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_MMTEL));
+ verify(mMockProxyCallbacks).imsFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_RCS));
}
/**
@@ -177,24 +181,56 @@
@Test
public void testBindEmergencyMmTel() throws RemoteException {
HashSet<ImsFeatureConfiguration.FeatureSlotPair> testFeatures = new HashSet<>();
- // Slot 1, Emergency MMTel
- testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(1, 0));
- // Slot 1, MmTel
- testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(1, 1));
+ testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(SLOT_0,
+ ImsFeature.FEATURE_EMERGENCY_MMTEL));
+ testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(SLOT_0,
+ ImsFeature.FEATURE_MMTEL));
bindAndConnectService(testFeatures);
- // We do not want this callback to happen for emergency MMTEL
- verify(mMockServiceControllerBinder, never()).createMmTelFeature(eq(0), any());
- verify(mMockCallbacks, never()).imsServiceFeatureCreated(eq(1), eq(0),
+ verify(mMockServiceControllerBinder).createMmTelFeature(eq(SLOT_0), any());
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_MMTEL),
eq(mTestImsServiceController));
- verify(mMockServiceControllerBinder).createMmTelFeature(eq(1), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(1), eq(1),
- eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0),
+ eq(ImsFeature.FEATURE_EMERGENCY_MMTEL), eq(mTestImsServiceController));
// Make sure this callback happens, which will notify the framework of emergency calling
// availability.
- verify(mMockProxyCallbacks).imsFeatureCreated(eq(1), eq(0));
- verify(mMockProxyCallbacks).imsFeatureCreated(eq(1), eq(1));
+ verify(mMockProxyCallbacks).imsFeatureCreated(eq(SLOT_0),
+ eq(ImsFeature.FEATURE_EMERGENCY_MMTEL));
+ verify(mMockProxyCallbacks).imsFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_MMTEL));
+ }
+
+ /**
+ * Tests to make sure that if EMERGENCY_MMTEL is specified, but not MMTEL, we do not bind to
+ * MMTEL.
+ */
+ @SmallTest
+ @Test
+ public void testBindEmergencyMmTelButNotMmTel() throws RemoteException {
+ HashSet<ImsFeatureConfiguration.FeatureSlotPair> testFeatures = new HashSet<>();
+ testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(SLOT_0,
+ ImsFeature.FEATURE_EMERGENCY_MMTEL));
+ // did not add FEATURE_MMTEL
+ testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(SLOT_0,
+ ImsFeature.FEATURE_RCS));
+
+ bindAndConnectService(testFeatures);
+
+ // Verify no MMTEL or EMERGENCY_MMTEL features are created
+ verify(mMockServiceControllerBinder, never()).createMmTelFeature(eq(SLOT_0), any());
+ verify(mMockCallbacks, never()).imsServiceFeatureCreated(eq(SLOT_0),
+ eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
+ verify(mMockCallbacks, never()).imsServiceFeatureCreated(eq(SLOT_0),
+ eq(ImsFeature.FEATURE_EMERGENCY_MMTEL), eq(mTestImsServiceController));
+ verify(mMockProxyCallbacks, never()).imsFeatureCreated(eq(SLOT_0),
+ eq(ImsFeature.FEATURE_EMERGENCY_MMTEL));
+ verify(mMockProxyCallbacks, never()).imsFeatureCreated(eq(SLOT_0),
+ eq(ImsFeature.FEATURE_MMTEL));
+ // verify RCS feature is created
+ verify(mMockServiceControllerBinder).createRcsFeature(eq(SLOT_0), any());
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_RCS),
+ eq(mTestImsServiceController));
+ verify(mMockProxyCallbacks).imsFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_RCS));
}
/**
@@ -205,10 +241,10 @@
@Test
public void testCallbacksHappenWhenAddedAfterBind() throws RemoteException {
HashSet<ImsFeatureConfiguration.FeatureSlotPair> testFeatures = new HashSet<>();
- // Slot 1, Emergency MMTel
- testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(1, 0));
- // Slot 1, MmTel
- testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(1, 1));
+ testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(SLOT_0,
+ ImsFeature.FEATURE_EMERGENCY_MMTEL));
+ testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(SLOT_0,
+ ImsFeature.FEATURE_MMTEL));
mTestImsServiceController.removeImsServiceFeatureCallbacks();
bindAndConnectService(testFeatures);
@@ -216,8 +252,9 @@
mTestImsServiceController.addImsServiceFeatureCallback(mMockProxyCallbacks);
// Make sure this callback happens for Emergency MMTEL and MMTEL
- verify(mMockProxyCallbacks).imsFeatureCreated(eq(1), eq(0));
- verify(mMockProxyCallbacks).imsFeatureCreated(eq(1), eq(1));
+ verify(mMockProxyCallbacks).imsFeatureCreated(eq(SLOT_0),
+ eq(ImsFeature.FEATURE_EMERGENCY_MMTEL));
+ verify(mMockProxyCallbacks).imsFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_MMTEL));
}
/**
@@ -228,20 +265,20 @@
@Test
public void testBindServiceAndConnectedDisconnected() throws RemoteException {
HashSet<ImsFeatureConfiguration.FeatureSlotPair> testFeatures = new HashSet<>();
- // Slot 1, MMTel
- testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(1, 1));
- // Slot 1, RCS
- testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(1, 2));
+ testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(SLOT_0,
+ ImsFeature.FEATURE_MMTEL));
+ testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(SLOT_0,
+ ImsFeature.FEATURE_RCS));
ServiceConnection conn = bindAndConnectService(testFeatures);
conn.onServiceDisconnected(mTestComponentName);
- verify(mMockCallbacks).imsServiceFeatureRemoved(eq(1), eq(1),
+ verify(mMockCallbacks).imsServiceFeatureRemoved(eq(SLOT_0), eq(ImsFeature.FEATURE_MMTEL),
eq(mTestImsServiceController));
- verify(mMockCallbacks).imsServiceFeatureRemoved(eq(1), eq(2),
+ verify(mMockCallbacks).imsServiceFeatureRemoved(eq(SLOT_0), eq(ImsFeature.FEATURE_RCS),
eq(mTestImsServiceController));
- verify(mMockProxyCallbacks).imsFeatureRemoved(eq(1), eq(1));
- verify(mMockProxyCallbacks).imsFeatureRemoved(eq(1), eq(2));
+ verify(mMockProxyCallbacks).imsFeatureRemoved(eq(SLOT_0), eq(ImsFeature.FEATURE_MMTEL));
+ verify(mMockProxyCallbacks).imsFeatureRemoved(eq(SLOT_0), eq(ImsFeature.FEATURE_RCS));
}
/**
@@ -252,23 +289,25 @@
@Test
public void testBindServiceBindUnbind() throws RemoteException {
HashSet<ImsFeatureConfiguration.FeatureSlotPair> testFeatures = new HashSet<>();
- // Slot 1, MMTel
- testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(1, 1));
- // Slot 1, RCS
- testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(1, 2));
+ testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(SLOT_0,
+ ImsFeature.FEATURE_MMTEL));
+ testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(SLOT_0,
+ ImsFeature.FEATURE_RCS));
ServiceConnection conn = bindAndConnectService(testFeatures);
mTestImsServiceController.unbind();
verify(mMockContext).unbindService(eq(conn));
- verify(mMockServiceControllerBinder).removeImsFeature(eq(1), eq(1), any());
- verify(mMockServiceControllerBinder).removeImsFeature(eq(1), eq(2), any());
- verify(mMockCallbacks).imsServiceFeatureRemoved(eq(1), eq(1),
+ verify(mMockServiceControllerBinder).removeImsFeature(eq(SLOT_0),
+ eq(ImsFeature.FEATURE_MMTEL), any());
+ verify(mMockServiceControllerBinder).removeImsFeature(eq(SLOT_0),
+ eq(ImsFeature.FEATURE_RCS), any());
+ verify(mMockCallbacks).imsServiceFeatureRemoved(eq(SLOT_0), eq(ImsFeature.FEATURE_MMTEL),
eq(mTestImsServiceController));
- verify(mMockCallbacks).imsServiceFeatureRemoved(eq(1), eq(2),
+ verify(mMockCallbacks).imsServiceFeatureRemoved(eq(SLOT_0), eq(ImsFeature.FEATURE_RCS),
eq(mTestImsServiceController));
- verify(mMockProxyCallbacks).imsFeatureRemoved(eq(1), eq(1));
- verify(mMockProxyCallbacks).imsFeatureRemoved(eq(1), eq(2));
+ verify(mMockProxyCallbacks).imsFeatureRemoved(eq(SLOT_0), eq(ImsFeature.FEATURE_MMTEL));
+ verify(mMockProxyCallbacks).imsFeatureRemoved(eq(SLOT_0), eq(ImsFeature.FEATURE_RCS));
}
/**
@@ -278,20 +317,20 @@
@Test
public void testBindServiceAndBinderDied() throws RemoteException {
HashSet<ImsFeatureConfiguration.FeatureSlotPair> testFeatures = new HashSet<>();
- // Slot 1, MMTel
- testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(1, 1));
- // Slot 1, RCS
- testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(1, 2));
+ testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(SLOT_0,
+ ImsFeature.FEATURE_MMTEL));
+ testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(SLOT_0,
+ ImsFeature.FEATURE_RCS));
ServiceConnection conn = bindAndConnectService(testFeatures);
conn.onBindingDied(null /*null*/);
- verify(mMockCallbacks).imsServiceFeatureRemoved(eq(1), eq(1),
+ verify(mMockCallbacks).imsServiceFeatureRemoved(eq(SLOT_0), eq(ImsFeature.FEATURE_MMTEL),
eq(mTestImsServiceController));
- verify(mMockCallbacks).imsServiceFeatureRemoved(eq(1), eq(2),
+ verify(mMockCallbacks).imsServiceFeatureRemoved(eq(SLOT_0), eq(ImsFeature.FEATURE_RCS),
eq(mTestImsServiceController));
- verify(mMockProxyCallbacks).imsFeatureRemoved(eq(1), eq(1));
- verify(mMockProxyCallbacks).imsFeatureRemoved(eq(1), eq(2));
+ verify(mMockProxyCallbacks).imsFeatureRemoved(eq(SLOT_0), eq(ImsFeature.FEATURE_MMTEL));
+ verify(mMockProxyCallbacks).imsFeatureRemoved(eq(SLOT_0), eq(ImsFeature.FEATURE_RCS));
}
/**
@@ -301,10 +340,10 @@
@Test
public void testBindServiceAndReturnedNull() throws RemoteException {
HashSet<ImsFeatureConfiguration.FeatureSlotPair> testFeatures = new HashSet<>();
- // Slot 1, MMTel
- testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(1, 1));
- // Slot 1, RCS
- testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(1, 2));
+ testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(SLOT_0,
+ ImsFeature.FEATURE_MMTEL));
+ testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(SLOT_0,
+ ImsFeature.FEATURE_RCS));
bindAndNullServiceError(testFeatures);
@@ -321,24 +360,85 @@
@Test
public void testBindServiceAndAddFeature() throws RemoteException {
HashSet<ImsFeatureConfiguration.FeatureSlotPair> testFeatures = new HashSet<>();
- // Slot 1, MMTel
- testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(1, 1));
+ testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(SLOT_0,
+ ImsFeature.FEATURE_MMTEL));
bindAndConnectService(testFeatures);
- verify(mMockServiceControllerBinder).createMmTelFeature(eq(1), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(1), eq(1),
+ verify(mMockServiceControllerBinder).createMmTelFeature(eq(SLOT_0), any());
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_MMTEL),
eq(mTestImsServiceController));
- verify(mMockProxyCallbacks).imsFeatureCreated(eq(1), eq(1));
+ verify(mMockProxyCallbacks).imsFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_MMTEL));
// Create a new list with an additional item
HashSet<ImsFeatureConfiguration.FeatureSlotPair> testFeaturesWithAddition = new HashSet<>(
testFeatures);
- testFeaturesWithAddition.add(new ImsFeatureConfiguration.FeatureSlotPair(2, 1));
+ testFeaturesWithAddition.add(new ImsFeatureConfiguration.FeatureSlotPair(SLOT_1,
+ ImsFeature.FEATURE_MMTEL));
mTestImsServiceController.changeImsServiceFeatures(testFeaturesWithAddition);
- verify(mMockServiceControllerBinder).createMmTelFeature(eq(2), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(2), eq(1),
+ verify(mMockServiceControllerBinder).createMmTelFeature(eq(SLOT_1), any());
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_1), eq(ImsFeature.FEATURE_MMTEL),
eq(mTestImsServiceController));
- verify(mMockProxyCallbacks).imsFeatureCreated(eq(2), eq(1));
+ verify(mMockProxyCallbacks).imsFeatureCreated(eq(SLOT_1), eq(ImsFeature.FEATURE_MMTEL));
+ }
+
+ /**
+ * Ensures that the when EMERGENCY_MMTEL_FEATURE is defined but not MMTEL_FEATURE when the
+ * features are changed, we do not bind to MMTEL.
+ */
+ @SmallTest
+ @Test
+ public void testBindServiceAndAddEmergencyButNotMmtel() throws RemoteException {
+ HashSet<ImsFeatureConfiguration.FeatureSlotPair> testFeatures = new HashSet<>();
+ testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(SLOT_0,
+ ImsFeature.FEATURE_RCS));
+ bindAndConnectService(testFeatures);
+ verify(mMockServiceControllerBinder).createRcsFeature(eq(SLOT_0), any());
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_RCS),
+ eq(mTestImsServiceController));
+ verify(mMockProxyCallbacks).imsFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_RCS));
+ // Add FEATURE_EMERGENCY_MMTEL and ensure it doesn't cause MMTEL bind
+ HashSet<ImsFeatureConfiguration.FeatureSlotPair> testFeaturesWithAddition = new HashSet<>(
+ testFeatures);
+ testFeaturesWithAddition.add(new ImsFeatureConfiguration.FeatureSlotPair(SLOT_1,
+ ImsFeature.FEATURE_EMERGENCY_MMTEL));
+
+ mTestImsServiceController.changeImsServiceFeatures(testFeaturesWithAddition);
+
+ verify(mMockServiceControllerBinder, never()).createMmTelFeature(eq(SLOT_1), any());
+ verify(mMockCallbacks, never()).imsServiceFeatureCreated(eq(SLOT_1),
+ eq(ImsFeature.FEATURE_MMTEL),
+ eq(mTestImsServiceController));
+ verify(mMockProxyCallbacks, never()).imsFeatureCreated(eq(SLOT_1),
+ eq(ImsFeature.FEATURE_MMTEL));
+ }
+
+ /**
+ * Ensures ImsServiceController disregards changes to features that result in the same feature
+ * set.
+ */
+ @SmallTest
+ @Test
+ public void testBindServiceCallChangeWithNoNewFeatures() throws RemoteException {
+ HashSet<ImsFeatureConfiguration.FeatureSlotPair> testFeatures = new HashSet<>();
+ testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(SLOT_0,
+ ImsFeature.FEATURE_MMTEL));
+ bindAndConnectService(testFeatures);
+ verify(mMockServiceControllerBinder).createMmTelFeature(eq(SLOT_0), any());
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_MMTEL),
+ eq(mTestImsServiceController));
+ verify(mMockProxyCallbacks).imsFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_MMTEL));
+
+ // Call change with the same features and make sure it is disregarded
+ mTestImsServiceController.changeImsServiceFeatures(testFeatures);
+
+ verify(mMockServiceControllerBinder, times(1)).createMmTelFeature(eq(SLOT_0), any());
+ verify(mMockServiceControllerBinder, never()).removeImsFeature(anyInt(), anyInt(), any());
+ verify(mMockCallbacks, times(1)).imsServiceFeatureCreated(eq(SLOT_0),
+ eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
+ verify(mMockCallbacks, never()).imsServiceFeatureRemoved(anyInt(), anyInt(), any());
+ verify(mMockProxyCallbacks, times(1)).imsFeatureCreated(eq(SLOT_0),
+ eq(ImsFeature.FEATURE_MMTEL));
+ verify(mMockProxyCallbacks, never()).imsFeatureRemoved(anyInt(), anyInt());
}
/**
@@ -348,30 +448,32 @@
@Test
public void testBindServiceAndRemoveFeature() throws RemoteException {
HashSet<ImsFeatureConfiguration.FeatureSlotPair> testFeatures = new HashSet<>();
- // Slot 1, MMTel
- testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(1, 1));
- // Slot 2, MMTel
- testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(2, 1));
+ testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(SLOT_0,
+ ImsFeature.FEATURE_MMTEL));
+ testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(SLOT_1,
+ ImsFeature.FEATURE_MMTEL));
bindAndConnectService(testFeatures);
- verify(mMockServiceControllerBinder).createMmTelFeature(eq(1), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(1), eq(1),
+ verify(mMockServiceControllerBinder).createMmTelFeature(eq(SLOT_0), any());
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_MMTEL),
eq(mTestImsServiceController));
- verify(mMockProxyCallbacks).imsFeatureCreated(eq(1), eq(1));
- verify(mMockServiceControllerBinder).createMmTelFeature(eq(2), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(2), eq(1),
+ verify(mMockProxyCallbacks).imsFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_MMTEL));
+ verify(mMockServiceControllerBinder).createMmTelFeature(eq(SLOT_1), any());
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_1), eq(ImsFeature.FEATURE_MMTEL),
eq(mTestImsServiceController));
- verify(mMockProxyCallbacks).imsFeatureCreated(eq(2), eq(1));
+ verify(mMockProxyCallbacks).imsFeatureCreated(eq(SLOT_1), eq(ImsFeature.FEATURE_MMTEL));
// Create a new list with one less item
HashSet<ImsFeatureConfiguration.FeatureSlotPair> testFeaturesWithSubtraction =
new HashSet<>(testFeatures);
- testFeaturesWithSubtraction.remove(new ImsFeatureConfiguration.FeatureSlotPair(2, 1));
+ testFeaturesWithSubtraction.remove(new ImsFeatureConfiguration.FeatureSlotPair(SLOT_1,
+ ImsFeature.FEATURE_MMTEL));
mTestImsServiceController.changeImsServiceFeatures(testFeaturesWithSubtraction);
- verify(mMockServiceControllerBinder).removeImsFeature(eq(2), eq(1), any());
- verify(mMockCallbacks).imsServiceFeatureRemoved(eq(2), eq(1),
+ verify(mMockServiceControllerBinder).removeImsFeature(eq(SLOT_1),
+ eq(ImsFeature.FEATURE_MMTEL), any());
+ verify(mMockCallbacks).imsServiceFeatureRemoved(eq(SLOT_1), eq(ImsFeature.FEATURE_MMTEL),
eq(mTestImsServiceController));
- verify(mMockProxyCallbacks).imsFeatureRemoved(eq(2), eq(1));
+ verify(mMockProxyCallbacks).imsFeatureRemoved(eq(SLOT_1), eq(ImsFeature.FEATURE_MMTEL));
}
/**
@@ -381,31 +483,33 @@
@Test
public void testBindServiceAndRemoveAllFeatures() throws RemoteException {
HashSet<ImsFeatureConfiguration.FeatureSlotPair> testFeatures = new HashSet<>();
- // slot 1, MMTel
- testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(1, 1));
- // slot 2, MMTel
- testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(2, 1));
+ testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(SLOT_0,
+ ImsFeature.FEATURE_MMTEL));
+ testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(SLOT_1,
+ ImsFeature.FEATURE_MMTEL));
bindAndConnectService(testFeatures);
- verify(mMockServiceControllerBinder).createMmTelFeature(eq(1), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(1), eq(1),
+ verify(mMockServiceControllerBinder).createMmTelFeature(eq(SLOT_0), any());
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_MMTEL),
eq(mTestImsServiceController));
- verify(mMockProxyCallbacks).imsFeatureCreated(eq(1), eq(1));
- verify(mMockServiceControllerBinder).createMmTelFeature(eq(2), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(2), eq(1),
+ verify(mMockProxyCallbacks).imsFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_MMTEL));
+ verify(mMockServiceControllerBinder).createMmTelFeature(eq(SLOT_1), any());
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_1), eq(ImsFeature.FEATURE_MMTEL),
eq(mTestImsServiceController));
- verify(mMockProxyCallbacks).imsFeatureCreated(eq(2), eq(1));
+ verify(mMockProxyCallbacks).imsFeatureCreated(eq(SLOT_1), eq(ImsFeature.FEATURE_MMTEL));
// Create a new empty list
mTestImsServiceController.changeImsServiceFeatures(new HashSet<>());
- verify(mMockServiceControllerBinder).removeImsFeature(eq(1), eq(1), any());
- verify(mMockCallbacks).imsServiceFeatureRemoved(eq(1), eq(1),
+ verify(mMockServiceControllerBinder).removeImsFeature(eq(SLOT_0),
+ eq(ImsFeature.FEATURE_MMTEL), any());
+ verify(mMockCallbacks).imsServiceFeatureRemoved(eq(SLOT_0), eq(ImsFeature.FEATURE_MMTEL),
eq(mTestImsServiceController));
- verify(mMockProxyCallbacks).imsFeatureRemoved(eq(1), eq(1));
- verify(mMockServiceControllerBinder).removeImsFeature(eq(2), eq(1), any());
- verify(mMockCallbacks).imsServiceFeatureRemoved(eq(2), eq(1),
+ verify(mMockProxyCallbacks).imsFeatureRemoved(eq(SLOT_0), eq(ImsFeature.FEATURE_MMTEL));
+ verify(mMockServiceControllerBinder).removeImsFeature(eq(SLOT_1),
+ eq(ImsFeature.FEATURE_MMTEL), any());
+ verify(mMockCallbacks).imsServiceFeatureRemoved(eq(SLOT_1), eq(ImsFeature.FEATURE_MMTEL),
eq(mTestImsServiceController));
- verify(mMockProxyCallbacks).imsFeatureRemoved(eq(2), eq(1));
+ verify(mMockProxyCallbacks).imsFeatureRemoved(eq(SLOT_1), eq(ImsFeature.FEATURE_MMTEL));
}
/**
@@ -415,22 +519,24 @@
@Test
public void testBindUnbindServiceAndAddFeature() throws RemoteException {
HashSet<ImsFeatureConfiguration.FeatureSlotPair> testFeatures = new HashSet<>();
- // Slot 1, MMTel
- testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(1, 1));
+ testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(SLOT_0,
+ ImsFeature.FEATURE_MMTEL));
bindAndConnectService(testFeatures);
mTestImsServiceController.unbind();
// Create a new list with an additional item
HashSet<ImsFeatureConfiguration.FeatureSlotPair> testFeaturesWithAddition = new HashSet<>(
testFeatures);
// Try to create an RCS feature
- testFeaturesWithAddition.add(new ImsFeatureConfiguration.FeatureSlotPair(1, 2));
+ testFeaturesWithAddition.add(new ImsFeatureConfiguration.FeatureSlotPair(SLOT_0,
+ ImsFeature.FEATURE_RCS));
mTestImsServiceController.changeImsServiceFeatures(testFeaturesWithAddition);
- verify(mMockServiceControllerBinder, never()).createRcsFeature(eq(1), any());
- verify(mMockCallbacks, never()).imsServiceFeatureCreated(eq(1), eq(2),
- eq(mTestImsServiceController));
- verify(mMockProxyCallbacks, never()).imsFeatureCreated(eq(1), eq(2));
+ verify(mMockServiceControllerBinder, never()).createRcsFeature(eq(SLOT_0), any());
+ verify(mMockCallbacks, never()).imsServiceFeatureCreated(eq(SLOT_0),
+ eq(ImsFeature.FEATURE_RCS), eq(mTestImsServiceController));
+ verify(mMockProxyCallbacks, never()).imsFeatureCreated(eq(SLOT_0),
+ eq(ImsFeature.FEATURE_RCS));
}
/**
@@ -441,10 +547,10 @@
@Test
public void testAutoBindAfterBinderDied() throws RemoteException {
HashSet<ImsFeatureConfiguration.FeatureSlotPair> testFeatures = new HashSet<>();
- // Slot 1, MMTel
- testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(1, 1));
- // Slot 1, RCS
- testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(1, 2));
+ testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(SLOT_0,
+ ImsFeature.FEATURE_MMTEL));
+ testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(SLOT_0,
+ ImsFeature.FEATURE_RCS));
ServiceConnection conn = bindAndConnectService(testFeatures);
conn.onBindingDied(null /*null*/);
@@ -462,10 +568,10 @@
@Test
public void testNoAutoBindBeforeTimeout() throws RemoteException {
HashSet<ImsFeatureConfiguration.FeatureSlotPair> testFeatures = new HashSet<>();
- // Slot 1, MMTel
- testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(1, 1));
- // Slot 1, RCS
- testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(1, 2));
+ testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(SLOT_0,
+ ImsFeature.FEATURE_MMTEL));
+ testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(SLOT_0,
+ ImsFeature.FEATURE_RCS));
ServiceConnection conn = bindAndConnectService(testFeatures);
conn.onBindingDied(null /*null*/);
@@ -481,10 +587,10 @@
@Test
public void testUnbindCauseAutoBindCancelAfterBinderDied() throws RemoteException {
HashSet<ImsFeatureConfiguration.FeatureSlotPair> testFeatures = new HashSet<>();
- // Slot 1, MMTel
- testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(1, 1));
- // Slot 1, RCS
- testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(1, 2));
+ testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(SLOT_0,
+ ImsFeature.FEATURE_MMTEL));
+ testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(SLOT_0,
+ ImsFeature.FEATURE_RCS));
ServiceConnection conn = bindAndConnectService(testFeatures);
conn.onBindingDied(null /*null*/);
@@ -505,10 +611,10 @@
@Test
public void testBindCauseAutoBindCancelAfterBinderDied() throws RemoteException {
HashSet<ImsFeatureConfiguration.FeatureSlotPair> testFeatures = new HashSet<>();
- // Slot 1, MMTel
- testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(1, 1));
- // Slot 1, RCS
- testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(1, 2));
+ testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(SLOT_0,
+ ImsFeature.FEATURE_MMTEL));
+ testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(SLOT_0,
+ ImsFeature.FEATURE_RCS));
ServiceConnection conn = bindAndConnectService(testFeatures);
conn.onBindingDied(null /*null*/);
mTestImsServiceController.bind(testFeatures);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneTest.java b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneTest.java
index 0db3204..2e7f8a5 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneTest.java
@@ -223,11 +223,25 @@
assertEquals(Phone.SuppService.SEPARATE,
((AsyncResult) messageArgumentCaptor.getValue().obj).result);
- // ringing call is idle
+ // ringing call is idle, only an active call present
+ doReturn(Call.State.ACTIVE).when(mForegroundCall).getState();
assertEquals(true, mImsPhoneUT.handleInCallMmiCommands("2"));
verify(mImsCT).holdActiveCall();
+ // background call is holding
+ doReturn(Call.State.HOLDING).when(mBackgroundCall).getState();
+ doReturn(Call.State.IDLE).when(mForegroundCall).getState();
+ assertEquals(true, mImsPhoneUT.handleInCallMmiCommands("2"));
+ verify(mImsCT).unholdHeldCall();
+
+ // background call is holding and there's an active foreground call
+ doReturn(Call.State.ACTIVE).when(mForegroundCall).getState();
+ assertEquals(true, mImsPhoneUT.handleInCallMmiCommands("2"));
+ verify(mImsCT, times(2)).holdActiveCall();
+
// ringing call is not idle
+ doReturn(Call.State.IDLE).when(mForegroundCall).getState();
+ doReturn(Call.State.IDLE).when(mBackgroundCall).getState();
doReturn(Call.State.INCOMING).when(mRingingCall).getState();
assertEquals(true, mImsPhoneUT.handleInCallMmiCommands("2"));
verify(mImsCT).acceptCall(ImsCallProfile.CALL_TYPE_VOICE);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccCarrierPrivilegeRulesTest.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccCarrierPrivilegeRulesTest.java
index 80353fe..b383bfa 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccCarrierPrivilegeRulesTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccCarrierPrivilegeRulesTest.java
@@ -30,6 +30,7 @@
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import com.android.internal.telephony.CommandException;
import com.android.internal.telephony.TelephonyTest;
import org.junit.After;
@@ -256,6 +257,38 @@
assertEquals(0, mUiccCarrierPrivilegeRules.getPackageNames().size());
}
+ @Test
+ @SmallTest
+ public void testRetryARAM_shouldRetry() {
+ AsyncResult ar1 = new AsyncResult(
+ null,
+ new int[]{0, 105, -123},
+ new CommandException(CommandException.Error.NO_SUCH_ELEMENT));
+ assertTrue(mUiccCarrierPrivilegeRules.shouldRetry(ar1, 0));
+
+ AsyncResult ar2 = new AsyncResult(
+ null,
+ new int[]{0},
+ new CommandException(CommandException.Error.MISSING_RESOURCE));
+ assertTrue(mUiccCarrierPrivilegeRules.shouldRetry(ar2, 0));
+
+ AsyncResult ar3 = new AsyncResult(
+ null,
+ new int[]{0, 105, 153},
+ new CommandException(CommandException.Error.INTERNAL_ERR));
+ assertTrue(mUiccCarrierPrivilegeRules.shouldRetry(ar3, 0));
+ }
+
+ @Test
+ @SmallTest
+ public void testRetryARAM_shouldNotRetry() {
+ AsyncResult ar = new AsyncResult(
+ null,
+ new int[]{0, 106, -126},
+ new CommandException(CommandException.Error.NO_SUCH_ELEMENT));
+ assertTrue(!mUiccCarrierPrivilegeRules.shouldRetry(ar, 0));
+ }
+
private static final String ARAM = "A00000015141434C00";
private static final String ARAD = "A00000015144414300";
private static final String PKCS15_AID = "A000000063504B43532D3135";