Merge "Show phone numbers from all sources in hidden menu"
diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml
index c941be2..22aa185 100644
--- a/res/values-hi/strings.xml
+++ b/res/values-hi/strings.xml
@@ -890,14 +890,14 @@
<string name="radio_info_ppp_resets_label" msgid="9131901102339077661">"चालू करने के बाद से पीपीपी रीसेट की संख्या:"</string>
<string name="radio_info_current_network_label" msgid="3052098695239642450">"मौजूदा नेटवर्क:"</string>
<string name="radio_info_ppp_received_label" msgid="5753592451640644889">"मिलने वाला डेटा :"</string>
- <string name="radio_info_gsm_service_label" msgid="6443348321714241328">"Voice की सेवा:"</string>
+ <string name="radio_info_gsm_service_label" msgid="6443348321714241328">"वॉइस सेवा:"</string>
<string name="radio_info_signal_strength_label" msgid="5545444702102543260">"सिग्नल कितना अच्छा है:"</string>
- <string name="radio_info_call_status_label" msgid="7693575431923095487">"Voice कॉल की स्थिति:"</string>
+ <string name="radio_info_call_status_label" msgid="7693575431923095487">"वॉइस कॉल की स्थिति:"</string>
<string name="radio_info_ppp_sent_label" msgid="6542208429356199695">"भेजा गया डेटा :"</string>
<string name="radio_info_message_waiting_label" msgid="1886549432566952078">"मैसेज वेटिंग:"</string>
<string name="radio_info_phone_number_label" msgid="2533852539562512203">"फ़ोन नंबर:"</string>
<string name="radio_info_band_mode_label" msgid="23480556225515290">"रेडियो का बैंड चुनें"</string>
- <string name="radio_info_voice_network_type_label" msgid="2395347336419593265">"Voice के नेटवर्क प्रकार:"</string>
+ <string name="radio_info_voice_network_type_label" msgid="2395347336419593265">"वॉइस नेटवर्क टाइप:"</string>
<string name="radio_info_data_network_type_label" msgid="8886597029237501929">"डेटा नेटवर्क प्रकार:"</string>
<string name="phone_index_label" msgid="6222406512768964268">"फ़ोन इंडेक्स चुनें"</string>
<string name="radio_info_set_perferred_label" msgid="7408131389363136210">"पसंदीदा नेटवर्क प्रकार सेट करें:"</string>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index 18ee718..06af4bc 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -297,7 +297,7 @@
<string name="sip_accounts_removed_notification_title" msgid="3528076957535736095">"Account SIP deprecati trovati e rimossi"</string>
<string name="sip_accounts_removed_notification_message" msgid="1916856744869791592">"Le chiamate SIP non sono più supportate dalla piattaforma Android.\nI tuoi account SIP esistenti (<xliff:g id="REMOVED_SIP_ACCOUNTS">%s</xliff:g>) sono stati rimossi.\nConferma l\'impostazione del tuo account predefinito per le chiamate."</string>
<string name="sip_accounts_removed_notification_action" msgid="3772778402370555562">"Vai alle impostazioni"</string>
- <string name="data_usage_title" msgid="8438592133893837464">"Utilizzo dei dati delle app"</string>
+ <string name="data_usage_title" msgid="8438592133893837464">"Utilizzo dati delle app"</string>
<string name="data_usage_template" msgid="6287906680674061783">"Dati mobili usati: <xliff:g id="ID_1">%1$s</xliff:g> nel periodo <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="advanced_options_title" msgid="9208195294513520934">"Avanzate"</string>
<string name="carrier_settings_euicc" msgid="1190237227261337749">"Operatore"</string>
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index 850bfbb..226dc72 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -846,9 +846,9 @@
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"Opnieuw opstarten"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"Annuleren"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"Mobiel radiovermogen"</string>
- <string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"Adresboek op simkaart weergeven"</string>
- <string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"Vaste nummers weergeven"</string>
- <string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"Servicenummers weergeven"</string>
+ <string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"Adresboek op simkaart bekijken"</string>
+ <string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"Vaste nummers bekijken"</string>
+ <string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"Servicenummers bekijken"</string>
<string name="radioInfo_menu_getIMS" msgid="1950869267853198232">"IMS-servicestatus"</string>
<string name="radio_info_ims_reg_status_title" msgid="6875885401313992007">"IMS-status"</string>
<string name="radio_info_ims_reg_status_registered" msgid="7095182114078864326">"Geregistreerd"</string>
diff --git a/src/com/android/phone/ImsStateCallbackController.java b/src/com/android/phone/ImsStateCallbackController.java
index c7f15bf..28fca59 100644
--- a/src/com/android/phone/ImsStateCallbackController.java
+++ b/src/com/android/phone/ImsStateCallbackController.java
@@ -47,6 +47,7 @@
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyRegistryManager;
import android.telephony.ims.feature.ImsFeature;
+import android.util.LocalLog;
import android.util.Log;
import android.util.SparseArray;
@@ -60,6 +61,7 @@
import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.ims.ImsResolver;
import com.android.internal.telephony.util.HandlerExecutor;
+import com.android.internal.util.IndentingPrintWriter;
import com.android.services.telephony.rcs.RcsFeatureController;
import com.android.telephony.Rlog;
@@ -74,6 +76,7 @@
public class ImsStateCallbackController {
private static final String TAG = "ImsStateCallbackController";
private static final boolean VDBG = false;
+ private static final int LOG_SIZE = 50;
/**
* Create a FeatureConnector for this class to use to connect to an ImsManager.
@@ -123,6 +126,7 @@
private static final int EVENT_MSIM_CONFIGURATION_CHANGE = 6;
private static ImsStateCallbackController sInstance;
+ private static final LocalLog sLocalLog = new LocalLog(LOG_SIZE);
/**
* get the instance
@@ -146,6 +150,8 @@
private HashMap<IBinder, CallbackWrapper> mWrappers = new HashMap<>();
+ private final Object mDumpLock = new Object();
+
private int mNumSlots;
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
@@ -197,41 +203,43 @@
@Override
public void handleMessage(Message msg) {
- logv("handleMessage: " + msg);
- switch (msg.what) {
- case EVENT_SUB_CHANGED:
- onSubChanged();
- break;
-
- case EVENT_REGISTER_CALLBACK:
- onRegisterCallback((ImsStateCallbackController.CallbackWrapper) msg.obj);
- break;
-
- case EVENT_UNREGISTER_CALLBACK:
- onUnregisterCallback((IImsStateCallback) msg.obj);
- break;
-
- case EVENT_CARRIER_CONFIG_CHANGED:
- onCarrierConfigChanged(msg.arg1);
- break;
-
- case EVENT_EXTERNAL_RCS_STATE_CHANGED:
- if (msg.obj == null) break;
- onExternalRcsStateChanged((ExternalRcsFeatureState) msg.obj);
- break;
-
- case EVENT_MSIM_CONFIGURATION_CHANGE:
- AsyncResult result = (AsyncResult) msg.obj;
- Integer numSlots = (Integer) result.result;
- if (numSlots == null) {
- Log.w(TAG, "msim config change with null num slots");
+ if (VDBG) logv("handleMessage: " + msg);
+ synchronized (mDumpLock) {
+ switch (msg.what) {
+ case EVENT_SUB_CHANGED:
+ onSubChanged();
break;
- }
- updateFeatureControllerSize(numSlots);
- break;
- default:
- loge("Unhandled event " + msg.what);
+ case EVENT_REGISTER_CALLBACK:
+ onRegisterCallback((ImsStateCallbackController.CallbackWrapper) msg.obj);
+ break;
+
+ case EVENT_UNREGISTER_CALLBACK:
+ onUnregisterCallback((IImsStateCallback) msg.obj);
+ break;
+
+ case EVENT_CARRIER_CONFIG_CHANGED:
+ onCarrierConfigChanged(msg.arg1);
+ break;
+
+ case EVENT_EXTERNAL_RCS_STATE_CHANGED:
+ if (msg.obj == null) break;
+ onExternalRcsStateChanged((ExternalRcsFeatureState) msg.obj);
+ break;
+
+ case EVENT_MSIM_CONFIGURATION_CHANGE:
+ AsyncResult result = (AsyncResult) msg.obj;
+ Integer numSlots = (Integer) result.result;
+ if (numSlots == null) {
+ Log.w(TAG, "msim config change with null num slots");
+ break;
+ }
+ updateFeatureControllerSize(numSlots);
+ break;
+
+ default:
+ loge("Unhandled event " + msg.what);
+ }
}
}
}
@@ -260,23 +268,25 @@
private String mLogPrefix = "";
MmTelFeatureListener(int slotId) {
- mLogPrefix = "[MMTEL, " + slotId + "] ";
- logv(mLogPrefix + "create");
+ mSlotId = slotId;
+ mLogPrefix = "[" + slotId + ", MMTEL] ";
+ if (VDBG) logv(mLogPrefix + "created");
+
mConnector = mMmTelFeatureFactory.create(
mApp, slotId, TAG, this, new HandlerExecutor(mHandler));
mConnector.connect();
}
void setSubId(int subId) {
- logv(mLogPrefix + "setSubId mSubId=" + mSubId + ", subId=" + subId);
+ if (VDBG) logv(mLogPrefix + "setSubId mSubId=" + mSubId + ", subId=" + subId);
if (mSubId == subId) return;
- logd(mLogPrefix + "setSubId subId changed");
+ logd(mLogPrefix + "setSubId changed subId=" + subId);
mSubId = subId;
}
void destroy() {
- logv(mLogPrefix + "destroy");
+ if (VDBG) logv(mLogPrefix + "destroy");
mConnector.disconnect();
mConnector = null;
}
@@ -345,10 +355,19 @@
// called from onRegisterCallback
boolean notifyState(CallbackWrapper wrapper) {
- logv(mLogPrefix + "notifyState subId=" + wrapper.mSubId);
+ if (VDBG) logv(mLogPrefix + "notifyState subId=" + wrapper.mSubId);
return wrapper.notifyState(mSubId, FEATURE_MMTEL, mState, mReason);
}
+
+ void dump(IndentingPrintWriter pw) {
+ pw.println("Listener={slotId=" + mSlotId
+ + ", subId=" + mSubId
+ + ", state=" + ImsFeature.STATE_LOG_MAP.get(mState)
+ + ", reason=" + imsStateReasonToString(mReason)
+ + ", hasConfig=" + mHasConfig
+ + "}");
+ }
}
private final class RcsFeatureListener implements FeatureConnector.Listener<RcsFeatureManager> {
@@ -390,8 +409,9 @@
private String mLogPrefix = "";
RcsFeatureListener(int slotId) {
- mLogPrefix = "[RCS, " + slotId + "] ";
- logv(mLogPrefix + "create");
+ mSlotId = slotId;
+ mLogPrefix = "[" + slotId + ", RCS] ";
+ if (VDBG) logv(mLogPrefix + "created");
mConnector = mRcsFeatureFactory.create(
mApp, slotId, this, new HandlerExecutor(mHandler), TAG);
@@ -399,15 +419,15 @@
}
void setSubId(int subId) {
- logv(mLogPrefix + "setSubId mSubId=" + mSubId + ", subId=" + subId);
+ if (VDBG) logv(mLogPrefix + "setSubId mSubId=" + mSubId + ", subId=" + subId);
if (mSubId == subId) return;
- logd(mLogPrefix + "setSubId subId changed");
+ logd(mLogPrefix + "setSubId changed subId=" + subId);
mSubId = subId;
}
void destroy() {
- logv(mLogPrefix + "destroy");
+ if (VDBG) logv(mLogPrefix + "destroy");
mConnector.disconnect();
mConnector = null;
@@ -450,7 +470,7 @@
}
if (mExternalState != null && !mExternalState.hasActiveFeatures()) {
- // notifyExternalState has notified REASON_NO_IMS_SERVICE_CONFIGURED already
+ // notifyExternalRcsState has notified REASON_NO_IMS_SERVICE_CONFIGURED already
// ignore it
return;
}
@@ -493,10 +513,12 @@
}
void notifyExternalRcsState(ExternalRcsFeatureState fs) {
- logv(mLogPrefix + "notifyExternalRcsState"
- + " state=" + (fs.mState == STATE_UNKNOWN
- ? "" : ImsFeature.STATE_LOG_MAP.get(fs.mState))
- + ", reason=" + imsStateReasonToString(fs.mReason));
+ if (VDBG) {
+ logv(mLogPrefix + "notifyExternalRcsState"
+ + " state=" + (fs.mState == STATE_UNKNOWN
+ ? "" : ImsFeature.STATE_LOG_MAP.get(fs.mState))
+ + ", reason=" + imsStateReasonToString(fs.mReason));
+ }
ExternalRcsFeatureState oldFs = mExternalState;
// External state is from TelephonyRcsService while a feature is added or removed.
@@ -539,7 +561,7 @@
// called from onRegisterCallback
boolean notifyState(CallbackWrapper wrapper) {
- logv(mLogPrefix + "notifyState subId=" + wrapper.mSubId);
+ if (VDBG) logv(mLogPrefix + "notifyState subId=" + wrapper.mSubId);
if (mHasConfig) {
if (mExternalState == null) {
@@ -554,6 +576,18 @@
return wrapper.notifyState(mSubId, FEATURE_RCS, mState, mReason);
}
+
+ void dump(IndentingPrintWriter pw) {
+ pw.println("Listener={slotId=" + mSlotId
+ + ", subId=" + mSubId
+ + ", state=" + ImsFeature.STATE_LOG_MAP.get(mState)
+ + ", reason=" + imsStateReasonToString(mReason)
+ + ", hasConfig=" + mHasConfig
+ + ", isReady=" + (mExternalState == null ? false : mExternalState.isReady())
+ + ", hasFeatures=" + (mExternalState == null ? false
+ : mExternalState.hasActiveFeatures())
+ + "}");
+ }
}
/**
@@ -564,12 +598,16 @@
private final int mRequiredFeature;
private final IImsStateCallback mCallback;
private final IBinder mBinder;
+ private final String mCallingPackage;
+ private int mLastReason = NOT_INITIALIZED;
- CallbackWrapper(int subId, int feature, IImsStateCallback callback) {
+ CallbackWrapper(int subId, int feature, IImsStateCallback callback,
+ String callingPackage) {
mSubId = subId;
mRequiredFeature = feature;
mCallback = callback;
mBinder = callback.asBinder();
+ mCallingPackage = callingPackage;
}
/**
@@ -579,10 +617,12 @@
* This instance shall be removed from the list.
*/
boolean notifyState(int subId, int feature, int state, int reason) {
- logv("CallbackWrapper notifyState subId=" + subId
- + ", feature=" + ImsFeature.FEATURE_LOG_MAP.get(feature)
- + ", state=" + ImsFeature.STATE_LOG_MAP.get(state)
- + ", reason=" + imsStateReasonToString(reason));
+ if (VDBG) {
+ logv("CallbackWrapper notifyState subId=" + subId
+ + ", feature=" + ImsFeature.FEATURE_LOG_MAP.get(feature)
+ + ", state=" + ImsFeature.STATE_LOG_MAP.get(state)
+ + ", reason=" + imsStateReasonToString(reason));
+ }
try {
if (state == STATE_READY) {
@@ -590,6 +630,7 @@
} else {
mCallback.onUnavailable(reason);
}
+ mLastReason = reason;
} catch (Exception e) {
loge("CallbackWrapper notifyState e=" + e);
return false;
@@ -599,7 +640,7 @@
}
void notifyInactive() {
- logv("CallbackWrapper notifyInactive subId=" + mSubId);
+ if (VDBG) logv("CallbackWrapper notifyInactive subId=" + mSubId);
try {
mCallback.onUnavailable(REASON_SUBSCRIPTION_INACTIVE);
@@ -607,6 +648,14 @@
// ignored
}
}
+
+ void dump(IndentingPrintWriter pw) {
+ pw.println("CallbackWrapper={subId=" + mSubId
+ + ", feature=" + ImsFeature.FEATURE_LOG_MAP.get(mRequiredFeature)
+ + ", reason=" + imsStateReasonToString(mLastReason)
+ + ", pkg=" + mCallingPackage
+ + "}");
+ }
}
private static class ExternalRcsFeatureState {
@@ -680,7 +729,7 @@
@VisibleForTesting
public void updateFeatureControllerSize(int newNumSlots) {
if (mNumSlots != newNumSlots) {
- Log.d(TAG, "updateFeatures: oldSlots=" + mNumSlots
+ logd("updateFeatures: oldSlots=" + mNumSlots
+ ", newNumSlots=" + newNumSlots);
if (mNumSlots < newNumSlots) {
for (int i = mNumSlots; i < newNumSlots; i++) {
@@ -712,8 +761,6 @@
*/
@VisibleForTesting
public void onSubChanged() {
- logv("onSubChanged size=" + mWrappers.size());
-
for (int i = 0; i < mMmTelFeatureListeners.size(); i++) {
MmTelFeatureListener l = mMmTelFeatureListeners.valueAt(i);
l.setSubId(getSubId(i));
@@ -729,7 +776,7 @@
ArrayList<IBinder> inactiveCallbacks = new ArrayList<>();
final int[] activeSubs = mSubscriptionManager.getActiveSubscriptionIdList();
- logv("onSubChanged activeSubs=" + Arrays.toString(activeSubs));
+ if (VDBG) logv("onSubChanged activeSubs=" + Arrays.toString(activeSubs));
// Remove callbacks for inactive subscriptions
for (IBinder binder : mWrappers.keySet()) {
@@ -748,10 +795,12 @@
}
private void onFeatureStateChange(int subId, int feature, int state, int reason) {
- logv("onFeatureStateChange subId=" + subId
- + ", feature=" + ImsFeature.FEATURE_LOG_MAP.get(feature)
- + ", state=" + ImsFeature.STATE_LOG_MAP.get(state)
- + ", reason=" + imsStateReasonToString(reason));
+ if (VDBG) {
+ logv("onFeatureStateChange subId=" + subId
+ + ", feature=" + ImsFeature.FEATURE_LOG_MAP.get(feature)
+ + ", state=" + ImsFeature.STATE_LOG_MAP.get(state)
+ + ", reason=" + imsStateReasonToString(reason));
+ }
ArrayList<IBinder> inactiveCallbacks = new ArrayList<>();
mWrappers.values().forEach(wrapper -> {
@@ -768,9 +817,11 @@
private void onRegisterCallback(CallbackWrapper wrapper) {
if (wrapper == null) return;
- logv("onRegisterCallback before size=" + mWrappers.size());
- logv("onRegisterCallback subId=" + wrapper.mSubId
- + ", feature=" + wrapper.mRequiredFeature);
+ if (VDBG) logv("onRegisterCallback before size=" + mWrappers.size());
+ if (VDBG) {
+ logv("onRegisterCallback subId=" + wrapper.mSubId
+ + ", feature=" + wrapper.mRequiredFeature);
+ }
// Not sure the following case can happen or not:
// step1) Subscription changed
@@ -801,7 +852,7 @@
}
}
- logv("onRegisterCallback after size=" + mWrappers.size());
+ if (VDBG) logv("onRegisterCallback after size=" + mWrappers.size());
}
private void onUnregisterCallback(IImsStateCallback cb) {
@@ -816,7 +867,7 @@
return;
}
- logd("onCarrierConfigChanged slotId=" + slotId);
+ logv("onCarrierConfigChanged slotId=" + slotId);
boolean hasConfig = verifyImsMmTelConfigured(slotId);
if (slotId < mMmTelFeatureListeners.size()) {
@@ -871,9 +922,11 @@
// Only when there is no feature, we can assume the state.
}
- logv("notifyExternalRcsStateChanged slotId=" + slotId
- + ", ready=" + ready
- + ", hasActiveFeatures=" + hasActiveFeatures);
+ if (VDBG) {
+ logv("notifyExternalRcsStateChanged slotId=" + slotId
+ + ", ready=" + ready
+ + ", hasActiveFeatures=" + hasActiveFeatures);
+ }
ExternalRcsFeatureState fs = new ExternalRcsFeatureState(slotId, state, reason);
mHandler.sendMessage(mHandler.obtainMessage(EVENT_EXTERNAL_RCS_STATE_CHANGED, fs));
@@ -884,7 +937,7 @@
*/
@VisibleForTesting
public void notifyCarrierConfigChanged(int slotId) {
- logv("notifyCarrierConfigChanged slotId=" + slotId);
+ if (VDBG) logv("notifyCarrierConfigChanged slotId=" + slotId);
mHandler.sendMessage(mHandler.obtainMessage(EVENT_CARRIER_CONFIG_CHANGED, slotId, 0));
}
/**
@@ -892,10 +945,14 @@
*
* @param feature for which state is changed, ImsFeature.FEATURE_*
*/
- public void registerImsStateCallback(int subId, int feature, IImsStateCallback cb) {
- logv("registerImsStateCallback subId=" + subId + ", feature=" + feature);
+ public void registerImsStateCallback(int subId, int feature, IImsStateCallback cb,
+ String callingPackage) {
+ if (VDBG) {
+ logv("registerImsStateCallback subId=" + subId
+ + ", feature=" + feature + ", pkg=" + callingPackage);
+ }
- CallbackWrapper wrapper = new CallbackWrapper(subId, feature, cb);
+ CallbackWrapper wrapper = new CallbackWrapper(subId, feature, cb, callingPackage);
mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_CALLBACK, wrapper));
}
@@ -903,7 +960,7 @@
* Unegister previously registered callback
*/
public void unregisterImsStateCallback(IImsStateCallback cb) {
- logv("unregisterImsStateCallback");
+ if (VDBG) logv("unregisterImsStateCallback");
mHandler.sendMessage(mHandler.obtainMessage(EVENT_UNREGISTER_CALLBACK, cb));
}
@@ -912,7 +969,10 @@
ArrayList<IBinder> inactiveCallbacks, String message) {
if (inactiveCallbacks == null || inactiveCallbacks.size() == 0) return;
- logv("removeInactiveCallbacks size=" + inactiveCallbacks.size() + " from " + message);
+ if (VDBG) {
+ logv("removeInactiveCallbacks size="
+ + inactiveCallbacks.size() + " from " + message);
+ }
for (IBinder binder : inactiveCallbacks) {
CallbackWrapper wrapper = mWrappers.get(binder);
@@ -958,7 +1018,7 @@
} else {
ret = mImsResolver.isImsServiceConfiguredForFeature(slotId, FEATURE_MMTEL);
}
- logv("verifyImsMmTelConfigured slotId=" + slotId + ", ret=" + ret);
+ if (VDBG) logv("verifyImsMmTelConfigured slotId=" + slotId + ", ret=" + ret);
return ret;
}
@@ -969,7 +1029,7 @@
} else {
ret = mImsResolver.isImsServiceConfiguredForFeature(slotId, FEATURE_RCS);
}
- logv("verifyImsRcsConfigured slotId=" + slotId + ", ret=" + ret);
+ if (VDBG) logv("verifyImsRcsConfigured slotId=" + slotId + ", ret=" + ret);
return ret;
}
@@ -991,6 +1051,8 @@
private static String imsStateReasonToString(int reason) {
switch(reason) {
+ case AVAILABLE:
+ return "READY";
case REASON_UNKNOWN_TEMPORARY_ERROR:
return "UNKNOWN_TEMPORARY_ERROR";
case REASON_UNKNOWN_PERMANENT_ERROR:
@@ -1028,7 +1090,7 @@
};
private void release() {
- logv("release");
+ if (VDBG) logv("release");
mTelephonyRegistryManager.removeOnSubscriptionsChangedListener(mSubChangedListener);
mApp.unregisterReceiver(mReceiver);
@@ -1049,7 +1111,7 @@
*/
@VisibleForTesting
public void destroy() {
- logv("destroy it");
+ if (VDBG) logv("destroy it");
release();
mHandler.getLooper().quit();
@@ -1072,17 +1134,51 @@
return mWrappers.containsKey(cb.asBinder());
}
- private static void logv(String msg) {
- if (VDBG) {
- Rlog.d(TAG, msg);
+ /**
+ * Dump this instance into a readable format for dumpsys usage.
+ */
+ public void dump(IndentingPrintWriter pw) {
+ pw.increaseIndent();
+ synchronized (mDumpLock) {
+ pw.println("CallbackWrappers:");
+ pw.increaseIndent();
+ mWrappers.values().forEach(wrapper -> wrapper.dump(pw));
+ pw.decreaseIndent();
+ pw.println("MmTelFeatureListeners:");
+ pw.increaseIndent();
+ for (int i = 0; i < mNumSlots; i++) {
+ MmTelFeatureListener l = mMmTelFeatureListeners.get(i);
+ if (l == null) continue;
+ l.dump(pw);
+ }
+ pw.decreaseIndent();
+ pw.println("RcsFeatureListeners:");
+ pw.increaseIndent();
+ for (int i = 0; i < mNumSlots; i++) {
+ RcsFeatureListener l = mRcsFeatureListeners.get(i);
+ if (l == null) continue;
+ l.dump(pw);
+ }
+ pw.decreaseIndent();
+ pw.println("Most recent logs:");
+ pw.increaseIndent();
+ sLocalLog.dump(pw);
+ pw.decreaseIndent();
}
+ pw.decreaseIndent();
+ }
+
+ private static void logv(String msg) {
+ Rlog.d(TAG, msg);
}
private static void logd(String msg) {
Rlog.d(TAG, msg);
+ sLocalLog.log(msg);
}
private static void loge(String msg) {
Rlog.e(TAG, msg);
+ sLocalLog.log(msg);
}
}
diff --git a/src/com/android/phone/PhoneGlobals.java b/src/com/android/phone/PhoneGlobals.java
index 9607919..e7cb28c 100644
--- a/src/com/android/phone/PhoneGlobals.java
+++ b/src/com/android/phone/PhoneGlobals.java
@@ -1038,6 +1038,12 @@
} catch (Exception e) {
e.printStackTrace();
}
+ pw.println("ImsStateCallbackController:");
+ try {
+ if (mImsStateCallbackController != null) mImsStateCallbackController.dump(pw);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
pw.decreaseIndent();
pw.println("------- End PhoneGlobals -------");
}
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index 55452f3..3721c40 100755
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -28,10 +28,13 @@
import android.Manifest.permission;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.app.AppOpsManager;
import android.app.PendingIntent;
import android.app.compat.CompatChanges;
import android.app.role.RoleManager;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledSince;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
@@ -105,7 +108,9 @@
import android.telephony.TelephonyScanManager;
import android.telephony.ThermalMitigationRequest;
import android.telephony.UiccCardInfo;
+import android.telephony.UiccPortInfo;
import android.telephony.UiccSlotInfo;
+import android.telephony.UiccSlotMapping;
import android.telephony.UssdResponse;
import android.telephony.VisualVoicemailSmsFilterSettings;
import android.telephony.data.ApnSetting;
@@ -218,6 +223,7 @@
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -404,6 +410,16 @@
"reset_network_erase_modem_config_enabled";
private static final int SET_NETWORK_SELECTION_MODE_AUTOMATIC_TIMEOUT_MS = 2000; // 2 seconds
+ /**
+ * With support for MEP(multiple enabled profile) in Android T, a SIM card can have more than
+ * one ICCID active at the same time.
+ * Apps should use below API signatures if targeting SDK is T and beyond.
+ *
+ * @hide
+ */
+ @ChangeId
+ @EnabledSince(targetSdkVersion = Build.VERSION_CODES.TIRAMISU)
+ public static final long GET_API_SIGNATURES_FROM_UICC_PORT_INFO = 202110963L;
/**
* A request object to use for transmitting data to an ICC.
@@ -8711,6 +8727,7 @@
.checkPackage(Binder.getCallingUid(), callingPackage);
boolean hasReadPermission = false;
+ boolean isIccIdAccessRestricted = false;
try {
enforceReadPrivilegedPermission("getUiccCardsInfo");
hasReadPermission = true;
@@ -8722,7 +8739,11 @@
throw new SecurityException("Caller does not have permission.");
}
}
-
+ // checking compatibility, if calling app's target SDK is T and beyond.
+ if (CompatChanges.isChangeEnabled(GET_API_SIGNATURES_FROM_UICC_PORT_INFO,
+ Binder.getCallingUid())) {
+ isIccIdAccessRestricted = true;
+ }
final long identity = Binder.clearCallingIdentity();
try {
UiccController uiccController = UiccController.getInstance();
@@ -8734,21 +8755,23 @@
// Remove private info if the caller doesn't have access
ArrayList<UiccCardInfo> filteredInfos = new ArrayList<>();
for (UiccCardInfo cardInfo : cardInfos) {
+ //setting the value after compatibility check
+ cardInfo.setIccIdAccessRestricted(isIccIdAccessRestricted);
// For an inactive eUICC, the UiccCard will be null even though the UiccCardInfo
// is available
- UiccCard card = uiccController.getUiccCardForSlot(cardInfo.getSlotIndex());
+ UiccCard card = uiccController.getUiccCardForSlot(cardInfo.getPhysicalSlotIndex());
// TODO remove card.getUiccPortList().length once MEP API refactoring CL is merged
// Get UiccPortInfo from CardInfo and process further based on each UiccPort
if (card == null || card.getUiccPortList().length == 0) {
// assume no access if the card or ports are unavailable
- filteredInfos.add(cardInfo.getUnprivileged());
+ filteredInfos.add(getUiccCardInfoUnPrivileged(cardInfo));
continue;
}
if (haveCarrierPrivilegeAccess(card, callingPackage)) {
filteredInfos.add(cardInfo);
} else {
- filteredInfos.add(cardInfo.getUnprivileged());
+ filteredInfos.add(getUiccCardInfoUnPrivileged(cardInfo));
}
}
return filteredInfos;
@@ -8757,10 +8780,70 @@
}
}
- @Override
- public UiccSlotInfo[] getUiccSlotsInfo() {
- enforceReadPrivilegedPermission("getUiccSlotsInfo");
+ /**
+ * Returns a copy of the UiccCardinfo with the EID and ICCID set to null. These values are
+ * generally private and require carrier privileges to view.
+ *
+ * @hide
+ */
+ @NonNull
+ public UiccCardInfo getUiccCardInfoUnPrivileged(UiccCardInfo cardInfo) {
+ List<UiccPortInfo> portinfo = new ArrayList<>();
+ for (UiccPortInfo portinfos : cardInfo.getPorts()) {
+ portinfo.add(getUiccPortInfoUnPrivileged(portinfos));
+ }
+ return new UiccCardInfo(
+ cardInfo.isEuicc(),
+ cardInfo.getCardId(),
+ null,
+ cardInfo.getPhysicalSlotIndex(),
+ cardInfo.isRemovable(),
+ cardInfo.isMultipleEnabledProfilesSupported(),
+ portinfo
+ );
+ }
+ /**
+ * @hide
+ * @return a copy of the UiccPortInfo with ICCID set to {@link UiccPortInfo#ICCID_REDACTED}.
+ * These values are generally private and require carrier privileges to view.
+ */
+ @NonNull
+ public UiccPortInfo getUiccPortInfoUnPrivileged(UiccPortInfo portInfo) {
+ return new UiccPortInfo(
+ UiccPortInfo.ICCID_REDACTED,
+ portInfo.getPortIndex(),
+ portInfo.getLogicalSlotIndex(),
+ portInfo.isActive()
+ );
+ }
+ @Override
+ public UiccSlotInfo[] getUiccSlotsInfo(String callingPackage) {
+ // Verify that tha callingPackage belongs to the calling UID
+ mApp.getSystemService(AppOpsManager.class)
+ .checkPackage(Binder.getCallingUid(), callingPackage);
+
+ boolean hasReadPermission = false;
+ boolean isLogicalSlotAccessRestricted = false;
+ String iccId;
+
+ try {
+ enforceReadPrivilegedPermission("getUiccSlotsInfo");
+ hasReadPermission = true;
+ } catch (SecurityException e) {
+ // even without READ_PRIVILEGED_PHONE_STATE, we allow the call to continue if the caller
+ // has carrier privileges on an active UICC
+ if (checkCarrierPrivilegesForPackageAnyPhone(callingPackage)
+ == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
+ hasReadPermission = true;
+ }
+ }
+
+ // checking compatibility, if calling app's target SDK is T and beyond.
+ if (CompatChanges.isChangeEnabled(GET_API_SIGNATURES_FROM_UICC_PORT_INFO,
+ Binder.getCallingUid())) {
+ isLogicalSlotAccessRestricted = true;
+ }
final long identity = Binder.clearCallingIdentity();
try {
UiccSlot[] slots = UiccController.getInstance().getUiccSlots();
@@ -8768,7 +8851,6 @@
Rlog.i(LOG_TAG, "slots is null.");
return null;
}
-
UiccSlotInfo[] infos = new UiccSlotInfo[slots.length];
for (int i = 0; i < slots.length; i++) {
UiccSlot slot = slots[i];
@@ -8778,12 +8860,24 @@
String cardId;
UiccCard card = slot.getUiccCard();
+ //if has read permission
+ if (hasReadPermission) {
+ iccId = slot.getIccId();
+ } else {
+ // if no read permission checking carrier
+ if (haveCarrierPrivilegeAccess(card, callingPackage)) {
+ iccId = slot.getIccId();
+ } else {
+ //if no carrier permission redact ICCID
+ iccId = IccUtils.TEST_ICCID;
+ }
+ }
if (card != null) {
cardId = card.getCardId();
} else {
cardId = slot.getEid();
if (TextUtils.isEmpty(cardId)) {
- cardId = slot.getIccId();
+ cardId = iccId;
}
}
@@ -8811,15 +8905,19 @@
break;
}
-
infos[i] = new UiccSlotInfo(
- slot.isActive(),
slot.isEuicc(),
cardId,
cardState,
- slot.getPhoneId(),
slot.isExtendedApduSupported(),
- slot.isRemovable());
+ slot.isRemovable(), Collections.singletonList(
+ new UiccPortInfo(
+ iccId,
+ 0 /* TODO: to use portList from UiccSlots */,
+ slot.getPhoneId(),
+ slot.isActive())));
+ //setting the value after compatibility check
+ infos[i].setLogicalSlotAccessRestricted(isLogicalSlotAccessRestricted);
}
return infos;
} finally {
@@ -8828,6 +8926,8 @@
}
@Override
+ @Deprecated
+ //TODO : once integrating with HAL Changes we can clean up this Internal API.
public boolean switchSlots(int[] physicalSlots) {
enforceModifyPermission();
@@ -8840,6 +8940,24 @@
}
@Override
+ @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ public boolean setSimSlotMapping(@NonNull List<UiccSlotMapping> slotMapping) {
+ enforceModifyPermission();
+
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ //TODO: once integrating the HAL changes we can proceed with to work on the parsing side
+ int[] physicalSlots = new int[slotMapping.size()];
+ for (int i = 0; i < physicalSlots.length; i++) {
+ physicalSlots[i] = slotMapping.get(i).getPhysicalSlotIndex();
+ }
+ return (Boolean) sendRequest(CMD_SWITCH_SLOTS, physicalSlots);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
public int getCardIdForDefaultEuicc(int subId, String callingPackage) {
final long identity = Binder.clearCallingIdentity();
try {
@@ -9422,7 +9540,7 @@
}
@Override
- public int[] getSlotsMapping() {
+ public int[] getSlotsMapping(@NonNull String callingPackage) {
enforceReadPrivilegedPermission("getSlotsMapping");
final long identity = Binder.clearCallingIdentity();
@@ -9430,7 +9548,7 @@
int phoneCount = TelephonyManager.getDefault().getPhoneCount();
// All logical slots should have a mapping to a physical slot.
int[] logicalSlotsMapping = new int[phoneCount];
- UiccSlotInfo[] slotInfos = getUiccSlotsInfo();
+ UiccSlotInfo[] slotInfos = getUiccSlotsInfo(callingPackage);
for (int i = 0; i < slotInfos.length; i++) {
if (SubscriptionManager.isValidPhoneId(slotInfos[i].getLogicalSlotIdx())) {
logicalSlotsMapping[slotInfos[i].getLogicalSlotIdx()] = i;
@@ -10927,7 +11045,8 @@
* Register an IMS connection state callback
*/
@Override
- public void registerImsStateCallback(int subId, int feature, IImsStateCallback cb) {
+ public void registerImsStateCallback(int subId, int feature, IImsStateCallback cb,
+ String callingPackage) {
if (feature == ImsFeature.FEATURE_MMTEL) {
// ImsMmTelManager
// The following also checks READ_PRIVILEGED_PHONE_STATE.
@@ -10959,10 +11078,14 @@
"IMS not available on device.");
}
+ if (callingPackage == null) {
+ callingPackage = getCurrentPackageName();
+ }
+
final long token = Binder.clearCallingIdentity();
try {
int slotId = getSlotIndexOrException(subId);
- controller.registerImsStateCallback(subId, feature, cb);
+ controller.registerImsStateCallback(subId, feature, cb, callingPackage);
} catch (ImsException e) {
throw new ServiceSpecificException(e.getCode());
} finally {
diff --git a/src/com/android/phone/settings/RadioInfo.java b/src/com/android/phone/settings/RadioInfo.java
index fc4fce7..17adef3 100644
--- a/src/com/android/phone/settings/RadioInfo.java
+++ b/src/com/android/phone/settings/RadioInfo.java
@@ -17,6 +17,7 @@
package com.android.phone.settings;
import static android.net.ConnectivityManager.NetworkCallback;
+
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import android.content.ComponentName;
@@ -57,7 +58,6 @@
import android.telephony.CellSignalStrengthLte;
import android.telephony.CellSignalStrengthWcdma;
import android.telephony.DataSpecificRegistrationInfo;
-import android.telephony.data.NetworkSlicingConfig;
import android.telephony.NetworkRegistrationInfo;
import android.telephony.PhysicalChannelConfig;
import android.telephony.RadioAccessFamily;
@@ -66,6 +66,7 @@
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyCallback;
import android.telephony.TelephonyManager;
+import android.telephony.data.NetworkSlicingConfig;
import android.text.TextUtils;
import android.util.Log;
import android.view.Menu;
@@ -102,8 +103,8 @@
import java.util.concurrent.Executor;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.TimeoutException;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
/**
* Radio Information Class
diff --git a/src/com/android/services/telephony/rcs/SipSessionTracker.java b/src/com/android/services/telephony/rcs/SipSessionTracker.java
index 5ab482f..68e3065 100644
--- a/src/com/android/services/telephony/rcs/SipSessionTracker.java
+++ b/src/com/android/services/telephony/rcs/SipSessionTracker.java
@@ -24,6 +24,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.SipMessageParsingUtils;
+import com.android.internal.telephony.metrics.RcsStats;
import com.android.internal.util.IndentingPrintWriter;
import java.io.PrintWriter;
@@ -66,6 +67,14 @@
// associated pending operation.
private final ArrayMap<String, Runnable> mPendingAck = new ArrayMap<>();
+ private final RcsStats mRcsStats;
+ int mSubId;
+
+ public SipSessionTracker(int subId, RcsStats rcsStats) {
+ mSubId = subId;
+ mRcsStats = rcsStats;
+ }
+
/**
* Filter a SIP message to determine if it will result in a new SIP dialog. This will need to be
* successfully acknowledged by the remote IMS stack using
@@ -73,10 +82,10 @@
*
* @param message The Incoming SIP message.
*/
- public void filterSipMessage(SipMessage message) {
+ public void filterSipMessage(int direction, SipMessage message) {
final Runnable r;
if (startsEarlyDialog(message)) {
- r = getCreateDialogRunnable(message);
+ r = getCreateDialogRunnable(direction, message);
} else if (closesDialog(message)) {
r = getCloseDialogRunnable(message);
} else if (SipMessageParsingUtils.isSipResponse(message.getStartLine())) {
@@ -137,6 +146,8 @@
if (dialogsToCleanup.isEmpty()) return;
logi("Cleanup dialogs associated with call id: " + callId);
for (SipDialog d : dialogsToCleanup) {
+ mRcsStats.onSipTransportSessionClosed(mSubId, callId, 0,
+ d.getState() == d.STATE_CLOSED);
d.close();
logi("Dialog closed: " + d);
}
@@ -197,6 +208,9 @@
* Clears all tracked sessions.
*/
public void clearAllSessions() {
+ for (SipDialog d : mTrackedDialogs) {
+ mRcsStats.onSipTransportSessionClosed(mSubId, d.getCallId(), 0, false);
+ }
mTrackedDialogs.clear();
mPendingAck.clear();
}
@@ -262,7 +276,7 @@
return SIP_CLOSE_DIALOG_REQUEST_METHOD.equalsIgnoreCase(startLineSegments[0]);
}
- private Runnable getCreateDialogRunnable(SipMessage m) {
+ private Runnable getCreateDialogRunnable(int direction, SipMessage m) {
return () -> {
List<SipDialog> duplicateDialogs = mTrackedDialogs.stream()
.filter(d -> d.getCallId().equals(m.getCallIdParameter()))
@@ -273,6 +287,10 @@
return;
}
SipDialog dialog = SipDialog.fromSipMessage(m);
+ String[] startLineSegments =
+ SipMessageParsingUtils.splitStartLineAndVerify(m.getStartLine());
+ mRcsStats.earlySipTransportSession(startLineSegments[0], dialog.getCallId(),
+ direction);
logi("Starting new SipDialog: " + dialog);
mTrackedDialogs.add(dialog);
};
@@ -285,6 +303,7 @@
.collect(Collectors.toList());
if (dialogsToClose.isEmpty()) return;
logi("Closing dialogs associated with: " + m);
+ mRcsStats.onSipTransportSessionClosed(mSubId, m.getCallIdParameter(), 0, true);
for (SipDialog d : dialogsToClose) {
d.close();
logi("Dialog closed: " + d);
@@ -344,11 +363,13 @@
if (statusCode <= 100) return;
// If 300+, then this dialog has received an error response and should move to closed state.
if (statusCode >= 300) {
+ mRcsStats.onSipTransportSessionClosed(mSubId, m.getCallIdParameter(), statusCode, true);
d.close();
return;
}
if (toTag == null) logw("updateSipDialogState: No to tag for message: " + m);
if (statusCode >= 200) {
+ mRcsStats.confirmedSipTransportSession(m.getCallIdParameter(), statusCode);
d.confirm(toTag);
return;
}
diff --git a/src/com/android/services/telephony/rcs/TransportSipMessageValidator.java b/src/com/android/services/telephony/rcs/TransportSipMessageValidator.java
index 777026c..3b1b26d 100644
--- a/src/com/android/services/telephony/rcs/TransportSipMessageValidator.java
+++ b/src/com/android/services/telephony/rcs/TransportSipMessageValidator.java
@@ -16,6 +16,9 @@
package com.android.services.telephony.rcs;
+import static com.android.internal.telephony.TelephonyStatsLog.SIP_TRANSPORT_SESSION__SIP_MESSAGE_DIRECTION__INCOMING;
+import static com.android.internal.telephony.TelephonyStatsLog.SIP_TRANSPORT_SESSION__SIP_MESSAGE_DIRECTION__OUTGOING;
+
import android.telephony.ims.DelegateRegistrationState;
import android.telephony.ims.FeatureTagState;
import android.telephony.ims.SipDelegateConfiguration;
@@ -26,6 +29,8 @@
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.SipMessageParsingUtils;
+import com.android.internal.telephony.metrics.RcsStats;
import com.android.internal.util.IndentingPrintWriter;
import com.android.services.telephony.rcs.validator.IncomingTransportStateValidator;
import com.android.services.telephony.rcs.validator.MalformedSipMessageValidator;
@@ -145,11 +150,13 @@
private PendingTask mPendingClose;
private PendingRegCleanupTask mPendingRegCleanup;
private Consumer<Set<String>> mRegistrationAppliedConsumer;
+ private final RcsStats mRcsStats;
public TransportSipMessageValidator(int subId, ScheduledExecutorService executor) {
mSubId = subId;
mExecutor = executor;
- mSipSessionTracker = new SipSessionTracker();
+ mRcsStats = RcsStats.getInstance();
+ mSipSessionTracker = new SipSessionTracker(subId, mRcsStats);
mOutgoingTransportStateValidator = new OutgoingTransportStateValidator(mSipSessionTracker);
mIncomingTransportStateValidator = new IncomingTransportStateValidator();
mOutgoingMessageValidator = new MalformedSipMessageValidator().andThen(
@@ -163,7 +170,7 @@
public TransportSipMessageValidator(int subId, ScheduledExecutorService executor,
SipSessionTracker sipSessionTracker,
OutgoingTransportStateValidator outgoingStateValidator,
- IncomingTransportStateValidator incomingStateValidator) {
+ IncomingTransportStateValidator incomingStateValidator, RcsStats rcsStats) {
mSubId = subId;
mExecutor = executor;
mSipSessionTracker = sipSessionTracker;
@@ -171,6 +178,7 @@
mIncomingTransportStateValidator = incomingStateValidator;
mOutgoingMessageValidator = mOutgoingTransportStateValidator;
mIncomingMessageValidator = mIncomingTransportStateValidator;
+ mRcsStats = rcsStats;
}
/**
@@ -365,7 +373,11 @@
}
ValidationResult result = mOutgoingMessageValidator.validate(message);
logi("verifyOutgoingMessage: " + result + ", message=" + message);
- if (result.isValidated) mSipSessionTracker.filterSipMessage(message);
+ if (result.isValidated) {
+ mSipSessionTracker.filterSipMessage(
+ SIP_TRANSPORT_SESSION__SIP_MESSAGE_DIRECTION__OUTGOING, message);
+ }
+ updateForMetrics(SIP_TRANSPORT_SESSION__SIP_MESSAGE_DIRECTION__OUTGOING, message, result);
return result;
}
@@ -378,7 +390,11 @@
public ValidationResult verifyIncomingMessage(SipMessage message) {
ValidationResult result = mIncomingMessageValidator.validate(message);
logi("verifyIncomingMessage: " + result + ", message=" + message);
- if (result.isValidated) mSipSessionTracker.filterSipMessage(message);
+ if (result.isValidated) {
+ mSipSessionTracker.filterSipMessage(
+ SIP_TRANSPORT_SESSION__SIP_MESSAGE_DIRECTION__INCOMING, message);
+ }
+ updateForMetrics(SIP_TRANSPORT_SESSION__SIP_MESSAGE_DIRECTION__INCOMING, message, result);
return result;
}
@@ -539,6 +555,28 @@
.collect(Collectors.toSet());
}
+ private void updateForMetrics(int direction, SipMessage m, ValidationResult result) {
+ String[] startLineSegments = SipMessageParsingUtils
+ .splitStartLineAndVerify(m.getStartLine());
+ if (SipMessageParsingUtils.isSipRequest(m.getStartLine())) {
+ if (result.isValidated) {
+ // SipMessage add to list for Metrics stats
+ mRcsStats.onSipMessageRequest(m.getCallIdParameter(), startLineSegments[0],
+ direction);
+ } else {
+ //Message sending fail and there is no response.
+ mRcsStats.invalidatedMessageResult(mSubId, startLineSegments[0], direction,
+ result.restrictedReason);
+ }
+ } else if (SipMessageParsingUtils.isSipResponse(m.getStartLine())) {
+ int statusCode = Integer.parseInt(startLineSegments[1]);
+ mRcsStats.onSipMessageResponse(mSubId, m.getCallIdParameter(), statusCode,
+ result.restrictedReason);
+ } else {
+ logw("Message is Restricted");
+ }
+ }
+
private void logi(String log) {
Log.i(SipTransportController.LOG_TAG, LOG_TAG + "[" + mSubId + "] " + log);
mLocalLog.log("[I] " + log);
diff --git a/tests/src/com/android/phone/ImsStateCallbackControllerTest.java b/tests/src/com/android/phone/ImsStateCallbackControllerTest.java
index 75690bb..c493f6b 100644
--- a/tests/src/com/android/phone/ImsStateCallbackControllerTest.java
+++ b/tests/src/com/android/phone/ImsStateCallbackControllerTest.java
@@ -195,7 +195,7 @@
createController(1);
mImsStateCallbackController
- .registerImsStateCallback(SLOT_0_SUB_ID, FEATURE_MMTEL, mCallback0);
+ .registerImsStateCallback(SLOT_0_SUB_ID, FEATURE_MMTEL, mCallback0, "callback0");
processAllMessages();
assertTrue(mImsStateCallbackController.isRegistered(mCallback0));
verify(mCallback0, times(1)).onUnavailable(REASON_IMS_SERVICE_DISCONNECTED);
@@ -211,7 +211,7 @@
createController(1);
mImsStateCallbackController
- .registerImsStateCallback(SLOT_0_SUB_ID, FEATURE_MMTEL, mCallback0);
+ .registerImsStateCallback(SLOT_0_SUB_ID, FEATURE_MMTEL, mCallback0, "callback0");
processAllMessages();
assertTrue(mImsStateCallbackController.isRegistered(mCallback0));
verify(mCallback0, times(1)).onUnavailable(REASON_IMS_SERVICE_DISCONNECTED);
@@ -237,7 +237,7 @@
createController(1);
mImsStateCallbackController
- .registerImsStateCallback(SLOT_0_SUB_ID, FEATURE_MMTEL, mCallback0);
+ .registerImsStateCallback(SLOT_0_SUB_ID, FEATURE_MMTEL, mCallback0, "callback0");
processAllMessages();
assertTrue(mImsStateCallbackController.isRegistered(mCallback0));
verify(mCallback0, times(1)).onUnavailable(REASON_IMS_SERVICE_DISCONNECTED);
@@ -258,7 +258,7 @@
createController(1);
mImsStateCallbackController
- .registerImsStateCallback(SLOT_0_SUB_ID, FEATURE_MMTEL, mCallback0);
+ .registerImsStateCallback(SLOT_0_SUB_ID, FEATURE_MMTEL, mCallback0, "callback0");
processAllMessages();
assertTrue(mImsStateCallbackController.isRegistered(mCallback0));
verify(mCallback0, times(1)).onUnavailable(REASON_IMS_SERVICE_DISCONNECTED);
@@ -284,7 +284,7 @@
createController(1);
mImsStateCallbackController
- .registerImsStateCallback(SLOT_0_SUB_ID, FEATURE_RCS, mCallback0);
+ .registerImsStateCallback(SLOT_0_SUB_ID, FEATURE_RCS, mCallback0, "callback0");
processAllMessages();
assertTrue(mImsStateCallbackController.isRegistered(mCallback0));
verify(mCallback0, times(1)).onUnavailable(REASON_IMS_SERVICE_DISCONNECTED);
@@ -300,7 +300,7 @@
createController(1);
mImsStateCallbackController
- .registerImsStateCallback(SLOT_0_SUB_ID, FEATURE_RCS, mCallback0);
+ .registerImsStateCallback(SLOT_0_SUB_ID, FEATURE_RCS, mCallback0, "callback0");
processAllMessages();
assertTrue(mImsStateCallbackController.isRegistered(mCallback0));
verify(mCallback0, times(1)).onUnavailable(REASON_IMS_SERVICE_DISCONNECTED);
@@ -330,7 +330,7 @@
createController(1);
mImsStateCallbackController
- .registerImsStateCallback(SLOT_0_SUB_ID, FEATURE_RCS, mCallback0);
+ .registerImsStateCallback(SLOT_0_SUB_ID, FEATURE_RCS, mCallback0, "callback0");
processAllMessages();
assertTrue(mImsStateCallbackController.isRegistered(mCallback0));
verify(mCallback0, times(1)).onUnavailable(REASON_IMS_SERVICE_DISCONNECTED);
@@ -383,7 +383,7 @@
createController(1);
mImsStateCallbackController
- .registerImsStateCallback(SLOT_0_SUB_ID, FEATURE_RCS, mCallback0);
+ .registerImsStateCallback(SLOT_0_SUB_ID, FEATURE_RCS, mCallback0, "callback0");
processAllMessages();
assertTrue(mImsStateCallbackController.isRegistered(mCallback0));
verify(mCallback0, times(1)).onUnavailable(REASON_IMS_SERVICE_DISCONNECTED);
@@ -413,7 +413,7 @@
createController(1);
mImsStateCallbackController
- .registerImsStateCallback(SLOT_0_SUB_ID, FEATURE_RCS, mCallback0);
+ .registerImsStateCallback(SLOT_0_SUB_ID, FEATURE_RCS, mCallback0, "callback0");
processAllMessages();
assertTrue(mImsStateCallbackController.isRegistered(mCallback0));
verify(mCallback0, times(1)).onUnavailable(REASON_IMS_SERVICE_DISCONNECTED);
@@ -443,9 +443,9 @@
createController(2);
mImsStateCallbackController
- .registerImsStateCallback(SLOT_0_SUB_ID, FEATURE_MMTEL, mCallback0);
+ .registerImsStateCallback(SLOT_0_SUB_ID, FEATURE_MMTEL, mCallback0, "callback0");
mImsStateCallbackController
- .registerImsStateCallback(SLOT_1_SUB_ID, FEATURE_RCS, mCallback1);
+ .registerImsStateCallback(SLOT_1_SUB_ID, FEATURE_RCS, mCallback1, "callback1");
processAllMessages();
assertTrue(mImsStateCallbackController.isRegistered(mCallback0));
assertTrue(mImsStateCallbackController.isRegistered(mCallback1));
@@ -473,11 +473,11 @@
.thenReturn(false);
mImsStateCallbackController
- .registerImsStateCallback(SLOT_0_SUB_ID, FEATURE_MMTEL, mCallback0);
+ .registerImsStateCallback(SLOT_0_SUB_ID, FEATURE_MMTEL, mCallback0, "callback0");
mImsStateCallbackController
- .registerImsStateCallback(SLOT_1_SUB_ID, FEATURE_MMTEL, mCallback1);
+ .registerImsStateCallback(SLOT_1_SUB_ID, FEATURE_MMTEL, mCallback1, "callback1");
mImsStateCallbackController
- .registerImsStateCallback(SLOT_1_SUB_ID, FEATURE_RCS, mCallback2);
+ .registerImsStateCallback(SLOT_1_SUB_ID, FEATURE_RCS, mCallback2, "callback2");
processAllMessages();
assertTrue(mImsStateCallbackController.isRegistered(mCallback0));
assertTrue(mImsStateCallbackController.isRegistered(mCallback1));
@@ -609,13 +609,13 @@
// registration
mImsStateCallbackController
- .registerImsStateCallback(SLOT_0_SUB_ID, FEATURE_MMTEL, mCallback0);
+ .registerImsStateCallback(SLOT_0_SUB_ID, FEATURE_MMTEL, mCallback0, "callback0");
mImsStateCallbackController
- .registerImsStateCallback(SLOT_0_SUB_ID, FEATURE_RCS, mCallback1);
+ .registerImsStateCallback(SLOT_0_SUB_ID, FEATURE_RCS, mCallback1, "callback1");
mImsStateCallbackController
- .registerImsStateCallback(SLOT_1_SUB_ID, FEATURE_MMTEL, mCallback2);
+ .registerImsStateCallback(SLOT_1_SUB_ID, FEATURE_MMTEL, mCallback2, "callback2");
mImsStateCallbackController
- .registerImsStateCallback(SLOT_1_SUB_ID, FEATURE_RCS, mCallback3);
+ .registerImsStateCallback(SLOT_1_SUB_ID, FEATURE_RCS, mCallback3, "callback3");
processAllMessages();
assertTrue(mImsStateCallbackController.isRegistered(mCallback0));
assertTrue(mImsStateCallbackController.isRegistered(mCallback1));
diff --git a/tests/src/com/android/services/telephony/rcs/SipSessionTrackerTest.java b/tests/src/com/android/services/telephony/rcs/SipSessionTrackerTest.java
index 823a8be..37abb83 100644
--- a/tests/src/com/android/services/telephony/rcs/SipSessionTrackerTest.java
+++ b/tests/src/com/android/services/telephony/rcs/SipSessionTrackerTest.java
@@ -16,19 +16,28 @@
package com.android.services.telephony.rcs;
+import static com.android.internal.telephony.TelephonyStatsLog.SIP_TRANSPORT_SESSION__SIP_MESSAGE_DIRECTION__OUTGOING;
+
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertTrue;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.verify;
+
import android.net.Uri;
import android.telephony.ims.SipMessage;
import android.util.Base64;
import androidx.test.ext.junit.runners.AndroidJUnit4;
+import com.android.internal.telephony.metrics.RcsStats;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
import java.nio.ByteBuffer;
import java.util.Arrays;
@@ -90,11 +99,104 @@
// Keep track of the string entry so we can generate unique strings.
private int mStringEntryCounter = 0;
private SipSessionTracker mTrackerUT;
+ private static final int TEST_SUB_ID = 1;
+ private static final String TEST_INVITE_SIP_METHOD = "INVITE";
+ private static final int TEST_SIP_RESPONSE_CODE = 200;
+ private static final int TEST_SIP_CLOSE_RESPONSE_CODE = 0;
+ @Mock
+ private RcsStats mRcsStats;
@Before
public void setUp() {
mStringEntryCounter = 0;
- mTrackerUT = new SipSessionTracker();
+ MockitoAnnotations.initMocks(this);
+ mTrackerUT = new SipSessionTracker(TEST_SUB_ID, mRcsStats);
+ }
+
+ @Test
+ public void testMetricsEndedGracefullyBye() {
+ DialogAttributes attr = new DialogAttributes();
+ // INVITE
+ SipMessage inviteRequest = generateSipRequest(SipMessageUtils.INVITE_SIP_METHOD, attr);
+ filterMessage(inviteRequest, attr);
+ assertTrue(mTrackerUT.getConfirmedDialogs().isEmpty());
+ verifyContainsCallIds(mTrackerUT.getEarlyDialogs(), attr);
+
+ // confirmed dialog
+ attr.setToTag();
+ SipMessage inviteConfirm = generateSipResponse("200", "OK", attr);
+ filterMessage(inviteConfirm, attr);
+ assertTrue(mTrackerUT.getEarlyDialogs().isEmpty());
+ verifyContainsCallIds(mTrackerUT.getConfirmedDialogs(), attr);
+
+ // Gracefully Ended
+ SipMessage inviteClose = generateSipRequest(SipMessageUtils.BYE_SIP_METHOD, attr);
+ filterMessage(inviteClose, attr);
+
+ assertTrue(mTrackerUT.getEarlyDialogs().isEmpty());
+ assertTrue(mTrackerUT.getConfirmedDialogs().isEmpty());
+ verifyContainsCallIds(mTrackerUT.getClosedDialogs(), attr);
+
+ // verify Metrics information
+ verify(mRcsStats).onSipTransportSessionClosed(eq(TEST_SUB_ID), eq(attr.callId),
+ eq(TEST_SIP_CLOSE_RESPONSE_CODE), eq(true));
+ }
+
+ @Test
+ public void testMetricsCloseCleanupSession() {
+ //mTrackerUT.setRcsStats(mRcsStats);
+ DialogAttributes attr = new DialogAttributes();
+ // INVITE A -> B
+ SipMessage inviteRequest = generateSipRequest(SipMessageUtils.INVITE_SIP_METHOD, attr);
+ filterMessage(inviteRequest, attr);
+ assertTrue(mTrackerUT.getConfirmedDialogs().isEmpty());
+ verifyContainsCallIds(mTrackerUT.getEarlyDialogs(), attr);
+
+ // confirmed dialog
+ attr.setToTag();
+ SipMessage inviteConfirm = generateSipResponse("200", "OK", attr);
+ filterMessage(inviteConfirm, attr);
+ assertTrue(mTrackerUT.getEarlyDialogs().isEmpty());
+ verifyContainsCallIds(mTrackerUT.getConfirmedDialogs(), attr);
+
+ //forcefully close session
+ mTrackerUT.cleanupSession(attr.callId);
+ assertTrue(mTrackerUT.getEarlyDialogs().isEmpty());
+ assertTrue(mTrackerUT.getConfirmedDialogs().isEmpty());
+ assertTrue(mTrackerUT.getClosedDialogs().isEmpty());
+
+ // verify Metrics information
+ verify(mRcsStats).onSipTransportSessionClosed(eq(TEST_SUB_ID), eq(attr.callId),
+ eq(TEST_SIP_CLOSE_RESPONSE_CODE), eq(false));
+ }
+
+ @Test
+ public void testMetricsCloseClearAllSessions() {
+ //mTrackerUT.setRcsStats(mRcsStats);
+ DialogAttributes attr = new DialogAttributes();
+
+ // INVITE
+ SipMessage inviteRequest = generateSipRequest(SipMessageUtils.INVITE_SIP_METHOD, attr);
+ filterMessage(inviteRequest, attr);
+ assertTrue(mTrackerUT.getConfirmedDialogs().isEmpty());
+ verifyContainsCallIds(mTrackerUT.getEarlyDialogs(), attr);
+
+ // confirmed dialog
+ attr.setToTag();
+ SipMessage inviteConfirm = generateSipResponse("200", "OK", attr);
+ filterMessage(inviteConfirm, attr);
+ assertTrue(mTrackerUT.getEarlyDialogs().isEmpty());
+ verifyContainsCallIds(mTrackerUT.getConfirmedDialogs(), attr);
+
+ //forcefully close session
+ mTrackerUT.clearAllSessions();
+ assertTrue(mTrackerUT.getEarlyDialogs().isEmpty());
+ assertTrue(mTrackerUT.getConfirmedDialogs().isEmpty());
+ assertTrue(mTrackerUT.getClosedDialogs().isEmpty());
+
+ // verify Metrics information
+ verify(mRcsStats).onSipTransportSessionClosed(eq(TEST_SUB_ID), eq(attr.callId),
+ eq(TEST_SIP_CLOSE_RESPONSE_CODE), eq(false));
}
@Test
@@ -291,7 +393,8 @@
public void testAcknowledgeMessageFailed() {
DialogAttributes attr = new DialogAttributes();
SipMessage inviteRequest = generateSipRequest(SipMessageUtils.INVITE_SIP_METHOD, attr);
- mTrackerUT.filterSipMessage(inviteRequest);
+ mTrackerUT.filterSipMessage(
+ SIP_TRANSPORT_SESSION__SIP_MESSAGE_DIRECTION__OUTGOING, inviteRequest);
// Do not acknowledge the request and ensure that the operation has not been applied yet.
assertTrue(mTrackerUT.getConfirmedDialogs().isEmpty());
assertTrue(mTrackerUT.getEarlyDialogs().isEmpty());
@@ -310,8 +413,10 @@
// We unexpectedly received two filter requests for the same branchId without
// acknowledgePendingMessage being called in between. Ensure that when it is called, it
// applies both operations.
- mTrackerUT.filterSipMessage(inviteRequest);
- mTrackerUT.filterSipMessage(inviteConfirm);
+ mTrackerUT.filterSipMessage(
+ SIP_TRANSPORT_SESSION__SIP_MESSAGE_DIRECTION__OUTGOING, inviteRequest);
+ mTrackerUT.filterSipMessage(
+ SIP_TRANSPORT_SESSION__SIP_MESSAGE_DIRECTION__OUTGOING, inviteConfirm);
assertTrue(mTrackerUT.getEarlyDialogs().isEmpty());
assertTrue(mTrackerUT.getConfirmedDialogs().isEmpty());
// we should skip right to confirmed as both operations run back-to-back
@@ -321,7 +426,8 @@
}
private void filterMessage(SipMessage m, DialogAttributes attr) {
- mTrackerUT.filterSipMessage(m);
+ mTrackerUT.filterSipMessage(
+ SIP_TRANSPORT_SESSION__SIP_MESSAGE_DIRECTION__OUTGOING, m);
mTrackerUT.acknowledgePendingMessage(attr.branchId);
}
private void verifyContainsCallIds(Set<SipDialog> callIdSet, DialogAttributes... attrs) {
diff --git a/tests/src/com/android/services/telephony/rcs/TransportSipMessageValidatorTest.java b/tests/src/com/android/services/telephony/rcs/TransportSipMessageValidatorTest.java
index 4d222e3..0fe897f 100644
--- a/tests/src/com/android/services/telephony/rcs/TransportSipMessageValidatorTest.java
+++ b/tests/src/com/android/services/telephony/rcs/TransportSipMessageValidatorTest.java
@@ -16,6 +16,9 @@
package com.android.services.telephony.rcs;
+import static com.android.internal.telephony.TelephonyStatsLog.SIP_TRANSPORT_SESSION__SIP_MESSAGE_DIRECTION__INCOMING;
+import static com.android.internal.telephony.TelephonyStatsLog.SIP_TRANSPORT_SESSION__SIP_MESSAGE_DIRECTION__OUTGOING;
+
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
@@ -23,6 +26,7 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -37,6 +41,7 @@
import com.android.TelephonyTestBase;
import com.android.TestExecutorService;
+import com.android.internal.telephony.metrics.RcsStats;
import com.android.services.telephony.rcs.validator.IncomingTransportStateValidator;
import com.android.services.telephony.rcs.validator.OutgoingTransportStateValidator;
import com.android.services.telephony.rcs.validator.ValidationResult;
@@ -76,6 +81,8 @@
private IncomingTransportStateValidator mIncomingStateValidator;
@Mock
private OutgoingTransportStateValidator mOutgoingStateValidator;
+ @Mock
+ private RcsStats mRcsStats;
@Before
public void setUp() throws Exception {
@@ -117,12 +124,50 @@
}
@Test
+ public void testMetricsResponse() {
+ String testSipInviteMethod = "INVITE";
+ String testSipMessageMethod = "MESSAGE";
+ int testSipResponseCode = 200;
+ int testMessageError = 0;
+
+ TestExecutorService executor = new TestExecutorService();
+ TransportSipMessageValidator tracker = openTransport(executor);
+ // Since the incoming/outgoing messages were verified, there should have been two calls
+ // to filter the message.
+ verify(mSipSessionTracker).filterSipMessage(
+ SIP_TRANSPORT_SESSION__SIP_MESSAGE_DIRECTION__OUTGOING, TEST_MESSAGE);
+ verify(mSipSessionTracker).filterSipMessage(
+ SIP_TRANSPORT_SESSION__SIP_MESSAGE_DIRECTION__INCOMING, TEST_MESSAGE);
+
+ assertTrue(tracker.verifyOutgoingMessage(generateSipRequest("INVITE",
+ "testId1"), TEST_CONFIG_VERSION).isValidated);
+ verify(mRcsStats).onSipMessageRequest(eq("testId1"),
+ eq(testSipInviteMethod),
+ eq(SIP_TRANSPORT_SESSION__SIP_MESSAGE_DIRECTION__OUTGOING));
+
+ assertTrue(tracker.verifyOutgoingMessage(generateSipRequest("MESSAGE",
+ "testId2"), TEST_CONFIG_VERSION).isValidated);
+ verify(mRcsStats).onSipMessageRequest(eq("testId2"),
+ eq(testSipMessageMethod),
+ eq(SIP_TRANSPORT_SESSION__SIP_MESSAGE_DIRECTION__OUTGOING));
+
+ assertTrue(tracker.verifyIncomingMessage(
+ generateSipResponse("200", "OK", "testId2"))
+ .isValidated);
+ verify(mRcsStats).onSipMessageResponse(eq(TEST_SUB_ID), eq("testId2"),
+ eq(testSipResponseCode), eq(testMessageError));
+ }
+
+ @Test
public void testSessionTrackerFiltering() {
TestExecutorService executor = new TestExecutorService();
TransportSipMessageValidator tracker = openTransport(executor);
// Since the incoming/outgoing messages were verified, there should have been two calls
// to filter the message.
- verify(mSipSessionTracker, times(2)).filterSipMessage(TEST_MESSAGE);
+ verify(mSipSessionTracker).filterSipMessage(
+ SIP_TRANSPORT_SESSION__SIP_MESSAGE_DIRECTION__OUTGOING, TEST_MESSAGE);
+ verify(mSipSessionTracker).filterSipMessage(
+ SIP_TRANSPORT_SESSION__SIP_MESSAGE_DIRECTION__INCOMING, TEST_MESSAGE);
// ensure pass through methods are working
tracker.acknowledgePendingMessage("abc");
verify(mSipSessionTracker).acknowledgePendingMessage("abc");
@@ -140,7 +185,10 @@
assertFalse(tracker.verifyOutgoingMessage(TEST_MESSAGE, TEST_CONFIG_VERSION).isValidated);
// The number of times the filter method was called should still only be two after these
// messages were not validated.
- verify(mSipSessionTracker, times(2)).filterSipMessage(TEST_MESSAGE);
+ verify(mSipSessionTracker).filterSipMessage(
+ SIP_TRANSPORT_SESSION__SIP_MESSAGE_DIRECTION__OUTGOING, TEST_MESSAGE);
+ verify(mSipSessionTracker).filterSipMessage(
+ SIP_TRANSPORT_SESSION__SIP_MESSAGE_DIRECTION__INCOMING, TEST_MESSAGE);
}
@@ -482,6 +530,27 @@
doReturn(ValidationResult.SUCCESS).when(mIncomingStateValidator).validate(any());
doReturn(mIncomingStateValidator).when(mIncomingStateValidator).andThen(any());
return new TransportSipMessageValidator(TEST_SUB_ID, executor, mSipSessionTracker,
- mOutgoingStateValidator, mIncomingStateValidator);
+ mOutgoingStateValidator, mIncomingStateValidator, mRcsStats);
+ }
+
+ private SipMessage generateSipResponse(String statusCode, String statusString, String callId) {
+ String fromHeader = "Alice <sip:alice@atlanta.com>;tag=1928301774";
+ String toHeader = "Bob <sip:bob@biloxi.com>";
+ String branchId = "AAAA";
+ String fromTag = "tag=1928301774";
+ String toTag = "";
+ return SipMessageUtils.generateSipResponse(statusCode, statusString, fromHeader,
+ toHeader, branchId, callId, fromTag, toTag);
+ }
+
+ private SipMessage generateSipRequest(String requestMethod, String callId) {
+ String fromHeader = "Alice <sip:alice@atlanta.com>;tag=1928301774";
+ String toHeader = "Bob <sip:bob@biloxi.com>";
+ String branchId = "AAAA";
+ String fromTag = "tag=1928301774";
+ String toTag = "";
+ String toUri = "sip:bob@biloxi.com";
+ return SipMessageUtils.generateSipRequest(requestMethod, fromHeader, toHeader,
+ toUri, branchId, callId, fromTag, toTag);
}
}