ImsService Subscription Notifications

Provide a new API in ImsService that creates a new version of each ImsFeature and dependencies when a new subId is loaded.
The ImsService handles ImsFeature setup and teardown procedures to happen on a per-subscription basis instead of on a per-slot basis.
Provide the compatibility behavior for older devices that are not upgrading to using the new API.

Bug: 197991451
Test: atest FrameworksTelephonyTests:ImsServiceTest, atest CtsTelephonyTestCases:ImsServiceTest
Merged-In: I231da2f4479d4a4fb272edbf27e49f46833a082a
Change-Id: I231da2f4479d4a4fb272edbf27e49f46833a082a
This commit is contained in:
Jonggeon Kim
2021-11-25 10:16:57 +00:00
committed by Hakjun Choi
parent e5c38399ec
commit 5e08b37786
4 changed files with 232 additions and 42 deletions

View File

@@ -12921,14 +12921,21 @@ package android.telephony.ims {
public class ImsService extends android.app.Service { public class ImsService extends android.app.Service {
ctor public ImsService(); ctor public ImsService();
method public android.telephony.ims.feature.MmTelFeature createMmTelFeature(int); method @Nullable public android.telephony.ims.feature.MmTelFeature createEmergencyOnlyMmTelFeature(int);
method public android.telephony.ims.feature.RcsFeature createRcsFeature(int); method @Deprecated public android.telephony.ims.feature.MmTelFeature createMmTelFeature(int);
method public void disableIms(int); method @Nullable public android.telephony.ims.feature.MmTelFeature createMmTelFeatureForSubscription(int, int);
method public void enableIms(int); method @Deprecated public android.telephony.ims.feature.RcsFeature createRcsFeature(int);
method public android.telephony.ims.stub.ImsConfigImplBase getConfig(int); method @Nullable public android.telephony.ims.feature.RcsFeature createRcsFeatureForSubscription(int, int);
method @Deprecated public void disableIms(int);
method public void disableImsForSubscription(int, int);
method @Deprecated public void enableIms(int);
method public void enableImsForSubscription(int, int);
method @Deprecated public android.telephony.ims.stub.ImsConfigImplBase getConfig(int);
method @NonNull public android.telephony.ims.stub.ImsConfigImplBase getConfigForSubscription(int, int);
method @NonNull public java.util.concurrent.Executor getExecutor(); method @NonNull public java.util.concurrent.Executor getExecutor();
method public long getImsServiceCapabilities(); method public long getImsServiceCapabilities();
method public android.telephony.ims.stub.ImsRegistrationImplBase getRegistration(int); method @Deprecated public android.telephony.ims.stub.ImsRegistrationImplBase getRegistration(int);
method @NonNull public android.telephony.ims.stub.ImsRegistrationImplBase getRegistrationForSubscription(int, int);
method @Nullable public android.telephony.ims.stub.SipTransportImplBase getSipTransport(int); method @Nullable public android.telephony.ims.stub.SipTransportImplBase getSipTransport(int);
method public final void onUpdateSupportedImsFeatures(android.telephony.ims.stub.ImsFeatureConfiguration) throws android.os.RemoteException; method public final void onUpdateSupportedImsFeatures(android.telephony.ims.stub.ImsFeatureConfiguration) throws android.os.RemoteException;
method public android.telephony.ims.stub.ImsFeatureConfiguration querySupportedImsFeatures(); method public android.telephony.ims.stub.ImsFeatureConfiguration querySupportedImsFeatures();

View File

@@ -42,6 +42,7 @@ import android.telephony.ims.stub.ImsRegistrationImplBase;
import android.telephony.ims.stub.SipTransportImplBase; import android.telephony.ims.stub.SipTransportImplBase;
import android.util.Log; import android.util.Log;
import android.util.SparseArray; import android.util.SparseArray;
import android.util.SparseBooleanArray;
import com.android.ims.internal.IImsFeatureStatusCallback; import com.android.ims.internal.IImsFeatureStatusCallback;
import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting;
@@ -180,6 +181,12 @@ public class ImsService extends Service {
// call ImsFeature#onFeatureRemoved. // call ImsFeature#onFeatureRemoved.
private final SparseArray<SparseArray<ImsFeature>> mFeaturesBySlot = new SparseArray<>(); private final SparseArray<SparseArray<ImsFeature>> mFeaturesBySlot = new SparseArray<>();
// A map of slot id -> boolean array, where each entry in the boolean array corresponds to an
// ImsFeature that was created for a slot id and not a sub id for backwards compatibility
// purposes.
private final SparseArray<SparseBooleanArray> mCreateImsFeatureWithSlotIdFlagMap =
new SparseArray<>();
private IImsServiceControllerListener mListener; private IImsServiceControllerListener mListener;
private Executor mExecutor; private Executor mExecutor;
@@ -222,15 +229,36 @@ public class ImsService extends Service {
} }
@Override @Override
public IImsMmTelFeature createMmTelFeature(int slotId) { public IImsMmTelFeature createMmTelFeature(int slotId, int subId) {
return executeMethodAsyncForResult(() -> createMmTelFeatureInternal(slotId), MmTelFeature f = (MmTelFeature) getImsFeature(slotId, ImsFeature.FEATURE_MMTEL);
"createMmTelFeature"); if (f == null) {
return executeMethodAsyncForResult(() -> createMmTelFeatureInternal(slotId, subId),
"createMmTelFeature");
} else {
return f.getBinder();
}
} }
@Override @Override
public IImsRcsFeature createRcsFeature(int slotId) { public IImsMmTelFeature createEmergencyOnlyMmTelFeature(int slotId) {
return executeMethodAsyncForResult(() -> createRcsFeatureInternal(slotId), MmTelFeature f = (MmTelFeature) getImsFeature(slotId, ImsFeature.FEATURE_MMTEL);
"createRcsFeature"); if (f == null) {
return executeMethodAsyncForResult(() -> createEmergencyOnlyMmTelFeatureInternal(
slotId), "createEmergencyOnlyMmTelFeature");
} else {
return f.getBinder();
}
}
@Override
public IImsRcsFeature createRcsFeature(int slotId, int subId) {
RcsFeature f = (RcsFeature) getImsFeature(slotId, ImsFeature.FEATURE_RCS);
if (f == null) {
return executeMethodAsyncForResult(() ->
createRcsFeatureInternal(slotId, subId), "createRcsFeature");
} else {
return f.getBinder();
}
} }
@Override @Override
@@ -248,9 +276,14 @@ public class ImsService extends Service {
} }
@Override @Override
public void removeImsFeature(int slotId, int featureType) { public void removeImsFeature(int slotId, int featureType, boolean changeSubId) {
if (changeSubId && isImsFeatureCreatedForSlot(slotId, featureType)) {
Log.w(LOG_TAG, "Do not remove Ims feature for compatibility");
return;
}
executeMethodAsync(() -> ImsService.this.removeImsFeature(slotId, featureType), executeMethodAsync(() -> ImsService.this.removeImsFeature(slotId, featureType),
"removeImsFeature"); "removeImsFeature");
setImsFeatureCreatedForSlot(slotId, featureType, false);
} }
@Override @Override
@@ -279,9 +312,10 @@ public class ImsService extends Service {
} }
@Override @Override
public IImsConfig getConfig(int slotId) { public IImsConfig getConfig(int slotId, int subId) {
return executeMethodAsyncForResult(() -> { return executeMethodAsyncForResult(() -> {
ImsConfigImplBase c = ImsService.this.getConfig(slotId); ImsConfigImplBase c =
ImsService.this.getConfigForSubscription(slotId, subId);
if (c != null) { if (c != null) {
c.setDefaultExecutor(mExecutor); c.setDefaultExecutor(mExecutor);
return c.getIImsConfig(); return c.getIImsConfig();
@@ -292,9 +326,10 @@ public class ImsService extends Service {
} }
@Override @Override
public IImsRegistration getRegistration(int slotId) { public IImsRegistration getRegistration(int slotId, int subId) {
return executeMethodAsyncForResult(() -> { return executeMethodAsyncForResult(() -> {
ImsRegistrationImplBase r = ImsService.this.getRegistration(slotId); ImsRegistrationImplBase r =
ImsService.this.getRegistrationForSubscription(slotId, subId);
if (r != null) { if (r != null) {
r.setDefaultExecutor(mExecutor); r.setDefaultExecutor(mExecutor);
return r.getBinder(); return r.getBinder();
@@ -318,13 +353,15 @@ public class ImsService extends Service {
} }
@Override @Override
public void enableIms(int slotId) { public void enableIms(int slotId, int subId) {
executeMethodAsync(() -> ImsService.this.enableIms(slotId), "enableIms"); executeMethodAsync(() ->
ImsService.this.enableImsForSubscription(slotId, subId), "enableIms");
} }
@Override @Override
public void disableIms(int slotId) { public void disableIms(int slotId, int subId) {
executeMethodAsync(() -> ImsService.this.disableIms(slotId), "disableIms"); executeMethodAsync(() ->
ImsService.this.disableImsForSubscription(slotId, subId), "disableIms");
} }
// Call the methods with a clean calling identity on the executor and wait indefinitely for // Call the methods with a clean calling identity on the executor and wait indefinitely for
@@ -364,16 +401,8 @@ public class ImsService extends Service {
return null; return null;
} }
/** private IImsMmTelFeature createMmTelFeatureInternal(int slotId, int subscriptionId) {
* @hide MmTelFeature f = createMmTelFeatureForSubscription(slotId, subscriptionId);
*/
@VisibleForTesting
public SparseArray<ImsFeature> getFeatures(int slotId) {
return mFeaturesBySlot.get(slotId);
}
private IImsMmTelFeature createMmTelFeatureInternal(int slotId) {
MmTelFeature f = createMmTelFeature(slotId);
if (f != null) { if (f != null) {
setupFeature(f, slotId, ImsFeature.FEATURE_MMTEL); setupFeature(f, slotId, ImsFeature.FEATURE_MMTEL);
f.setDefaultExecutor(mExecutor); f.setDefaultExecutor(mExecutor);
@@ -384,8 +413,20 @@ public class ImsService extends Service {
} }
} }
private IImsRcsFeature createRcsFeatureInternal(int slotId) { private IImsMmTelFeature createEmergencyOnlyMmTelFeatureInternal(int slotId) {
RcsFeature f = createRcsFeature(slotId); MmTelFeature f = createEmergencyOnlyMmTelFeature(slotId);
if (f != null) {
setupFeature(f, slotId, ImsFeature.FEATURE_MMTEL);
f.setDefaultExecutor(mExecutor);
return f.getBinder();
} else {
Log.e(LOG_TAG, "createEmergencyOnlyMmTelFeatureInternal: null feature returned.");
return null;
}
}
private IImsRcsFeature createRcsFeatureInternal(int slotId, int subI) {
RcsFeature f = createRcsFeatureForSubscription(slotId, subI);
if (f != null) { if (f != null) {
f.setDefaultExecutor(mExecutor); f.setDefaultExecutor(mExecutor);
setupFeature(f, slotId, ImsFeature.FEATURE_RCS); setupFeature(f, slotId, ImsFeature.FEATURE_RCS);
@@ -466,6 +507,49 @@ public class ImsService extends Service {
f.onFeatureRemoved(); f.onFeatureRemoved();
features.remove(featureType); features.remove(featureType);
} }
}
/**
* @hide
*/
@VisibleForTesting
public ImsFeature getImsFeature(int slotId, int featureType) {
synchronized (mFeaturesBySlot) {
// Get SparseArray for Features, by querying slot Id
SparseArray<ImsFeature> features = mFeaturesBySlot.get(slotId);
if (features == null) {
return null;
}
return features.get(featureType);
}
}
private void setImsFeatureCreatedForSlot(int slotId,
@ImsFeature.FeatureType int featureType, boolean createdForSlot) {
synchronized (mCreateImsFeatureWithSlotIdFlagMap) {
getImsFeatureCreatedForSlot(slotId).put(featureType, createdForSlot);
}
}
/**
* @hide
*/
@VisibleForTesting
public boolean isImsFeatureCreatedForSlot(int slotId,
@ImsFeature.FeatureType int featureType) {
synchronized (mCreateImsFeatureWithSlotIdFlagMap) {
return getImsFeatureCreatedForSlot(slotId).get(featureType);
}
}
private SparseBooleanArray getImsFeatureCreatedForSlot(int slotId) {
SparseBooleanArray createFlag = mCreateImsFeatureWithSlotIdFlagMap.get(slotId);
if (createFlag == null) {
createFlag = new SparseBooleanArray();
mCreateImsFeatureWithSlotIdFlagMap.put(slotId, createFlag);
}
return createFlag;
} }
/** /**
@@ -523,28 +607,96 @@ public class ImsService extends Service {
public void readyForFeatureCreation() { public void readyForFeatureCreation() {
} }
/**
* The framework has enabled IMS for the subscription specified, the ImsService should register
* for IMS and perform all appropriate initialization to bring up all ImsFeatures.
*
* @param slotId The slot ID that IMS will be enabled for.
* @param subscriptionId The subscription ID that IMS will be enabled for.
*/
public void enableImsForSubscription(int slotId, int subscriptionId) {
enableIms(slotId);
}
/**
* The framework has disabled IMS for the subscription specified. The ImsService must deregister
* for IMS and set capability status to false for all ImsFeatures.
* @param slotId The slot ID that IMS will be disabled for.
* @param subscriptionId The subscription ID that IMS will be disabled for.
*/
public void disableImsForSubscription(int slotId, int subscriptionId) {
disableIms(slotId);
}
/** /**
* The framework has enabled IMS for the slot specified, the ImsService should register for IMS * The framework has enabled IMS for the slot specified, the ImsService should register for IMS
* and perform all appropriate initialization to bring up all ImsFeatures. * and perform all appropriate initialization to bring up all ImsFeatures.
* @deprecated Use {@link #enableImsForSubscription} instead.
*/ */
@Deprecated
public void enableIms(int slotId) { public void enableIms(int slotId) {
} }
/** /**
* The framework has disabled IMS for the slot specified. The ImsService must deregister for IMS * The framework has disabled IMS for the slot specified. The ImsService must deregister for IMS
* and set capability status to false for all ImsFeatures. * and set capability status to false for all ImsFeatures.
* @deprecated Use {@link #disableImsForSubscription} instead.
*/ */
@Deprecated
public void disableIms(int slotId) { public void disableIms(int slotId) {
} }
/**
* When called, the framework is requesting that a new {@link MmTelFeature} is created for the
* specified subscription.
*
* @param subscriptionId The subscription ID that the MMTEL Feature is being created for.
* @return The newly created {@link MmTelFeature} associated with the subscription or null if
* the feature is not supported.
*/
public @Nullable MmTelFeature createMmTelFeatureForSubscription(int slotId,
int subscriptionId) {
setImsFeatureCreatedForSlot(slotId, ImsFeature.FEATURE_MMTEL, true);
return createMmTelFeature(slotId);
}
/**
* When called, the framework is requesting that a new {@link RcsFeature} is created for the
* specified subscription.
*
* @param subscriptionId The subscription ID that the RCS Feature is being created for.
* @return The newly created {@link RcsFeature} associated with the subscription or null if the
* feature is not supported.
*/
public @Nullable RcsFeature createRcsFeatureForSubscription(int slotId, int subscriptionId) {
setImsFeatureCreatedForSlot(slotId, ImsFeature.FEATURE_RCS, true);
return createRcsFeature(slotId);
}
/**
* When called, the framework is requesting that a new emergency-only {@link MmTelFeature} is
* created for the specified slot. For emergency calls, there is no known Subscription Id.
*
* @param slotId The slot ID that the MMTEL Feature is being created for.
* @return An MmTelFeature instance to be used for the slot ID when there is not
* subscription inserted. Only requested when there is no subscription active on
* the specified slot.
*/
public @Nullable MmTelFeature createEmergencyOnlyMmTelFeature(int slotId) {
setImsFeatureCreatedForSlot(slotId, ImsFeature.FEATURE_MMTEL, true);
return createMmTelFeature(slotId);
}
/** /**
* When called, the framework is requesting that a new {@link MmTelFeature} is created for the * When called, the framework is requesting that a new {@link MmTelFeature} is created for the
* specified slot. * specified slot.
* @deprecated Use {@link #createMmTelFeatureForSubscription} instead
* *
* @param slotId The slot ID that the MMTEL Feature is being created for. * @param slotId The slot ID that the MMTEL Feature is being created for.
* @return The newly created {@link MmTelFeature} associated with the slot or null if the * @return The newly created {@link MmTelFeature} associated with the slot or null if the
* feature is not supported. * feature is not supported.
*/ */
@Deprecated
public MmTelFeature createMmTelFeature(int slotId) { public MmTelFeature createMmTelFeature(int slotId) {
return null; return null;
} }
@@ -552,32 +704,62 @@ public class ImsService extends Service {
/** /**
* When called, the framework is requesting that a new {@link RcsFeature} is created for the * When called, the framework is requesting that a new {@link RcsFeature} is created for the
* specified slot. * specified slot.
* @deprecated Use {@link #createRcsFeatureForSubscription} instead
* *
* @param slotId The slot ID that the RCS Feature is being created for. * @param slotId The slot ID that the RCS Feature is being created for.
* @return The newly created {@link RcsFeature} associated with the slot or null if the feature * @return The newly created {@link RcsFeature} associated with the slot or null if the feature
* is not supported. * is not supported.
*/ */
@Deprecated
public RcsFeature createRcsFeature(int slotId) { public RcsFeature createRcsFeature(int slotId) {
return null; return null;
} }
/**
* Return the {@link ImsConfigImplBase} implementation associated with the provided
* subscription. This will be used by the platform to get/set specific IMS related
* configurations.
*
* @param subscriptionId The subscription ID that the IMS configuration is associated with.
* @return ImsConfig implementation that is associated with the specified subscription.
*/
public @NonNull ImsConfigImplBase getConfigForSubscription(int slotId, int subscriptionId) {
return getConfig(slotId);
}
/**
* Return the {@link ImsRegistrationImplBase} implementation associated with the provided
* subscription.
*
* @param subscriptionId The subscription ID that is associated with the IMS Registration.
* @return the ImsRegistration implementation associated with the subscription.
*/
public @NonNull ImsRegistrationImplBase getRegistrationForSubscription(int slotId,
int subscriptionId) {
return getRegistration(slotId);
}
/** /**
* Return the {@link ImsConfigImplBase} implementation associated with the provided slot. This * Return the {@link ImsConfigImplBase} implementation associated with the provided slot. This
* will be used by the platform to get/set specific IMS related configurations. * will be used by the platform to get/set specific IMS related configurations.
* @deprecated use {@link #getConfigForSubscription} instead.
* *
* @param slotId The slot that the IMS configuration is associated with. * @param slotId The slot that the IMS configuration is associated with.
* @return ImsConfig implementation that is associated with the specified slot. * @return ImsConfig implementation that is associated with the specified slot.
*/ */
@Deprecated
public ImsConfigImplBase getConfig(int slotId) { public ImsConfigImplBase getConfig(int slotId) {
return new ImsConfigImplBase(); return new ImsConfigImplBase();
} }
/** /**
* Return the {@link ImsRegistrationImplBase} implementation associated with the provided slot. * Return the {@link ImsRegistrationImplBase} implementation associated with the provided slot.
* @deprecated use {@link #getRegistrationForSubscription} instead.
* *
* @param slotId The slot that is associated with the IMS Registration. * @param slotId The slot that is associated with the IMS Registration.
* @return the ImsRegistration implementation associated with the slot. * @return the ImsRegistration implementation associated with the slot.
*/ */
@Deprecated
public ImsRegistrationImplBase getRegistration(int slotId) { public ImsRegistrationImplBase getRegistration(int slotId) {
return new ImsRegistrationImplBase(); return new ImsRegistrationImplBase();
} }

View File

@@ -32,18 +32,19 @@ import com.android.ims.internal.IImsFeatureStatusCallback;
*/ */
interface IImsServiceController { interface IImsServiceController {
void setListener(IImsServiceControllerListener l); void setListener(IImsServiceControllerListener l);
IImsMmTelFeature createMmTelFeature(int slotId); IImsMmTelFeature createMmTelFeature(int slotId, int subId);
IImsRcsFeature createRcsFeature(int slotId); IImsMmTelFeature createEmergencyOnlyMmTelFeature(int slotId);
IImsRcsFeature createRcsFeature(int slotId, int subId);
ImsFeatureConfiguration querySupportedImsFeatures(); ImsFeatureConfiguration querySupportedImsFeatures();
long getImsServiceCapabilities(); long getImsServiceCapabilities();
void addFeatureStatusCallback(int slotId, int featureType, in IImsFeatureStatusCallback c); void addFeatureStatusCallback(int slotId, int featureType, in IImsFeatureStatusCallback c);
void removeFeatureStatusCallback(int slotId, int featureType, in IImsFeatureStatusCallback c); void removeFeatureStatusCallback(int slotId, int featureType, in IImsFeatureStatusCallback c);
// Synchronous call to ensure the ImsService is ready before continuing with feature creation. // Synchronous call to ensure the ImsService is ready before continuing with feature creation.
void notifyImsServiceReadyForFeatureCreation(); void notifyImsServiceReadyForFeatureCreation();
void removeImsFeature(int slotId, int featureType); void removeImsFeature(int slotId, int featureType, boolean changeSubId);
IImsConfig getConfig(int slotId); IImsConfig getConfig(int slotId, int subId);
IImsRegistration getRegistration(int slotId); IImsRegistration getRegistration(int slotId, int subId);
ISipTransport getSipTransport(int slotId); ISipTransport getSipTransport(int slotId);
oneway void enableIms(int slotId); oneway void enableIms(int slotId, int subId);
oneway void disableIms(int slotId); oneway void disableIms(int slotId, int subId);
} }

View File

@@ -23,11 +23,11 @@ import com.android.ims.ImsFeatureContainer;
* {@hide} * {@hide}
*/ */
oneway interface IImsServiceFeatureCallback { oneway interface IImsServiceFeatureCallback {
void imsFeatureCreated(in ImsFeatureContainer feature); void imsFeatureCreated(in ImsFeatureContainer feature, int subId);
// Reason defined in FeatureConnector.UnavailableReason // Reason defined in FeatureConnector.UnavailableReason
void imsFeatureRemoved(int reason); void imsFeatureRemoved(int reason);
// Status defined in ImsFeature.ImsState. // Status defined in ImsFeature.ImsState.
void imsStatusChanged(int status); void imsStatusChanged(int status, int subId);
//Capabilities defined in ImsService.ImsServiceCapability //Capabilities defined in ImsService.ImsServiceCapability
void updateCapabilities(long capabilities); void updateCapabilities(long capabilities);
} }