Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ef4cbddd authored by Hakjun Choi's avatar Hakjun Choi Committed by Android (Google) Code Review
Browse files

Merge "Executor Pattern for ImsSmsImplBase"

parents 4845b2c4 0780dded
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -16031,6 +16031,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);
+69 −26
Original line number Diff line number Diff line
@@ -84,10 +84,12 @@ public class MmTelFeature extends ImsFeature {

    private static final String LOG_TAG = "MmTelFeature";
    private Executor mExecutor;
    private ImsSmsImplBase mSmsImpl;

    private HashMap<ImsTrafficSessionCallback, ImsTrafficSessionCallbackWrapper> mTrafficCallbacks =
            new HashMap<>();
    /**
     * Creates a new MmTelFeature using the Executor set in {@link ImsService#getExecutor}
     * @hide
     */
    @SystemApi
@@ -269,50 +271,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
@@ -347,6 +353,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 {
@@ -370,6 +389,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> T executeMethodAsyncForResult(Supplier<T> r,
                String errorLogName) throws RemoteException {
            CompletableFuture<T> future = CompletableFuture.supplyAsync(
@@ -396,16 +426,16 @@ public class MmTelFeature extends ImsFeature {
            }
        }

        @Override
        public void setTerminalBasedCallWaitingStatus(boolean enabled) throws RemoteException {
            synchronized (mLock) {
        private <T> T executeMethodAsyncForResultNoException(Supplier<T> r,
                String errorLogName, Executor executor) {
            CompletableFuture<T> future = CompletableFuture.supplyAsync(
                    () -> TelephonyUtils.runWithCleanCallingIdentity(r), executor);
            try {
                    MmTelFeature.this.setTerminalBasedCallWaitingStatus(enabled);
                } catch (ServiceSpecificException se) {
                    throw new ServiceSpecificException(se.errorCode, se.getMessage());
                } catch (Exception e) {
                    throw new RemoteException(e.getMessage());
                }
                return future.get();
            } catch (ExecutionException | InterruptedException e) {
                Log.w(LOG_TAG, "MmTelFeature Binder - " + errorLogName + " exception: "
                        + e.getMessage());
                return null;
            }
        }
    };
@@ -1490,6 +1520,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.
@@ -1638,35 +1681,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();
    }

    /**
@@ -1683,7 +1726,7 @@ public class MmTelFeature extends ImsFeature {
    }

    private String getSmsFormat() {
        return getSmsImplementation().getSmsFormat();
        return getImsSmsImpl().getSmsFormat();
    }

    /**
+42 −0
Original line number Diff line number Diff line
@@ -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.
     * <p>
     * @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;
    }
}