Merge "(ImsService API changes for Better IMS Threading) ImsService to execute binder calls in Executor." am: 984a31a9fb am: ad01874cbf
Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1958681 Change-Id: Ib6785ff5e815f564a17d4eedd617520d258fa5c0
This commit is contained in:
@@ -12926,6 +12926,7 @@ package android.telephony.ims {
|
|||||||
method public void disableIms(int);
|
method public void disableIms(int);
|
||||||
method public void enableIms(int);
|
method public void enableIms(int);
|
||||||
method public android.telephony.ims.stub.ImsConfigImplBase getConfig(int);
|
method public android.telephony.ims.stub.ImsConfigImplBase getConfig(int);
|
||||||
|
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 public android.telephony.ims.stub.ImsRegistrationImplBase getRegistration(int);
|
||||||
method @Nullable public android.telephony.ims.stub.SipTransportImplBase getSipTransport(int);
|
method @Nullable public android.telephony.ims.stub.SipTransportImplBase getSipTransport(int);
|
||||||
@@ -13546,6 +13547,7 @@ package android.telephony.ims.feature {
|
|||||||
|
|
||||||
public class MmTelFeature extends android.telephony.ims.feature.ImsFeature {
|
public class MmTelFeature extends android.telephony.ims.feature.ImsFeature {
|
||||||
ctor public MmTelFeature();
|
ctor public MmTelFeature();
|
||||||
|
ctor public MmTelFeature(@NonNull java.util.concurrent.Executor);
|
||||||
method public void changeEnabledCapabilities(@NonNull android.telephony.ims.feature.CapabilityChangeRequest, @NonNull android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy);
|
method public void changeEnabledCapabilities(@NonNull android.telephony.ims.feature.CapabilityChangeRequest, @NonNull android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy);
|
||||||
method public void changeOfferedRtpHeaderExtensionTypes(@NonNull java.util.Set<android.telephony.ims.RtpHeaderExtensionType>);
|
method public void changeOfferedRtpHeaderExtensionTypes(@NonNull java.util.Set<android.telephony.ims.RtpHeaderExtensionType>);
|
||||||
method @Nullable public android.telephony.ims.ImsCallProfile createCallProfile(int, int);
|
method @Nullable public android.telephony.ims.ImsCallProfile createCallProfile(int, int);
|
||||||
@@ -13579,7 +13581,7 @@ package android.telephony.ims.feature {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public class RcsFeature extends android.telephony.ims.feature.ImsFeature {
|
public class RcsFeature extends android.telephony.ims.feature.ImsFeature {
|
||||||
ctor @Deprecated public RcsFeature();
|
ctor public RcsFeature();
|
||||||
ctor public RcsFeature(@NonNull java.util.concurrent.Executor);
|
ctor public RcsFeature(@NonNull java.util.concurrent.Executor);
|
||||||
method public void changeEnabledCapabilities(@NonNull android.telephony.ims.feature.CapabilityChangeRequest, @NonNull android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy);
|
method public void changeEnabledCapabilities(@NonNull android.telephony.ims.feature.CapabilityChangeRequest, @NonNull android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy);
|
||||||
method @NonNull public android.telephony.ims.stub.RcsCapabilityExchangeImplBase createCapabilityExchangeImpl(@NonNull android.telephony.ims.stub.CapabilityExchangeEventListener);
|
method @NonNull public android.telephony.ims.stub.RcsCapabilityExchangeImplBase createCapabilityExchangeImpl(@NonNull android.telephony.ims.stub.CapabilityExchangeEventListener);
|
||||||
@@ -13684,6 +13686,7 @@ package android.telephony.ims.stub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public class ImsConfigImplBase {
|
public class ImsConfigImplBase {
|
||||||
|
ctor public ImsConfigImplBase(@NonNull java.util.concurrent.Executor);
|
||||||
ctor public ImsConfigImplBase();
|
ctor public ImsConfigImplBase();
|
||||||
method public int getConfigInt(int);
|
method public int getConfigInt(int);
|
||||||
method public String getConfigString(int);
|
method public String getConfigString(int);
|
||||||
@@ -13736,6 +13739,7 @@ package android.telephony.ims.stub {
|
|||||||
|
|
||||||
public class ImsRegistrationImplBase {
|
public class ImsRegistrationImplBase {
|
||||||
ctor public ImsRegistrationImplBase();
|
ctor public ImsRegistrationImplBase();
|
||||||
|
ctor public ImsRegistrationImplBase(@NonNull java.util.concurrent.Executor);
|
||||||
method public final void onDeregistered(android.telephony.ims.ImsReasonInfo);
|
method public final void onDeregistered(android.telephony.ims.ImsReasonInfo);
|
||||||
method public final void onRegistered(int);
|
method public final void onRegistered(int);
|
||||||
method public final void onRegistered(@NonNull android.telephony.ims.ImsRegistrationAttributes);
|
method public final void onRegistered(@NonNull android.telephony.ims.ImsRegistrationAttributes);
|
||||||
@@ -13848,6 +13852,7 @@ package android.telephony.ims.stub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public class SipTransportImplBase {
|
public class SipTransportImplBase {
|
||||||
|
ctor public SipTransportImplBase();
|
||||||
ctor public SipTransportImplBase(@NonNull java.util.concurrent.Executor);
|
ctor public SipTransportImplBase(@NonNull java.util.concurrent.Executor);
|
||||||
method public void createSipDelegate(int, @NonNull android.telephony.ims.DelegateRequest, @NonNull android.telephony.ims.DelegateStateCallback, @NonNull android.telephony.ims.DelegateMessageCallback);
|
method public void createSipDelegate(int, @NonNull android.telephony.ims.DelegateRequest, @NonNull android.telephony.ims.DelegateStateCallback, @NonNull android.telephony.ims.DelegateMessageCallback);
|
||||||
method public void destroySipDelegate(@NonNull android.telephony.ims.stub.SipDelegate, int);
|
method public void destroySipDelegate(@NonNull android.telephony.ims.stub.SipDelegate, int);
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
package android.telephony.ims;
|
package android.telephony.ims;
|
||||||
|
|
||||||
import android.annotation.LongDef;
|
import android.annotation.LongDef;
|
||||||
|
import android.annotation.NonNull;
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.annotation.SystemApi;
|
import android.annotation.SystemApi;
|
||||||
@@ -44,11 +45,18 @@ import android.util.SparseArray;
|
|||||||
|
|
||||||
import com.android.ims.internal.IImsFeatureStatusCallback;
|
import com.android.ims.internal.IImsFeatureStatusCallback;
|
||||||
import com.android.internal.annotations.VisibleForTesting;
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
|
import com.android.internal.telephony.util.TelephonyUtils;
|
||||||
|
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.CancellationException;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.CompletionException;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main ImsService implementation, which binds via the Telephony ImsResolver. Services that extend
|
* Main ImsService implementation, which binds via the Telephony ImsResolver. Services that extend
|
||||||
@@ -173,7 +181,21 @@ public class ImsService extends Service {
|
|||||||
private final SparseArray<SparseArray<ImsFeature>> mFeaturesBySlot = new SparseArray<>();
|
private final SparseArray<SparseArray<ImsFeature>> mFeaturesBySlot = new SparseArray<>();
|
||||||
|
|
||||||
private IImsServiceControllerListener mListener;
|
private IImsServiceControllerListener mListener;
|
||||||
|
private Executor mExecutor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new ImsService.
|
||||||
|
* <p>
|
||||||
|
* Method stubs called from the framework will be called asynchronously. Vendor specifies the
|
||||||
|
* {@link Executor} that the methods stubs will be called. If mExecutor is set to null by
|
||||||
|
* vendor use Runnable::run.
|
||||||
|
*/
|
||||||
|
public ImsService() {
|
||||||
|
mExecutor = ImsService.this.getExecutor();
|
||||||
|
if (mExecutor == null) {
|
||||||
|
mExecutor = Runnable::run;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Listener that notifies the framework of ImsService changes.
|
* Listener that notifies the framework of ImsService changes.
|
||||||
@@ -201,38 +223,45 @@ public class ImsService extends Service {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IImsMmTelFeature createMmTelFeature(int slotId) {
|
public IImsMmTelFeature createMmTelFeature(int slotId) {
|
||||||
return createMmTelFeatureInternal(slotId);
|
return executeMethodAsyncForResult(() -> createMmTelFeatureInternal(slotId),
|
||||||
|
"createMmTelFeature");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IImsRcsFeature createRcsFeature(int slotId) {
|
public IImsRcsFeature createRcsFeature(int slotId) {
|
||||||
return createRcsFeatureInternal(slotId);
|
return executeMethodAsyncForResult(() -> createRcsFeatureInternal(slotId),
|
||||||
|
"createRcsFeature");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addFeatureStatusCallback(int slotId, int featureType,
|
public void addFeatureStatusCallback(int slotId, int featureType,
|
||||||
IImsFeatureStatusCallback c) {
|
IImsFeatureStatusCallback c) {
|
||||||
ImsService.this.addImsFeatureStatusCallback(slotId, featureType, c);
|
executeMethodAsync(() -> ImsService.this.addImsFeatureStatusCallback(
|
||||||
|
slotId, featureType, c), "addFeatureStatusCallback");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeFeatureStatusCallback(int slotId, int featureType,
|
public void removeFeatureStatusCallback(int slotId, int featureType,
|
||||||
IImsFeatureStatusCallback c) {
|
IImsFeatureStatusCallback c) {
|
||||||
ImsService.this.removeImsFeatureStatusCallback(slotId, featureType, c);
|
executeMethodAsync(() -> ImsService.this.removeImsFeatureStatusCallback(
|
||||||
|
slotId, featureType, c), "removeFeatureStatusCallback");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeImsFeature(int slotId, int featureType) {
|
public void removeImsFeature(int slotId, int featureType) {
|
||||||
ImsService.this.removeImsFeature(slotId, featureType);
|
executeMethodAsync(() -> ImsService.this.removeImsFeature(slotId, featureType),
|
||||||
|
"removeImsFeature");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ImsFeatureConfiguration querySupportedImsFeatures() {
|
public ImsFeatureConfiguration querySupportedImsFeatures() {
|
||||||
return ImsService.this.querySupportedImsFeatures();
|
return executeMethodAsyncForResult(() -> ImsService.this.querySupportedImsFeatures(),
|
||||||
|
"ImsFeatureConfiguration");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getImsServiceCapabilities() {
|
public long getImsServiceCapabilities() {
|
||||||
|
return executeMethodAsyncForResult(() -> {
|
||||||
long caps = ImsService.this.getImsServiceCapabilities();
|
long caps = ImsService.this.getImsServiceCapabilities();
|
||||||
long sanitizedCaps = sanitizeCapabilities(caps);
|
long sanitizedCaps = sanitizeCapabilities(caps);
|
||||||
if (caps != sanitizedCaps) {
|
if (caps != sanitizedCaps) {
|
||||||
@@ -240,39 +269,86 @@ public class ImsService extends Service {
|
|||||||
+ Long.toHexString(caps ^ sanitizedCaps));
|
+ Long.toHexString(caps ^ sanitizedCaps));
|
||||||
}
|
}
|
||||||
return sanitizedCaps;
|
return sanitizedCaps;
|
||||||
|
}, "getImsServiceCapabilities");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void notifyImsServiceReadyForFeatureCreation() {
|
public void notifyImsServiceReadyForFeatureCreation() {
|
||||||
ImsService.this.readyForFeatureCreation();
|
executeMethodAsync(() -> ImsService.this.readyForFeatureCreation(),
|
||||||
|
"notifyImsServiceReadyForFeatureCreation");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IImsConfig getConfig(int slotId) {
|
public IImsConfig getConfig(int slotId) {
|
||||||
|
return executeMethodAsyncForResult(() -> {
|
||||||
ImsConfigImplBase c = ImsService.this.getConfig(slotId);
|
ImsConfigImplBase c = ImsService.this.getConfig(slotId);
|
||||||
return c != null ? c.getIImsConfig() : null;
|
if (c != null) {
|
||||||
|
c.setDefaultExecutor(mExecutor);
|
||||||
|
return c.getIImsConfig();
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}, "getConfig");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IImsRegistration getRegistration(int slotId) {
|
public IImsRegistration getRegistration(int slotId) {
|
||||||
|
return executeMethodAsyncForResult(() -> {
|
||||||
ImsRegistrationImplBase r = ImsService.this.getRegistration(slotId);
|
ImsRegistrationImplBase r = ImsService.this.getRegistration(slotId);
|
||||||
return r != null ? r.getBinder() : null;
|
if (r != null) {
|
||||||
|
r.setDefaultExecutor(mExecutor);
|
||||||
|
return r.getBinder();
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}, "getRegistration");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ISipTransport getSipTransport(int slotId) {
|
public ISipTransport getSipTransport(int slotId) {
|
||||||
|
return executeMethodAsyncForResult(() -> {
|
||||||
SipTransportImplBase s = ImsService.this.getSipTransport(slotId);
|
SipTransportImplBase s = ImsService.this.getSipTransport(slotId);
|
||||||
return s != null ? s.getBinder() : null;
|
if (s != null) {
|
||||||
|
s.setDefaultExecutor(mExecutor);
|
||||||
|
return s.getBinder();
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}, "getSipTransport");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void enableIms(int slotId) {
|
public void enableIms(int slotId) {
|
||||||
ImsService.this.enableIms(slotId);
|
executeMethodAsync(() -> ImsService.this.enableIms(slotId), "enableIms");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void disableIms(int slotId) {
|
public void disableIms(int slotId) {
|
||||||
ImsService.this.disableIms(slotId);
|
executeMethodAsync(() -> ImsService.this.disableIms(slotId), "disableIms");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the methods with a clean calling identity on the executor and wait indefinitely for
|
||||||
|
// the future to return.
|
||||||
|
private void executeMethodAsync(Runnable r, String errorLogName) {
|
||||||
|
try {
|
||||||
|
CompletableFuture.runAsync(
|
||||||
|
() -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor).join();
|
||||||
|
} catch (CancellationException | CompletionException e) {
|
||||||
|
Log.w(LOG_TAG, "ImsService Binder - " + errorLogName + " exception: "
|
||||||
|
+ e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T> T executeMethodAsyncForResult(Supplier<T> r, String errorLogName) {
|
||||||
|
CompletableFuture<T> future = CompletableFuture.supplyAsync(
|
||||||
|
() -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor);
|
||||||
|
try {
|
||||||
|
return future.get();
|
||||||
|
} catch (ExecutionException | InterruptedException e) {
|
||||||
|
Log.w(LOG_TAG, "ImsService Binder - " + errorLogName + " exception: "
|
||||||
|
+ e.getMessage());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -300,6 +376,7 @@ public class ImsService extends Service {
|
|||||||
MmTelFeature f = createMmTelFeature(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);
|
||||||
return f.getBinder();
|
return f.getBinder();
|
||||||
} else {
|
} else {
|
||||||
Log.e(LOG_TAG, "createMmTelFeatureInternal: null feature returned.");
|
Log.e(LOG_TAG, "createMmTelFeatureInternal: null feature returned.");
|
||||||
@@ -310,6 +387,7 @@ public class ImsService extends Service {
|
|||||||
private IImsRcsFeature createRcsFeatureInternal(int slotId) {
|
private IImsRcsFeature createRcsFeatureInternal(int slotId) {
|
||||||
RcsFeature f = createRcsFeature(slotId);
|
RcsFeature f = createRcsFeature(slotId);
|
||||||
if (f != null) {
|
if (f != null) {
|
||||||
|
f.setDefaultExecutor(mExecutor);
|
||||||
setupFeature(f, slotId, ImsFeature.FEATURE_RCS);
|
setupFeature(f, slotId, ImsFeature.FEATURE_RCS);
|
||||||
return f.getBinder();
|
return f.getBinder();
|
||||||
} else {
|
} else {
|
||||||
@@ -562,4 +640,15 @@ public class ImsService extends Service {
|
|||||||
result.append("}");
|
result.append("}");
|
||||||
return result.toString();
|
return result.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ImsService will now be able to define an Executor that the ImsService can be used to
|
||||||
|
* execute the methods. By default all ImsService level method calls will use this Executor.
|
||||||
|
* The ImsService has set the default executor as Runnable::run,
|
||||||
|
* Should be override or default executor will be used.
|
||||||
|
* @return an Executor used to execute methods called remotely by the framework.
|
||||||
|
*/
|
||||||
|
public @NonNull Executor getExecutor() {
|
||||||
|
return Runnable::run;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,16 +40,25 @@ import android.telephony.ims.stub.ImsRegistrationImplBase;
|
|||||||
import android.telephony.ims.stub.ImsSmsImplBase;
|
import android.telephony.ims.stub.ImsSmsImplBase;
|
||||||
import android.telephony.ims.stub.ImsUtImplBase;
|
import android.telephony.ims.stub.ImsUtImplBase;
|
||||||
import android.util.ArraySet;
|
import android.util.ArraySet;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
import com.android.ims.internal.IImsCallSession;
|
import com.android.ims.internal.IImsCallSession;
|
||||||
import com.android.ims.internal.IImsEcbm;
|
import com.android.ims.internal.IImsEcbm;
|
||||||
import com.android.ims.internal.IImsMultiEndpoint;
|
import com.android.ims.internal.IImsMultiEndpoint;
|
||||||
import com.android.ims.internal.IImsUt;
|
import com.android.ims.internal.IImsUt;
|
||||||
|
import com.android.internal.telephony.util.TelephonyUtils;
|
||||||
|
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.CancellationException;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.CompletionException;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base implementation for Voice and SMS (IR-92) and Video (IR-94) IMS support.
|
* Base implementation for Voice and SMS (IR-92) and Video (IR-94) IMS support.
|
||||||
@@ -60,6 +69,7 @@ import java.util.Set;
|
|||||||
public class MmTelFeature extends ImsFeature {
|
public class MmTelFeature extends ImsFeature {
|
||||||
|
|
||||||
private static final String LOG_TAG = "MmTelFeature";
|
private static final String LOG_TAG = "MmTelFeature";
|
||||||
|
private Executor mExecutor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @hide
|
* @hide
|
||||||
@@ -68,160 +78,261 @@ public class MmTelFeature extends ImsFeature {
|
|||||||
public MmTelFeature() {
|
public MmTelFeature() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new MmTelFeature using the Executor specified for methods being called by the
|
||||||
|
* framework.
|
||||||
|
* @param executor The executor for the framework to use when executing the methods overridden
|
||||||
|
* by the implementation of MmTelFeature.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@SystemApi
|
||||||
|
public MmTelFeature(@NonNull Executor executor) {
|
||||||
|
super();
|
||||||
|
mExecutor = executor;
|
||||||
|
}
|
||||||
|
|
||||||
private final IImsMmTelFeature mImsMMTelBinder = new IImsMmTelFeature.Stub() {
|
private final IImsMmTelFeature mImsMMTelBinder = new IImsMmTelFeature.Stub() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setListener(IImsMmTelListener l) {
|
public void setListener(IImsMmTelListener l) {
|
||||||
MmTelFeature.this.setListener(l);
|
executeMethodAsyncNoException(() -> MmTelFeature.this.setListener(l), "setListener");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getFeatureState() throws RemoteException {
|
public int getFeatureState() throws RemoteException {
|
||||||
try {
|
return executeMethodAsyncForResult(() -> MmTelFeature.this.getFeatureState(),
|
||||||
return MmTelFeature.this.getFeatureState();
|
"getFeatureState");
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RemoteException(e.getMessage());
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ImsCallProfile createCallProfile(int callSessionType, int callType)
|
public ImsCallProfile createCallProfile(int callSessionType, int callType)
|
||||||
throws RemoteException {
|
throws RemoteException {
|
||||||
synchronized (mLock) {
|
return executeMethodAsyncForResult(() -> MmTelFeature.this.createCallProfile(
|
||||||
try {
|
callSessionType, callType), "createCallProfile");
|
||||||
return MmTelFeature.this.createCallProfile(callSessionType, callType);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RemoteException(e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void changeOfferedRtpHeaderExtensionTypes(List<RtpHeaderExtensionType> types)
|
public void changeOfferedRtpHeaderExtensionTypes(List<RtpHeaderExtensionType> types)
|
||||||
throws RemoteException {
|
throws RemoteException {
|
||||||
synchronized (mLock) {
|
executeMethodAsync(() -> MmTelFeature.this.changeOfferedRtpHeaderExtensionTypes(
|
||||||
try {
|
new ArraySet<>(types)), "changeOfferedRtpHeaderExtensionTypes");
|
||||||
MmTelFeature.this.changeOfferedRtpHeaderExtensionTypes(new ArraySet<>(types));
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RemoteException(e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IImsCallSession createCallSession(ImsCallProfile profile) throws RemoteException {
|
public IImsCallSession createCallSession(ImsCallProfile profile) throws RemoteException {
|
||||||
synchronized (mLock) {
|
AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
|
||||||
|
IImsCallSession result = executeMethodAsyncForResult(() -> {
|
||||||
|
try {
|
||||||
return createCallSessionInterface(profile);
|
return createCallSessionInterface(profile);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
exceptionRef.set(e);
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
}, "createCallSession");
|
||||||
|
|
||||||
|
if (exceptionRef.get() != null) {
|
||||||
|
throw exceptionRef.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int shouldProcessCall(String[] numbers) {
|
public int shouldProcessCall(String[] numbers) {
|
||||||
synchronized (mLock) {
|
Integer result = executeMethodAsyncForResultNoException(() ->
|
||||||
return MmTelFeature.this.shouldProcessCall(numbers);
|
MmTelFeature.this.shouldProcessCall(numbers), "shouldProcessCall");
|
||||||
|
if (result != null) {
|
||||||
|
return result.intValue();
|
||||||
|
} else {
|
||||||
|
return PROCESS_CALL_CSFB;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IImsUt getUtInterface() throws RemoteException {
|
public IImsUt getUtInterface() throws RemoteException {
|
||||||
synchronized (mLock) {
|
AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
|
||||||
|
IImsUt result = executeMethodAsyncForResult(() -> {
|
||||||
|
try {
|
||||||
return MmTelFeature.this.getUtInterface();
|
return MmTelFeature.this.getUtInterface();
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
exceptionRef.set(e);
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
}, "getUtInterface");
|
||||||
|
|
||||||
|
if (exceptionRef.get() != null) {
|
||||||
|
throw exceptionRef.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IImsEcbm getEcbmInterface() throws RemoteException {
|
public IImsEcbm getEcbmInterface() throws RemoteException {
|
||||||
synchronized (mLock) {
|
AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
|
||||||
|
IImsEcbm result = executeMethodAsyncForResult(() -> {
|
||||||
|
try {
|
||||||
return MmTelFeature.this.getEcbmInterface();
|
return MmTelFeature.this.getEcbmInterface();
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
exceptionRef.set(e);
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
}, "getEcbmInterface");
|
||||||
|
|
||||||
|
if (exceptionRef.get() != null) {
|
||||||
|
throw exceptionRef.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setUiTtyMode(int uiTtyMode, Message onCompleteMessage) throws RemoteException {
|
public void setUiTtyMode(int uiTtyMode, Message onCompleteMessage) throws RemoteException {
|
||||||
synchronized (mLock) {
|
executeMethodAsync(() -> MmTelFeature.this.setUiTtyMode(uiTtyMode, onCompleteMessage),
|
||||||
try {
|
"setUiTtyMode");
|
||||||
MmTelFeature.this.setUiTtyMode(uiTtyMode, onCompleteMessage);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RemoteException(e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IImsMultiEndpoint getMultiEndpointInterface() throws RemoteException {
|
public IImsMultiEndpoint getMultiEndpointInterface() throws RemoteException {
|
||||||
synchronized (mLock) {
|
AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
|
||||||
|
IImsMultiEndpoint result = executeMethodAsyncForResult(() -> {
|
||||||
|
try {
|
||||||
return MmTelFeature.this.getMultiEndpointInterface();
|
return MmTelFeature.this.getMultiEndpointInterface();
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
exceptionRef.set(e);
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
}, "getMultiEndpointInterface");
|
||||||
|
|
||||||
|
if (exceptionRef.get() != null) {
|
||||||
|
throw exceptionRef.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int queryCapabilityStatus() {
|
public int queryCapabilityStatus() {
|
||||||
return MmTelFeature.this.queryCapabilityStatus().mCapabilities;
|
Integer result = executeMethodAsyncForResultNoException(() -> MmTelFeature.this
|
||||||
|
.queryCapabilityStatus().mCapabilities, "queryCapabilityStatus");
|
||||||
|
|
||||||
|
if (result != null) {
|
||||||
|
return result.intValue();
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addCapabilityCallback(IImsCapabilityCallback c) {
|
public void addCapabilityCallback(IImsCapabilityCallback c) {
|
||||||
// no need to lock, structure already handles multithreading.
|
executeMethodAsyncNoException(() -> MmTelFeature.this
|
||||||
MmTelFeature.this.addCapabilityCallback(c);
|
.addCapabilityCallback(c), "addCapabilityCallback");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeCapabilityCallback(IImsCapabilityCallback c) {
|
public void removeCapabilityCallback(IImsCapabilityCallback c) {
|
||||||
// no need to lock, structure already handles multithreading.
|
executeMethodAsyncNoException(() -> MmTelFeature.this
|
||||||
MmTelFeature.this.removeCapabilityCallback(c);
|
.removeCapabilityCallback(c), "removeCapabilityCallback");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void changeCapabilitiesConfiguration(CapabilityChangeRequest request,
|
public void changeCapabilitiesConfiguration(CapabilityChangeRequest request,
|
||||||
IImsCapabilityCallback c) {
|
IImsCapabilityCallback c) {
|
||||||
MmTelFeature.this.requestChangeEnabledCapabilities(request, c);
|
executeMethodAsyncNoException(() -> MmTelFeature.this
|
||||||
|
.requestChangeEnabledCapabilities(request, c),
|
||||||
|
"changeCapabilitiesConfiguration");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void queryCapabilityConfiguration(int capability, int radioTech,
|
public void queryCapabilityConfiguration(int capability, int radioTech,
|
||||||
IImsCapabilityCallback c) {
|
IImsCapabilityCallback c) {
|
||||||
queryCapabilityConfigurationInternal(capability, radioTech, c);
|
executeMethodAsyncNoException(() -> queryCapabilityConfigurationInternal(
|
||||||
|
capability, radioTech, c), "queryCapabilityConfiguration");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setSmsListener(IImsSmsListener l) {
|
public void setSmsListener(IImsSmsListener l) {
|
||||||
MmTelFeature.this.setSmsListener(l);
|
executeMethodAsyncNoException(() -> MmTelFeature.this.setSmsListener(l),
|
||||||
|
"setSmsListener");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendSms(int token, int messageRef, String format, String smsc, boolean retry,
|
public void sendSms(int token, int messageRef, String format, String smsc, boolean retry,
|
||||||
byte[] pdu) {
|
byte[] pdu) {
|
||||||
synchronized (mLock) {
|
executeMethodAsyncNoException(() -> MmTelFeature.this
|
||||||
MmTelFeature.this.sendSms(token, messageRef, format, smsc, retry, pdu);
|
.sendSms(token, messageRef, format, smsc, retry, pdu), "sendSms");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void acknowledgeSms(int token, int messageRef, int result) {
|
public void acknowledgeSms(int token, int messageRef, int result) {
|
||||||
synchronized (mLock) {
|
executeMethodAsyncNoException(() -> MmTelFeature.this
|
||||||
MmTelFeature.this.acknowledgeSms(token, messageRef, result);
|
.acknowledgeSms(token, messageRef, result), "acknowledgeSms");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void acknowledgeSmsReport(int token, int messageRef, int result) {
|
public void acknowledgeSmsReport(int token, int messageRef, int result) {
|
||||||
synchronized (mLock) {
|
executeMethodAsyncNoException(() -> MmTelFeature.this
|
||||||
MmTelFeature.this.acknowledgeSmsReport(token, messageRef, result);
|
.acknowledgeSmsReport(token, messageRef, result), "acknowledgeSmsReport");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getSmsFormat() {
|
public String getSmsFormat() {
|
||||||
synchronized (mLock) {
|
return executeMethodAsyncForResultNoException(() -> MmTelFeature.this
|
||||||
return MmTelFeature.this.getSmsFormat();
|
.getSmsFormat(), "getSmsFormat");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSmsReady() {
|
public void onSmsReady() {
|
||||||
synchronized (mLock) {
|
executeMethodAsyncNoException(() -> MmTelFeature.this.onSmsReady(),
|
||||||
MmTelFeature.this.onSmsReady();
|
"onSmsReady");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the methods with a clean calling identity on the executor and wait indefinitely for
|
||||||
|
// the future to return.
|
||||||
|
private void executeMethodAsync(Runnable r, String errorLogName) throws RemoteException {
|
||||||
|
try {
|
||||||
|
CompletableFuture.runAsync(
|
||||||
|
() -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor).join();
|
||||||
|
} catch (CancellationException | CompletionException e) {
|
||||||
|
Log.w(LOG_TAG, "MmTelFeature Binder - " + errorLogName + " exception: "
|
||||||
|
+ e.getMessage());
|
||||||
|
throw new RemoteException(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void executeMethodAsyncNoException(Runnable r, String errorLogName) {
|
||||||
|
try {
|
||||||
|
CompletableFuture.runAsync(
|
||||||
|
() -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor).join();
|
||||||
|
} catch (CancellationException | CompletionException e) {
|
||||||
|
Log.w(LOG_TAG, "MmTelFeature Binder - " + errorLogName + " exception: "
|
||||||
|
+ e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T> T executeMethodAsyncForResult(Supplier<T> r,
|
||||||
|
String errorLogName) throws RemoteException {
|
||||||
|
CompletableFuture<T> future = CompletableFuture.supplyAsync(
|
||||||
|
() -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor);
|
||||||
|
try {
|
||||||
|
return future.get();
|
||||||
|
} catch (ExecutionException | InterruptedException e) {
|
||||||
|
Log.w(LOG_TAG, "MmTelFeature Binder - " + errorLogName + " exception: "
|
||||||
|
+ e.getMessage());
|
||||||
|
throw new RemoteException(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T> T executeMethodAsyncForResultNoException(Supplier<T> r,
|
||||||
|
String errorLogName) {
|
||||||
|
CompletableFuture<T> future = CompletableFuture.supplyAsync(
|
||||||
|
() -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor);
|
||||||
|
try {
|
||||||
|
return future.get();
|
||||||
|
} catch (ExecutionException | InterruptedException e) {
|
||||||
|
Log.w(LOG_TAG, "MmTelFeature Binder - " + errorLogName + " exception: "
|
||||||
|
+ e.getMessage());
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -672,7 +783,12 @@ public class MmTelFeature extends ImsFeature {
|
|||||||
public IImsCallSession createCallSessionInterface(ImsCallProfile profile)
|
public IImsCallSession createCallSessionInterface(ImsCallProfile profile)
|
||||||
throws RemoteException {
|
throws RemoteException {
|
||||||
ImsCallSessionImplBase s = MmTelFeature.this.createCallSession(profile);
|
ImsCallSessionImplBase s = MmTelFeature.this.createCallSession(profile);
|
||||||
return s != null ? s.getServiceImpl() : null;
|
if (s != null) {
|
||||||
|
s.setDefaultExecutor(mExecutor);
|
||||||
|
return s.getServiceImpl();
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -713,7 +829,12 @@ public class MmTelFeature extends ImsFeature {
|
|||||||
*/
|
*/
|
||||||
protected IImsUt getUtInterface() throws RemoteException {
|
protected IImsUt getUtInterface() throws RemoteException {
|
||||||
ImsUtImplBase utImpl = getUt();
|
ImsUtImplBase utImpl = getUt();
|
||||||
return utImpl != null ? utImpl.getInterface() : null;
|
if (utImpl != null) {
|
||||||
|
utImpl.setDefaultExecutor(mExecutor);
|
||||||
|
return utImpl.getInterface();
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -721,7 +842,12 @@ public class MmTelFeature extends ImsFeature {
|
|||||||
*/
|
*/
|
||||||
protected IImsEcbm getEcbmInterface() throws RemoteException {
|
protected IImsEcbm getEcbmInterface() throws RemoteException {
|
||||||
ImsEcbmImplBase ecbmImpl = getEcbm();
|
ImsEcbmImplBase ecbmImpl = getEcbm();
|
||||||
return ecbmImpl != null ? ecbmImpl.getImsEcbm() : null;
|
if (ecbmImpl != null) {
|
||||||
|
ecbmImpl.setDefaultExecutor(mExecutor);
|
||||||
|
return ecbmImpl.getImsEcbm();
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -729,7 +855,12 @@ public class MmTelFeature extends ImsFeature {
|
|||||||
*/
|
*/
|
||||||
public IImsMultiEndpoint getMultiEndpointInterface() throws RemoteException {
|
public IImsMultiEndpoint getMultiEndpointInterface() throws RemoteException {
|
||||||
ImsMultiEndpointImplBase multiendpointImpl = getMultiEndpoint();
|
ImsMultiEndpointImplBase multiendpointImpl = getMultiEndpoint();
|
||||||
return multiendpointImpl != null ? multiendpointImpl.getIImsMultiEndpoint() : null;
|
if (multiendpointImpl != null) {
|
||||||
|
multiendpointImpl.setDefaultExecutor(mExecutor);
|
||||||
|
return multiendpointImpl.getIImsMultiEndpoint();
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -859,4 +990,16 @@ public class MmTelFeature extends ImsFeature {
|
|||||||
public final IImsMmTelFeature getBinder() {
|
public final IImsMmTelFeature getBinder() {
|
||||||
return mImsMMTelBinder;
|
return mImsMMTelBinder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set default Executor from ImsService.
|
||||||
|
* @param executor The default executor for the framework to use when executing the methods
|
||||||
|
* overridden by the implementation of MmTelFeature.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public final void setDefaultExecutor(@NonNull Executor executor) {
|
||||||
|
if (mExecutor == null) {
|
||||||
|
mExecutor = executor;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ public class RcsFeature extends ImsFeature {
|
|||||||
// Reference the outer class in order to have better test coverage metrics instead of
|
// Reference the outer class in order to have better test coverage metrics instead of
|
||||||
// creating a inner class referencing the outer class directly.
|
// creating a inner class referencing the outer class directly.
|
||||||
private final RcsFeature mReference;
|
private final RcsFeature mReference;
|
||||||
private final Executor mExecutor;
|
private Executor mExecutor;
|
||||||
|
|
||||||
RcsFeatureBinder(RcsFeature classRef, @CallbackExecutor Executor executor) {
|
RcsFeatureBinder(RcsFeature classRef, @CallbackExecutor Executor executor) {
|
||||||
mReference = classRef;
|
mReference = classRef;
|
||||||
@@ -259,7 +259,7 @@ public class RcsFeature extends ImsFeature {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final Executor mExecutor;
|
private Executor mExecutor;
|
||||||
private final RcsFeatureBinder mImsRcsBinder;
|
private final RcsFeatureBinder mImsRcsBinder;
|
||||||
private RcsCapabilityExchangeImplBase mCapabilityExchangeImpl;
|
private RcsCapabilityExchangeImplBase mCapabilityExchangeImpl;
|
||||||
private CapabilityExchangeEventListener mCapExchangeEventListener;
|
private CapabilityExchangeEventListener mCapExchangeEventListener;
|
||||||
@@ -270,13 +270,9 @@ public class RcsFeature extends ImsFeature {
|
|||||||
* Method stubs called from the framework will be called asynchronously. To specify the
|
* Method stubs called from the framework will be called asynchronously. To specify the
|
||||||
* {@link Executor} that the methods stubs will be called, use
|
* {@link Executor} that the methods stubs will be called, use
|
||||||
* {@link RcsFeature#RcsFeature(Executor)} instead.
|
* {@link RcsFeature#RcsFeature(Executor)} instead.
|
||||||
*
|
|
||||||
* @deprecated Use {@link #RcsFeature(Executor)} to create the RcsFeature.
|
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
|
||||||
public RcsFeature() {
|
public RcsFeature() {
|
||||||
super();
|
super();
|
||||||
mExecutor = Runnable::run;
|
|
||||||
// Run on the Binder threads that call them.
|
// Run on the Binder threads that call them.
|
||||||
mImsRcsBinder = new RcsFeatureBinder(this, mExecutor);
|
mImsRcsBinder = new RcsFeatureBinder(this, mExecutor);
|
||||||
}
|
}
|
||||||
@@ -477,4 +473,17 @@ public class RcsFeature extends ImsFeature {
|
|||||||
return mCapabilityExchangeImpl;
|
return mCapabilityExchangeImpl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set default Executor from ImsService.
|
||||||
|
* @param executor The default executor for the framework to use when executing the methods
|
||||||
|
* overridden by the implementation of RcsFeature.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public final void setDefaultExecutor(@NonNull Executor executor) {
|
||||||
|
if (mImsRcsBinder.mExecutor == null) {
|
||||||
|
mExecutor = executor;
|
||||||
|
mImsRcsBinder.mExecutor = executor;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,12 +30,20 @@ import android.telephony.ims.RtpHeaderExtension;
|
|||||||
import android.telephony.ims.RtpHeaderExtensionType;
|
import android.telephony.ims.RtpHeaderExtensionType;
|
||||||
import android.telephony.ims.aidl.IImsCallSessionListener;
|
import android.telephony.ims.aidl.IImsCallSessionListener;
|
||||||
import android.util.ArraySet;
|
import android.util.ArraySet;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
import com.android.ims.internal.IImsCallSession;
|
import com.android.ims.internal.IImsCallSession;
|
||||||
import com.android.ims.internal.IImsVideoCallProvider;
|
import com.android.ims.internal.IImsVideoCallProvider;
|
||||||
|
import com.android.internal.telephony.util.TelephonyUtils;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.CancellationException;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.CompletionException;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base implementation of IImsCallSession, which implements stub versions of the methods available.
|
* Base implementation of IImsCallSession, which implements stub versions of the methods available.
|
||||||
@@ -48,6 +56,8 @@ import java.util.Set;
|
|||||||
// DO NOT remove or change the existing APIs, only add new ones to this Base implementation or you
|
// DO NOT remove or change the existing APIs, only add new ones to this Base implementation or you
|
||||||
// will break other implementations of ImsCallSession maintained by other ImsServices.
|
// will break other implementations of ImsCallSession maintained by other ImsServices.
|
||||||
public class ImsCallSessionImplBase implements AutoCloseable {
|
public class ImsCallSessionImplBase implements AutoCloseable {
|
||||||
|
|
||||||
|
private static final String LOG_TAG = "ImsCallSessionImplBase";
|
||||||
/**
|
/**
|
||||||
* Notify USSD Mode.
|
* Notify USSD Mode.
|
||||||
*/
|
*/
|
||||||
@@ -110,185 +120,235 @@ public class ImsCallSessionImplBase implements AutoCloseable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Executor mExecutor = Runnable::run;
|
||||||
|
|
||||||
// Non-final for injection by tests
|
// Non-final for injection by tests
|
||||||
private IImsCallSession mServiceImpl = new IImsCallSession.Stub() {
|
private IImsCallSession mServiceImpl = new IImsCallSession.Stub() {
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() {
|
||||||
ImsCallSessionImplBase.this.close();
|
executeMethodAsync(() -> ImsCallSessionImplBase.this.close(), "close");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getCallId() {
|
public String getCallId() {
|
||||||
return ImsCallSessionImplBase.this.getCallId();
|
return executeMethodAsyncForResult(() -> ImsCallSessionImplBase.this.getCallId(),
|
||||||
|
"getCallId");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ImsCallProfile getCallProfile() {
|
public ImsCallProfile getCallProfile() {
|
||||||
return ImsCallSessionImplBase.this.getCallProfile();
|
return executeMethodAsyncForResult(() -> ImsCallSessionImplBase.this.getCallProfile(),
|
||||||
|
"getCallProfile");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ImsCallProfile getLocalCallProfile() {
|
public ImsCallProfile getLocalCallProfile() {
|
||||||
return ImsCallSessionImplBase.this.getLocalCallProfile();
|
return executeMethodAsyncForResult(() -> ImsCallSessionImplBase.this
|
||||||
|
.getLocalCallProfile(), "getLocalCallProfile");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ImsCallProfile getRemoteCallProfile() {
|
public ImsCallProfile getRemoteCallProfile() {
|
||||||
return ImsCallSessionImplBase.this.getRemoteCallProfile();
|
return executeMethodAsyncForResult(() -> ImsCallSessionImplBase.this
|
||||||
|
.getRemoteCallProfile(), "getRemoteCallProfile");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getProperty(String name) {
|
public String getProperty(String name) {
|
||||||
return ImsCallSessionImplBase.this.getProperty(name);
|
return executeMethodAsyncForResult(() -> ImsCallSessionImplBase.this.getProperty(name),
|
||||||
|
"getProperty");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getState() {
|
public int getState() {
|
||||||
return ImsCallSessionImplBase.this.getState();
|
return executeMethodAsyncForResult(() -> ImsCallSessionImplBase.this.getState(),
|
||||||
|
"getState");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isInCall() {
|
public boolean isInCall() {
|
||||||
return ImsCallSessionImplBase.this.isInCall();
|
return executeMethodAsyncForResult(() -> ImsCallSessionImplBase.this.isInCall(),
|
||||||
|
"isInCall");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setListener(IImsCallSessionListener listener) {
|
public void setListener(IImsCallSessionListener listener) {
|
||||||
ImsCallSessionImplBase.this.setListener(new ImsCallSessionListener(listener));
|
executeMethodAsync(() -> ImsCallSessionImplBase.this.setListener(
|
||||||
|
new ImsCallSessionListener(listener)), "setListener");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setMute(boolean muted) {
|
public void setMute(boolean muted) {
|
||||||
ImsCallSessionImplBase.this.setMute(muted);
|
executeMethodAsync(() -> ImsCallSessionImplBase.this.setMute(muted), "setMute");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void start(String callee, ImsCallProfile profile) {
|
public void start(String callee, ImsCallProfile profile) {
|
||||||
ImsCallSessionImplBase.this.start(callee, profile);
|
executeMethodAsync(() -> ImsCallSessionImplBase.this.start(callee, profile), "start");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void startConference(String[] participants, ImsCallProfile profile) throws
|
public void startConference(String[] participants, ImsCallProfile profile) throws
|
||||||
RemoteException {
|
RemoteException {
|
||||||
ImsCallSessionImplBase.this.startConference(participants, profile);
|
executeMethodAsync(() -> ImsCallSessionImplBase.this.startConference(participants,
|
||||||
|
profile), "startConference");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void accept(int callType, ImsStreamMediaProfile profile) {
|
public void accept(int callType, ImsStreamMediaProfile profile) {
|
||||||
ImsCallSessionImplBase.this.accept(callType, profile);
|
executeMethodAsync(() -> ImsCallSessionImplBase.this.accept(callType, profile),
|
||||||
|
"accept");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deflect(String deflectNumber) {
|
public void deflect(String deflectNumber) {
|
||||||
ImsCallSessionImplBase.this.deflect(deflectNumber);
|
executeMethodAsync(() -> ImsCallSessionImplBase.this.deflect(deflectNumber),
|
||||||
|
"deflect");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void reject(int reason) {
|
public void reject(int reason) {
|
||||||
ImsCallSessionImplBase.this.reject(reason);
|
executeMethodAsync(() -> ImsCallSessionImplBase.this.reject(reason), "reject");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void transfer(@NonNull String number, boolean isConfirmationRequired) {
|
public void transfer(@NonNull String number, boolean isConfirmationRequired) {
|
||||||
ImsCallSessionImplBase.this.transfer(number, isConfirmationRequired);
|
executeMethodAsync(() -> ImsCallSessionImplBase.this.transfer(number,
|
||||||
|
isConfirmationRequired), "transfer");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void consultativeTransfer(@NonNull IImsCallSession transferToSession) {
|
public void consultativeTransfer(@NonNull IImsCallSession transferToSession) {
|
||||||
|
executeMethodAsync(() -> {
|
||||||
ImsCallSessionImplBase otherSession = new ImsCallSessionImplBase();
|
ImsCallSessionImplBase otherSession = new ImsCallSessionImplBase();
|
||||||
otherSession.setServiceImpl(transferToSession);
|
otherSession.setServiceImpl(transferToSession);
|
||||||
ImsCallSessionImplBase.this.transfer(otherSession);
|
ImsCallSessionImplBase.this.transfer(otherSession);
|
||||||
|
}, "consultativeTransfer");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void terminate(int reason) {
|
public void terminate(int reason) {
|
||||||
ImsCallSessionImplBase.this.terminate(reason);
|
executeMethodAsync(() -> ImsCallSessionImplBase.this.terminate(reason), "terminate");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void hold(ImsStreamMediaProfile profile) {
|
public void hold(ImsStreamMediaProfile profile) {
|
||||||
ImsCallSessionImplBase.this.hold(profile);
|
executeMethodAsync(() -> ImsCallSessionImplBase.this.hold(profile), "hold");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void resume(ImsStreamMediaProfile profile) {
|
public void resume(ImsStreamMediaProfile profile) {
|
||||||
ImsCallSessionImplBase.this.resume(profile);
|
executeMethodAsync(() -> ImsCallSessionImplBase.this.resume(profile), "resume");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void merge() {
|
public void merge() {
|
||||||
ImsCallSessionImplBase.this.merge();
|
executeMethodAsync(() -> ImsCallSessionImplBase.this.merge(), "merge");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(int callType, ImsStreamMediaProfile profile) {
|
public void update(int callType, ImsStreamMediaProfile profile) {
|
||||||
ImsCallSessionImplBase.this.update(callType, profile);
|
executeMethodAsync(() -> ImsCallSessionImplBase.this.update(callType, profile),
|
||||||
|
"update");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void extendToConference(String[] participants) {
|
public void extendToConference(String[] participants) {
|
||||||
ImsCallSessionImplBase.this.extendToConference(participants);
|
executeMethodAsync(() -> ImsCallSessionImplBase.this.extendToConference(participants),
|
||||||
|
"extendToConference");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void inviteParticipants(String[] participants) {
|
public void inviteParticipants(String[] participants) {
|
||||||
ImsCallSessionImplBase.this.inviteParticipants(participants);
|
executeMethodAsync(() -> ImsCallSessionImplBase.this.inviteParticipants(participants),
|
||||||
|
"inviteParticipants");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeParticipants(String[] participants) {
|
public void removeParticipants(String[] participants) {
|
||||||
ImsCallSessionImplBase.this.removeParticipants(participants);
|
executeMethodAsync(() -> ImsCallSessionImplBase.this.removeParticipants(participants),
|
||||||
|
"removeParticipants");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendDtmf(char c, Message result) {
|
public void sendDtmf(char c, Message result) {
|
||||||
ImsCallSessionImplBase.this.sendDtmf(c, result);
|
executeMethodAsync(() -> ImsCallSessionImplBase.this.sendDtmf(c, result), "sendDtmf");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void startDtmf(char c) {
|
public void startDtmf(char c) {
|
||||||
ImsCallSessionImplBase.this.startDtmf(c);
|
executeMethodAsync(() -> ImsCallSessionImplBase.this.startDtmf(c), "startDtmf");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void stopDtmf() {
|
public void stopDtmf() {
|
||||||
ImsCallSessionImplBase.this.stopDtmf();
|
executeMethodAsync(() -> ImsCallSessionImplBase.this.stopDtmf(), "stopDtmf");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendUssd(String ussdMessage) {
|
public void sendUssd(String ussdMessage) {
|
||||||
ImsCallSessionImplBase.this.sendUssd(ussdMessage);
|
executeMethodAsync(() -> ImsCallSessionImplBase.this.sendUssd(ussdMessage), "sendUssd");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IImsVideoCallProvider getVideoCallProvider() {
|
public IImsVideoCallProvider getVideoCallProvider() {
|
||||||
return ImsCallSessionImplBase.this.getVideoCallProvider();
|
return executeMethodAsyncForResult(() -> ImsCallSessionImplBase.this
|
||||||
|
.getVideoCallProvider(), "getVideoCallProvider");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isMultiparty() {
|
public boolean isMultiparty() {
|
||||||
return ImsCallSessionImplBase.this.isMultiparty();
|
return executeMethodAsyncForResult(() -> ImsCallSessionImplBase.this.isMultiparty(),
|
||||||
|
"isMultiparty");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendRttModifyRequest(ImsCallProfile toProfile) {
|
public void sendRttModifyRequest(ImsCallProfile toProfile) {
|
||||||
ImsCallSessionImplBase.this.sendRttModifyRequest(toProfile);
|
executeMethodAsync(() -> ImsCallSessionImplBase.this.sendRttModifyRequest(toProfile),
|
||||||
|
"sendRttModifyRequest");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendRttModifyResponse(boolean status) {
|
public void sendRttModifyResponse(boolean status) {
|
||||||
ImsCallSessionImplBase.this.sendRttModifyResponse(status);
|
executeMethodAsync(() -> ImsCallSessionImplBase.this.sendRttModifyResponse(status),
|
||||||
|
"sendRttModifyResponse");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendRttMessage(String rttMessage) {
|
public void sendRttMessage(String rttMessage) {
|
||||||
ImsCallSessionImplBase.this.sendRttMessage(rttMessage);
|
executeMethodAsync(() -> ImsCallSessionImplBase.this.sendRttMessage(rttMessage),
|
||||||
|
"sendRttMessage");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendRtpHeaderExtensions(@NonNull List<RtpHeaderExtension> extensions) {
|
public void sendRtpHeaderExtensions(@NonNull List<RtpHeaderExtension> extensions) {
|
||||||
ImsCallSessionImplBase.this.sendRtpHeaderExtensions(
|
executeMethodAsync(() -> ImsCallSessionImplBase.this.sendRtpHeaderExtensions(
|
||||||
new ArraySet<RtpHeaderExtension>(extensions));
|
new ArraySet<RtpHeaderExtension>(extensions)), "sendRtpHeaderExtensions");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the methods with a clean calling identity on the executor and wait indefinitely for
|
||||||
|
// the future to return.
|
||||||
|
private void executeMethodAsync(Runnable r, String errorLogName) {
|
||||||
|
try {
|
||||||
|
CompletableFuture.runAsync(
|
||||||
|
() -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor).join();
|
||||||
|
} catch (CancellationException | CompletionException e) {
|
||||||
|
Log.w(LOG_TAG, "ImsCallSessionImplBase Binder - " + errorLogName + " exception: "
|
||||||
|
+ e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T> T executeMethodAsyncForResult(Supplier<T> r,
|
||||||
|
String errorLogName) {
|
||||||
|
CompletableFuture<T> future = CompletableFuture.supplyAsync(
|
||||||
|
() -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor);
|
||||||
|
try {
|
||||||
|
return future.get();
|
||||||
|
} catch (ExecutionException | InterruptedException e) {
|
||||||
|
Log.w(LOG_TAG, "ImsCallSessionImplBase Binder - " + errorLogName + " exception: "
|
||||||
|
+ e.getMessage());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -674,4 +734,14 @@ public class ImsCallSessionImplBase implements AutoCloseable {
|
|||||||
public void setServiceImpl(IImsCallSession serviceImpl) {
|
public void setServiceImpl(IImsCallSession serviceImpl) {
|
||||||
mServiceImpl = serviceImpl;
|
mServiceImpl = serviceImpl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set default Executor from MmTelFeature.
|
||||||
|
* @param executor The default executor for the framework to use when executing the methods
|
||||||
|
* overridden by the implementation of ImsCallSession.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public final void setDefaultExecutor(@NonNull Executor executor) {
|
||||||
|
mExecutor = executor;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,12 +33,21 @@ import android.util.Log;
|
|||||||
import com.android.ims.ImsConfig;
|
import com.android.ims.ImsConfig;
|
||||||
import com.android.internal.annotations.VisibleForTesting;
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
import com.android.internal.telephony.util.RemoteCallbackListExt;
|
import com.android.internal.telephony.util.RemoteCallbackListExt;
|
||||||
|
import com.android.internal.telephony.util.TelephonyUtils;
|
||||||
|
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.concurrent.CancellationException;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.CompletionException;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Controls the modification of IMS specific configurations. For more information on the supported
|
* Controls the modification of IMS specific configurations. For more information on the supported
|
||||||
@@ -81,21 +90,48 @@ public class ImsConfigImplBase {
|
|||||||
WeakReference<ImsConfigImplBase> mImsConfigImplBaseWeakReference;
|
WeakReference<ImsConfigImplBase> mImsConfigImplBaseWeakReference;
|
||||||
private HashMap<Integer, Integer> mProvisionedIntValue = new HashMap<>();
|
private HashMap<Integer, Integer> mProvisionedIntValue = new HashMap<>();
|
||||||
private HashMap<Integer, String> mProvisionedStringValue = new HashMap<>();
|
private HashMap<Integer, String> mProvisionedStringValue = new HashMap<>();
|
||||||
|
private final Object mLock = new Object();
|
||||||
|
private Executor mExecutor;
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public ImsConfigStub(ImsConfigImplBase imsConfigImplBase) {
|
public ImsConfigStub(ImsConfigImplBase imsConfigImplBase, Executor executor) {
|
||||||
|
mExecutor = executor;
|
||||||
mImsConfigImplBaseWeakReference =
|
mImsConfigImplBaseWeakReference =
|
||||||
new WeakReference<ImsConfigImplBase>(imsConfigImplBase);
|
new WeakReference<ImsConfigImplBase>(imsConfigImplBase);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addImsConfigCallback(IImsConfigCallback c) throws RemoteException {
|
public void addImsConfigCallback(IImsConfigCallback c) throws RemoteException {
|
||||||
|
AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
|
||||||
|
executeMethodAsync(()-> {
|
||||||
|
try {
|
||||||
getImsConfigImpl().addImsConfigCallback(c);
|
getImsConfigImpl().addImsConfigCallback(c);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
exceptionRef.set(e);
|
||||||
|
}
|
||||||
|
}, "addImsConfigCallback");
|
||||||
|
|
||||||
|
if (exceptionRef.get() != null) {
|
||||||
|
Log.d(TAG, "ImsConfigImplBase Exception addImsConfigCallback");
|
||||||
|
throw exceptionRef.get();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeImsConfigCallback(IImsConfigCallback c) throws RemoteException {
|
public void removeImsConfigCallback(IImsConfigCallback c) throws RemoteException {
|
||||||
|
AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
|
||||||
|
executeMethodAsync(()-> {
|
||||||
|
try {
|
||||||
getImsConfigImpl().removeImsConfigCallback(c);
|
getImsConfigImpl().removeImsConfigCallback(c);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
exceptionRef.set(e);
|
||||||
|
}
|
||||||
|
}, "removeImsConfigCallback");
|
||||||
|
|
||||||
|
if (exceptionRef.get() != null) {
|
||||||
|
Log.d(TAG, "ImsConfigImplBase Exception removeImsConfigCallback");
|
||||||
|
throw exceptionRef.get();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -108,17 +144,35 @@ public class ImsConfigImplBase {
|
|||||||
* unavailable.
|
* unavailable.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public synchronized int getConfigInt(int item) throws RemoteException {
|
public int getConfigInt(int item) throws RemoteException {
|
||||||
|
AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
|
||||||
|
int retVal = executeMethodAsyncForResult(()-> {
|
||||||
|
int returnVal = ImsConfig.OperationStatusConstants.UNKNOWN;
|
||||||
|
synchronized (mLock) {
|
||||||
if (mProvisionedIntValue.containsKey(item)) {
|
if (mProvisionedIntValue.containsKey(item)) {
|
||||||
return mProvisionedIntValue.get(item);
|
return mProvisionedIntValue.get(item);
|
||||||
} else {
|
} else {
|
||||||
int retVal = getImsConfigImpl().getConfigInt(item);
|
try {
|
||||||
if (retVal != ImsConfig.OperationStatusConstants.UNKNOWN) {
|
returnVal = getImsConfigImpl().getConfigInt(item);
|
||||||
updateCachedValue(item, retVal, false);
|
if (returnVal != ImsConfig.OperationStatusConstants.UNKNOWN) {
|
||||||
|
mProvisionedIntValue.put(item, returnVal);
|
||||||
}
|
}
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
exceptionRef.set(e);
|
||||||
|
return returnVal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return returnVal;
|
||||||
|
}, "getConfigInt");
|
||||||
|
|
||||||
|
if (exceptionRef.get() != null) {
|
||||||
|
Log.d(TAG, "ImsConfigImplBase Exception getConfigString");
|
||||||
|
throw exceptionRef.get();
|
||||||
|
}
|
||||||
|
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the value for ims service/capabilities parameters. It first checks its local cache,
|
* Gets the value for ims service/capabilities parameters. It first checks its local cache,
|
||||||
@@ -129,17 +183,35 @@ public class ImsConfigImplBase {
|
|||||||
* @return value in String format.
|
* @return value in String format.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public synchronized String getConfigString(int item) throws RemoteException {
|
public String getConfigString(int item) throws RemoteException {
|
||||||
|
AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
|
||||||
|
String retVal = executeMethodAsyncForResult(()-> {
|
||||||
|
String returnVal = null;
|
||||||
|
synchronized (mLock) {
|
||||||
if (mProvisionedStringValue.containsKey(item)) {
|
if (mProvisionedStringValue.containsKey(item)) {
|
||||||
return mProvisionedStringValue.get(item);
|
returnVal = mProvisionedStringValue.get(item);
|
||||||
} else {
|
} else {
|
||||||
String retVal = getImsConfigImpl().getConfigString(item);
|
try {
|
||||||
if (retVal != null) {
|
returnVal = getImsConfigImpl().getConfigString(item);
|
||||||
updateCachedValue(item, retVal, false);
|
if (returnVal != null) {
|
||||||
|
mProvisionedStringValue.put(item, returnVal);
|
||||||
}
|
}
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
exceptionRef.set(e);
|
||||||
|
return returnVal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return returnVal;
|
||||||
|
}, "getConfigString");
|
||||||
|
|
||||||
|
if (exceptionRef.get() != null) {
|
||||||
|
Log.d(TAG, "ImsConfigImplBase Exception getConfigString");
|
||||||
|
throw exceptionRef.get();
|
||||||
|
}
|
||||||
|
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the value for IMS service/capabilities parameters by the operator device
|
* Sets the value for IMS service/capabilities parameters by the operator device
|
||||||
@@ -153,14 +225,32 @@ public class ImsConfigImplBase {
|
|||||||
* {@link #CONFIG_RESULT_FAILED} or {@link #CONFIG_RESULT_SUCCESS}.
|
* {@link #CONFIG_RESULT_FAILED} or {@link #CONFIG_RESULT_SUCCESS}.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public synchronized int setConfigInt(int item, int value) throws RemoteException {
|
public int setConfigInt(int item, int value) throws RemoteException {
|
||||||
|
AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
|
||||||
|
int retVal = executeMethodAsyncForResult(()-> {
|
||||||
|
int returnVal = ImsConfig.OperationStatusConstants.UNKNOWN;
|
||||||
|
try {
|
||||||
|
synchronized (mLock) {
|
||||||
mProvisionedIntValue.remove(item);
|
mProvisionedIntValue.remove(item);
|
||||||
int retVal = getImsConfigImpl().setConfig(item, value);
|
returnVal = getImsConfigImpl().setConfig(item, value);
|
||||||
if (retVal == ImsConfig.OperationStatusConstants.SUCCESS) {
|
if (returnVal == ImsConfig.OperationStatusConstants.SUCCESS) {
|
||||||
updateCachedValue(item, value, true);
|
mProvisionedIntValue.put(item, value);
|
||||||
} else {
|
} else {
|
||||||
Log.d(TAG, "Set provision value of " + item +
|
Log.d(TAG, "Set provision value of " + item
|
||||||
" to " + value + " failed with error code " + retVal);
|
+ " to " + value + " failed with error code " + returnVal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
notifyImsConfigChanged(item, value);
|
||||||
|
return returnVal;
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
exceptionRef.set(e);
|
||||||
|
return returnVal;
|
||||||
|
}
|
||||||
|
}, "setConfigInt");
|
||||||
|
|
||||||
|
if (exceptionRef.get() != null) {
|
||||||
|
Log.d(TAG, "ImsConfigImplBase Exception setConfigInt");
|
||||||
|
throw exceptionRef.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
return retVal;
|
return retVal;
|
||||||
@@ -178,12 +268,30 @@ public class ImsConfigImplBase {
|
|||||||
* {@link #CONFIG_RESULT_FAILED} or {@link #CONFIG_RESULT_SUCCESS}.
|
* {@link #CONFIG_RESULT_FAILED} or {@link #CONFIG_RESULT_SUCCESS}.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public synchronized int setConfigString(int item, String value)
|
public int setConfigString(int item, String value)
|
||||||
throws RemoteException {
|
throws RemoteException {
|
||||||
|
AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
|
||||||
|
int retVal = executeMethodAsyncForResult(()-> {
|
||||||
|
int returnVal = ImsConfig.OperationStatusConstants.UNKNOWN;
|
||||||
|
try {
|
||||||
|
synchronized (mLock) {
|
||||||
mProvisionedStringValue.remove(item);
|
mProvisionedStringValue.remove(item);
|
||||||
int retVal = getImsConfigImpl().setConfig(item, value);
|
returnVal = getImsConfigImpl().setConfig(item, value);
|
||||||
if (retVal == ImsConfig.OperationStatusConstants.SUCCESS) {
|
if (returnVal == ImsConfig.OperationStatusConstants.SUCCESS) {
|
||||||
updateCachedValue(item, value, true);
|
mProvisionedStringValue.put(item, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
notifyImsConfigChanged(item, value);
|
||||||
|
return returnVal;
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
exceptionRef.set(e);
|
||||||
|
return returnVal;
|
||||||
|
}
|
||||||
|
}, "setConfigString");
|
||||||
|
|
||||||
|
if (exceptionRef.get() != null) {
|
||||||
|
Log.d(TAG, "ImsConfigImplBase Exception setConfigInt");
|
||||||
|
throw exceptionRef.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
return retVal;
|
return retVal;
|
||||||
@@ -191,7 +299,19 @@ public class ImsConfigImplBase {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateImsCarrierConfigs(PersistableBundle bundle) throws RemoteException {
|
public void updateImsCarrierConfigs(PersistableBundle bundle) throws RemoteException {
|
||||||
|
AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
|
||||||
|
executeMethodAsync(()-> {
|
||||||
|
try {
|
||||||
getImsConfigImpl().updateImsCarrierConfigs(bundle);
|
getImsConfigImpl().updateImsCarrierConfigs(bundle);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
exceptionRef.set(e);
|
||||||
|
}
|
||||||
|
}, "updateImsCarrierConfigs");
|
||||||
|
|
||||||
|
if (exceptionRef.get() != null) {
|
||||||
|
Log.d(TAG, "ImsConfigImplBase Exception updateImsCarrierConfigs");
|
||||||
|
throw exceptionRef.get();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private ImsConfigImplBase getImsConfigImpl() throws RemoteException {
|
private ImsConfigImplBase getImsConfigImpl() throws RemoteException {
|
||||||
@@ -206,13 +326,37 @@ public class ImsConfigImplBase {
|
|||||||
@Override
|
@Override
|
||||||
public void notifyRcsAutoConfigurationReceived(byte[] config, boolean isCompressed)
|
public void notifyRcsAutoConfigurationReceived(byte[] config, boolean isCompressed)
|
||||||
throws RemoteException {
|
throws RemoteException {
|
||||||
|
AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
|
||||||
|
executeMethodAsync(()-> {
|
||||||
|
try {
|
||||||
getImsConfigImpl().onNotifyRcsAutoConfigurationReceived(config, isCompressed);
|
getImsConfigImpl().onNotifyRcsAutoConfigurationReceived(config, isCompressed);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
exceptionRef.set(e);
|
||||||
|
}
|
||||||
|
}, "notifyRcsAutoConfigurationReceived");
|
||||||
|
|
||||||
|
if (exceptionRef.get() != null) {
|
||||||
|
Log.d(TAG, "ImsConfigImplBase Exception notifyRcsAutoConfigurationReceived");
|
||||||
|
throw exceptionRef.get();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void notifyRcsAutoConfigurationRemoved()
|
public void notifyRcsAutoConfigurationRemoved()
|
||||||
throws RemoteException {
|
throws RemoteException {
|
||||||
|
AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
|
||||||
|
executeMethodAsync(()-> {
|
||||||
|
try {
|
||||||
getImsConfigImpl().onNotifyRcsAutoConfigurationRemoved();
|
getImsConfigImpl().onNotifyRcsAutoConfigurationRemoved();
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
exceptionRef.set(e);
|
||||||
|
}
|
||||||
|
}, "notifyRcsAutoConfigurationRemoved");
|
||||||
|
|
||||||
|
if (exceptionRef.get() != null) {
|
||||||
|
Log.d(TAG, "ImsConfigImplBase Exception notifyRcsAutoConfigurationRemoved");
|
||||||
|
throw exceptionRef.get();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void notifyImsConfigChanged(int item, int value) throws RemoteException {
|
private void notifyImsConfigChanged(int item, int value) throws RemoteException {
|
||||||
@@ -223,50 +367,144 @@ public class ImsConfigImplBase {
|
|||||||
getImsConfigImpl().notifyConfigChanged(item, value);
|
getImsConfigImpl().notifyConfigChanged(item, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected synchronized void updateCachedValue(int item, int value, boolean notifyChange)
|
protected void updateCachedValue(int item, int value) {
|
||||||
throws RemoteException {
|
synchronized (mLock) {
|
||||||
mProvisionedIntValue.put(item, value);
|
mProvisionedIntValue.put(item, value);
|
||||||
if (notifyChange) {
|
|
||||||
notifyImsConfigChanged(item, value);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected synchronized void updateCachedValue(int item, String value,
|
protected void updateCachedValue(int item, String value) {
|
||||||
boolean notifyChange) throws RemoteException {
|
synchronized (mLock) {
|
||||||
mProvisionedStringValue.put(item, value);
|
mProvisionedStringValue.put(item, value);
|
||||||
if (notifyChange) {
|
|
||||||
notifyImsConfigChanged(item, value);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addRcsConfigCallback(IRcsConfigCallback c) throws RemoteException {
|
public void addRcsConfigCallback(IRcsConfigCallback c) throws RemoteException {
|
||||||
|
AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
|
||||||
|
executeMethodAsync(()-> {
|
||||||
|
try {
|
||||||
getImsConfigImpl().addRcsConfigCallback(c);
|
getImsConfigImpl().addRcsConfigCallback(c);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
exceptionRef.set(e);
|
||||||
|
}
|
||||||
|
}, "addRcsConfigCallback");
|
||||||
|
|
||||||
|
if (exceptionRef.get() != null) {
|
||||||
|
Log.d(TAG, "ImsConfigImplBase Exception addRcsConfigCallback");
|
||||||
|
throw exceptionRef.get();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeRcsConfigCallback(IRcsConfigCallback c) throws RemoteException {
|
public void removeRcsConfigCallback(IRcsConfigCallback c) throws RemoteException {
|
||||||
|
AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
|
||||||
|
executeMethodAsync(()-> {
|
||||||
|
try {
|
||||||
getImsConfigImpl().removeRcsConfigCallback(c);
|
getImsConfigImpl().removeRcsConfigCallback(c);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
exceptionRef.set(e);
|
||||||
|
}
|
||||||
|
}, "removeRcsConfigCallback");
|
||||||
|
|
||||||
|
if (exceptionRef.get() != null) {
|
||||||
|
Log.d(TAG, "ImsConfigImplBase Exception removeRcsConfigCallback");
|
||||||
|
throw exceptionRef.get();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void triggerRcsReconfiguration() throws RemoteException {
|
public void triggerRcsReconfiguration() throws RemoteException {
|
||||||
|
AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
|
||||||
|
executeMethodAsync(()-> {
|
||||||
|
try {
|
||||||
getImsConfigImpl().triggerAutoConfiguration();
|
getImsConfigImpl().triggerAutoConfiguration();
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
exceptionRef.set(e);
|
||||||
|
}
|
||||||
|
}, "triggerRcsReconfiguration");
|
||||||
|
|
||||||
|
if (exceptionRef.get() != null) {
|
||||||
|
Log.d(TAG, "ImsConfigImplBase Exception triggerRcsReconfiguration");
|
||||||
|
throw exceptionRef.get();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setRcsClientConfiguration(RcsClientConfiguration rcc) throws RemoteException {
|
public void setRcsClientConfiguration(RcsClientConfiguration rcc) throws RemoteException {
|
||||||
|
AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
|
||||||
|
executeMethodAsync(()-> {
|
||||||
|
try {
|
||||||
getImsConfigImpl().setRcsClientConfiguration(rcc);
|
getImsConfigImpl().setRcsClientConfiguration(rcc);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
exceptionRef.set(e);
|
||||||
|
}
|
||||||
|
}, "setRcsClientConfiguration");
|
||||||
|
|
||||||
|
if (exceptionRef.get() != null) {
|
||||||
|
Log.d(TAG, "ImsConfigImplBase Exception setRcsClientConfiguration");
|
||||||
|
throw exceptionRef.get();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void notifyIntImsConfigChanged(int item, int value) throws RemoteException {
|
public void notifyIntImsConfigChanged(int item, int value) throws RemoteException {
|
||||||
|
AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
|
||||||
|
executeMethodAsync(()-> {
|
||||||
|
try {
|
||||||
notifyImsConfigChanged(item, value);
|
notifyImsConfigChanged(item, value);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
exceptionRef.set(e);
|
||||||
|
}
|
||||||
|
}, "notifyIntImsConfigChanged");
|
||||||
|
|
||||||
|
if (exceptionRef.get() != null) {
|
||||||
|
Log.d(TAG, "ImsConfigImplBase Exception notifyIntImsConfigChanged");
|
||||||
|
throw exceptionRef.get();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void notifyStringImsConfigChanged(int item, String value) throws RemoteException {
|
public void notifyStringImsConfigChanged(int item, String value) throws RemoteException {
|
||||||
|
AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
|
||||||
|
executeMethodAsync(()-> {
|
||||||
|
try {
|
||||||
notifyImsConfigChanged(item, value);
|
notifyImsConfigChanged(item, value);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
exceptionRef.set(e);
|
||||||
|
}
|
||||||
|
}, "notifyStringImsConfigChanged");
|
||||||
|
|
||||||
|
if (exceptionRef.get() != null) {
|
||||||
|
Log.d(TAG, "ImsConfigImplBase Exception notifyStringImsConfigChanged");
|
||||||
|
throw exceptionRef.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the methods with a clean calling identity on the executor and wait indefinitely for
|
||||||
|
// the future to return.
|
||||||
|
private void executeMethodAsync(Runnable r, String errorLogName) throws RemoteException {
|
||||||
|
try {
|
||||||
|
CompletableFuture.runAsync(
|
||||||
|
() -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor).join();
|
||||||
|
} catch (CancellationException | CompletionException e) {
|
||||||
|
Log.w(TAG, "ImsConfigImplBase Binder - " + errorLogName + " exception: "
|
||||||
|
+ e.getMessage());
|
||||||
|
throw new RemoteException(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T> T executeMethodAsyncForResult(Supplier<T> r,
|
||||||
|
String errorLogName) throws RemoteException {
|
||||||
|
CompletableFuture<T> future = CompletableFuture.supplyAsync(
|
||||||
|
() -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor);
|
||||||
|
try {
|
||||||
|
return future.get();
|
||||||
|
} catch (ExecutionException | InterruptedException e) {
|
||||||
|
Log.w(TAG, "ImsConfigImplBase Binder - " + errorLogName + " exception: "
|
||||||
|
+ e.getMessage());
|
||||||
|
throw new RemoteException(e.getMessage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -303,15 +541,24 @@ public class ImsConfigImplBase {
|
|||||||
ImsConfigStub mImsConfigStub;
|
ImsConfigStub mImsConfigStub;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used for compatibility between older versions of the ImsService.
|
* Create a ImsConfig using the Executor specified for methods being called by the
|
||||||
|
* framework.
|
||||||
|
* @param executor The executor for the framework to use when executing the methods overridden
|
||||||
|
* by the implementation of ImsConfig.
|
||||||
|
*/
|
||||||
|
public ImsConfigImplBase(@NonNull Executor executor) {
|
||||||
|
mImsConfigStub = new ImsConfigStub(this, executor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public ImsConfigImplBase(Context context) {
|
public ImsConfigImplBase(@NonNull Context context) {
|
||||||
mImsConfigStub = new ImsConfigStub(this);
|
mImsConfigStub = new ImsConfigStub(this, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ImsConfigImplBase() {
|
public ImsConfigImplBase() {
|
||||||
mImsConfigStub = new ImsConfigStub(this);
|
mImsConfigStub = new ImsConfigStub(this, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -427,8 +674,10 @@ public class ImsConfigImplBase {
|
|||||||
* @param value in Integer format.
|
* @param value in Integer format.
|
||||||
*/
|
*/
|
||||||
public final void notifyProvisionedValueChanged(int item, int value) {
|
public final void notifyProvisionedValueChanged(int item, int value) {
|
||||||
|
mImsConfigStub.updateCachedValue(item, value);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
mImsConfigStub.updateCachedValue(item, value, true);
|
mImsConfigStub.notifyImsConfigChanged(item, value);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
Log.w(TAG, "notifyProvisionedValueChanged(int): Framework connection is dead.");
|
Log.w(TAG, "notifyProvisionedValueChanged(int): Framework connection is dead.");
|
||||||
}
|
}
|
||||||
@@ -443,8 +692,10 @@ public class ImsConfigImplBase {
|
|||||||
* @param value in String format.
|
* @param value in String format.
|
||||||
*/
|
*/
|
||||||
public final void notifyProvisionedValueChanged(int item, String value) {
|
public final void notifyProvisionedValueChanged(int item, String value) {
|
||||||
|
mImsConfigStub.updateCachedValue(item, value);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
mImsConfigStub.updateCachedValue(item, value, true);
|
mImsConfigStub.notifyImsConfigChanged(item, value);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
Log.w(TAG, "notifyProvisionedValueChanged(string): Framework connection is dead.");
|
Log.w(TAG, "notifyProvisionedValueChanged(string): Framework connection is dead.");
|
||||||
}
|
}
|
||||||
@@ -582,4 +833,16 @@ public class ImsConfigImplBase {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set default Executor from ImsService.
|
||||||
|
* @param executor The default executor for the framework to use when executing the methods
|
||||||
|
* overridden by the implementation of ImsConfig.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public final void setDefaultExecutor(@NonNull Executor executor) {
|
||||||
|
if (mImsConfigStub.mExecutor == null) {
|
||||||
|
mImsConfigStub.mExecutor = executor;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,14 +16,21 @@
|
|||||||
|
|
||||||
package android.telephony.ims.stub;
|
package android.telephony.ims.stub;
|
||||||
|
|
||||||
|
import android.annotation.NonNull;
|
||||||
import android.annotation.SystemApi;
|
import android.annotation.SystemApi;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.android.ims.internal.IImsEcbm;
|
import com.android.ims.internal.IImsEcbm;
|
||||||
import com.android.ims.internal.IImsEcbmListener;
|
import com.android.ims.internal.IImsEcbmListener;
|
||||||
|
import com.android.internal.telephony.util.TelephonyUtils;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.concurrent.CancellationException;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.CompletionException;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base implementation of ImsEcbm, which implements stub versions of the methods
|
* Base implementation of ImsEcbm, which implements stub versions of the methods
|
||||||
@@ -40,10 +47,12 @@ public class ImsEcbmImplBase {
|
|||||||
|
|
||||||
private final Object mLock = new Object();
|
private final Object mLock = new Object();
|
||||||
private IImsEcbmListener mListener;
|
private IImsEcbmListener mListener;
|
||||||
|
private Executor mExecutor = Runnable::run;
|
||||||
|
|
||||||
private final IImsEcbm mImsEcbm = new IImsEcbm.Stub() {
|
private final IImsEcbm mImsEcbm = new IImsEcbm.Stub() {
|
||||||
@Override
|
@Override
|
||||||
public void setListener(IImsEcbmListener listener) {
|
public void setListener(IImsEcbmListener listener) {
|
||||||
synchronized (mLock) {
|
executeMethodAsync(() -> {
|
||||||
if (mListener != null && !mListener.asBinder().isBinderAlive()) {
|
if (mListener != null && !mListener.asBinder().isBinderAlive()) {
|
||||||
Log.w(TAG, "setListener: discarding dead Binder");
|
Log.w(TAG, "setListener: discarding dead Binder");
|
||||||
mListener = null;
|
mListener = null;
|
||||||
@@ -62,12 +71,25 @@ public class ImsEcbmImplBase {
|
|||||||
+ "listener");
|
+ "listener");
|
||||||
mListener = listener;
|
mListener = listener;
|
||||||
}
|
}
|
||||||
}
|
}, "setListener");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void exitEmergencyCallbackMode() {
|
public void exitEmergencyCallbackMode() {
|
||||||
ImsEcbmImplBase.this.exitEmergencyCallbackMode();
|
executeMethodAsync(() -> ImsEcbmImplBase.this.exitEmergencyCallbackMode(),
|
||||||
|
"exitEmergencyCallbackMode");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the methods with a clean calling identity on the executor and wait indefinitely for
|
||||||
|
// the future to return.
|
||||||
|
private void executeMethodAsync(Runnable r, String errorLogName) {
|
||||||
|
try {
|
||||||
|
CompletableFuture.runAsync(
|
||||||
|
() -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor).join();
|
||||||
|
} catch (CancellationException | CompletionException e) {
|
||||||
|
Log.w(TAG, "ImsEcbmImplBase Binder - " + errorLogName + " exception: "
|
||||||
|
+ e.getMessage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -123,4 +145,14 @@ public class ImsEcbmImplBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set default Executor from MmTelFeature.
|
||||||
|
* @param executor The default executor for the framework to use when executing the methods
|
||||||
|
* overridden by the implementation of ImsEcbm.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public final void setDefaultExecutor(@NonNull Executor executor) {
|
||||||
|
mExecutor = executor;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package android.telephony.ims.stub;
|
package android.telephony.ims.stub;
|
||||||
|
|
||||||
|
import android.annotation.NonNull;
|
||||||
import android.annotation.SystemApi;
|
import android.annotation.SystemApi;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.telephony.ims.ImsExternalCallState;
|
import android.telephony.ims.ImsExternalCallState;
|
||||||
@@ -23,9 +24,14 @@ import android.util.Log;
|
|||||||
|
|
||||||
import com.android.ims.internal.IImsExternalCallStateListener;
|
import com.android.ims.internal.IImsExternalCallStateListener;
|
||||||
import com.android.ims.internal.IImsMultiEndpoint;
|
import com.android.ims.internal.IImsMultiEndpoint;
|
||||||
|
import com.android.internal.telephony.util.TelephonyUtils;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.concurrent.CancellationException;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.CompletionException;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base implementation of ImsMultiEndpoint, which implements stub versions of the methods
|
* Base implementation of ImsMultiEndpoint, which implements stub versions of the methods
|
||||||
@@ -43,11 +49,13 @@ public class ImsMultiEndpointImplBase {
|
|||||||
|
|
||||||
private IImsExternalCallStateListener mListener;
|
private IImsExternalCallStateListener mListener;
|
||||||
private final Object mLock = new Object();
|
private final Object mLock = new Object();
|
||||||
|
private Executor mExecutor = Runnable::run;
|
||||||
|
|
||||||
private final IImsMultiEndpoint mImsMultiEndpoint = new IImsMultiEndpoint.Stub() {
|
private final IImsMultiEndpoint mImsMultiEndpoint = new IImsMultiEndpoint.Stub() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setListener(IImsExternalCallStateListener listener) throws RemoteException {
|
public void setListener(IImsExternalCallStateListener listener) throws RemoteException {
|
||||||
synchronized (mLock) {
|
executeMethodAsync(() -> {
|
||||||
if (mListener != null && !mListener.asBinder().isBinderAlive()) {
|
if (mListener != null && !mListener.asBinder().isBinderAlive()) {
|
||||||
Log.w(TAG, "setListener: discarding dead Binder");
|
Log.w(TAG, "setListener: discarding dead Binder");
|
||||||
mListener = null;
|
mListener = null;
|
||||||
@@ -67,12 +75,25 @@ public class ImsMultiEndpointImplBase {
|
|||||||
+ "listener");
|
+ "listener");
|
||||||
mListener = listener;
|
mListener = listener;
|
||||||
}
|
}
|
||||||
}
|
}, "setListener");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void requestImsExternalCallStateInfo() throws RemoteException {
|
public void requestImsExternalCallStateInfo() throws RemoteException {
|
||||||
ImsMultiEndpointImplBase.this.requestImsExternalCallStateInfo();
|
executeMethodAsync(() -> ImsMultiEndpointImplBase.this
|
||||||
|
.requestImsExternalCallStateInfo(), "requestImsExternalCallStateInfo");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the methods with a clean calling identity on the executor and wait indefinitely for
|
||||||
|
// the future to return.
|
||||||
|
private void executeMethodAsync(Runnable r, String errorLogName) {
|
||||||
|
try {
|
||||||
|
CompletableFuture.runAsync(
|
||||||
|
() -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor).join();
|
||||||
|
} catch (CancellationException | CompletionException e) {
|
||||||
|
Log.w(TAG, "ImsMultiEndpointImplBase Binder - " + errorLogName + " exception: "
|
||||||
|
+ e.getMessage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -108,4 +129,14 @@ public class ImsMultiEndpointImplBase {
|
|||||||
public void requestImsExternalCallStateInfo() {
|
public void requestImsExternalCallStateInfo() {
|
||||||
Log.d(TAG, "requestImsExternalCallStateInfo() not implemented");
|
Log.d(TAG, "requestImsExternalCallStateInfo() not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set default Executor from MmTelFeature.
|
||||||
|
* @param executor The default executor for the framework to use when executing the methods
|
||||||
|
* overridden by the implementation of ImsMultiEndpoint.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public final void setDefaultExecutor(@NonNull Executor executor) {
|
||||||
|
mExecutor = executor;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,10 +31,19 @@ import android.telephony.ims.aidl.IImsRegistrationCallback;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.android.internal.telephony.util.RemoteCallbackListExt;
|
import com.android.internal.telephony.util.RemoteCallbackListExt;
|
||||||
|
import com.android.internal.telephony.util.TelephonyUtils;
|
||||||
import com.android.internal.util.ArrayUtils;
|
import com.android.internal.util.ArrayUtils;
|
||||||
|
|
||||||
|
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.util.concurrent.CancellationException;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.CompletionException;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Controls IMS registration for this ImsService and notifies the framework when the IMS
|
* Controls IMS registration for this ImsService and notifies the framework when the IMS
|
||||||
@@ -92,39 +101,114 @@ public class ImsRegistrationImplBase {
|
|||||||
// yet.
|
// yet.
|
||||||
private static final int REGISTRATION_STATE_UNKNOWN = -1;
|
private static final int REGISTRATION_STATE_UNKNOWN = -1;
|
||||||
|
|
||||||
|
private Executor mExecutor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new ImsRegistration.
|
||||||
|
* <p>
|
||||||
|
* Method stubs called from the framework will be called asynchronously. To specify the
|
||||||
|
* {@link Executor} that the methods stubs will be called, use
|
||||||
|
* {@link ImsRegistrationImplBase#ImsRegistrationImplBase(Executor)} instead.
|
||||||
|
*/
|
||||||
|
public ImsRegistrationImplBase() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a ImsRegistration using the Executor specified for methods being called by the
|
||||||
|
* framework.
|
||||||
|
* @param executor The executor for the framework to use when executing the methods overridden
|
||||||
|
* by the implementation of ImsRegistration.
|
||||||
|
*/
|
||||||
|
public ImsRegistrationImplBase(@NonNull Executor executor) {
|
||||||
|
super();
|
||||||
|
mExecutor = executor;
|
||||||
|
}
|
||||||
|
|
||||||
private final IImsRegistration mBinder = new IImsRegistration.Stub() {
|
private final IImsRegistration mBinder = new IImsRegistration.Stub() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @ImsRegistrationTech int getRegistrationTechnology() throws RemoteException {
|
public @ImsRegistrationTech int getRegistrationTechnology() throws RemoteException {
|
||||||
synchronized (mLock) {
|
return executeMethodAsyncForResult(() -> (mRegistrationAttributes == null)
|
||||||
return (mRegistrationAttributes == null) ? REGISTRATION_TECH_NONE
|
? REGISTRATION_TECH_NONE : mRegistrationAttributes.getRegistrationTechnology(),
|
||||||
: mRegistrationAttributes.getRegistrationTechnology();
|
"getRegistrationTechnology");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addRegistrationCallback(IImsRegistrationCallback c) throws RemoteException {
|
public void addRegistrationCallback(IImsRegistrationCallback c) throws RemoteException {
|
||||||
|
AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
|
||||||
|
executeMethodAsync(() -> {
|
||||||
|
try {
|
||||||
ImsRegistrationImplBase.this.addRegistrationCallback(c);
|
ImsRegistrationImplBase.this.addRegistrationCallback(c);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
exceptionRef.set(e);
|
||||||
|
}
|
||||||
|
}, "addRegistrationCallback");
|
||||||
|
|
||||||
|
if (exceptionRef.get() != null) {
|
||||||
|
throw exceptionRef.get();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeRegistrationCallback(IImsRegistrationCallback c) throws RemoteException {
|
public void removeRegistrationCallback(IImsRegistrationCallback c) throws RemoteException {
|
||||||
ImsRegistrationImplBase.this.removeRegistrationCallback(c);
|
executeMethodAsync(() -> ImsRegistrationImplBase.this.removeRegistrationCallback(c),
|
||||||
|
"removeRegistrationCallback");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void triggerFullNetworkRegistration(int sipCode, String sipReason) {
|
public void triggerFullNetworkRegistration(int sipCode, String sipReason) {
|
||||||
ImsRegistrationImplBase.this.triggerFullNetworkRegistration(sipCode, sipReason);
|
executeMethodAsyncNoException(() -> ImsRegistrationImplBase.this
|
||||||
|
.triggerFullNetworkRegistration(sipCode, sipReason),
|
||||||
|
"triggerFullNetworkRegistration");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void triggerUpdateSipDelegateRegistration() {
|
public void triggerUpdateSipDelegateRegistration() {
|
||||||
ImsRegistrationImplBase.this.updateSipDelegateRegistration();
|
executeMethodAsyncNoException(() -> ImsRegistrationImplBase.this
|
||||||
|
.updateSipDelegateRegistration(), "triggerUpdateSipDelegateRegistration");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void triggerSipDelegateDeregistration() {
|
public void triggerSipDelegateDeregistration() {
|
||||||
ImsRegistrationImplBase.this.triggerSipDelegateDeregistration();
|
executeMethodAsyncNoException(() -> ImsRegistrationImplBase.this
|
||||||
|
.triggerSipDelegateDeregistration(), "triggerSipDelegateDeregistration");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the methods with a clean calling identity on the executor and wait indefinitely for
|
||||||
|
// the future to return.
|
||||||
|
private void executeMethodAsync(Runnable r, String errorLogName) throws RemoteException {
|
||||||
|
try {
|
||||||
|
CompletableFuture.runAsync(
|
||||||
|
() -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor).join();
|
||||||
|
} catch (CancellationException | CompletionException e) {
|
||||||
|
Log.w(LOG_TAG, "ImsRegistrationImplBase Binder - " + errorLogName + " exception: "
|
||||||
|
+ e.getMessage());
|
||||||
|
throw new RemoteException(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void executeMethodAsyncNoException(Runnable r, String errorLogName) {
|
||||||
|
try {
|
||||||
|
CompletableFuture.runAsync(
|
||||||
|
() -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor).join();
|
||||||
|
} catch (CancellationException | CompletionException e) {
|
||||||
|
Log.w(LOG_TAG, "ImsRegistrationImplBase Binder - " + errorLogName + " exception: "
|
||||||
|
+ e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T> T executeMethodAsyncForResult(Supplier<T> r,
|
||||||
|
String errorLogName) throws RemoteException {
|
||||||
|
CompletableFuture<T> future = CompletableFuture.supplyAsync(
|
||||||
|
() -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor);
|
||||||
|
try {
|
||||||
|
return future.get();
|
||||||
|
} catch (ExecutionException | InterruptedException e) {
|
||||||
|
Log.w(LOG_TAG, "ImsRegistrationImplBase Binder - " + errorLogName + " exception: "
|
||||||
|
+ e.getMessage());
|
||||||
|
throw new RemoteException(e.getMessage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -394,4 +478,16 @@ public class ImsRegistrationImplBase {
|
|||||||
onSubscriberAssociatedUriChanged(c, uris);
|
onSubscriberAssociatedUriChanged(c, uris);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set default Executor from ImsService.
|
||||||
|
* @param executor The default executor for the framework to use when executing the methods
|
||||||
|
* overridden by the implementation of Registration.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public final void setDefaultExecutor(@NonNull Executor executor) {
|
||||||
|
if (mExecutor == null) {
|
||||||
|
mExecutor = executor;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,10 +27,17 @@ import android.util.Log;
|
|||||||
|
|
||||||
import com.android.ims.internal.IImsUt;
|
import com.android.ims.internal.IImsUt;
|
||||||
import com.android.ims.internal.IImsUtListener;
|
import com.android.ims.internal.IImsUtListener;
|
||||||
|
import com.android.internal.telephony.util.TelephonyUtils;
|
||||||
|
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.concurrent.CancellationException;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.CompletionException;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base implementation of IMS UT interface, which implements stubs. Override these methods to
|
* Base implementation of IMS UT interface, which implements stubs. Override these methods to
|
||||||
@@ -119,96 +126,108 @@ public class ImsUtImplBase {
|
|||||||
*/
|
*/
|
||||||
public static final int INVALID_RESULT = -1;
|
public static final int INVALID_RESULT = -1;
|
||||||
|
|
||||||
|
private Executor mExecutor = Runnable::run;
|
||||||
|
|
||||||
private final IImsUt.Stub mServiceImpl = new IImsUt.Stub() {
|
private final IImsUt.Stub mServiceImpl = new IImsUt.Stub() {
|
||||||
private final Object mLock = new Object();
|
private final Object mLock = new Object();
|
||||||
private ImsUtListener mUtListener;
|
private ImsUtListener mUtListener;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() throws RemoteException {
|
public void close() throws RemoteException {
|
||||||
ImsUtImplBase.this.close();
|
executeMethodAsync(() ->ImsUtImplBase.this.close(), "close");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int queryCallBarring(int cbType) throws RemoteException {
|
public int queryCallBarring(int cbType) throws RemoteException {
|
||||||
return ImsUtImplBase.this.queryCallBarring(cbType);
|
return executeMethodAsyncForResult(() -> ImsUtImplBase.this.queryCallBarring(cbType),
|
||||||
|
"queryCallBarring");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int queryCallForward(int condition, String number) throws RemoteException {
|
public int queryCallForward(int condition, String number) throws RemoteException {
|
||||||
return ImsUtImplBase.this.queryCallForward(condition, number);
|
return executeMethodAsyncForResult(() -> ImsUtImplBase.this.queryCallForward(
|
||||||
|
condition, number), "queryCallForward");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int queryCallWaiting() throws RemoteException {
|
public int queryCallWaiting() throws RemoteException {
|
||||||
return ImsUtImplBase.this.queryCallWaiting();
|
return executeMethodAsyncForResult(() -> ImsUtImplBase.this.queryCallWaiting(),
|
||||||
|
"queryCallWaiting");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int queryCLIR() throws RemoteException {
|
public int queryCLIR() throws RemoteException {
|
||||||
return ImsUtImplBase.this.queryCLIR();
|
return executeMethodAsyncForResult(() -> ImsUtImplBase.this.queryCLIR(), "queryCLIR");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int queryCLIP() throws RemoteException {
|
public int queryCLIP() throws RemoteException {
|
||||||
return ImsUtImplBase.this.queryCLIP();
|
return executeMethodAsyncForResult(() -> ImsUtImplBase.this.queryCLIP(), "queryCLIP");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int queryCOLR() throws RemoteException {
|
public int queryCOLR() throws RemoteException {
|
||||||
return ImsUtImplBase.this.queryCOLR();
|
return executeMethodAsyncForResult(() -> ImsUtImplBase.this.queryCOLR(), "queryCOLR");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int queryCOLP() throws RemoteException {
|
public int queryCOLP() throws RemoteException {
|
||||||
return ImsUtImplBase.this.queryCOLP();
|
return executeMethodAsyncForResult(() -> ImsUtImplBase.this.queryCOLP(), "queryCOLP");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int transact(Bundle ssInfo) throws RemoteException {
|
public int transact(Bundle ssInfo) throws RemoteException {
|
||||||
return ImsUtImplBase.this.transact(ssInfo);
|
return executeMethodAsyncForResult(() -> ImsUtImplBase.this.transact(ssInfo),
|
||||||
|
"transact");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int updateCallBarring(int cbType, int action, String[] barrList) throws
|
public int updateCallBarring(int cbType, int action, String[] barrList) throws
|
||||||
RemoteException {
|
RemoteException {
|
||||||
return ImsUtImplBase.this.updateCallBarring(cbType, action, barrList);
|
return executeMethodAsyncForResult(() -> ImsUtImplBase.this.updateCallBarring(
|
||||||
|
cbType, action, barrList), "updateCallBarring");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int updateCallForward(int action, int condition, String number, int serviceClass,
|
public int updateCallForward(int action, int condition, String number, int serviceClass,
|
||||||
int timeSeconds) throws RemoteException {
|
int timeSeconds) throws RemoteException {
|
||||||
return ImsUtImplBase.this.updateCallForward(action, condition, number, serviceClass,
|
return executeMethodAsyncForResult(() -> ImsUtImplBase.this.updateCallForward(
|
||||||
timeSeconds);
|
action, condition, number, serviceClass, timeSeconds), "updateCallForward");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int updateCallWaiting(boolean enable, int serviceClass) throws RemoteException {
|
public int updateCallWaiting(boolean enable, int serviceClass) throws RemoteException {
|
||||||
return ImsUtImplBase.this.updateCallWaiting(enable, serviceClass);
|
return executeMethodAsyncForResult(() -> ImsUtImplBase.this.updateCallWaiting(
|
||||||
|
enable, serviceClass), "updateCallWaiting");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int updateCLIR(int clirMode) throws RemoteException {
|
public int updateCLIR(int clirMode) throws RemoteException {
|
||||||
return ImsUtImplBase.this.updateCLIR(clirMode);
|
return executeMethodAsyncForResult(() -> ImsUtImplBase.this.updateCLIR(clirMode),
|
||||||
|
"updateCLIR");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int updateCLIP(boolean enable) throws RemoteException {
|
public int updateCLIP(boolean enable) throws RemoteException {
|
||||||
return ImsUtImplBase.this.updateCLIP(enable);
|
return executeMethodAsyncForResult(() -> ImsUtImplBase.this.updateCLIP(enable),
|
||||||
|
"updateCLIP");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int updateCOLR(int presentation) throws RemoteException {
|
public int updateCOLR(int presentation) throws RemoteException {
|
||||||
return ImsUtImplBase.this.updateCOLR(presentation);
|
return executeMethodAsyncForResult(() -> ImsUtImplBase.this.updateCOLR(presentation),
|
||||||
|
"updateCOLR");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int updateCOLP(boolean enable) throws RemoteException {
|
public int updateCOLP(boolean enable) throws RemoteException {
|
||||||
return ImsUtImplBase.this.updateCOLP(enable);
|
return executeMethodAsyncForResult(() -> ImsUtImplBase.this.updateCOLP(enable),
|
||||||
|
"updateCOLP");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setListener(IImsUtListener listener) throws RemoteException {
|
public void setListener(IImsUtListener listener) throws RemoteException {
|
||||||
synchronized (mLock) {
|
executeMethodAsync(() -> {
|
||||||
if (mUtListener != null
|
if (mUtListener != null
|
||||||
&& !mUtListener.getListenerInterface().asBinder().isBinderAlive()) {
|
&& !mUtListener.getListenerInterface().asBinder().isBinderAlive()) {
|
||||||
Log.w(TAG, "setListener: discarding dead Binder");
|
Log.w(TAG, "setListener: discarding dead Binder");
|
||||||
@@ -229,29 +248,59 @@ public class ImsUtImplBase {
|
|||||||
+ "listener");
|
+ "listener");
|
||||||
mUtListener = new ImsUtListener(listener);
|
mUtListener = new ImsUtListener(listener);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
ImsUtImplBase.this.setListener(mUtListener);
|
ImsUtImplBase.this.setListener(mUtListener);
|
||||||
|
}, "setListener");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int queryCallBarringForServiceClass(int cbType, int serviceClass)
|
public int queryCallBarringForServiceClass(int cbType, int serviceClass)
|
||||||
throws RemoteException {
|
throws RemoteException {
|
||||||
return ImsUtImplBase.this.queryCallBarringForServiceClass(cbType, serviceClass);
|
return executeMethodAsyncForResult(() -> ImsUtImplBase.this
|
||||||
|
.queryCallBarringForServiceClass(cbType, serviceClass),
|
||||||
|
"queryCallBarringForServiceClass");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int updateCallBarringForServiceClass(int cbType, int action,
|
public int updateCallBarringForServiceClass(int cbType, int action,
|
||||||
String[] barrList, int serviceClass) throws RemoteException {
|
String[] barrList, int serviceClass) throws RemoteException {
|
||||||
return ImsUtImplBase.this.updateCallBarringForServiceClass(
|
return executeMethodAsyncForResult(() -> ImsUtImplBase.this
|
||||||
cbType, action, barrList, serviceClass);
|
.updateCallBarringForServiceClass(cbType, action, barrList, serviceClass),
|
||||||
|
"updateCallBarringForServiceClass");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int updateCallBarringWithPassword(int cbType, int action, String[] barrList,
|
public int updateCallBarringWithPassword(int cbType, int action, String[] barrList,
|
||||||
int serviceClass, String password) throws RemoteException {
|
int serviceClass, String password) throws RemoteException {
|
||||||
return ImsUtImplBase.this.updateCallBarringWithPassword(
|
return executeMethodAsyncForResult(() -> ImsUtImplBase.this
|
||||||
cbType, action, barrList, serviceClass, password);
|
.updateCallBarringWithPassword(cbType, action, barrList, serviceClass,
|
||||||
|
password), "updateCallBarringWithPassword");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the methods with a clean calling identity on the executor and wait indefinitely for
|
||||||
|
// the future to return.
|
||||||
|
private void executeMethodAsync(Runnable r, String errorLogName) throws RemoteException {
|
||||||
|
try {
|
||||||
|
CompletableFuture.runAsync(
|
||||||
|
() -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor).join();
|
||||||
|
} catch (CancellationException | CompletionException e) {
|
||||||
|
Log.w(TAG, "ImsUtImplBase Binder - " + errorLogName + " exception: "
|
||||||
|
+ e.getMessage());
|
||||||
|
throw new RemoteException(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T> T executeMethodAsyncForResult(Supplier<T> r,
|
||||||
|
String errorLogName) throws RemoteException {
|
||||||
|
CompletableFuture<T> future = CompletableFuture.supplyAsync(
|
||||||
|
() -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor);
|
||||||
|
try {
|
||||||
|
return future.get();
|
||||||
|
} catch (ExecutionException | InterruptedException e) {
|
||||||
|
Log.w(TAG, "ImsUtImplBase Binder - " + errorLogName + " exception: "
|
||||||
|
+ e.getMessage());
|
||||||
|
throw new RemoteException(e.getMessage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -470,4 +519,14 @@ public class ImsUtImplBase {
|
|||||||
public IImsUt getInterface() {
|
public IImsUt getInterface() {
|
||||||
return mServiceImpl;
|
return mServiceImpl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set default Executor from MmTelFeature.
|
||||||
|
* @param executor The default executor for the framework to use when executing the methods
|
||||||
|
* overridden by the implementation of ImsUT.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public final void setDefaultExecutor(@NonNull Executor executor) {
|
||||||
|
mExecutor = executor;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -86,9 +86,20 @@ public class SipTransportImplBase {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private final Executor mBinderExecutor;
|
private Executor mBinderExecutor;
|
||||||
private final ArrayList<SipDelegateAidlWrapper> mDelegates = new ArrayList<>();
|
private final ArrayList<SipDelegateAidlWrapper> mDelegates = new ArrayList<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new SipTransport.
|
||||||
|
* <p>
|
||||||
|
* Method stubs called from the framework will be called asynchronously. To specify the
|
||||||
|
* {@link Executor} that the methods stubs will be called, use
|
||||||
|
* {@link SipTransportImplBase#SipTransportImplBase(Executor)} instead.
|
||||||
|
*/
|
||||||
|
public SipTransportImplBase() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an implementation of SipTransportImplBase.
|
* Create an implementation of SipTransportImplBase.
|
||||||
*
|
*
|
||||||
@@ -212,4 +223,16 @@ public class SipTransportImplBase {
|
|||||||
public ISipTransport getBinder() {
|
public ISipTransport getBinder() {
|
||||||
return mSipTransportImpl;
|
return mSipTransportImpl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set default Executor from ImsService.
|
||||||
|
* @param executor The default executor for the framework to use when executing the methods
|
||||||
|
* overridden by the implementation of SipTransport.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public final void setDefaultExecutor(@NonNull Executor executor) {
|
||||||
|
if (mBinderExecutor == null) {
|
||||||
|
mBinderExecutor = executor;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user