summaryrefslogtreecommitdiff
path: root/src/com/android/server/telecom/PhoneAccountRegistrar.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/server/telecom/PhoneAccountRegistrar.java')
-rw-r--r--src/com/android/server/telecom/PhoneAccountRegistrar.java119
1 files changed, 102 insertions, 17 deletions
diff --git a/src/com/android/server/telecom/PhoneAccountRegistrar.java b/src/com/android/server/telecom/PhoneAccountRegistrar.java
index acf07e35a..5f23e4d70 100644
--- a/src/com/android/server/telecom/PhoneAccountRegistrar.java
+++ b/src/com/android/server/telecom/PhoneAccountRegistrar.java
@@ -61,6 +61,7 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.XmlUtils;
import com.android.modules.utils.ModifiedUtf8;
+import com.android.server.telecom.flags.Flags;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -389,26 +390,62 @@ public class PhoneAccountRegistrar {
account.getGroupId()));
}
- // Potentially update the default voice subid in SubscriptionManager.
+ // Potentially update the default voice subid in SubscriptionManager so that Telephony and
+ // Telecom are in sync.
int newSubId = accountHandle == null ? SubscriptionManager.INVALID_SUBSCRIPTION_ID :
getSubscriptionIdForPhoneAccount(accountHandle);
- if (isSimAccount || accountHandle == null) {
- int currentVoiceSubId = mSubscriptionManager.getDefaultVoiceSubscriptionId();
- if (newSubId != currentVoiceSubId) {
- Log.i(this, "setUserSelectedOutgoingPhoneAccount: update voice sub; "
- + "account=%s, subId=%d", accountHandle, newSubId);
- mSubscriptionManager.setDefaultVoiceSubscriptionId(newSubId);
+ if (Flags.onlyUpdateTelephonyOnValidSubIds()) {
+ if (shouldUpdateTelephonyDefaultVoiceSubId(accountHandle, isSimAccount, newSubId)) {
+ updateDefaultVoiceSubId(newSubId, accountHandle);
} else {
- Log.i(this, "setUserSelectedOutgoingPhoneAccount: no change to voice sub");
+ Log.i(this, "setUserSelectedOutgoingPhoneAccount: %s is not a sub", accountHandle);
}
} else {
- Log.i(this, "setUserSelectedOutgoingPhoneAccount: %s is not a sub", accountHandle);
+ if (isSimAccount || accountHandle == null) {
+ updateDefaultVoiceSubId(newSubId, accountHandle);
+ } else {
+ Log.i(this, "setUserSelectedOutgoingPhoneAccount: %s is not a sub", accountHandle);
+ }
}
-
write();
fireDefaultOutgoingChanged();
}
+ private void updateDefaultVoiceSubId(int newSubId, PhoneAccountHandle accountHandle){
+ int currentVoiceSubId = mSubscriptionManager.getDefaultVoiceSubscriptionId();
+ if (newSubId != currentVoiceSubId) {
+ Log.i(this, "setUserSelectedOutgoingPhoneAccount: update voice sub; "
+ + "account=%s, subId=%d", accountHandle, newSubId);
+ mSubscriptionManager.setDefaultVoiceSubscriptionId(newSubId);
+ } else {
+ Log.i(this, "setUserSelectedOutgoingPhoneAccount: no change to voice sub");
+ }
+ }
+
+ // This helper is important for CTS testing. [PhoneAccount]s created by Telecom in CTS are
+ // assigned a subId value of INVALID_SUBSCRIPTION_ID (-1) by Telephony. However, when
+ // Telephony has a default outgoing calling voice account of -1, that translates to no default
+ // account (user should be prompted to select an acct when making MOs). In order to avoid
+ // Telephony clearing out the newly changed default [PhoneAccount] in Telecom, Telephony should
+ // not be updated. This situation will never occur in production since [PhoneAccount]s in
+ // production are assigned non-negative subId values.
+ private boolean shouldUpdateTelephonyDefaultVoiceSubId(PhoneAccountHandle phoneAccountHandle,
+ boolean isSimAccount, int newSubId) {
+ // user requests no call preference
+ if (phoneAccountHandle == null) {
+ return true;
+ }
+ // do not update Telephony if the newSubId is invalid
+ if (newSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+ Log.w(this, "shouldUpdateTelephonyDefaultVoiceSubId: "
+ + "invalid subId scenario, not updating Telephony. "
+ + "phoneAccountHandle=[%s], isSimAccount=[%b], newSubId=[%s]",
+ phoneAccountHandle, isSimAccount, newSubId);
+ return false;
+ }
+ return isSimAccount;
+ }
+
boolean isUserSelectedSmsPhoneAccount(PhoneAccountHandle accountHandle) {
return getSubscriptionIdForPhoneAccount(accountHandle) ==
SubscriptionManager.getDefaultSmsSubscriptionId();
@@ -897,13 +934,15 @@ public class PhoneAccountRegistrar {
* @throws IllegalArgumentException if MAX_PHONE_ACCOUNT_REGISTRATIONS are reached
*/
private void enforceMaxPhoneAccountLimit(@NonNull PhoneAccount account) {
- final PhoneAccountHandle accountHandle = account.getAccountHandle();
- final UserHandle user = accountHandle.getUserHandle();
- final ComponentName componentName = accountHandle.getComponentName();
-
- if (getPhoneAccountHandles(0, null, componentName.getPackageName(),
- true /* includeDisabled */, user, false /* crossUserAccess */).size()
- >= MAX_PHONE_ACCOUNT_REGISTRATIONS) {
+ List<PhoneAccount> unverifiedAccounts = getAccountsForPackage_BypassResolveComp(
+ account.getAccountHandle().getComponentName().getPackageName(),
+ account.getAccountHandle().getUserHandle());
+ // verify each phone account is backed by a valid ConnectionService. If the
+ // ConnectionService has been disabled or cannot be resolved, unregister the accounts.
+ List<PhoneAccount> verifiedAccounts =
+ cleanupUnresolvableConnectionServiceAccounts(unverifiedAccounts);
+ // enforce the max phone account limit for the application registering accounts
+ if (verifiedAccounts.size() >= MAX_PHONE_ACCOUNT_REGISTRATIONS) {
EventLog.writeEvent(0x534e4554, "259064622", Binder.getCallingUid(),
"enforceMaxPhoneAccountLimit");
throw new IllegalArgumentException(
@@ -1550,6 +1589,51 @@ public class PhoneAccountRegistrar {
}
/**
+ * This getter should be used when you want to bypass the {@link
+ * PhoneAccountRegistrar#resolveComponent(PhoneAccountHandle)} check when fetching accounts
+ */
+ @VisibleForTesting
+ public List<PhoneAccount> getAccountsForPackage_BypassResolveComp(String packageName,
+ UserHandle userHandle) {
+ List<PhoneAccount> accounts = new ArrayList<>(mState.accounts.size());
+ for (PhoneAccount m : mState.accounts) {
+ PhoneAccountHandle handle = m.getAccountHandle();
+
+ if (packageName != null && !packageName.equals(
+ handle.getComponentName().getPackageName())) {
+ // Not the right package name; skip this one.
+ continue;
+ }
+
+ if (!isVisibleForUser(m, userHandle, false)) {
+ // Account is not visible for the current user; skip this one.
+ continue;
+ }
+ accounts.add(m);
+ }
+ return accounts;
+ }
+
+ @VisibleForTesting
+ public List<PhoneAccount> cleanupUnresolvableConnectionServiceAccounts(
+ List<PhoneAccount> accounts) {
+ ArrayList<PhoneAccount> verifiedAccounts = new ArrayList<>();
+ for (PhoneAccount account : accounts) {
+ PhoneAccountHandle handle = account.getAccountHandle();
+ // if the ConnectionService has been disabled or can longer be found, remove the handle
+ if (resolveComponent(handle).isEmpty()) {
+ Log.i(this,
+ "Cannot resolve the ConnectionService for handle=[%s]; unregistering"
+ + " account", handle);
+ unregisterPhoneAccount(handle);
+ } else {
+ verifiedAccounts.add(account);
+ }
+ }
+ return verifiedAccounts;
+ }
+
+ /**
* Clean up the orphan {@code PhoneAccount}. An orphan {@code PhoneAccount} is a phone
* account that does not have a {@code UserHandle} or belongs to a deleted package.
*
@@ -1662,6 +1746,7 @@ public class PhoneAccountRegistrar {
} else {
pw.println(defaultOutgoing);
}
+ pw.println("defaultVoiceSubId: " + SubscriptionManager.getDefaultVoiceSubscriptionId());
pw.println("simCallManager: " + getSimCallManager(mCurrentUserHandle));
pw.println("phoneAccounts:");
pw.increaseIndent();