diff --git a/thread/service/java/com/android/server/thread/ThreadNetworkControllerService.java b/thread/service/java/com/android/server/thread/ThreadNetworkControllerService.java index 6a9ae717d2..af9abdf2dc 100644 --- a/thread/service/java/com/android/server/thread/ThreadNetworkControllerService.java +++ b/thread/service/java/com/android/server/thread/ThreadNetworkControllerService.java @@ -1387,14 +1387,6 @@ final class ThreadNetworkControllerService extends IThreadNetworkController.Stub } } - private void notifyThreadEnabledUpdated(IStateCallback callback, int enabledState) { - try { - callback.onThreadEnableStateChanged(enabledState); - } catch (RemoteException ignored) { - // do nothing if the client is dead - } - } - public void unregisterStateCallback(IStateCallback callback) { checkOnHandlerThread(); if (!mStateCallbacks.containsKey(callback)) { @@ -1461,15 +1453,19 @@ final class ThreadNetworkControllerService extends IThreadNetworkController.Stub } } - @Override - public void onThreadEnabledChanged(int state) { - mHandler.post(() -> onThreadEnabledChangedInternal(state)); - } - - private void onThreadEnabledChangedInternal(int state) { + private void onThreadEnabledChanged(int state, long listenerId) { checkOnHandlerThread(); - for (IStateCallback callback : mStateCallbacks.keySet()) { - notifyThreadEnabledUpdated(callback, otStateToAndroidState(state)); + boolean stateChanged = (mState == null || mState.threadEnabled != state); + + for (var callbackEntry : mStateCallbacks.entrySet()) { + if (!stateChanged && callbackEntry.getValue().id != listenerId) { + continue; + } + try { + callbackEntry.getKey().onThreadEnableStateChanged(otStateToAndroidState(state)); + } catch (RemoteException ignored) { + // do nothing if the client is dead + } } } @@ -1496,6 +1492,7 @@ final class ThreadNetworkControllerService extends IThreadNetworkController.Stub onInterfaceStateChanged(newState.isInterfaceUp); onDeviceRoleChanged(newState.deviceRole, listenerId); onPartitionIdChanged(newState.partitionId, listenerId); + onThreadEnabledChanged(newState.threadEnabled, listenerId); mState = newState; ActiveOperationalDataset newActiveDataset; diff --git a/thread/tests/cts/src/android/net/thread/cts/ThreadNetworkControllerTest.java b/thread/tests/cts/src/android/net/thread/cts/ThreadNetworkControllerTest.java index dea4279e53..11c4819b7e 100644 --- a/thread/tests/cts/src/android/net/thread/cts/ThreadNetworkControllerTest.java +++ b/thread/tests/cts/src/android/net/thread/cts/ThreadNetworkControllerTest.java @@ -43,7 +43,6 @@ import static com.android.testutils.TestPermissionUtil.runAsShell; import static com.google.common.truth.Truth.assertThat; import static com.google.common.util.concurrent.MoreExecutors.directExecutor; -import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertThrows; import static org.junit.Assert.fail; @@ -173,6 +172,17 @@ public class ThreadNetworkControllerTest { } } + @Test + public void subscribeThreadEnableState_getActiveDataset_onThreadEnableStateChangedNotCalled() + throws Exception { + EnabledStateListener listener = new EnabledStateListener(mController); + listener.expectThreadEnabledState(STATE_ENABLED); + + getActiveOperationalDataset(mController); + + listener.expectCallbackNotCalled(); + } + @Test public void registerStateCallback_returnsUpdatedEnabledStates() throws Exception { CompletableFuture setFuture1 = new CompletableFuture<>(); @@ -1016,7 +1026,11 @@ public class ThreadNetworkControllerTest { } public void expectThreadEnabledState(int enabled) { - assertNotNull(mReadHead.poll(ENABLED_TIMEOUT_MILLIS, e -> (e == enabled))); + assertThat(mReadHead.poll(ENABLED_TIMEOUT_MILLIS, e -> (e == enabled))).isNotNull(); + } + + public void expectCallbackNotCalled() { + assertThat(mReadHead.poll(CALLBACK_TIMEOUT_MILLIS, e -> true)).isNull(); } public void unregisterStateCallback() {