diff --git a/core/api/system-current.txt b/core/api/system-current.txt index dbd6cac45e9e7..ddd274d5a79a7 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -15932,6 +15932,7 @@ package android.telephony.ims.stub { public class ImsSmsImplBase { ctor public ImsSmsImplBase(); + ctor public ImsSmsImplBase(@NonNull java.util.concurrent.Executor); method public void acknowledgeSms(int, @IntRange(from=0, to=65535) int, int); method public void acknowledgeSms(int, @IntRange(from=0, to=65535) int, int, @NonNull byte[]); method public void acknowledgeSmsReport(int, @IntRange(from=0, to=65535) int, int); diff --git a/telephony/java/android/telephony/ims/feature/MmTelFeature.java b/telephony/java/android/telephony/ims/feature/MmTelFeature.java index 4710c1f4dbf3f..a1f2f108a1488 100644 --- a/telephony/java/android/telephony/ims/feature/MmTelFeature.java +++ b/telephony/java/android/telephony/ims/feature/MmTelFeature.java @@ -75,8 +75,10 @@ public class MmTelFeature extends ImsFeature { private static final String LOG_TAG = "MmTelFeature"; private Executor mExecutor; + private ImsSmsImplBase mSmsImpl; /** + * Creates a new MmTelFeature using the Executor set in {@link ImsService#getExecutor} * @hide */ @SystemApi @@ -258,50 +260,54 @@ public class MmTelFeature extends ImsFeature { @Override public void setSmsListener(IImsSmsListener l) { executeMethodAsyncNoException(() -> MmTelFeature.this.setSmsListener(l), - "setSmsListener"); + "setSmsListener", getImsSmsImpl().getExecutor()); } @Override public void sendSms(int token, int messageRef, String format, String smsc, boolean retry, byte[] pdu) { executeMethodAsyncNoException(() -> MmTelFeature.this - .sendSms(token, messageRef, format, smsc, retry, pdu), "sendSms"); + .sendSms(token, messageRef, format, smsc, retry, pdu), "sendSms", + getImsSmsImpl().getExecutor()); } @Override public void onMemoryAvailable(int token) { executeMethodAsyncNoException(() -> MmTelFeature.this - .onMemoryAvailable(token), "onMemoryAvailable"); + .onMemoryAvailable(token), "onMemoryAvailable", getImsSmsImpl().getExecutor()); } @Override public void acknowledgeSms(int token, int messageRef, int result) { executeMethodAsyncNoException(() -> MmTelFeature.this - .acknowledgeSms(token, messageRef, result), "acknowledgeSms"); + .acknowledgeSms(token, messageRef, result), "acknowledgeSms", + getImsSmsImpl().getExecutor()); } @Override public void acknowledgeSmsWithPdu(int token, int messageRef, int result, byte[] pdu) { executeMethodAsyncNoException(() -> MmTelFeature.this - .acknowledgeSms(token, messageRef, result, pdu), "acknowledgeSms"); + .acknowledgeSms(token, messageRef, result, pdu), "acknowledgeSms", + getImsSmsImpl().getExecutor()); } @Override public void acknowledgeSmsReport(int token, int messageRef, int result) { executeMethodAsyncNoException(() -> MmTelFeature.this - .acknowledgeSmsReport(token, messageRef, result), "acknowledgeSmsReport"); + .acknowledgeSmsReport(token, messageRef, result), "acknowledgeSmsReport", + getImsSmsImpl().getExecutor()); } @Override public String getSmsFormat() { return executeMethodAsyncForResultNoException(() -> MmTelFeature.this - .getSmsFormat(), "getSmsFormat"); + .getSmsFormat(), "getSmsFormat", getImsSmsImpl().getExecutor()); } @Override public void onSmsReady() { executeMethodAsyncNoException(() -> MmTelFeature.this.onSmsReady(), - "onSmsReady"); + "onSmsReady", getImsSmsImpl().getExecutor()); } @Override @@ -336,6 +342,19 @@ public class MmTelFeature extends ImsFeature { () -> MmTelFeature.this.notifySrvccCanceled(), "notifySrvccCanceled"); } + @Override + public void setTerminalBasedCallWaitingStatus(boolean enabled) throws RemoteException { + synchronized (mLock) { + try { + MmTelFeature.this.setTerminalBasedCallWaitingStatus(enabled); + } catch (ServiceSpecificException se) { + throw new ServiceSpecificException(se.errorCode, se.getMessage()); + } catch (Exception e) { + throw new RemoteException(e.getMessage()); + } + } + } + // 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 { @@ -359,6 +378,17 @@ public class MmTelFeature extends ImsFeature { } } + private void executeMethodAsyncNoException(Runnable r, String errorLogName, + Executor executor) { + try { + CompletableFuture.runAsync( + () -> TelephonyUtils.runWithCleanCallingIdentity(r), executor).join(); + } catch (CancellationException | CompletionException e) { + Log.w(LOG_TAG, "MmTelFeature Binder - " + errorLogName + " exception: " + + e.getMessage()); + } + } + private T executeMethodAsyncForResult(Supplier r, String errorLogName) throws RemoteException { CompletableFuture future = CompletableFuture.supplyAsync( @@ -385,16 +415,16 @@ public class MmTelFeature extends ImsFeature { } } - @Override - public void setTerminalBasedCallWaitingStatus(boolean enabled) throws RemoteException { - synchronized (mLock) { - try { - MmTelFeature.this.setTerminalBasedCallWaitingStatus(enabled); - } catch (ServiceSpecificException se) { - throw new ServiceSpecificException(se.errorCode, se.getMessage()); - } catch (Exception e) { - throw new RemoteException(e.getMessage()); - } + private T executeMethodAsyncForResultNoException(Supplier r, + String errorLogName, Executor executor) { + CompletableFuture future = CompletableFuture.supplyAsync( + () -> TelephonyUtils.runWithCleanCallingIdentity(r), executor); + try { + return future.get(); + } catch (ExecutionException | InterruptedException e) { + Log.w(LOG_TAG, "MmTelFeature Binder - " + errorLogName + " exception: " + + e.getMessage()); + return null; } } }; @@ -995,6 +1025,19 @@ public class MmTelFeature extends ImsFeature { } } + /** + * @hide + */ + public @NonNull ImsSmsImplBase getImsSmsImpl() { + synchronized (mLock) { + if (mSmsImpl == null) { + mSmsImpl = getSmsImplementation(); + mSmsImpl.setDefaultExecutor(mExecutor); + } + return mSmsImpl; + } + } + /** * @return The {@link ImsUtImplBase} Ut interface implementation for the supplementary service * configuration. @@ -1143,35 +1186,35 @@ public class MmTelFeature extends ImsFeature { } private void setSmsListener(IImsSmsListener listener) { - getSmsImplementation().registerSmsListener(listener); + getImsSmsImpl().registerSmsListener(listener); } private void sendSms(int token, int messageRef, String format, String smsc, boolean isRetry, byte[] pdu) { - getSmsImplementation().sendSms(token, messageRef, format, smsc, isRetry, pdu); + getImsSmsImpl().sendSms(token, messageRef, format, smsc, isRetry, pdu); } private void onMemoryAvailable(int token) { - getSmsImplementation().onMemoryAvailable(token); + getImsSmsImpl().onMemoryAvailable(token); } private void acknowledgeSms(int token, int messageRef, @ImsSmsImplBase.DeliverStatusResult int result) { - getSmsImplementation().acknowledgeSms(token, messageRef, result); + getImsSmsImpl().acknowledgeSms(token, messageRef, result); } private void acknowledgeSms(int token, int messageRef, @ImsSmsImplBase.DeliverStatusResult int result, byte[] pdu) { - getSmsImplementation().acknowledgeSms(token, messageRef, result, pdu); + getImsSmsImpl().acknowledgeSms(token, messageRef, result, pdu); } private void acknowledgeSmsReport(int token, int messageRef, @ImsSmsImplBase.StatusReportResult int result) { - getSmsImplementation().acknowledgeSmsReport(token, messageRef, result); + getImsSmsImpl().acknowledgeSmsReport(token, messageRef, result); } private void onSmsReady() { - getSmsImplementation().onReady(); + getImsSmsImpl().onReady(); } /** @@ -1188,7 +1231,7 @@ public class MmTelFeature extends ImsFeature { } private String getSmsFormat() { - return getSmsImplementation().getSmsFormat(); + return getImsSmsImpl().getSmsFormat(); } /** diff --git a/telephony/java/android/telephony/ims/stub/ImsSmsImplBase.java b/telephony/java/android/telephony/ims/stub/ImsSmsImplBase.java index daab84eb077c4..17cb3b46e0f14 100644 --- a/telephony/java/android/telephony/ims/stub/ImsSmsImplBase.java +++ b/telephony/java/android/telephony/ims/stub/ImsSmsImplBase.java @@ -28,6 +28,7 @@ import android.util.Log; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.concurrent.Executor; /** * Base implementation for SMS over IMS. @@ -129,6 +130,22 @@ public class ImsSmsImplBase { // Lock for feature synchronization private final Object mLock = new Object(); private IImsSmsListener mListener; + private Executor mExecutor; + + /** + * Create a new ImsSmsImplBase using the Executor set in MmTelFeature + */ + public ImsSmsImplBase() { + } + + /** + * Create a new ImsSmsImplBase with specified executor. + *

+ * @param executor Default executor for ImsSmsImplBase + */ + public ImsSmsImplBase(@NonNull Executor executor) { + mExecutor = executor; + } /** * Registers a listener responsible for handling tasks like delivering messages. @@ -482,4 +499,29 @@ public class ImsSmsImplBase { public void onReady() { // Base Implementation - Should be overridden } + + /** + * Set default Executor for ImsSmsImplBase. + * + * @param executor The default executor for the framework to use when executing the methods + * overridden by the implementation of ImsSms. + * @hide + */ + public final void setDefaultExecutor(@NonNull Executor executor) { + if (mExecutor == null) { + mExecutor = executor; + } + } + + /** + * Get Executor from ImsSmsImplBase. + * If there is no settings for the executor, all ImsSmsImplBase method calls will use + * Runnable::run as default + * + * @return an Executor used to execute methods in ImsSms called remotely by the framework. + * @hide + */ + public @NonNull Executor getExecutor() { + return mExecutor != null ? mExecutor : Runnable::run; + } }