Fix potential NPE during initialization
1) Guard TelephonyRcsService from null PersistableBundles
from CarrierConfigManager in the scenarios where we are receving
non-INVALID subIds during initialization.
2) Ensure that CarrierConfigLoader is initialized before
TelephonyRcsService needs to use it.
Bug: 266581853
Test: flash on device, ensure calls/sms/UCE works properly
Change-Id: Ia34ead1bcddedf75613a05b81c2b77861201e7b2
diff --git a/src/com/android/phone/PhoneGlobals.java b/src/com/android/phone/PhoneGlobals.java
index 78a734a..200dc75 100644
--- a/src/com/android/phone/PhoneGlobals.java
+++ b/src/com/android/phone/PhoneGlobals.java
@@ -527,6 +527,8 @@
imsRcsController = ImsRcsController.init(this);
+ configLoader = CarrierConfigLoader.init(this);
+
if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY_IMS)) {
mImsStateCallbackController =
ImsStateCallbackController.make(this, PhoneFactory.getPhones().length);
@@ -538,8 +540,6 @@
ImsProvisioningController.make(this, PhoneFactory.getPhones().length);
}
- configLoader = CarrierConfigLoader.init(this);
-
// Create the CallNotifier singleton, which handles
// asynchronous events from the telephony layer (like
// launching the incoming-call UI when an incoming call comes
diff --git a/src/com/android/services/telephony/rcs/TelephonyRcsService.java b/src/com/android/services/telephony/rcs/TelephonyRcsService.java
index 13b3a7d..3a8ad62 100644
--- a/src/com/android/services/telephony/rcs/TelephonyRcsService.java
+++ b/src/com/android/services/telephony/rcs/TelephonyRcsService.java
@@ -25,6 +25,7 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
+import android.os.PersistableBundle;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
import android.util.Log;
@@ -351,23 +352,17 @@
private boolean doesSubscriptionSupportPresence(int subId) {
if (!SubscriptionManager.isValidSubscriptionId(subId)) return false;
- CarrierConfigManager carrierConfigManager =
- mContext.getSystemService(CarrierConfigManager.class);
- if (carrierConfigManager == null) return false;
- boolean supportsUce = carrierConfigManager.getConfigForSubId(subId).getBoolean(
- CarrierConfigManager.Ims.KEY_ENABLE_PRESENCE_PUBLISH_BOOL);
- supportsUce |= carrierConfigManager.getConfigForSubId(subId).getBoolean(
- CarrierConfigManager.KEY_USE_RCS_SIP_OPTIONS_BOOL);
+ boolean supportsUce = getConfig(subId,
+ CarrierConfigManager.Ims.KEY_ENABLE_PRESENCE_PUBLISH_BOOL, false /*default*/);
+ supportsUce |= getConfig(subId,
+ CarrierConfigManager.KEY_USE_RCS_SIP_OPTIONS_BOOL, false /*default*/);
return supportsUce;
}
private boolean doesSubscriptionSupportSingleRegistration(int subId) {
if (!SubscriptionManager.isValidSubscriptionId(subId)) return false;
- CarrierConfigManager carrierConfigManager =
- mContext.getSystemService(CarrierConfigManager.class);
- if (carrierConfigManager == null) return false;
- return carrierConfigManager.getConfigForSubId(subId).getBoolean(
- CarrierConfigManager.Ims.KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL);
+ return getConfig(subId, CarrierConfigManager.Ims.KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL,
+ false /*defaultValue*/);
}
private int getSubscriptionFromSlot(int slotId) {
@@ -384,6 +379,16 @@
}
/**
+ * @return the boolean result corresponding to a boolean {@link CarrierConfigManager} key.
+ */
+ private boolean getConfig(int subId, String key, boolean defaultValue) {
+ CarrierConfigManager c = mContext.getSystemService(CarrierConfigManager.class);
+ if (c == null) return defaultValue;
+ PersistableBundle b = c.getConfigForSubId(subId, key);
+ return b != null ? b.getBoolean(key, defaultValue) : defaultValue;
+ }
+
+ /**
* Dump this instance into a readable format for dumpsys usage.
*/
public void dump(FileDescriptor fd, PrintWriter printWriter, String[] args) {
diff --git a/tests/src/com/android/TestContext.java b/tests/src/com/android/TestContext.java
index 720d235..111df53 100644
--- a/tests/src/com/android/TestContext.java
+++ b/tests/src/com/android/TestContext.java
@@ -17,6 +17,7 @@
package com.android;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doAnswer;
import android.content.AttributionSource;
@@ -73,13 +74,12 @@
MockitoAnnotations.initMocks(this);
doAnswer((Answer<PersistableBundle>) invocation -> {
int subId = (int) invocation.getArguments()[0];
- if (subId < 0) {
- return new PersistableBundle();
- }
- PersistableBundle b = mCarrierConfigs.get(subId);
-
- return (b != null ? b : new PersistableBundle());
+ return getTestConfigs(subId);
}).when(mMockCarrierConfigManager).getConfigForSubId(anyInt());
+ doAnswer((Answer<PersistableBundle>) invocation -> {
+ int subId = (int) invocation.getArguments()[0];
+ return getTestConfigs(subId);
+ }).when(mMockCarrierConfigManager).getConfigForSubId(anyInt(), anyString());
}
@Override
@@ -252,18 +252,16 @@
public void grantPermission(String permission) {
synchronized (mPermissionTable) {
- if (mPermissionTable != null && permission != null) {
- mPermissionTable.remove(STUB_PERMISSION_ENABLE_ALL);
- mPermissionTable.add(permission);
- }
+ if (permission == null) return;
+ mPermissionTable.remove(STUB_PERMISSION_ENABLE_ALL);
+ mPermissionTable.add(permission);
}
}
public void revokePermission(String permission) {
synchronized (mPermissionTable) {
- if (mPermissionTable != null && permission != null) {
- mPermissionTable.remove(permission);
- }
+ if (permission == null) return;
+ mPermissionTable.remove(permission);
}
}
@@ -281,6 +279,14 @@
return mReceiver;
}
+ private PersistableBundle getTestConfigs(int subId) {
+ if (subId < 0) {
+ return new PersistableBundle();
+ }
+ PersistableBundle b = getCarrierConfig(subId);
+ return (b != null ? b : new PersistableBundle());
+ }
+
private static void logd(String s) {
Log.d(TAG, s);
}