diff options
Diffstat (limited to 'src/com/android/server/telecom/PhoneAccountRegistrar.java')
-rw-r--r-- | src/com/android/server/telecom/PhoneAccountRegistrar.java | 119 |
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(); |