From ed157259875680e6f8d3032f996f1b519e989b49 Mon Sep 17 00:00:00 2001 From: Handa Wang Date: Mon, 23 Sep 2024 08:48:47 +0000 Subject: [PATCH 1/2] [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 --- .../ThreadNetworkControllerService.java | 38 +++++++++++-------- .../ThreadNetworkControllerServiceTest.java | 5 +-- 2 files changed, 24 insertions(+), 19 deletions(-) diff --git a/thread/service/java/com/android/server/thread/ThreadNetworkControllerService.java b/thread/service/java/com/android/server/thread/ThreadNetworkControllerService.java index 3d854d7963..fa692b08c4 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 @@ final class ThreadNetworkControllerService extends IThreadNetworkController.Stub private boolean mUserRestricted; private boolean mForceStopOtDaemonEnabled; - private OtDaemonConfiguration mOtDaemonConfig; private InfraLinkState mInfraLinkState; @VisibleForTesting @@ -249,7 +248,6 @@ final class ThreadNetworkControllerService extends IThreadNetworkController.Stub // 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 @@ final class ThreadNetworkControllerService extends IThreadNetworkController.Stub otDaemon.initialize( mTunIfController.getTunFd(), shouldEnableThread(), + newOtDaemonConfig(mPersistentSettings.getConfiguration()), mNsdPublisher, getMeshcopTxtAttributes(mResources.get()), mOtDaemonCallbackProxy, @@ -556,22 +555,21 @@ final class ThreadNetworkControllerService extends IThreadNetworkController.Stub 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 @@ final class ThreadNetworkControllerService extends IThreadNetworkController.Stub } } } - // 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 @@ final class ThreadNetworkControllerService extends IThreadNetworkController.Stub 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 b97e2b79c9..7ac404fc1d 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 @@ public final class ThreadNetworkControllerServiceTest { .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 From 651bfdaaf75e1d3a106ed58cc07aab7a5dc9a22f Mon Sep 17 00:00:00 2001 From: Handa Wang Date: Mon, 23 Sep 2024 08:48:53 +0000 Subject: [PATCH 2/2] [Thread] make ThreadNetworkController#setConfiguration a system API This CL turns setConfiguration into a system API, including the ThreadConfiguration#Builder and the #setNat64Enabled method. Bug: 368456504 Change-Id: I0ff2ed81271dcceea295d169a46a02f05aeda5d6 --- common/thread_flags.aconfig | 9 +++++++ framework-t/api/system-current.txt | 8 ++++++ .../net/thread/ThreadConfiguration.java | 27 +++++++++++++++++-- .../net/thread/ThreadNetworkController.java | 12 ++++++--- .../cts/ThreadNetworkControllerTest.java | 11 +++----- 5 files changed, 53 insertions(+), 14 deletions(-) diff --git a/common/thread_flags.aconfig b/common/thread_flags.aconfig index 14b70d0563..60120bcc54 100644 --- a/common/thread_flags.aconfig +++ b/common/thread_flags.aconfig @@ -35,3 +35,12 @@ flag { description: "Controls whether the Android Thread Ephemeral Key feature is enabled" bug: "348323500" } + +flag { + name: "set_nat64_configuration_enabled" + is_exported: true + is_fixed_read_only: true + namespace: "thread_network" + description: "Controls whether the setConfiguration API of NAT64 feature is enabled" + bug: "368456504" +} diff --git a/framework-t/api/system-current.txt b/framework-t/api/system-current.txt index 09a3681f4e..08129eb8e3 100644 --- a/framework-t/api/system-current.txt +++ b/framework-t/api/system-current.txt @@ -506,6 +506,13 @@ package android.net.thread { field @NonNull public static final android.os.Parcelable.Creator CREATOR; } + @FlaggedApi("com.android.net.thread.flags.set_nat64_configuration_enabled") public static final class ThreadConfiguration.Builder { + ctor @FlaggedApi("com.android.net.thread.flags.set_nat64_configuration_enabled") public ThreadConfiguration.Builder(); + ctor @FlaggedApi("com.android.net.thread.flags.set_nat64_configuration_enabled") public ThreadConfiguration.Builder(@NonNull android.net.thread.ThreadConfiguration); + method @FlaggedApi("com.android.net.thread.flags.set_nat64_configuration_enabled") @NonNull public android.net.thread.ThreadConfiguration build(); + method @FlaggedApi("com.android.net.thread.flags.set_nat64_configuration_enabled") @NonNull public android.net.thread.ThreadConfiguration.Builder setNat64Enabled(boolean); + } + @FlaggedApi("com.android.net.thread.flags.thread_enabled") public final class ThreadNetworkController { method @FlaggedApi("com.android.net.thread.flags.epskc_enabled") @RequiresPermission("android.permission.THREAD_NETWORK_PRIVILEGED") public void activateEphemeralKeyMode(@NonNull java.time.Duration, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver); method public void createRandomizedDataset(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver); @@ -520,6 +527,7 @@ package android.net.thread { method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerStateCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.thread.ThreadNetworkController.StateCallback); method @RequiresPermission("android.permission.THREAD_NETWORK_PRIVILEGED") public void scheduleMigration(@NonNull android.net.thread.PendingOperationalDataset, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver); method @FlaggedApi("com.android.net.thread.flags.channel_max_powers_enabled") @RequiresPermission("android.permission.THREAD_NETWORK_PRIVILEGED") public void setChannelMaxPowers(@NonNull @Size(min=1) android.util.SparseIntArray, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver); + method @FlaggedApi("com.android.net.thread.flags.set_nat64_configuration_enabled") @RequiresPermission(android.Manifest.permission.THREAD_NETWORK_PRIVILEGED) public void setConfiguration(@NonNull android.net.thread.ThreadConfiguration, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver); method @RequiresPermission("android.permission.THREAD_NETWORK_PRIVILEGED") public void setEnabled(boolean, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver); method @FlaggedApi("com.android.net.thread.flags.configuration_enabled") @RequiresPermission(android.Manifest.permission.THREAD_NETWORK_PRIVILEGED) public void unregisterConfigurationCallback(@NonNull java.util.function.Consumer); method @RequiresPermission(allOf={android.Manifest.permission.ACCESS_NETWORK_STATE, "android.permission.THREAD_NETWORK_PRIVILEGED"}) public void unregisterOperationalDatasetCallback(@NonNull android.net.thread.ThreadNetworkController.OperationalDatasetCallback); diff --git a/thread/framework/java/android/net/thread/ThreadConfiguration.java b/thread/framework/java/android/net/thread/ThreadConfiguration.java index 1c2553511a..e6fa1efd1e 100644 --- a/thread/framework/java/android/net/thread/ThreadConfiguration.java +++ b/thread/framework/java/android/net/thread/ThreadConfiguration.java @@ -126,18 +126,29 @@ public final class ThreadConfiguration implements Parcelable { * * @hide */ + @FlaggedApi(Flags.FLAG_SET_NAT64_CONFIGURATION_ENABLED) + @SystemApi public static final class Builder { private boolean mNat64Enabled = false; private boolean mDhcpv6PdEnabled = false; - /** Creates a new {@link Builder} object with all features disabled. */ + /** + * Creates a new {@link Builder} object with all features disabled. + * + * @hide + */ + @FlaggedApi(Flags.FLAG_SET_NAT64_CONFIGURATION_ENABLED) + @SystemApi public Builder() {} /** * Creates a new {@link Builder} object from a {@link ThreadConfiguration} object. * * @param config the Border Router configurations to be copied + * @hide */ + @FlaggedApi(Flags.FLAG_SET_NAT64_CONFIGURATION_ENABLED) + @SystemApi public Builder(@NonNull ThreadConfiguration config) { Objects.requireNonNull(config); @@ -150,7 +161,11 @@ public final class ThreadConfiguration implements Parcelable { * *

Enabling this feature will allow Thread devices to connect to the internet/cloud over * IPv4. + * + * @hide */ + @FlaggedApi(Flags.FLAG_SET_NAT64_CONFIGURATION_ENABLED) + @SystemApi @NonNull public Builder setNat64Enabled(boolean enabled) { this.mNat64Enabled = enabled; @@ -162,6 +177,8 @@ public final class ThreadConfiguration implements Parcelable { * *

Enabling this feature will allow Thread devices to connect to the internet/cloud over * IPv6. + * + * @hide */ @NonNull public Builder setDhcpv6PdEnabled(boolean enabled) { @@ -169,7 +186,13 @@ public final class ThreadConfiguration implements Parcelable { return this; } - /** Creates a new {@link ThreadConfiguration} object. */ + /** + * Creates a new {@link ThreadConfiguration} object. + * + * @hide + */ + @FlaggedApi(Flags.FLAG_SET_NAT64_CONFIGURATION_ENABLED) + @SystemApi @NonNull public ThreadConfiguration build() { return new ThreadConfiguration(this); diff --git a/thread/framework/java/android/net/thread/ThreadNetworkController.java b/thread/framework/java/android/net/thread/ThreadNetworkController.java index 1222398f67..bac2501c5a 100644 --- a/thread/framework/java/android/net/thread/ThreadNetworkController.java +++ b/thread/framework/java/android/net/thread/ThreadNetworkController.java @@ -748,15 +748,19 @@ public final class ThreadNetworkController { * OutcomeReceiver#onResult} will be called, and the {@code configuration} will be applied and * persisted to the device; the configuration changes can be observed by {@link * #registerConfigurationCallback}. On failure, {@link OutcomeReceiver#onError} of {@code - * receiver} will be invoked with a specific error. + * receiver} will be invoked with a specific error: + * + *

    + *
  • {@link ThreadNetworkException#ERROR_UNSUPPORTED_FEATURE} the configuration enables a + * feature which is not supported by the platform. + *
* * @param configuration the configuration to set * @param executor the executor to execute {@code receiver} * @param receiver the receiver to receive result of this operation - * @hide */ - // @FlaggedApi(ThreadNetworkFlags.FLAG_CONFIGURATION_ENABLED) - // @RequiresPermission(permission.THREAD_NETWORK_PRIVILEGED) + @FlaggedApi(Flags.FLAG_SET_NAT64_CONFIGURATION_ENABLED) + @RequiresPermission(permission.THREAD_NETWORK_PRIVILEGED) public void setConfiguration( @NonNull ThreadConfiguration configuration, @NonNull @CallbackExecutor Executor executor, 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 1792bfb37a..07438e9a9c 100644 --- a/thread/tests/cts/src/android/net/thread/cts/ThreadNetworkControllerTest.java +++ b/thread/tests/cts/src/android/net/thread/cts/ThreadNetworkControllerTest.java @@ -182,6 +182,7 @@ public class ThreadNetworkControllerTest { @After public void tearDown() throws Exception { dropAllPermissions(); + setEnabledAndWait(mController, true); leaveAndWait(mController); tearDownTestNetwork(); setConfigurationAndWait(mController, DEFAULT_CONFIG); @@ -1148,15 +1149,9 @@ public class ThreadNetworkControllerTest { CompletableFuture setFuture2 = new CompletableFuture<>(); ConfigurationListener listener = new ConfigurationListener(mController); ThreadConfiguration config1 = - new ThreadConfiguration.Builder() - .setNat64Enabled(true) - .setDhcpv6PdEnabled(true) - .build(); + new ThreadConfiguration.Builder().setNat64Enabled(true).build(); ThreadConfiguration config2 = - new ThreadConfiguration.Builder() - .setNat64Enabled(false) - .setDhcpv6PdEnabled(true) - .build(); + new ThreadConfiguration.Builder().setNat64Enabled(false).build(); try { runAsShell(