Add the ability to set simultaneous calling accounts in PhoneAccount
Bug: 319904227
Test: atest CtsTelecomTestCases:PhoneAccountTest
Change-Id: I82287ed8c339785d21758c9549bc36549535011e
diff --git a/telecomm/java/android/telecom/PhoneAccount.java b/telecomm/java/android/telecom/PhoneAccount.java
index 94c737d..dedeaf6 100644
--- a/telecomm/java/android/telecom/PhoneAccount.java
+++ b/telecomm/java/android/telecom/PhoneAccount.java
@@ -18,6 +18,7 @@
import static android.Manifest.permission.MODIFY_PHONE_STATE;
+import android.annotation.FlaggedApi;
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
@@ -30,11 +31,15 @@
import android.telephony.CarrierConfigManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
+import android.util.ArraySet;
+
+import com.android.internal.telephony.flags.Flags;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
+import java.util.Set;
/**
* Represents a distinct method to place or receive a phone call. Apps which can place calls and
@@ -491,6 +496,7 @@
private final Bundle mExtras;
private boolean mIsEnabled;
private String mGroupId;
+ private final Set<PhoneAccountHandle> mSimultaneousCallingRestriction;
@Override
public boolean equals(Object o) {
@@ -508,7 +514,9 @@
Objects.equals(mShortDescription, that.mShortDescription) &&
Objects.equals(mSupportedUriSchemes, that.mSupportedUriSchemes) &&
areBundlesEqual(mExtras, that.mExtras) &&
- Objects.equals(mGroupId, that.mGroupId);
+ Objects.equals(mGroupId, that.mGroupId)
+ && Objects.equals(mSimultaneousCallingRestriction,
+ that.mSimultaneousCallingRestriction);
}
@Override
@@ -516,7 +524,7 @@
return Objects.hash(mAccountHandle, mAddress, mSubscriptionAddress, mCapabilities,
mHighlightColor, mLabel, mShortDescription, mSupportedUriSchemes,
mSupportedAudioRoutes,
- mExtras, mIsEnabled, mGroupId);
+ mExtras, mIsEnabled, mGroupId, mSimultaneousCallingRestriction);
}
/**
@@ -537,6 +545,7 @@
private Bundle mExtras;
private boolean mIsEnabled = false;
private String mGroupId = "";
+ private Set<PhoneAccountHandle> mSimultaneousCallingRestriction = null;
/**
* Creates a builder with the specified {@link PhoneAccountHandle} and label.
@@ -787,6 +796,56 @@
}
/**
+ * Restricts the ability of this {@link PhoneAccount} to ONLY support simultaneous calling
+ * with the other {@link PhoneAccountHandle}s in this Set.
+ * <p>
+ * If two or more {@link PhoneAccount}s support calling simultaneously, it means that
+ * Telecom allows the user to place additional outgoing calls and receive additional
+ * incoming calls using other {@link PhoneAccount}s while this PhoneAccount also has one or
+ * more active calls.
+ * <p>
+ * If this setter method is never called or cleared using
+ * {@link #clearSimultaneousCallingRestriction()}, there is no restriction and all
+ * {@link PhoneAccount}s registered to Telecom by this package support simultaneous calling.
+ * <p>
+ * Note: Simultaneous calling restrictions can only be placed on {@link PhoneAccount}s that
+ * were registered by the same application. Simultaneous calling across applications is
+ * always possible as long as the {@link Connection} supports hold. If a
+ * {@link PhoneAccountHandle} is included here and the package name doesn't match this
+ * application's package name, {@link TelecomManager#registerPhoneAccount(PhoneAccount)}
+ * will throw a {@link SecurityException}.
+ *
+ * @param handles The other {@link PhoneAccountHandle}s that support calling simultaneously
+ * with this one. If set to null, there is no restriction and simultaneous calling is
+ * supported across all {@link PhoneAccount}s registered by this package.
+ * @return The Builder used to set up the new PhoneAccount.
+ */
+ @FlaggedApi(Flags.FLAG_SIMULTANEOUS_CALLING_INDICATIONS)
+ public @NonNull Builder setSimultaneousCallingRestriction(
+ @NonNull Set<PhoneAccountHandle> handles) {
+ if (handles == null) {
+ throw new IllegalArgumentException("the Set of PhoneAccountHandles must not be "
+ + "null");
+ }
+ mSimultaneousCallingRestriction = handles;
+ return this;
+ }
+
+ /**
+ * Clears a previously set simultaneous calling restriction set when
+ * {@link PhoneAccount.Builder#Builder(PhoneAccount)} is used to create a new PhoneAccount
+ * from an existing one.
+ *
+ * @return The Builder used to set up the new PhoneAccount.
+ * @see #setSimultaneousCallingRestriction(Set)
+ */
+ @FlaggedApi(Flags.FLAG_SIMULTANEOUS_CALLING_INDICATIONS)
+ public @NonNull Builder clearSimultaneousCallingRestriction() {
+ mSimultaneousCallingRestriction = null;
+ return this;
+ }
+
+ /**
* Creates an instance of a {@link PhoneAccount} based on the current builder settings.
*
* @return The {@link PhoneAccount}.
@@ -810,7 +869,8 @@
mExtras,
mSupportedAudioRoutes,
mIsEnabled,
- mGroupId);
+ mGroupId,
+ mSimultaneousCallingRestriction);
}
}
@@ -827,7 +887,8 @@
Bundle extras,
int supportedAudioRoutes,
boolean isEnabled,
- String groupId) {
+ String groupId,
+ Set<PhoneAccountHandle> simultaneousCallingRestriction) {
mAccountHandle = account;
mAddress = address;
mSubscriptionAddress = subscriptionAddress;
@@ -841,6 +902,7 @@
mSupportedAudioRoutes = supportedAudioRoutes;
mIsEnabled = isEnabled;
mGroupId = groupId;
+ mSimultaneousCallingRestriction = simultaneousCallingRestriction;
}
public static Builder builder(
@@ -1050,6 +1112,49 @@
return (mCapabilities & CAPABILITY_SELF_MANAGED) == CAPABILITY_SELF_MANAGED;
}
+ /**
+ * If a restriction is set (see {@link #hasSimultaneousCallingRestriction()}), this method
+ * returns the Set of {@link PhoneAccountHandle}s that are allowed to support calls
+ * simultaneously with this {@link PhoneAccount}.
+ * <p>
+ * If this {@link PhoneAccount} is busy with one or more ongoing calls, a restriction is set on
+ * this PhoneAccount (see {@link #hasSimultaneousCallingRestriction()} to check), and a new
+ * incoming or outgoing call is received or placed on a PhoneAccount that is not in this Set,
+ * Telecom will reject or cancel the pending call in favor of keeping the ongoing call alive.
+ * <p>
+ * Note: Simultaneous calling restrictions can only be placed on {@link PhoneAccount}s that
+ * were registered by the same application. Simultaneous calling across applications is
+ * always possible as long as the {@link Connection} supports hold.
+ *
+ * @return the Set of {@link PhoneAccountHandle}s that this {@link PhoneAccount} supports
+ * simultaneous calls with.
+ * @throws IllegalStateException If there is no restriction set on this {@link PhoneAccount}
+ * and this method is called. Whether or not there is a restriction can be checked using
+ * {@link #hasSimultaneousCallingRestriction()}.
+ */
+ @FlaggedApi(Flags.FLAG_SIMULTANEOUS_CALLING_INDICATIONS)
+ public @NonNull Set<PhoneAccountHandle> getSimultaneousCallingRestriction() {
+ if (mSimultaneousCallingRestriction == null) {
+ throw new IllegalStateException("This method can not be called if there is no "
+ + "simultaneous calling restriction. See #hasSimultaneousCallingRestriction");
+ }
+ return mSimultaneousCallingRestriction;
+ }
+
+ /**
+ * Whether or not this {@link PhoneAccount} contains a simultaneous calling restriction on it.
+ *
+ * @return {@code true} if this PhoneAccount contains a simultaneous calling restriction,
+ * {@code false} if it does not. Use {@link #getSimultaneousCallingRestriction()} to query which
+ * other {@link PhoneAccount}s support simultaneous calling with this one.
+ * @see #getSimultaneousCallingRestriction() for more information on how the sinultaneous
+ * calling restriction works.
+ */
+ @FlaggedApi(Flags.FLAG_SIMULTANEOUS_CALLING_INDICATIONS)
+ public boolean hasSimultaneousCallingRestriction() {
+ return mSimultaneousCallingRestriction != null;
+ }
+
//
// Parcelable implementation
//
@@ -1095,6 +1200,12 @@
out.writeBundle(mExtras);
out.writeString(mGroupId);
out.writeInt(mSupportedAudioRoutes);
+ if (mSimultaneousCallingRestriction == null) {
+ out.writeBoolean(false);
+ } else {
+ out.writeBoolean(true);
+ out.writeTypedList(mSimultaneousCallingRestriction.stream().toList());
+ }
}
public static final @android.annotation.NonNull Creator<PhoneAccount> CREATOR
@@ -1140,6 +1251,13 @@
mExtras = in.readBundle();
mGroupId = in.readString();
mSupportedAudioRoutes = in.readInt();
+ if (in.readBoolean()) {
+ List<PhoneAccountHandle> list = new ArrayList<>();
+ in.readTypedList(list, PhoneAccountHandle.CREATOR);
+ mSimultaneousCallingRestriction = new ArraySet<>(list);
+ } else {
+ mSimultaneousCallingRestriction = null;
+ }
}
@Override