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

Unverified Commit 7465b153 authored by Michael Bestas's avatar Michael Bestas
Browse files

Merge tag 'android-15.0.0_r26' into staging/lineage-22.2_merge-android-15.0.0_r26

Android 15.0.0 release 26

# -----BEGIN PGP SIGNATURE-----
#
# iF0EABECAB0WIQRDQNE1cO+UXoOBCWTorT+BmrEOeAUCZ/gLMwAKCRDorT+BmrEO
# eHkqAJ43Az3wdikXynsHzyCFe6zJn2ABOACfdD9P5ltYMnTDgEphUg9RUrF3jbQ=
# =eh7J
# -----END PGP SIGNATURE-----
# gpg: Signature made Thu Apr 10 21:17:23 2025 EEST
# gpg:                using DSA key 4340D13570EF945E83810964E8AD3F819AB10E78
# gpg: Good signature from "The Android Open Source Project <initial-contribution@android.com>" [ultimate]

* tag 'android-15.0.0_r26':
  Remove the scheduled executor anomalies from the ConnectionServiceWrapper.
  Remove the scheduled executor anomalies from the ConnectionServiceWrapper.
  Ensure ScheduledExecutor is not shutdown before scheduling timeout cleanup.
  Ensure connection is unbound on call redirection timeout.

Change-Id: I68adacbe271d64d4814ab340eb3df71052cc6b96
parents 5256bf1c 5fff8695
Loading
Loading
Loading
Loading
+31 −10
Original line number Diff line number Diff line
@@ -79,6 +79,7 @@ import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
@@ -1655,11 +1656,21 @@ public class ConnectionServiceWrapper extends ServiceBinder implements
                        }
                    }
                };
                // Post cleanup to the executor service and cache the future, so we can cancel it if
                // needed.
                ScheduledFuture<?> future = mScheduledExecutor.schedule(r.getRunnableToCancel(),
                        SERVICE_BINDING_TIMEOUT, TimeUnit.MILLISECONDS);
                if (mScheduledExecutor != null && !mScheduledExecutor.isShutdown()) {
                    try {
                        // Post cleanup to the executor service and cache the future,
                        // so we can cancel it if needed.
                        ScheduledFuture<?> future = mScheduledExecutor.schedule(
                                r.getRunnableToCancel(),SERVICE_BINDING_TIMEOUT,
                                TimeUnit.MILLISECONDS);
                        mScheduledFutureMap.put(call, future);
                    } catch (RejectedExecutionException e) {
                        Log.e(this, e, "createConference: mScheduledExecutor was "
                                + "already shutdown");
                    }
                } else {
                    Log.w(this, "createConference: Scheduled executor is null or shutdown");
                }
                try {
                    mServiceInterface.createConference(
                            call.getConnectionManagerPhoneAccount(),
@@ -1784,11 +1795,21 @@ public class ConnectionServiceWrapper extends ServiceBinder implements
                        }
                    }
                };
                // Post cleanup to the executor service and cache the future, so we can cancel it if
                // needed.
                ScheduledFuture<?> future = mScheduledExecutor.schedule(r.getRunnableToCancel(),
                        SERVICE_BINDING_TIMEOUT, TimeUnit.MILLISECONDS);
                if (mScheduledExecutor != null && !mScheduledExecutor.isShutdown()) {
                    try {
                        // Post cleanup to the executor service and cache the future,
                        // so we can cancel it if needed.
                        ScheduledFuture<?> future = mScheduledExecutor.schedule(
                                r.getRunnableToCancel(),SERVICE_BINDING_TIMEOUT,
                                TimeUnit.MILLISECONDS);
                        mScheduledFutureMap.put(call, future);
                    } catch (RejectedExecutionException e) {
                        Log.e(this, e, "createConnection: mScheduledExecutor was "
                                + "already shutdown");
                    }
                } else {
                    Log.w(this, "createConnection: Scheduled executor is null or shutdown");
                }
                try {
                    if (mFlags.cswServiceInterfaceIsNull() && mServiceInterface == null) {
                        if (mFlags.dontTimeoutDestroyedCalls()) {
+8 −0
Original line number Diff line number Diff line
@@ -133,6 +133,14 @@ public class CallRedirectionProcessor implements CallRedirectionCallback {
                            + mServiceType + " call redirection service");
                }
            }
            Log.i(this, "notifyTimeout: call redirection has timed out so "
                    + "unbinding the connection");
            if (mConnection != null) {
                // We still need to call unbind even if the service disconnected.
                mContext.unbindService(mConnection);
                mConnection = null;
            }
            mService = null;
        }

        private class CallRedirectionServiceConnection implements ServiceConnection {
+12 −0
Original line number Diff line number Diff line
@@ -221,6 +221,9 @@ public class CallRedirectionProcessorTest extends TelecomTestCase {
        verify(mCallsManager, times(1)).onCallRedirectionComplete(eq(mCall), any(),
                eq(mPhoneAccountHandle), eq(null), eq(SPEAKER_PHONE_ON), eq(VIDEO_STATE),
                eq(false), eq(CallRedirectionProcessor.UI_TYPE_NO_ACTION));
        // Verify service was unbound
        verify(mContext, times(1)).
                unbindService(any(ServiceConnection.class));
    }

    @Test
@@ -249,6 +252,9 @@ public class CallRedirectionProcessorTest extends TelecomTestCase {
        verify(mCallsManager, times(1)).onCallRedirectionComplete(eq(mCall), any(),
                eq(mPhoneAccountHandle), eq(null), eq(SPEAKER_PHONE_ON), eq(VIDEO_STATE),
                eq(true), eq(CallRedirectionProcessor.UI_TYPE_USER_DEFINED_TIMEOUT));
        // Verify service was unbound
        verify(mContext, times(1)).
                unbindService(any(ServiceConnection.class));
    }

    @Test
@@ -280,6 +286,9 @@ public class CallRedirectionProcessorTest extends TelecomTestCase {
        verify(mCallsManager, times(1)).onCallRedirectionComplete(eq(mCall), any(),
                eq(mPhoneAccountHandle), eq(null), eq(SPEAKER_PHONE_ON), eq(VIDEO_STATE),
                eq(true), eq(CallRedirectionProcessor.UI_TYPE_USER_DEFINED_TIMEOUT));
        // Verify service was unbound
        verify(mContext, times(1)).
                unbindService(any(ServiceConnection.class));

        // Wait for another carrier timeout time, but should not expect any carrier service request
        // is triggered.
@@ -289,6 +298,9 @@ public class CallRedirectionProcessorTest extends TelecomTestCase {
        verify(mCallsManager, times(1)).onCallRedirectionComplete(eq(mCall), any(),
                eq(mPhoneAccountHandle), eq(null), eq(SPEAKER_PHONE_ON), eq(VIDEO_STATE),
                eq(true), eq(CallRedirectionProcessor.UI_TYPE_USER_DEFINED_TIMEOUT));
        // Verify service was unbound
        verify(mContext, times(1)).
                unbindService(any(ServiceConnection.class));
    }

    @Test