diff --git a/service-t/Android.bp b/service-t/Android.bp index ab38c7a22d..81378f5ead 100644 --- a/service-t/Android.bp +++ b/service-t/Android.bp @@ -109,13 +109,15 @@ java_library { ":service-mdns-droidstubs", ], exclude_srcs: [ + "src/com/android/server/connectivity/mdns/internal/MdnsRealtimeScheduler.java", "src/com/android/server/connectivity/mdns/internal/SocketNetlinkMonitor.java", - "src/com/android/server/connectivity/mdns/SocketNetLinkMonitorFactory.java", "src/com/android/server/connectivity/mdns/MdnsAdvertiser.java", "src/com/android/server/connectivity/mdns/MdnsAnnouncer.java", "src/com/android/server/connectivity/mdns/MdnsInterfaceAdvertiser.java", "src/com/android/server/connectivity/mdns/MdnsProber.java", "src/com/android/server/connectivity/mdns/MdnsRecordRepository.java", + "src/com/android/server/connectivity/mdns/SchedulerFactory.java", + "src/com/android/server/connectivity/mdns/SocketNetLinkMonitorFactory.java", ], static_libs: [ "net-utils-device-common-mdns-standalone-build-test", @@ -132,7 +134,10 @@ java_library { droidstubs { name: "service-mdns-droidstubs", - srcs: ["src/com/android/server/connectivity/mdns/SocketNetLinkMonitorFactory.java"], + srcs: [ + "src/com/android/server/connectivity/mdns/SchedulerFactory.java", + "src/com/android/server/connectivity/mdns/SocketNetLinkMonitorFactory.java", + ], libs: [ "net-utils-device-common-mdns-standalone-build-test", "service-connectivity-tiramisu-pre-jarjar", diff --git a/service-t/src/com/android/server/connectivity/mdns/DiscoveryExecutor.java b/service-t/src/com/android/server/connectivity/mdns/DiscoveryExecutor.java index 21af1a14c9..99354f89ce 100644 --- a/service-t/src/com/android/server/connectivity/mdns/DiscoveryExecutor.java +++ b/service-t/src/com/android/server/connectivity/mdns/DiscoveryExecutor.java @@ -49,7 +49,13 @@ public class DiscoveryExecutor implements Executor { @NonNull private final ArrayList> mPendingTasks = new ArrayList<>(); - DiscoveryExecutor(@Nullable Looper defaultLooper) { + @GuardedBy("mPendingTasks") + @Nullable + Scheduler mScheduler; + @NonNull private final MdnsFeatureFlags mMdnsFeatureFlags; + + DiscoveryExecutor(@Nullable Looper defaultLooper, @NonNull MdnsFeatureFlags mdnsFeatureFlags) { + mMdnsFeatureFlags = mdnsFeatureFlags; if (defaultLooper != null) { this.mHandlerThread = null; synchronized (mPendingTasks) { @@ -62,7 +68,7 @@ public class DiscoveryExecutor implements Executor { synchronized (mPendingTasks) { mHandler = new Handler(getLooper()); for (Pair pendingTask : mPendingTasks) { - mHandler.postDelayed(pendingTask.first, pendingTask.second); + executeDelayed(pendingTask.first, pendingTask.second); } mPendingTasks.clear(); } @@ -95,15 +101,33 @@ public class DiscoveryExecutor implements Executor { /** Execute the given function after the specified amount of time elapses. */ public void executeDelayed(Runnable function, long delayMillis) { final Handler handler; + final Scheduler scheduler; synchronized (mPendingTasks) { if (this.mHandler == null) { mPendingTasks.add(Pair.create(function, delayMillis)); return; } else { handler = this.mHandler; + if (mMdnsFeatureFlags.mIsAccurateDelayCallbackEnabled + && this.mScheduler == null) { + this.mScheduler = SchedulerFactory.createScheduler(mHandler); + } + scheduler = this.mScheduler; } } - handler.postDelayed(function, delayMillis); + if (scheduler != null) { + if (delayMillis == 0L) { + handler.post(function); + return; + } + if (HandlerUtils.isRunningOnHandlerThread(handler)) { + scheduler.postDelayed(function, delayMillis); + } else { + handler.post(() -> scheduler.postDelayed(function, delayMillis)); + } + } else { + handler.postDelayed(function, delayMillis); + } } /** Shutdown the thread if necessary. */ @@ -111,6 +135,11 @@ public class DiscoveryExecutor implements Executor { if (this.mHandlerThread != null) { this.mHandlerThread.quitSafely(); } + synchronized (mPendingTasks) { + if (mScheduler != null) { + mScheduler.close(); + } + } } /** diff --git a/service-t/src/com/android/server/connectivity/mdns/MdnsDiscoveryManager.java b/service-t/src/com/android/server/connectivity/mdns/MdnsDiscoveryManager.java index 33bcb70d7e..8cd366206e 100644 --- a/service-t/src/com/android/server/connectivity/mdns/MdnsDiscoveryManager.java +++ b/service-t/src/com/android/server/connectivity/mdns/MdnsDiscoveryManager.java @@ -125,7 +125,7 @@ public class MdnsDiscoveryManager implements MdnsSocketClientBase.Callback { this.sharedLog = sharedLog; this.perSocketServiceTypeClients = new PerSocketServiceTypeClients(); this.mdnsFeatureFlags = mdnsFeatureFlags; - this.discoveryExecutor = new DiscoveryExecutor(socketClient.getLooper()); + this.discoveryExecutor = new DiscoveryExecutor(socketClient.getLooper(), mdnsFeatureFlags); } /** diff --git a/service-t/src/com/android/server/connectivity/mdns/MdnsServiceTypeClient.java b/service-t/src/com/android/server/connectivity/mdns/MdnsServiceTypeClient.java index 56d4b9aff2..95f4fffa7a 100644 --- a/service-t/src/com/android/server/connectivity/mdns/MdnsServiceTypeClient.java +++ b/service-t/src/com/android/server/connectivity/mdns/MdnsServiceTypeClient.java @@ -37,7 +37,6 @@ import androidx.annotation.VisibleForTesting; import com.android.net.module.util.CollectionUtils; import com.android.net.module.util.DnsUtils; -import com.android.net.module.util.RealtimeScheduler; import com.android.net.module.util.SharedLog; import com.android.server.connectivity.mdns.util.MdnsUtils; @@ -96,9 +95,9 @@ public class MdnsServiceTypeClient { private final boolean removeServiceAfterTtlExpires = MdnsConfigs.removeServiceAfterTtlExpires(); private final Clock clock; - // Use RealtimeScheduler for query scheduling, which allows for more accurate sending of + // Use MdnsRealtimeScheduler for query scheduling, which allows for more accurate sending of // queries. - @Nullable private final RealtimeScheduler realtimeScheduler; + @Nullable private final Scheduler scheduler; @Nullable private MdnsSearchOptions searchOptions; @@ -193,7 +192,7 @@ public class MdnsServiceTypeClient { sharedLog.log(String.format("Query sent with transactionId: %d. " + "Next run: sessionId: %d, in %d ms", sentResult.transactionId, args.sessionId, timeToNextTaskMs)); - if (realtimeScheduler != null) { + if (scheduler != null) { setDelayedTask(args, timeToNextTaskMs); } else { dependencies.sendMessageDelayed( @@ -264,11 +263,11 @@ public class MdnsServiceTypeClient { } /** - * @see RealtimeScheduler + * @see Scheduler */ @Nullable - public RealtimeScheduler createRealtimeScheduler(@NonNull Handler handler) { - return new RealtimeScheduler(handler); + public Scheduler createScheduler(@NonNull Handler handler) { + return SchedulerFactory.createScheduler(handler); } } @@ -317,8 +316,8 @@ public class MdnsServiceTypeClient { this.mdnsQueryScheduler = new MdnsQueryScheduler(); this.cacheKey = new MdnsServiceCache.CacheKey(serviceType, socketKey); this.featureFlags = featureFlags; - this.realtimeScheduler = featureFlags.isAccurateDelayCallbackEnabled() - ? dependencies.createRealtimeScheduler(handler) : null; + this.scheduler = featureFlags.isAccurateDelayCallbackEnabled() + ? dependencies.createScheduler(handler) : null; } /** @@ -328,8 +327,8 @@ public class MdnsServiceTypeClient { removeScheduledTask(); mdnsQueryScheduler.cancelScheduledRun(); serviceCache.unregisterServiceExpiredCallback(cacheKey); - if (realtimeScheduler != null) { - realtimeScheduler.close(); + if (scheduler != null) { + scheduler.close(); } } @@ -339,8 +338,8 @@ public class MdnsServiceTypeClient { } private void setDelayedTask(ScheduledQueryTaskArgs args, long timeToNextTaskMs) { - realtimeScheduler.removeDelayedMessage(EVENT_START_QUERYTASK); - realtimeScheduler.sendDelayedMessage( + scheduler.removeDelayedMessage(EVENT_START_QUERYTASK); + scheduler.sendDelayedMessage( handler.obtainMessage(EVENT_START_QUERYTASK, args), timeToNextTaskMs); } @@ -404,7 +403,7 @@ public class MdnsServiceTypeClient { final long timeToNextTaskMs = calculateTimeToNextTask(args, now); sharedLog.log(String.format("Schedule a query. Next run: sessionId: %d, in %d ms", args.sessionId, timeToNextTaskMs)); - if (realtimeScheduler != null) { + if (scheduler != null) { setDelayedTask(args, timeToNextTaskMs); } else { dependencies.sendMessageDelayed( @@ -451,8 +450,8 @@ public class MdnsServiceTypeClient { } private void removeScheduledTask() { - if (realtimeScheduler != null) { - realtimeScheduler.removeDelayedMessage(EVENT_START_QUERYTASK); + if (scheduler != null) { + scheduler.removeDelayedMessage(EVENT_START_QUERYTASK); } else { dependencies.removeMessages(handler, EVENT_START_QUERYTASK); } @@ -541,8 +540,8 @@ public class MdnsServiceTypeClient { } } } - final boolean hasScheduledTask = realtimeScheduler != null - ? realtimeScheduler.hasDelayedMessage(EVENT_START_QUERYTASK) + final boolean hasScheduledTask = scheduler != null + ? scheduler.hasDelayedMessage(EVENT_START_QUERYTASK) : dependencies.hasMessages(handler, EVENT_START_QUERYTASK); if (hasScheduledTask) { final long now = clock.elapsedRealtime(); @@ -556,7 +555,7 @@ public class MdnsServiceTypeClient { final long timeToNextTaskMs = calculateTimeToNextTask(args, now); sharedLog.log(String.format("Reschedule a query. Next run: sessionId: %d, in %d ms", args.sessionId, timeToNextTaskMs)); - if (realtimeScheduler != null) { + if (scheduler != null) { setDelayedTask(args, timeToNextTaskMs); } else { dependencies.sendMessageDelayed( diff --git a/service-t/src/com/android/server/connectivity/mdns/Scheduler.java b/service-t/src/com/android/server/connectivity/mdns/Scheduler.java new file mode 100644 index 0000000000..85a8e76f22 --- /dev/null +++ b/service-t/src/com/android/server/connectivity/mdns/Scheduler.java @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.connectivity.mdns; + +import android.os.Message; + +import androidx.annotation.NonNull; + +/** + * The interface for scheduler. + */ +public interface Scheduler { + /** + * Set a message to be sent after a specified delay. + */ + boolean sendDelayedMessage(@NonNull Message message, long delayMs); + + /** + * Remove a scheduled message. + */ + void removeDelayedMessage(int what); + + /** + * Check if there is a scheduled message. + */ + boolean hasDelayedMessage(int what); + + /** + * Set a runnable to be executed after a specified delay. + */ + boolean postDelayed(@NonNull Runnable runnable, long delayMs); + + /** + * Close this object. + */ + void close(); +} diff --git a/service-t/src/com/android/server/connectivity/mdns/SchedulerFactory.java b/service-t/src/com/android/server/connectivity/mdns/SchedulerFactory.java new file mode 100644 index 0000000000..1cc9a6b58b --- /dev/null +++ b/service-t/src/com/android/server/connectivity/mdns/SchedulerFactory.java @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.connectivity.mdns; + +import android.annotation.NonNull; +import android.os.Handler; + +import com.android.server.connectivity.mdns.internal.MdnsRealtimeScheduler; + +/** + * The factory class for creating a scheduler. + */ +public class SchedulerFactory { + + /** + * Creates an realtime delay callback. + */ + public static Scheduler createScheduler(@NonNull Handler handler) { + return new MdnsRealtimeScheduler(handler); + } + + private SchedulerFactory() { + } +} diff --git a/service-t/src/com/android/server/connectivity/mdns/internal/MdnsRealtimeScheduler.java b/service-t/src/com/android/server/connectivity/mdns/internal/MdnsRealtimeScheduler.java new file mode 100644 index 0000000000..eff7085809 --- /dev/null +++ b/service-t/src/com/android/server/connectivity/mdns/internal/MdnsRealtimeScheduler.java @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.connectivity.mdns.internal; + +import android.os.Handler; +import android.os.Message; + +import androidx.annotation.NonNull; + +import com.android.net.module.util.RealtimeScheduler; +import com.android.server.connectivity.mdns.Scheduler; + +/** + * The delay callback for delivering scheduled tasks accurately. + */ +public class MdnsRealtimeScheduler extends RealtimeScheduler implements + Scheduler { + private static final String TAG = MdnsRealtimeScheduler.class.getSimpleName(); + + public MdnsRealtimeScheduler(@NonNull Handler handler) { + super(handler); + } + + public boolean sendDelayedMessage(@NonNull Message message, long delayMs) { + return super.sendDelayedMessage(message, delayMs); + } + + public void removeDelayedMessage(int what) { + super.removeDelayedMessage(what); + } + + public boolean hasDelayedMessage(int what) { + return super.hasDelayedMessage(what); + } + + public boolean postDelayed(@NonNull Runnable runnable, long delayMs) { + return super.postDelayed(runnable, delayMs); + } + + public void close() { + super.close(); + } +} diff --git a/staticlibs/Android.bp b/staticlibs/Android.bp index b064723bbc..abfc4473d4 100644 --- a/staticlibs/Android.bp +++ b/staticlibs/Android.bp @@ -427,11 +427,7 @@ java_library { srcs: [ "device/com/android/net/module/util/FdEventsReader.java", "device/com/android/net/module/util/HandlerUtils.java", - "device/com/android/net/module/util/JniUtil.java", - "device/com/android/net/module/util/RealtimeScheduler.java", "device/com/android/net/module/util/SharedLog.java", - "device/com/android/net/module/util/ServiceConnectivityJni.java", - "device/com/android/net/module/util/TimerFdUtils.java", "framework/com/android/net/module/util/ByteUtils.java", "framework/com/android/net/module/util/CollectionUtils.java", "framework/com/android/net/module/util/DnsUtils.java", diff --git a/tests/unit/java/com/android/server/connectivity/mdns/DiscoveryExecutorTest.kt b/tests/unit/java/com/android/server/connectivity/mdns/DiscoveryExecutorTest.kt index 51539a0e18..67fb4280b1 100644 --- a/tests/unit/java/com/android/server/connectivity/mdns/DiscoveryExecutorTest.kt +++ b/tests/unit/java/com/android/server/connectivity/mdns/DiscoveryExecutorTest.kt @@ -17,6 +17,7 @@ package com.android.server.connectivity.mdns import android.os.Build +import android.os.Handler import android.os.HandlerThread import android.testing.TestableLooper import com.android.testutils.DevSdkIgnoreRule @@ -36,6 +37,8 @@ private const val DEFAULT_TIMEOUT = 2000L @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.S_V2) class DiscoveryExecutorTest { private val thread = HandlerThread(DiscoveryExecutorTest::class.simpleName).apply { start() } + private val handler by lazy { Handler(thread.looper) } + private val testableLooper by lazy { TestableLooper(thread.looper) } @After fun tearDown() { @@ -45,8 +48,10 @@ class DiscoveryExecutorTest { @Test fun testCheckAndRunOnHandlerThread() { - val testableLooper = TestableLooper(thread.looper) - val executor = DiscoveryExecutor(testableLooper.looper) + val executor = DiscoveryExecutor( + testableLooper.looper, + MdnsFeatureFlags.newBuilder().build() + ) try { val future = CompletableFuture() executor.checkAndRunOnHandlerThread { future.complete(true) } @@ -58,17 +63,17 @@ class DiscoveryExecutorTest { // Create a DiscoveryExecutor with the null defaultLooper and verify the task can execute // normally. - val executor2 = DiscoveryExecutor(null /* defaultLooper */) + val executor2 = DiscoveryExecutor( + null /* defaultLooper */, + MdnsFeatureFlags.newBuilder().build() + ) val future2 = CompletableFuture() executor2.checkAndRunOnHandlerThread { future2.complete(true) } assertTrue(future2.get(DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS)) executor2.shutDown() } - @Test - fun testExecute() { - val testableLooper = TestableLooper(thread.looper) - val executor = DiscoveryExecutor(testableLooper.looper) + private fun verifyExecute(executor: DiscoveryExecutor) { try { val future = CompletableFuture() executor.execute { future.complete(true) } @@ -80,10 +85,28 @@ class DiscoveryExecutorTest { } } + @Test + fun testExecute() { + verifyExecute(DiscoveryExecutor( + testableLooper.looper, + MdnsFeatureFlags.newBuilder().build() + )) + } + + @Test + fun testExecute_RealtimeScheduler() { + verifyExecute(DiscoveryExecutor( + testableLooper.looper, + MdnsFeatureFlags.newBuilder().setIsAccurateDelayCallbackEnabled(true).build() + )) + } + @Test fun testExecuteDelayed() { - val testableLooper = TestableLooper(thread.looper) - val executor = DiscoveryExecutor(testableLooper.looper) + val executor = DiscoveryExecutor( + testableLooper.looper, + MdnsFeatureFlags.newBuilder().build() + ) try { // Verify the executeDelayed method val future = CompletableFuture() @@ -107,4 +130,21 @@ class DiscoveryExecutorTest { testableLooper.destroy() } } + + @Test + fun testExecuteDelayed_RealtimeScheduler() { + val executor = DiscoveryExecutor( + thread.looper, + MdnsFeatureFlags.newBuilder().setIsAccurateDelayCallbackEnabled(true).build() + ) + try { + // Verify the executeDelayed method + val future = CompletableFuture() + // Schedule a task with 50ms delay + executor.executeDelayed({ future.complete(true) }, 50L) + assertTrue(future.get(500L, TimeUnit.MILLISECONDS)) + } finally { + testableLooper.destroy() + } + } } diff --git a/tests/unit/java/com/android/server/connectivity/mdns/MdnsServiceTypeClientTests.java b/tests/unit/java/com/android/server/connectivity/mdns/MdnsServiceTypeClientTests.java index dad03e0631..b9c0d2f7ca 100644 --- a/tests/unit/java/com/android/server/connectivity/mdns/MdnsServiceTypeClientTests.java +++ b/tests/unit/java/com/android/server/connectivity/mdns/MdnsServiceTypeClientTests.java @@ -59,7 +59,6 @@ import android.os.Message; import android.text.TextUtils; import com.android.net.module.util.CollectionUtils; -import com.android.net.module.util.RealtimeScheduler; import com.android.net.module.util.SharedLog; import com.android.server.connectivity.mdns.MdnsServiceInfo.TextEntry; import com.android.server.connectivity.mdns.util.MdnsUtils; @@ -129,7 +128,7 @@ public class MdnsServiceTypeClientTests { @Mock private MdnsServiceTypeClient.Dependencies mockDeps; @Mock - private RealtimeScheduler mockRealtimeScheduler; + private Scheduler mockScheduler; @Captor private ArgumentCaptor serviceInfoCaptor; @@ -250,14 +249,14 @@ public class MdnsServiceTypeClientTests { doAnswer(inv -> { realHandler = (Handler) inv.getArguments()[0]; - return mockRealtimeScheduler; - }).when(mockDeps).createRealtimeScheduler(any(Handler.class)); + return mockScheduler; + }).when(mockDeps).createScheduler(any(Handler.class)); doAnswer(inv -> { message = (Message) inv.getArguments()[0]; latestDelayMs = (long) inv.getArguments()[1]; return null; - }).when(mockRealtimeScheduler).sendDelayedMessage(any(), anyLong()); + }).when(mockScheduler).sendDelayedMessage(any(), anyLong()); client = makeMdnsServiceTypeClient(featureFlags); } @@ -2137,7 +2136,7 @@ public class MdnsServiceTypeClientTests { .setNumOfQueriesBeforeBackoff(numOfQueriesBeforeBackoff) .build(); startSendAndReceive(mockListenerOne, searchOptions); - verify(mockRealtimeScheduler, times(1)).removeDelayedMessage(EVENT_START_QUERYTASK); + verify(mockScheduler, times(1)).removeDelayedMessage(EVENT_START_QUERYTASK); // Verify that the first query has been sent. verifyAndSendQuery(0 /* index */, 0 /* timeInMs */, true /* expectsUnicastResponse */, @@ -2159,13 +2158,13 @@ public class MdnsServiceTypeClientTests { // 0.8 * smallestRemainingTtl is larger than time to next run. long currentTime = TEST_TTL / 2 + TEST_ELAPSED_REALTIME; doReturn(currentTime).when(mockDecoderClock).elapsedRealtime(); - doReturn(true).when(mockRealtimeScheduler).hasDelayedMessage(EVENT_START_QUERYTASK); + doReturn(true).when(mockScheduler).hasDelayedMessage(EVENT_START_QUERYTASK); processResponse(createResponse( "service-instance-1", "192.0.2.123", 5353, SERVICE_TYPE_LABELS, Collections.emptyMap(), TEST_TTL), socketKey); // Verify that the message removal occurred. - verify(mockRealtimeScheduler, times(6)).removeDelayedMessage(EVENT_START_QUERYTASK); + verify(mockScheduler, times(6)).removeDelayedMessage(EVENT_START_QUERYTASK); assertNotNull(message); verifyAndSendQuery(3 /* index */, (long) (TEST_TTL / 2 * 0.8) /* timeInMs */, true /* expectsUnicastResponse */, true /* multipleSocketDiscovery */, @@ -2174,7 +2173,7 @@ public class MdnsServiceTypeClientTests { // Stop sending packets. stopSendAndReceive(mockListenerOne); - verify(mockRealtimeScheduler, times(8)).removeDelayedMessage(EVENT_START_QUERYTASK); + verify(mockScheduler, times(8)).removeDelayedMessage(EVENT_START_QUERYTASK); } @Test @@ -2184,12 +2183,12 @@ public class MdnsServiceTypeClientTests { // Start query startSendAndReceive(mockListenerOne, MdnsSearchOptions.newBuilder().build()); - verify(mockRealtimeScheduler, times(1)).removeDelayedMessage(EVENT_START_QUERYTASK); + verify(mockScheduler, times(1)).removeDelayedMessage(EVENT_START_QUERYTASK); // Stop query and verify the close() method has been called. stopSendAndReceive(mockListenerOne); - verify(mockRealtimeScheduler, times(2)).removeDelayedMessage(EVENT_START_QUERYTASK); - verify(mockRealtimeScheduler).close(); + verify(mockScheduler, times(2)).removeDelayedMessage(EVENT_START_QUERYTASK); + verify(mockScheduler).close(); } private static MdnsServiceInfo matchServiceName(String name) { @@ -2247,8 +2246,7 @@ public class MdnsServiceTypeClientTests { .sendMessage(any(Handler.class), any(Message.class)); // Verify the task has been scheduled. if (useAccurateDelayCallback) { - verify(mockRealtimeScheduler, times(scheduledCount)) - .sendDelayedMessage(any(), anyLong()); + verify(mockScheduler, times(scheduledCount)).sendDelayedMessage(any(), anyLong()); } else { verify(mockDeps, times(scheduledCount)) .sendMessageDelayed(any(Handler.class), any(Message.class), anyLong());