[Thread] implement the ThreadNetworkController#setConfiguration at
service

This CL implements the ThreadNetworkController#setConfiguration. When
the ThreadNetworkControllerService receives this call, the configuration
is passed to ot-daemon and triggers according OT APIs. On success, the
configuration is persisted to the local storage and triggers
OutcomeReceiver#onSuccess. On failure, it triggers
OutcomeReceiver#onError.

Bug: 368456504

Change-Id: I570ec3fead204cd3b6c05629ef409967245350b8
diff --git a/thread/service/java/com/android/server/thread/ThreadNetworkControllerService.java b/thread/service/java/com/android/server/thread/ThreadNetworkControllerService.java
index 3d854d7..fa692b0 100644
--- a/thread/service/java/com/android/server/thread/ThreadNetworkControllerService.java
+++ b/thread/service/java/com/android/server/thread/ThreadNetworkControllerService.java
@@ -220,7 +220,6 @@
     private boolean mUserRestricted;
     private boolean mForceStopOtDaemonEnabled;
 
-    private OtDaemonConfiguration mOtDaemonConfig;
     private InfraLinkState mInfraLinkState;
 
     @VisibleForTesting
@@ -249,7 +248,6 @@
         // TODO: networkToLinkProperties should be shared with NsdPublisher, add a test/assert to
         // verify they are the same.
         mNetworkToLinkProperties = networkToLinkProperties;
-        mOtDaemonConfig = new OtDaemonConfiguration.Builder().build();
         mInfraLinkState = new InfraLinkState.Builder().build();
         mPersistentSettings = persistentSettings;
         mNsdPublisher = nsdPublisher;
@@ -346,6 +344,7 @@
         otDaemon.initialize(
                 mTunIfController.getTunFd(),
                 shouldEnableThread(),
+                newOtDaemonConfig(mPersistentSettings.getConfiguration()),
                 mNsdPublisher,
                 getMeshcopTxtAttributes(mResources.get()),
                 mOtDaemonCallbackProxy,
@@ -556,22 +555,21 @@
     public void setConfiguration(
             @NonNull ThreadConfiguration configuration, @NonNull IOperationReceiver receiver) {
         enforceAllPermissionsGranted(PERMISSION_THREAD_NETWORK_PRIVILEGED);
-        mHandler.post(() -> setConfigurationInternal(configuration, receiver));
+        mHandler.post(
+                () ->
+                        setConfigurationInternal(
+                                configuration, new OperationReceiverWrapper(receiver)));
     }
 
     private void setConfigurationInternal(
             @NonNull ThreadConfiguration configuration,
-            @NonNull IOperationReceiver operationReceiver) {
+            @NonNull OperationReceiverWrapper receiver) {
         checkOnHandlerThread();
 
         LOG.i("Set Thread configuration: " + configuration);
 
         final boolean changed = mPersistentSettings.putConfiguration(configuration);
-        try {
-            operationReceiver.onSuccess();
-        } catch (RemoteException e) {
-            // do nothing if the client is dead
-        }
+        receiver.onSuccess();
         if (changed) {
             for (IConfigurationReceiver configReceiver : mConfigurationReceivers.keySet()) {
                 try {
@@ -581,7 +579,22 @@
                 }
             }
         }
-        // TODO: set the configuration at ot-daemon
+        try {
+            getOtDaemon()
+                    .setConfiguration(
+                            newOtDaemonConfig(configuration),
+                            new LoggingOtStatusReceiver("setConfiguration"));
+        } catch (RemoteException | ThreadNetworkException e) {
+            LOG.e("otDaemon.setConfiguration failed. Config: " + configuration, e);
+        }
+    }
+
+    private static OtDaemonConfiguration newOtDaemonConfig(
+            @NonNull ThreadConfiguration threadConfig) {
+        return new OtDaemonConfiguration.Builder()
+                .setNat64Enabled(threadConfig.isNat64Enabled())
+                .setDhcpv6PdEnabled(threadConfig.isDhcpv6PdEnabled())
+                .build();
     }
 
     @Override
@@ -1477,11 +1490,6 @@
         return builder.build();
     }
 
-    private static OtDaemonConfiguration.Builder newOtDaemonConfigBuilder(
-            OtDaemonConfiguration config) {
-        return new OtDaemonConfiguration.Builder();
-    }
-
     private static InfraLinkState.Builder newInfraLinkStateBuilder() {
         return new InfraLinkState.Builder().setInterfaceName("");
     }
diff --git a/thread/tests/unit/src/com/android/server/thread/ThreadNetworkControllerServiceTest.java b/thread/tests/unit/src/com/android/server/thread/ThreadNetworkControllerServiceTest.java
index b97e2b7..7ac404f 100644
--- a/thread/tests/unit/src/com/android/server/thread/ThreadNetworkControllerServiceTest.java
+++ b/thread/tests/unit/src/com/android/server/thread/ThreadNetworkControllerServiceTest.java
@@ -741,10 +741,7 @@
                         .setDhcpv6PdEnabled(false)
                         .build();
         ThreadConfiguration config2 =
-                new ThreadConfiguration.Builder()
-                        .setNat64Enabled(true)
-                        .setDhcpv6PdEnabled(true)
-                        .build();
+                new ThreadConfiguration.Builder().setNat64Enabled(true).build();
         ThreadConfiguration config3 =
                 new ThreadConfiguration.Builder(config2).build(); // Same as config2