Merge changes I0b3ac7b4,I90385146 into main

* changes:
  Add Abstract Class for RealtimeScheduler
  Implement RealtimeScheduler in DiscoveryExecutor
diff --git a/service-t/Android.bp b/service-t/Android.bp
index ab38c7a..81378f5 100644
--- a/service-t/Android.bp
+++ b/service-t/Android.bp
@@ -109,13 +109,15 @@
         ":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 @@
 
 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 21af1a1..99354f8 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 @@
     @NonNull
     private final ArrayList<Pair<Runnable, Long>> 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 @@
                     synchronized (mPendingTasks) {
                         mHandler = new Handler(getLooper());
                         for (Pair<Runnable, Long> pendingTask : mPendingTasks) {
-                            mHandler.postDelayed(pendingTask.first, pendingTask.second);
+                            executeDelayed(pendingTask.first, pendingTask.second);
                         }
                         mPendingTasks.clear();
                     }
@@ -95,15 +101,33 @@
     /** 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 @@
         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 33bcb70..8cd3662 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 @@
         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 56d4b9a..95f4fff 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 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 @@
     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 @@
                     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 @@
         }
 
         /**
-         * @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 @@
         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 @@
         removeScheduledTask();
         mdnsQueryScheduler.cancelScheduledRun();
         serviceCache.unregisterServiceExpiredCallback(cacheKey);
-        if (realtimeScheduler != null) {
-            realtimeScheduler.close();
+        if (scheduler != null) {
+            scheduler.close();
         }
     }
 
@@ -339,8 +338,8 @@
     }
 
     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 @@
             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 @@
     }
 
     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 @@
                 }
             }
         }
-        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 @@
                 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 0000000..85a8e76
--- /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 0000000..1cc9a6b
--- /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 0000000..eff7085
--- /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 b064723..abfc447 100644
--- a/staticlibs/Android.bp
+++ b/staticlibs/Android.bp
@@ -427,11 +427,7 @@
     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 51539a0..67fb428 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 @@
 @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 @@
 
     @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<Boolean>()
             executor.checkAndRunOnHandlerThread { future.complete(true) }
@@ -58,17 +63,17 @@
 
         // 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<Boolean>()
         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<Boolean>()
             executor.execute { future.complete(true) }
@@ -81,9 +86,27 @@
     }
 
     @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<Boolean>()
@@ -107,4 +130,21 @@
             testableLooper.destroy()
         }
     }
+
+    @Test
+    fun testExecuteDelayed_RealtimeScheduler() {
+        val executor = DiscoveryExecutor(
+                thread.looper,
+                MdnsFeatureFlags.newBuilder().setIsAccurateDelayCallbackEnabled(true).build()
+        )
+        try {
+            // Verify the executeDelayed method
+            val future = CompletableFuture<Boolean>()
+            // 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 dad03e0..b9c0d2f 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.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 @@
     @Mock
     private MdnsServiceTypeClient.Dependencies mockDeps;
     @Mock
-    private RealtimeScheduler mockRealtimeScheduler;
+    private Scheduler mockScheduler;
     @Captor
     private ArgumentCaptor<MdnsServiceInfo> serviceInfoCaptor;
 
@@ -250,14 +249,14 @@
 
         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 @@
                 .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 @@
         // 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 @@
 
         // 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 @@
 
         // 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 @@
                 .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());