fix TelecomManager#getters for transactional accounts
Currently, if an application registers accounts with
CAPABILITY_SUPPORTS_TRANSACTIONAL_OPERATIONS and tries to fetch
the account via a TelecomManager#getter, the account will not be
returned.
The bug is a result of the check in
PhoneAccountRegistrar#resolveComponent that ensures there is a valid
ConnectionService for the application fetching the accounts.
In U, applications that utilize accounts with
CAPABILITY_SUPPORTS_TRANSACTIONAL_OPERATIONS do not need to create a
ConnectionService. Therefore, this check should be bypassed for such
accounts.
Fixes: 266873410
Test: testFetchingTransactionalAccounts + manual
Change-Id: I7c4ba664230547bc7145c79d874bec3507101feb
diff --git a/src/com/android/server/telecom/PhoneAccountRegistrar.java b/src/com/android/server/telecom/PhoneAccountRegistrar.java
index 3c6934a..8a29955 100644
--- a/src/com/android/server/telecom/PhoneAccountRegistrar.java
+++ b/src/com/android/server/telecom/PhoneAccountRegistrar.java
@@ -873,7 +873,7 @@
public void registerPhoneAccount(PhoneAccount account) {
// Enforce the requirement that a connection service for a phone account has the correct
// permission.
- if (!hasTransactionalCallCapabilites(account) &&
+ if (!hasTransactionalCallCapabilities(account) &&
!phoneAccountRequiresBindPermission(account.getAccountHandle())) {
Log.w(this,
"Phone account %s does not have BIND_TELECOM_CONNECTION_SERVICE permission.",
@@ -1062,7 +1062,7 @@
boolean isNewAccount;
// add self-managed capability for transactional accounts that are missing it
- if (hasTransactionalCallCapabilites(account) &&
+ if (hasTransactionalCallCapabilities(account) &&
!account.hasCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED)) {
account = account.toBuilder()
.setCapabilities(account.getCapabilities()
@@ -1367,13 +1367,13 @@
* @return {@code True} if the phone account has permission.
*/
public boolean phoneAccountRequiresBindPermission(PhoneAccountHandle phoneAccountHandle) {
- List<ResolveInfo> resolveInfos = resolveComponent(phoneAccountHandle);
- if (resolveInfos.isEmpty()) {
- Log.w(this, "phoneAccount %s not found", phoneAccountHandle.getComponentName());
+ if (hasTransactionalCallCapabilities(getPhoneAccountUnchecked(phoneAccountHandle))) {
return false;
}
- if (hasTransactionalCallCapabilites(getPhoneAccountUnchecked(phoneAccountHandle))) {
+ List<ResolveInfo> resolveInfos = resolveComponent(phoneAccountHandle);
+ if (resolveInfos.isEmpty()) {
+ Log.w(this, "phoneAccount %s not found", phoneAccountHandle.getComponentName());
return false;
}
@@ -1396,7 +1396,7 @@
}
@VisibleForTesting
- public boolean hasTransactionalCallCapabilites(PhoneAccount phoneAccount) {
+ public boolean hasTransactionalCallCapabilities(PhoneAccount phoneAccount) {
if (phoneAccount == null) {
return false;
}
@@ -1530,7 +1530,10 @@
}
PhoneAccountHandle handle = m.getAccountHandle();
- if (resolveComponent(handle).isEmpty()) {
+ // PhoneAccounts with CAPABILITY_SUPPORTS_TRANSACTIONAL_OPERATIONS do not require a
+ // ConnectionService and will fail [resolveComponent(PhoneAccountHandle)]. Bypass
+ // the [resolveComponent(PhoneAccountHandle)] for transactional accounts.
+ if (!hasTransactionalCallCapabilities(m) && resolveComponent(handle).isEmpty()) {
// This component cannot be resolved anymore; skip this one.
continue;
}
diff --git a/tests/src/com/android/server/telecom/tests/PhoneAccountRegistrarTest.java b/tests/src/com/android/server/telecom/tests/PhoneAccountRegistrarTest.java
index cef032f..e573bb8 100644
--- a/tests/src/com/android/server/telecom/tests/PhoneAccountRegistrarTest.java
+++ b/tests/src/com/android/server/telecom/tests/PhoneAccountRegistrarTest.java
@@ -23,8 +23,6 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyObject;
-import static org.mockito.ArgumentMatchers.isA;
import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
@@ -707,7 +705,7 @@
.setCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED)
.build();
- assertFalse(mRegistrar.hasTransactionalCallCapabilites(accountWithoutCapability));
+ assertFalse(mRegistrar.hasTransactionalCallCapabilities(accountWithoutCapability));
try {
mRegistrar.registerPhoneAccount(accountWithoutCapability);
@@ -730,7 +728,7 @@
PhoneAccount.CAPABILITY_SUPPORTS_TRANSACTIONAL_OPERATIONS)
.build();
- assertTrue(mRegistrar.hasTransactionalCallCapabilites(accountWithCapability));
+ assertTrue(mRegistrar.hasTransactionalCallCapabilities(accountWithCapability));
try {
mRegistrar.registerPhoneAccount(accountWithCapability);
@@ -752,7 +750,7 @@
PhoneAccount.CAPABILITY_SUPPORTS_TRANSACTIONAL_OPERATIONS)
.build();
- assertTrue(mRegistrar.hasTransactionalCallCapabilites(accountWithCapability));
+ assertTrue(mRegistrar.hasTransactionalCallCapabilities(accountWithCapability));
try {
// WHEN
@@ -1684,6 +1682,24 @@
}
}
+ /**
+ * PhoneAccounts with CAPABILITY_SUPPORTS_TRANSACTIONAL_OPERATIONS do not require a
+ * ConnectionService. Ensure that such an account can be registered and fetched.
+ */
+ @Test
+ public void testFetchingTransactionalAccounts() {
+ PhoneAccount account = makeBuilderWithBindCapabilities(
+ makeQuickAccountHandle(TEST_ID)).build();
+
+ try {
+ assertEquals(0, mRegistrar.getAllPhoneAccounts(null, true).size());
+ registerAndEnableAccount(account);
+ assertEquals(1, mRegistrar.getAllPhoneAccounts(null, true).size());
+ } finally {
+ mRegistrar.unregisterPhoneAccount(account.getAccountHandle());
+ }
+ }
+
private static PhoneAccount.Builder makeBuilderWithBindCapabilities(PhoneAccountHandle handle) {
return new PhoneAccount.Builder(handle, TEST_LABEL)
.setCapabilities(PhoneAccount.CAPABILITY_SUPPORTS_TRANSACTIONAL_OPERATIONS);