1 /* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 * in compliance with the License. You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software distributed under the License 10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 * or implied. See the License for the specific language governing permissions and limitations under 12 * the License. 13 */ 14 15 package com.android.server.thread; 16 17 import static android.Manifest.permission.NETWORK_SETTINGS; 18 import static android.content.pm.PackageManager.PERMISSION_GRANTED; 19 import static android.net.MulticastRoutingConfig.CONFIG_FORWARD_NONE; 20 import static android.net.MulticastRoutingConfig.FORWARD_SELECTED; 21 import static android.net.MulticastRoutingConfig.FORWARD_WITH_MIN_SCOPE; 22 import static android.net.NetworkCapabilities.TRANSPORT_THREAD; 23 import static android.net.thread.ActiveOperationalDataset.CHANNEL_PAGE_24_GHZ; 24 import static android.net.thread.ActiveOperationalDataset.LENGTH_EXTENDED_PAN_ID; 25 import static android.net.thread.ActiveOperationalDataset.LENGTH_MESH_LOCAL_PREFIX_BITS; 26 import static android.net.thread.ActiveOperationalDataset.LENGTH_NETWORK_KEY; 27 import static android.net.thread.ActiveOperationalDataset.LENGTH_PSKC; 28 import static android.net.thread.ActiveOperationalDataset.MESH_LOCAL_PREFIX_FIRST_BYTE; 29 import static android.net.thread.ActiveOperationalDataset.SecurityPolicy.DEFAULT_ROTATION_TIME_HOURS; 30 import static android.net.thread.ThreadNetworkController.DEVICE_ROLE_DETACHED; 31 import static android.net.thread.ThreadNetworkController.EPHEMERAL_KEY_DISABLED; 32 import static android.net.thread.ThreadNetworkController.STATE_DISABLED; 33 import static android.net.thread.ThreadNetworkController.STATE_DISABLING; 34 import static android.net.thread.ThreadNetworkController.STATE_ENABLED; 35 import static android.net.thread.ThreadNetworkController.THREAD_VERSION_1_3; 36 import static android.net.thread.ThreadNetworkException.ERROR_ABORTED; 37 import static android.net.thread.ThreadNetworkException.ERROR_BUSY; 38 import static android.net.thread.ThreadNetworkException.ERROR_FAILED_PRECONDITION; 39 import static android.net.thread.ThreadNetworkException.ERROR_INTERNAL_ERROR; 40 import static android.net.thread.ThreadNetworkException.ERROR_REJECTED_BY_PEER; 41 import static android.net.thread.ThreadNetworkException.ERROR_RESOURCE_EXHAUSTED; 42 import static android.net.thread.ThreadNetworkException.ERROR_RESPONSE_BAD_FORMAT; 43 import static android.net.thread.ThreadNetworkException.ERROR_THREAD_DISABLED; 44 import static android.net.thread.ThreadNetworkException.ERROR_TIMEOUT; 45 import static android.net.thread.ThreadNetworkException.ERROR_UNSUPPORTED_CHANNEL; 46 import static android.net.thread.ThreadNetworkException.ERROR_UNSUPPORTED_FEATURE; 47 import static android.net.thread.ThreadNetworkManager.DISALLOW_THREAD_NETWORK; 48 import static android.net.thread.ThreadNetworkManager.PERMISSION_THREAD_NETWORK_PRIVILEGED; 49 import static android.net.thread.ThreadNetworkManager.PERMISSION_THREAD_NETWORK_TESTING; 50 51 import static com.android.server.thread.openthread.IOtDaemon.ErrorCode.OT_ERROR_ABORT; 52 import static com.android.server.thread.openthread.IOtDaemon.ErrorCode.OT_ERROR_BUSY; 53 import static com.android.server.thread.openthread.IOtDaemon.ErrorCode.OT_ERROR_FAILED_PRECONDITION; 54 import static com.android.server.thread.openthread.IOtDaemon.ErrorCode.OT_ERROR_INVALID_STATE; 55 import static com.android.server.thread.openthread.IOtDaemon.ErrorCode.OT_ERROR_NOT_IMPLEMENTED; 56 import static com.android.server.thread.openthread.IOtDaemon.ErrorCode.OT_ERROR_NO_BUFS; 57 import static com.android.server.thread.openthread.IOtDaemon.ErrorCode.OT_ERROR_PARSE; 58 import static com.android.server.thread.openthread.IOtDaemon.ErrorCode.OT_ERROR_REASSEMBLY_TIMEOUT; 59 import static com.android.server.thread.openthread.IOtDaemon.ErrorCode.OT_ERROR_REJECTED; 60 import static com.android.server.thread.openthread.IOtDaemon.ErrorCode.OT_ERROR_RESPONSE_TIMEOUT; 61 import static com.android.server.thread.openthread.IOtDaemon.ErrorCode.OT_ERROR_THREAD_DISABLED; 62 import static com.android.server.thread.openthread.IOtDaemon.ErrorCode.OT_ERROR_UNSUPPORTED_CHANNEL; 63 import static com.android.server.thread.openthread.IOtDaemon.OT_STATE_DISABLED; 64 import static com.android.server.thread.openthread.IOtDaemon.OT_STATE_DISABLING; 65 import static com.android.server.thread.openthread.IOtDaemon.OT_STATE_ENABLED; 66 import static com.android.server.thread.openthread.IOtDaemon.TUN_IF_NAME; 67 68 import static java.nio.charset.StandardCharsets.UTF_8; 69 70 import android.Manifest.permission; 71 import android.annotation.NonNull; 72 import android.annotation.Nullable; 73 import android.annotation.RequiresPermission; 74 import android.annotation.TargetApi; 75 import android.content.BroadcastReceiver; 76 import android.content.Context; 77 import android.content.Intent; 78 import android.content.IntentFilter; 79 import android.content.res.Resources; 80 import android.net.ConnectivityManager; 81 import android.net.InetAddresses; 82 import android.net.IpPrefix; 83 import android.net.LinkAddress; 84 import android.net.LinkProperties; 85 import android.net.LocalNetworkConfig; 86 import android.net.LocalNetworkInfo; 87 import android.net.MulticastRoutingConfig; 88 import android.net.Network; 89 import android.net.NetworkAgent; 90 import android.net.NetworkAgentConfig; 91 import android.net.NetworkCapabilities; 92 import android.net.NetworkProvider; 93 import android.net.NetworkRequest; 94 import android.net.NetworkScore; 95 import android.net.TestNetworkSpecifier; 96 import android.net.thread.ActiveOperationalDataset; 97 import android.net.thread.ActiveOperationalDataset.SecurityPolicy; 98 import android.net.thread.ChannelMaxPower; 99 import android.net.thread.IActiveOperationalDatasetReceiver; 100 import android.net.thread.IConfigurationReceiver; 101 import android.net.thread.IOperationReceiver; 102 import android.net.thread.IOperationalDatasetCallback; 103 import android.net.thread.IOutputReceiver; 104 import android.net.thread.IStateCallback; 105 import android.net.thread.IThreadNetworkController; 106 import android.net.thread.OperationalDatasetTimestamp; 107 import android.net.thread.PendingOperationalDataset; 108 import android.net.thread.ThreadConfiguration; 109 import android.net.thread.ThreadNetworkController; 110 import android.net.thread.ThreadNetworkController.DeviceRole; 111 import android.net.thread.ThreadNetworkException; 112 import android.net.thread.ThreadNetworkException.ErrorCode; 113 import android.os.Build; 114 import android.os.Handler; 115 import android.os.HandlerThread; 116 import android.os.IBinder; 117 import android.os.Looper; 118 import android.os.ParcelFileDescriptor; 119 import android.os.RemoteException; 120 import android.os.SystemClock; 121 import android.os.UserManager; 122 import android.util.SparseArray; 123 124 import com.android.connectivity.resources.R; 125 import com.android.internal.annotations.VisibleForTesting; 126 import com.android.net.module.util.IIpv4PrefixRequest; 127 import com.android.net.module.util.RoutingCoordinatorManager; 128 import com.android.net.module.util.SharedLog; 129 import com.android.server.ServiceManagerWrapper; 130 import com.android.server.connectivity.ConnectivityResources; 131 import com.android.server.connectivity.MockableSystemProperties; 132 import com.android.server.thread.openthread.BackboneRouterState; 133 import com.android.server.thread.openthread.DnsTxtAttribute; 134 import com.android.server.thread.openthread.IChannelMasksReceiver; 135 import com.android.server.thread.openthread.IOtDaemon; 136 import com.android.server.thread.openthread.IOtDaemonCallback; 137 import com.android.server.thread.openthread.IOtOutputReceiver; 138 import com.android.server.thread.openthread.IOtStatusReceiver; 139 import com.android.server.thread.openthread.InfraLinkState; 140 import com.android.server.thread.openthread.Ipv6AddressInfo; 141 import com.android.server.thread.openthread.MeshcopTxtAttributes; 142 import com.android.server.thread.openthread.OnMeshPrefixConfig; 143 import com.android.server.thread.openthread.OtDaemonConfiguration; 144 import com.android.server.thread.openthread.OtDaemonState; 145 146 import libcore.util.HexEncoding; 147 148 import java.io.IOException; 149 import java.net.Inet6Address; 150 import java.net.InetAddress; 151 import java.security.SecureRandom; 152 import java.time.Clock; 153 import java.time.DateTimeException; 154 import java.time.Instant; 155 import java.util.ArrayList; 156 import java.util.HashMap; 157 import java.util.List; 158 import java.util.Map; 159 import java.util.Objects; 160 import java.util.Random; 161 import java.util.function.Supplier; 162 import java.util.regex.Pattern; 163 164 /** 165 * Implementation of the {@link ThreadNetworkController} API. 166 * 167 * <p>Threading model: This class is not Thread-safe and should only be accessed from the 168 * ThreadNetworkService class. Additional attention should be paid to handle the threading code 169 * correctly: 1. All member fields other than `mHandler` and `mContext` MUST be accessed from the 170 * thread of `mHandler` 2. In the @Override methods, the actual work MUST be dispatched to the 171 * HandlerThread except for arguments or permissions checking 172 */ 173 @TargetApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 174 final class ThreadNetworkControllerService extends IThreadNetworkController.Stub { 175 private static final String TAG = "ControllerService"; 176 private static final SharedLog LOG = ThreadNetworkLogger.forSubComponent(TAG); 177 178 // The model name length in utf-8 bytes 179 private static final int MAX_MODEL_NAME_UTF8_BYTES = 24; 180 181 // The max vendor name length in utf-8 bytes 182 private static final int MAX_VENDOR_NAME_UTF8_BYTES = 24; 183 184 // This regex pattern allows "XXXXXX", "XX:XX:XX" and "XX-XX-XX" OUI formats. 185 // Note that this regex allows "XX:XX-XX" as well but we don't need to be a strict checker 186 private static final String OUI_REGEX = "^([0-9A-Fa-f]{2}[:-]?){2}([0-9A-Fa-f]{2})$"; 187 188 // The channel mask that indicates all channels from channel 11 to channel 24 189 private static final int CHANNEL_MASK_11_TO_24 = 0x1FFF800; 190 191 // Below member fields can be accessed from both the binder and handler threads 192 193 private final Context mContext; 194 private final Handler mHandler; 195 private final MockableSystemProperties mSystemProperties; 196 197 // Below member fields can only be accessed from the handler thread (`mHandler`). In 198 // particular, the constructor does not run on the handler thread, so it must not touch any of 199 // the non-final fields, nor must it mutate any of the non-final fields inside these objects. 200 201 private final NetworkProvider mNetworkProvider; 202 private final Supplier<IOtDaemon> mOtDaemonSupplier; 203 private final ConnectivityManager mConnectivityManager; 204 private final RoutingCoordinatorManager mRoutingCoordinatorManager; 205 private final TunInterfaceController mTunIfController; 206 private final InfraInterfaceController mInfraIfController; 207 private final NsdPublisher mNsdPublisher; 208 private final OtDaemonCallbackProxy mOtDaemonCallbackProxy = new OtDaemonCallbackProxy(); 209 private final Nat64CidrController mNat64CidrController = new Nat64CidrController(); 210 private final ConnectivityResources mResources; 211 private final Supplier<String> mCountryCodeSupplier; 212 private final Map<IConfigurationReceiver, IBinder.DeathRecipient> mConfigurationReceivers = 213 new HashMap<>(); 214 215 // This should not be directly used for calling IOtDaemon APIs because ot-daemon may die and 216 // {@code mOtDaemon} will be set to {@code null}. Instead, use {@code getOtDaemon()} 217 @Nullable private IOtDaemon mOtDaemon; 218 @Nullable private NetworkAgent mNetworkAgent; 219 @Nullable private NetworkAgent mTestNetworkAgent; 220 221 private MulticastRoutingConfig mUpstreamMulticastRoutingConfig = CONFIG_FORWARD_NONE; 222 private MulticastRoutingConfig mDownstreamMulticastRoutingConfig = CONFIG_FORWARD_NONE; 223 private Network mUpstreamNetwork; 224 private NetworkRequest mUpstreamNetworkRequest; 225 private UpstreamNetworkCallback mUpstreamNetworkCallback; 226 private TestNetworkSpecifier mUpstreamTestNetworkSpecifier; 227 private ThreadNetworkCallback mThreadNetworkCallback; 228 private final Map<Network, LinkProperties> mNetworkToLinkProperties; 229 private final ThreadPersistentSettings mPersistentSettings; 230 private final UserManager mUserManager; 231 private boolean mUserRestricted; 232 private boolean mForceStopOtDaemonEnabled; 233 234 private InfraLinkState mInfraLinkState; 235 236 @VisibleForTesting ThreadNetworkControllerService( Context context, Handler handler, MockableSystemProperties systemProperties, NetworkProvider networkProvider, Supplier<IOtDaemon> otDaemonSupplier, ConnectivityManager connectivityManager, RoutingCoordinatorManager routingCoordinatorManager, TunInterfaceController tunIfController, InfraInterfaceController infraIfController, ThreadPersistentSettings persistentSettings, NsdPublisher nsdPublisher, UserManager userManager, ConnectivityResources resources, Supplier<String> countryCodeSupplier, Map<Network, LinkProperties> networkToLinkProperties)237 ThreadNetworkControllerService( 238 Context context, 239 Handler handler, 240 MockableSystemProperties systemProperties, 241 NetworkProvider networkProvider, 242 Supplier<IOtDaemon> otDaemonSupplier, 243 ConnectivityManager connectivityManager, 244 RoutingCoordinatorManager routingCoordinatorManager, 245 TunInterfaceController tunIfController, 246 InfraInterfaceController infraIfController, 247 ThreadPersistentSettings persistentSettings, 248 NsdPublisher nsdPublisher, 249 UserManager userManager, 250 ConnectivityResources resources, 251 Supplier<String> countryCodeSupplier, 252 Map<Network, LinkProperties> networkToLinkProperties) { 253 mContext = context; 254 mHandler = handler; 255 mSystemProperties = systemProperties; 256 mNetworkProvider = networkProvider; 257 mOtDaemonSupplier = otDaemonSupplier; 258 mConnectivityManager = connectivityManager; 259 mRoutingCoordinatorManager = routingCoordinatorManager; 260 mTunIfController = tunIfController; 261 mInfraIfController = infraIfController; 262 mUpstreamNetworkRequest = newUpstreamNetworkRequest(); 263 // TODO: networkToLinkProperties should be shared with NsdPublisher, add a test/assert to 264 // verify they are the same. 265 mNetworkToLinkProperties = networkToLinkProperties; 266 mInfraLinkState = new InfraLinkState.Builder().build(); 267 mPersistentSettings = persistentSettings; 268 mNsdPublisher = nsdPublisher; 269 mUserManager = userManager; 270 mResources = resources; 271 mCountryCodeSupplier = countryCodeSupplier; 272 } 273 newInstance( Context context, ThreadPersistentSettings persistentSettings, Supplier<String> countryCodeSupplier)274 public static ThreadNetworkControllerService newInstance( 275 Context context, 276 ThreadPersistentSettings persistentSettings, 277 Supplier<String> countryCodeSupplier) { 278 HandlerThread handlerThread = new HandlerThread("ThreadHandlerThread"); 279 handlerThread.start(); 280 Handler handler = new Handler(handlerThread.getLooper()); 281 NetworkProvider networkProvider = 282 new NetworkProvider(context, handlerThread.getLooper(), "ThreadNetworkProvider"); 283 Map<Network, LinkProperties> networkToLinkProperties = new HashMap<>(); 284 final ConnectivityManager connectivityManager = 285 context.getSystemService(ConnectivityManager.class); 286 final RoutingCoordinatorManager routingCoordinatorManager = 287 new RoutingCoordinatorManager( 288 context, connectivityManager.getRoutingCoordinatorService()); 289 290 return new ThreadNetworkControllerService( 291 context, 292 handler, 293 new MockableSystemProperties(), 294 networkProvider, 295 () -> IOtDaemon.Stub.asInterface(ServiceManagerWrapper.waitForService("ot_daemon")), 296 connectivityManager, 297 routingCoordinatorManager, 298 new TunInterfaceController(TUN_IF_NAME), 299 new InfraInterfaceController(), 300 persistentSettings, 301 NsdPublisher.newInstance(context, handler, networkToLinkProperties), 302 context.getSystemService(UserManager.class), 303 new ConnectivityResources(context), 304 countryCodeSupplier, 305 networkToLinkProperties); 306 } 307 newUpstreamNetworkRequest()308 private NetworkRequest newUpstreamNetworkRequest() { 309 NetworkRequest.Builder builder = new NetworkRequest.Builder(); 310 311 if (mUpstreamTestNetworkSpecifier != null) { 312 // Test networks don't have NET_CAPABILITY_TRUSTED 313 return builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED) 314 .addTransportType(NetworkCapabilities.TRANSPORT_TEST) 315 .setNetworkSpecifier(mUpstreamTestNetworkSpecifier) 316 .build(); 317 } 318 return builder.addTransportType(NetworkCapabilities.TRANSPORT_WIFI) 319 .addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET) 320 .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) 321 .build(); 322 } 323 maybeInitializeOtDaemon()324 private void maybeInitializeOtDaemon() { 325 if (!shouldEnableThread()) { 326 return; 327 } 328 329 LOG.i("Starting OT daemon..."); 330 331 try { 332 getOtDaemon(); 333 } catch (RemoteException e) { 334 LOG.e("Failed to initialize ot-daemon", e); 335 } catch (ThreadNetworkException e) { 336 // no ThreadNetworkException.ERROR_THREAD_DISABLED error should be thrown 337 throw new AssertionError(e); 338 } 339 } 340 getOtDaemon()341 private IOtDaemon getOtDaemon() throws RemoteException, ThreadNetworkException { 342 checkOnHandlerThread(); 343 344 if (mForceStopOtDaemonEnabled) { 345 throw new ThreadNetworkException( 346 ERROR_THREAD_DISABLED, "ot-daemon is forcibly stopped"); 347 } 348 349 if (mOtDaemon != null) { 350 return mOtDaemon; 351 } 352 353 IOtDaemon otDaemon = mOtDaemonSupplier.get(); 354 if (otDaemon == null) { 355 throw new RemoteException("Internal error: failed to start OT daemon"); 356 } 357 358 otDaemon.initialize( 359 shouldEnableThread(), 360 newOtDaemonConfig(mPersistentSettings.getConfiguration()), 361 mTunIfController.getTunFd(), 362 mNsdPublisher, 363 getMeshcopTxtAttributes(mResources.get(), mSystemProperties), 364 mCountryCodeSupplier.get(), 365 FeatureFlags.isTrelEnabled(), 366 mOtDaemonCallbackProxy); 367 otDaemon.asBinder().linkToDeath(() -> mHandler.post(this::onOtDaemonDied), 0); 368 mOtDaemon = otDaemon; 369 mHandler.post(mNat64CidrController::maybeUpdateNat64Cidr); 370 return mOtDaemon; 371 } 372 getVendorName(Resources resources, MockableSystemProperties systemProperties)373 static String getVendorName(Resources resources, MockableSystemProperties systemProperties) { 374 final String PROP_MANUFACTURER = "ro.product.manufacturer"; 375 String vendorName = resources.getString(R.string.config_thread_vendor_name); 376 if (vendorName.equalsIgnoreCase(PROP_MANUFACTURER)) { 377 vendorName = systemProperties.get(PROP_MANUFACTURER); 378 // Assume it's always ASCII chars in ro.product.manufacturer 379 if (vendorName.length() > MAX_VENDOR_NAME_UTF8_BYTES) { 380 vendorName = vendorName.substring(0, MAX_VENDOR_NAME_UTF8_BYTES); 381 } 382 } 383 return vendorName; 384 } 385 getModelName(Resources resources, MockableSystemProperties systemProperties)386 static String getModelName(Resources resources, MockableSystemProperties systemProperties) { 387 final String PROP_MODEL = "ro.product.model"; 388 String modelName = resources.getString(R.string.config_thread_model_name); 389 if (modelName.equalsIgnoreCase(PROP_MODEL)) { 390 modelName = systemProperties.get(PROP_MODEL); 391 // Assume it's always ASCII chars in ro.product.model 392 if (modelName.length() > MAX_MODEL_NAME_UTF8_BYTES) { 393 modelName = modelName.substring(0, MAX_MODEL_NAME_UTF8_BYTES); 394 } 395 } 396 return modelName; 397 } 398 399 @VisibleForTesting getMeshcopTxtAttributes( Resources resources, MockableSystemProperties systemProperties)400 static MeshcopTxtAttributes getMeshcopTxtAttributes( 401 Resources resources, MockableSystemProperties systemProperties) { 402 final String vendorName = getVendorName(resources, systemProperties); 403 final String modelName = getModelName(resources, systemProperties); 404 final String vendorOui = resources.getString(R.string.config_thread_vendor_oui); 405 final String[] vendorSpecificTxts = 406 resources.getStringArray(R.array.config_thread_mdns_vendor_specific_txts); 407 408 if (!modelName.isEmpty()) { 409 if (modelName.getBytes(UTF_8).length > MAX_MODEL_NAME_UTF8_BYTES) { 410 throw new IllegalStateException( 411 "Model name is longer than " 412 + MAX_MODEL_NAME_UTF8_BYTES 413 + "utf-8 bytes: " 414 + modelName); 415 } 416 } 417 418 if (!vendorName.isEmpty()) { 419 if (vendorName.getBytes(UTF_8).length > MAX_VENDOR_NAME_UTF8_BYTES) { 420 throw new IllegalStateException( 421 "Vendor name is longer than " 422 + MAX_VENDOR_NAME_UTF8_BYTES 423 + " utf-8 bytes: " 424 + vendorName); 425 } 426 } 427 428 if (!vendorOui.isEmpty() && !Pattern.compile(OUI_REGEX).matcher(vendorOui).matches()) { 429 throw new IllegalStateException("Vendor OUI is invalid: " + vendorOui); 430 } 431 432 MeshcopTxtAttributes meshcopTxts = new MeshcopTxtAttributes(); 433 meshcopTxts.modelName = modelName; 434 meshcopTxts.vendorName = vendorName; 435 meshcopTxts.vendorOui = HexEncoding.decode(vendorOui.replace("-", "").replace(":", "")); 436 meshcopTxts.nonStandardTxtEntries = makeVendorSpecificTxtAttrs(vendorSpecificTxts); 437 438 return meshcopTxts; 439 } 440 441 /** 442 * Parses vendor-specific TXT entries from "=" separated strings into list of {@link 443 * DnsTxtAttribute}. 444 * 445 * @throws IllegalArgumentsException if invalid TXT entries are found in {@code vendorTxts} 446 */ 447 @VisibleForTesting makeVendorSpecificTxtAttrs(String[] vendorTxts)448 static List<DnsTxtAttribute> makeVendorSpecificTxtAttrs(String[] vendorTxts) { 449 List<DnsTxtAttribute> txts = new ArrayList<>(); 450 for (String txt : vendorTxts) { 451 String[] kv = txt.split("=", 2 /* limit */); // Split with only the first '=' 452 if (kv.length < 1) { 453 throw new IllegalArgumentException( 454 "Invalid vendor-specific TXT is found in resources: " + txt); 455 } 456 457 if (kv[0].length() < 2) { 458 throw new IllegalArgumentException( 459 "Invalid vendor-specific TXT key \"" 460 + kv[0] 461 + "\": it must contain at least 2 characters"); 462 } 463 464 if (!kv[0].startsWith("v")) { 465 throw new IllegalArgumentException( 466 "Invalid vendor-specific TXT key \"" 467 + kv[0] 468 + "\": it doesn't start with \"v\""); 469 } 470 471 txts.add(new DnsTxtAttribute(kv[0], (kv.length >= 2 ? kv[1] : "").getBytes(UTF_8))); 472 } 473 return txts; 474 } 475 onOtDaemonDied()476 private void onOtDaemonDied() { 477 checkOnHandlerThread(); 478 LOG.w("OT daemon is dead, clean up..."); 479 480 OperationReceiverWrapper.onOtDaemonDied(); 481 OutputReceiverWrapper.onOtDaemonDied(); 482 mOtDaemonCallbackProxy.onOtDaemonDied(); 483 mTunIfController.onOtDaemonDied(); 484 mNsdPublisher.onOtDaemonDied(); 485 mOtDaemon = null; 486 maybeInitializeOtDaemon(); 487 } 488 initialize()489 public void initialize() { 490 mHandler.post(() -> initializeInternal()); 491 } 492 initializeInternal()493 private void initializeInternal() { 494 checkOnHandlerThread(); 495 496 LOG.v( 497 "Initializing Thread system service: Thread is " 498 + (shouldEnableThread() ? "enabled" : "disabled")); 499 try { 500 mTunIfController.createTunInterface(); 501 } catch (IOException e) { 502 throw new IllegalStateException("Failed to create Thread tunnel interface", e); 503 } 504 mConnectivityManager.registerNetworkProvider(mNetworkProvider); 505 mUserRestricted = isThreadUserRestricted(); 506 registerUserRestrictionsReceiver(); 507 508 if (isBorderRouterMode()) { 509 requestUpstreamNetwork(); 510 registerThreadNetworkCallback(); 511 } else { 512 cancelRequestUpstreamNetwork(); 513 unregisterThreadNetworkCallback(); 514 } 515 maybeInitializeOtDaemon(); 516 } 517 518 /** 519 * Force stops ot-daemon immediately and prevents ot-daemon from being restarted by 520 * system_server again. 521 * 522 * <p>This is for VTS testing only. 523 */ 524 @RequiresPermission(PERMISSION_THREAD_NETWORK_PRIVILEGED) forceStopOtDaemonForTest(boolean enabled, @NonNull IOperationReceiver receiver)525 void forceStopOtDaemonForTest(boolean enabled, @NonNull IOperationReceiver receiver) { 526 enforceAllPermissionsGranted(PERMISSION_THREAD_NETWORK_PRIVILEGED); 527 528 mHandler.post( 529 () -> 530 forceStopOtDaemonForTestInternal( 531 enabled, 532 new OperationReceiverWrapper( 533 receiver, true /* expectOtDaemonDied */))); 534 } 535 forceStopOtDaemonForTestInternal( boolean enabled, @NonNull OperationReceiverWrapper receiver)536 private void forceStopOtDaemonForTestInternal( 537 boolean enabled, @NonNull OperationReceiverWrapper receiver) { 538 checkOnHandlerThread(); 539 if (enabled == mForceStopOtDaemonEnabled) { 540 receiver.onSuccess(); 541 return; 542 } 543 544 if (!enabled) { 545 mForceStopOtDaemonEnabled = false; 546 maybeInitializeOtDaemon(); 547 receiver.onSuccess(); 548 return; 549 } 550 551 try { 552 getOtDaemon().terminate(); 553 // Do not invoke the {@code receiver} callback here but wait for ot-daemon to 554 // become dead, so that it's guaranteed that ot-daemon is stopped when {@code 555 // receiver} is completed 556 } catch (RemoteException e) { 557 LOG.e("otDaemon.terminate failed", e); 558 receiver.onError(ERROR_INTERNAL_ERROR, "Thread stack error"); 559 } catch (ThreadNetworkException e) { 560 // No ThreadNetworkException.ERROR_THREAD_DISABLED error will be thrown 561 throw new AssertionError(e); 562 } finally { 563 mForceStopOtDaemonEnabled = true; 564 } 565 } 566 setEnabled(boolean isEnabled, @NonNull IOperationReceiver receiver)567 public void setEnabled(boolean isEnabled, @NonNull IOperationReceiver receiver) { 568 enforceAllPermissionsGranted(PERMISSION_THREAD_NETWORK_PRIVILEGED); 569 570 mHandler.post( 571 () -> 572 setEnabledInternal( 573 isEnabled, 574 true /* persist */, 575 new OperationReceiverWrapper(receiver))); 576 } 577 setEnabledInternal( boolean isEnabled, boolean persist, @NonNull OperationReceiverWrapper receiver)578 private void setEnabledInternal( 579 boolean isEnabled, boolean persist, @NonNull OperationReceiverWrapper receiver) { 580 checkOnHandlerThread(); 581 if (isEnabled && isThreadUserRestricted()) { 582 receiver.onError( 583 ERROR_FAILED_PRECONDITION, 584 "Cannot enable Thread: forbidden by user restriction"); 585 return; 586 } 587 588 LOG.i("Set Thread enabled: " + isEnabled + ", persist: " + persist); 589 590 if (persist) { 591 // The persistent setting keeps the desired enabled state, thus it's set regardless 592 // the otDaemon set enabled state operation succeeded or not, so that it can recover 593 // to the desired value after reboot. 594 mPersistentSettings.put(ThreadPersistentSettings.KEY_THREAD_ENABLED, isEnabled); 595 } 596 597 try { 598 getOtDaemon().setThreadEnabled(isEnabled, newOtStatusReceiver(receiver)); 599 } catch (RemoteException | ThreadNetworkException e) { 600 LOG.e("otDaemon.setThreadEnabled failed", e); 601 receiver.onError(e); 602 } 603 } 604 605 @Override setConfiguration( @onNull ThreadConfiguration configuration, @NonNull IOperationReceiver receiver)606 public void setConfiguration( 607 @NonNull ThreadConfiguration configuration, @NonNull IOperationReceiver receiver) { 608 enforceAllPermissionsGranted(PERMISSION_THREAD_NETWORK_PRIVILEGED); 609 mHandler.post( 610 () -> 611 setConfigurationInternal( 612 configuration, new OperationReceiverWrapper(receiver))); 613 } 614 setConfigurationInternal( @onNull ThreadConfiguration configuration, @NonNull OperationReceiverWrapper receiver)615 private void setConfigurationInternal( 616 @NonNull ThreadConfiguration configuration, 617 @NonNull OperationReceiverWrapper receiver) { 618 checkOnHandlerThread(); 619 620 LOG.i("Set Thread configuration: " + configuration); 621 622 final boolean changed = mPersistentSettings.putConfiguration(configuration); 623 624 if (changed) { 625 if (isBorderRouterMode()) { 626 requestUpstreamNetwork(); 627 registerThreadNetworkCallback(); 628 } else { 629 cancelRequestUpstreamNetwork(); 630 unregisterThreadNetworkCallback(); 631 disableBorderRouting(); 632 } 633 } 634 635 receiver.onSuccess(); 636 637 if (changed) { 638 for (IConfigurationReceiver configReceiver : mConfigurationReceivers.keySet()) { 639 try { 640 configReceiver.onConfigurationChanged(configuration); 641 } catch (RemoteException e) { 642 // do nothing if the client is dead 643 } 644 } 645 } 646 647 try { 648 getOtDaemon() 649 .setConfiguration( 650 newOtDaemonConfig(configuration), 651 new LoggingOtStatusReceiver("setConfiguration")); 652 } catch (RemoteException | ThreadNetworkException e) { 653 LOG.e("otDaemon.setConfiguration failed. Config: " + configuration, e); 654 } 655 mNat64CidrController.maybeUpdateNat64Cidr(); 656 } 657 newOtDaemonConfig(ThreadConfiguration threadConfig)658 private OtDaemonConfiguration newOtDaemonConfig(ThreadConfiguration threadConfig) { 659 int srpServerConfig = R.bool.config_thread_srp_server_wait_for_border_routing_enabled; 660 boolean srpServerWaitEnabled = mResources.get().getBoolean(srpServerConfig); 661 int autoJoinConfig = R.bool.config_thread_border_router_auto_join_enabled; 662 boolean autoJoinEnabled = mResources.get().getBoolean(autoJoinConfig); 663 boolean countryCodeEnabled = 664 mResources.get().getBoolean(R.bool.config_thread_country_code_enabled); 665 return new OtDaemonConfiguration.Builder() 666 .setBorderRouterEnabled(threadConfig.isBorderRouterEnabled()) 667 .setNat64Enabled(threadConfig.isNat64Enabled()) 668 .setDhcpv6PdEnabled(threadConfig.isDhcpv6PdEnabled()) 669 .setSrpServerWaitForBorderRoutingEnabled(srpServerWaitEnabled) 670 .setBorderRouterAutoJoinEnabled(autoJoinEnabled) 671 .setCountryCodeEnabled(countryCodeEnabled) 672 .setVendorName(getVendorName(mResources.get(), mSystemProperties)) 673 .setModelName(getModelName(mResources.get(), mSystemProperties)) 674 .build(); 675 } 676 677 /** Returns {@code true} if this device is operating as a border router. */ isBorderRouterMode()678 private boolean isBorderRouterMode() { 679 return mPersistentSettings.getConfiguration().isBorderRouterEnabled(); 680 } 681 682 @Override registerConfigurationCallback(@onNull IConfigurationReceiver callback)683 public void registerConfigurationCallback(@NonNull IConfigurationReceiver callback) { 684 enforceAllPermissionsGranted(permission.THREAD_NETWORK_PRIVILEGED); 685 mHandler.post(() -> registerConfigurationCallbackInternal(callback)); 686 } 687 registerConfigurationCallbackInternal(@onNull IConfigurationReceiver callback)688 private void registerConfigurationCallbackInternal(@NonNull IConfigurationReceiver callback) { 689 checkOnHandlerThread(); 690 if (mConfigurationReceivers.containsKey(callback)) { 691 throw new IllegalStateException("Registering the same IConfigurationReceiver twice"); 692 } 693 IBinder.DeathRecipient deathRecipient = 694 () -> mHandler.post(() -> unregisterConfigurationCallbackInternal(callback)); 695 try { 696 callback.asBinder().linkToDeath(deathRecipient, 0); 697 } catch (RemoteException e) { 698 return; 699 } 700 mConfigurationReceivers.put(callback, deathRecipient); 701 try { 702 callback.onConfigurationChanged(mPersistentSettings.getConfiguration()); 703 } catch (RemoteException e) { 704 // do nothing if the client is dead 705 } 706 } 707 708 @Override unregisterConfigurationCallback(@onNull IConfigurationReceiver callback)709 public void unregisterConfigurationCallback(@NonNull IConfigurationReceiver callback) { 710 enforceAllPermissionsGranted(permission.THREAD_NETWORK_PRIVILEGED); 711 mHandler.post(() -> unregisterConfigurationCallbackInternal(callback)); 712 } 713 unregisterConfigurationCallbackInternal(@onNull IConfigurationReceiver callback)714 private void unregisterConfigurationCallbackInternal(@NonNull IConfigurationReceiver callback) { 715 checkOnHandlerThread(); 716 if (!mConfigurationReceivers.containsKey(callback)) { 717 return; 718 } 719 callback.asBinder().unlinkToDeath(mConfigurationReceivers.remove(callback), 0); 720 } 721 registerUserRestrictionsReceiver()722 private void registerUserRestrictionsReceiver() { 723 mContext.registerReceiver( 724 new BroadcastReceiver() { 725 @Override 726 public void onReceive(Context context, Intent intent) { 727 onUserRestrictionsChanged(isThreadUserRestricted()); 728 } 729 }, 730 new IntentFilter(UserManager.ACTION_USER_RESTRICTIONS_CHANGED), 731 null /* broadcastPermission */, 732 mHandler); 733 } 734 onUserRestrictionsChanged(boolean newUserRestrictedState)735 private void onUserRestrictionsChanged(boolean newUserRestrictedState) { 736 checkOnHandlerThread(); 737 if (mUserRestricted == newUserRestrictedState) { 738 return; 739 } 740 LOG.i( 741 "Thread user restriction changed: " 742 + mUserRestricted 743 + " -> " 744 + newUserRestrictedState); 745 mUserRestricted = newUserRestrictedState; 746 747 final boolean shouldEnableThread = shouldEnableThread(); 748 final IOperationReceiver receiver = 749 new IOperationReceiver.Stub() { 750 @Override 751 public void onSuccess() { 752 LOG.v( 753 (shouldEnableThread ? "Enabled" : "Disabled") 754 + " Thread due to user restriction change"); 755 } 756 757 @Override 758 public void onError(int errorCode, String errorMessage) { 759 LOG.e( 760 "Failed to " 761 + (shouldEnableThread ? "enable" : "disable") 762 + " Thread for user restriction change"); 763 } 764 }; 765 // Do not save the user restriction state to persistent settings so that the user 766 // configuration won't be overwritten 767 setEnabledInternal( 768 shouldEnableThread, false /* persist */, new OperationReceiverWrapper(receiver)); 769 } 770 771 /** Returns {@code true} if Thread has been restricted for the user. */ isThreadUserRestricted()772 private boolean isThreadUserRestricted() { 773 return mUserManager.hasUserRestriction(DISALLOW_THREAD_NETWORK); 774 } 775 776 /** 777 * Returns {@code true} if Thread should be enabled based on current settings, runtime user 778 * restriction state. 779 */ shouldEnableThread()780 private boolean shouldEnableThread() { 781 return !mForceStopOtDaemonEnabled 782 && !mUserRestricted 783 && mPersistentSettings.get(ThreadPersistentSettings.KEY_THREAD_ENABLED); 784 } 785 requestUpstreamNetwork()786 private void requestUpstreamNetwork() { 787 if (mUpstreamNetworkCallback != null) { 788 return; 789 } 790 mUpstreamNetworkCallback = new UpstreamNetworkCallback(); 791 mConnectivityManager.registerNetworkCallback( 792 mUpstreamNetworkRequest, mUpstreamNetworkCallback, mHandler); 793 } 794 cancelRequestUpstreamNetwork()795 private void cancelRequestUpstreamNetwork() { 796 if (mUpstreamNetworkCallback == null) { 797 return; 798 } 799 mNetworkToLinkProperties.clear(); 800 mConnectivityManager.unregisterNetworkCallback(mUpstreamNetworkCallback); 801 mUpstreamNetworkCallback = null; 802 } 803 804 private final class UpstreamNetworkCallback extends ConnectivityManager.NetworkCallback { 805 @Override onAvailable(@onNull Network network)806 public void onAvailable(@NonNull Network network) { 807 checkOnHandlerThread(); 808 LOG.i("Upstream network available: " + network); 809 } 810 811 @Override onLost(@onNull Network network)812 public void onLost(@NonNull Network network) { 813 checkOnHandlerThread(); 814 LOG.i("Upstream network lost: " + network); 815 816 // TODO: disable border routing when upsteam network disconnected 817 } 818 819 @Override onLinkPropertiesChanged( @onNull Network network, @NonNull LinkProperties newLinkProperties)820 public void onLinkPropertiesChanged( 821 @NonNull Network network, @NonNull LinkProperties newLinkProperties) { 822 checkOnHandlerThread(); 823 824 LinkProperties oldLinkProperties = mNetworkToLinkProperties.get(network); 825 if (Objects.equals(oldLinkProperties, newLinkProperties)) { 826 return; 827 } 828 LOG.i("Upstream network changed: " + oldLinkProperties + " -> " + newLinkProperties); 829 mNetworkToLinkProperties.put(network, newLinkProperties); 830 831 // TODO: disable border routing if netIfName is null 832 if (network.equals(mUpstreamNetwork)) { 833 setInfraLinkState(newInfraLinkStateBuilder(newLinkProperties).build()); 834 } 835 } 836 } 837 838 private final class ThreadNetworkCallback extends ConnectivityManager.NetworkCallback { 839 @Override onAvailable(@onNull Network network)840 public void onAvailable(@NonNull Network network) { 841 checkOnHandlerThread(); 842 LOG.i("Thread network is available: " + network); 843 } 844 845 @Override onLost(@onNull Network network)846 public void onLost(@NonNull Network network) { 847 checkOnHandlerThread(); 848 LOG.i("Thread network is lost: " + network); 849 setInfraLinkState(newInfraLinkStateBuilder().build()); 850 } 851 852 @Override onLocalNetworkInfoChanged( @onNull Network network, @NonNull LocalNetworkInfo localNetworkInfo)853 public void onLocalNetworkInfoChanged( 854 @NonNull Network network, @NonNull LocalNetworkInfo localNetworkInfo) { 855 checkOnHandlerThread(); 856 LOG.i( 857 "LocalNetworkInfo of Thread network changed: {threadNetwork: " 858 + network 859 + ", localNetworkInfo: " 860 + localNetworkInfo 861 + "}"); 862 mUpstreamNetwork = localNetworkInfo.getUpstreamNetwork(); 863 if (mUpstreamNetwork == null) { 864 setInfraLinkState(newInfraLinkStateBuilder().build()); 865 return; 866 } 867 if (mNetworkToLinkProperties.containsKey(mUpstreamNetwork)) { 868 setInfraLinkState( 869 newInfraLinkStateBuilder(mNetworkToLinkProperties.get(mUpstreamNetwork)) 870 .build()); 871 } 872 mNsdPublisher.setNetworkForHostResolution(mUpstreamNetwork); 873 } 874 } 875 registerThreadNetworkCallback()876 private void registerThreadNetworkCallback() { 877 if (mThreadNetworkCallback != null) { 878 return; 879 } 880 881 mThreadNetworkCallback = new ThreadNetworkCallback(); 882 NetworkRequest request = 883 new NetworkRequest.Builder() 884 // clearCapabilities() is needed to remove forbidden capabilities and UID 885 // requirement. 886 .clearCapabilities() 887 .addTransportType(TRANSPORT_THREAD) 888 .addCapability(NetworkCapabilities.NET_CAPABILITY_LOCAL_NETWORK) 889 .build(); 890 mConnectivityManager.registerNetworkCallback(request, mThreadNetworkCallback, mHandler); 891 } 892 unregisterThreadNetworkCallback()893 private void unregisterThreadNetworkCallback() { 894 if (mThreadNetworkCallback == null) { 895 return; 896 } 897 mConnectivityManager.unregisterNetworkCallback(mThreadNetworkCallback); 898 mThreadNetworkCallback = null; 899 } 900 901 /** Injects a {@link NetworkAgent} for testing. */ 902 @VisibleForTesting setTestNetworkAgent(@ullable NetworkAgent testNetworkAgent)903 void setTestNetworkAgent(@Nullable NetworkAgent testNetworkAgent) { 904 mTestNetworkAgent = testNetworkAgent; 905 } 906 newNetworkAgent()907 private NetworkAgent newNetworkAgent() { 908 if (mTestNetworkAgent != null) { 909 return mTestNetworkAgent; 910 } 911 912 final var netCapsBuilder = 913 new NetworkCapabilities.Builder() 914 .addTransportType(TRANSPORT_THREAD) 915 .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED) 916 .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED); 917 final var scoreBuilder = new NetworkScore.Builder(); 918 919 netCapsBuilder.addCapability(NetworkCapabilities.NET_CAPABILITY_LOCAL_NETWORK); 920 scoreBuilder.setKeepConnectedReason(NetworkScore.KEEP_CONNECTED_LOCAL_NETWORK); 921 922 return new NetworkAgent( 923 mContext, 924 mHandler.getLooper(), 925 LOG.getTag(), 926 netCapsBuilder.build(), 927 getTunIfLinkProperties(), 928 newLocalNetworkConfig(), 929 scoreBuilder.build(), 930 new NetworkAgentConfig.Builder().build(), 931 mNetworkProvider) { 932 933 // TODO(b/374037595): use NetworkFactory to handle dynamic network requests 934 @Override 935 public void onNetworkUnwanted() { 936 LOG.i("Thread network is unwanted by ConnectivityService"); 937 // TODO(b/374037595): leave() the current network when the new APIs for mobile 938 // is available 939 } 940 }; 941 } 942 943 private LocalNetworkConfig newLocalNetworkConfig() { 944 return new LocalNetworkConfig.Builder() 945 .setUpstreamMulticastRoutingConfig(mUpstreamMulticastRoutingConfig) 946 .setDownstreamMulticastRoutingConfig(mDownstreamMulticastRoutingConfig) 947 .setUpstreamSelector(mUpstreamNetworkRequest) 948 .build(); 949 } 950 951 private void registerThreadNetwork() { 952 if (mNetworkAgent != null) { 953 return; 954 } 955 956 mNetworkAgent = newNetworkAgent(); 957 mNetworkAgent.register(); 958 mNetworkAgent.markConnected(); 959 LOG.i("Registered Thread network"); 960 } 961 962 private void unregisterThreadNetwork() { 963 if (mNetworkAgent == null) { 964 // unregisterThreadNetwork can be called every time this device becomes detached or 965 // disabled and the mNetworkAgent may not be created in this cases 966 return; 967 } 968 969 LOG.v("Unregistering Thread network agent"); 970 971 mNetworkAgent.unregister(); 972 mNetworkAgent = null; 973 } 974 975 @Override 976 public int getThreadVersion() { 977 return THREAD_VERSION_1_3; 978 } 979 980 @Override 981 public void activateEphemeralKeyMode(long lifetimeMillis, IOperationReceiver receiver) { 982 enforceAllPermissionsGranted(PERMISSION_THREAD_NETWORK_PRIVILEGED); 983 984 mHandler.post( 985 () -> 986 activateEphemeralKeyModeInternal( 987 lifetimeMillis, new OperationReceiverWrapper(receiver))); 988 } 989 990 private void activateEphemeralKeyModeInternal( 991 long lifetimeMillis, OperationReceiverWrapper receiver) { 992 checkOnHandlerThread(); 993 994 if (!isBorderRouterMode()) { 995 receiver.onError( 996 ERROR_FAILED_PRECONDITION, "This device is not configured a Border Router"); 997 return; 998 } 999 1000 try { 1001 getOtDaemon().activateEphemeralKeyMode(lifetimeMillis, newOtStatusReceiver(receiver)); 1002 } catch (RemoteException | ThreadNetworkException e) { 1003 LOG.e("otDaemon.activateEphemeralKeyMode failed", e); 1004 receiver.onError(e); 1005 } 1006 } 1007 1008 @Override 1009 public void deactivateEphemeralKeyMode(IOperationReceiver receiver) { 1010 enforceAllPermissionsGranted(PERMISSION_THREAD_NETWORK_PRIVILEGED); 1011 1012 mHandler.post( 1013 () -> deactivateEphemeralKeyModeInternal(new OperationReceiverWrapper(receiver))); 1014 } 1015 1016 private void deactivateEphemeralKeyModeInternal(OperationReceiverWrapper receiver) { 1017 checkOnHandlerThread(); 1018 1019 if (!isBorderRouterMode()) { 1020 receiver.onError( 1021 ERROR_FAILED_PRECONDITION, "This device is not configured a Border Router"); 1022 return; 1023 } 1024 1025 try { 1026 getOtDaemon().deactivateEphemeralKeyMode(newOtStatusReceiver(receiver)); 1027 } catch (RemoteException | ThreadNetworkException e) { 1028 LOG.e("otDaemon.deactivateEphemeralKeyMode failed", e); 1029 receiver.onError(e); 1030 } 1031 } 1032 1033 @Override 1034 public void createRandomizedDataset( 1035 String networkName, IActiveOperationalDatasetReceiver receiver) { 1036 ActiveOperationalDatasetReceiverWrapper receiverWrapper = 1037 new ActiveOperationalDatasetReceiverWrapper(receiver); 1038 mHandler.post(() -> createRandomizedDatasetInternal(networkName, receiverWrapper)); 1039 } 1040 1041 private void createRandomizedDatasetInternal( 1042 String networkName, @NonNull ActiveOperationalDatasetReceiverWrapper receiver) { 1043 checkOnHandlerThread(); 1044 1045 try { 1046 getOtDaemon().getChannelMasks(newChannelMasksReceiver(networkName, receiver)); 1047 } catch (RemoteException | ThreadNetworkException e) { 1048 LOG.e("otDaemon.getChannelMasks failed", e); 1049 receiver.onError(e); 1050 } 1051 } 1052 1053 private IChannelMasksReceiver newChannelMasksReceiver( 1054 String networkName, ActiveOperationalDatasetReceiverWrapper receiver) { 1055 return new IChannelMasksReceiver.Stub() { 1056 @Override 1057 public void onSuccess(int supportedChannelMask, int preferredChannelMask) { 1058 ActiveOperationalDataset dataset = 1059 createRandomizedDataset( 1060 networkName, 1061 supportedChannelMask, 1062 preferredChannelMask, 1063 new Random(), 1064 new SecureRandom()); 1065 1066 receiver.onSuccess(dataset); 1067 } 1068 1069 @Override 1070 public void onError(int errorCode, String errorMessage) { 1071 receiver.onError(otErrorToAndroidError(errorCode), errorMessage); 1072 } 1073 }; 1074 } 1075 1076 private static ActiveOperationalDataset createRandomizedDataset( 1077 String networkName, 1078 int supportedChannelMask, 1079 int preferredChannelMask, 1080 Random random, 1081 SecureRandom secureRandom) { 1082 boolean authoritative = false; 1083 Instant now = Instant.now(); 1084 try { 1085 Clock clock = SystemClock.currentNetworkTimeClock(); 1086 now = clock.instant(); 1087 authoritative = true; 1088 } catch (DateTimeException e) { 1089 LOG.w("Failed to get authoritative time: " + e.getMessage()); 1090 } 1091 1092 int panId = random.nextInt(/* bound= */ 0xffff); 1093 final byte[] meshLocalPrefix = newRandomBytes(random, LENGTH_MESH_LOCAL_PREFIX_BITS / 8); 1094 meshLocalPrefix[0] = MESH_LOCAL_PREFIX_FIRST_BYTE; 1095 1096 final SparseArray<byte[]> channelMask = new SparseArray<>(1); 1097 channelMask.put(CHANNEL_PAGE_24_GHZ, channelMaskToByteArray(supportedChannelMask)); 1098 final int channel = selectChannel(supportedChannelMask, preferredChannelMask, random); 1099 1100 final byte[] securityFlags = new byte[] {(byte) 0xff, (byte) 0xf8}; 1101 1102 return new ActiveOperationalDataset.Builder() 1103 .setActiveTimestamp(OperationalDatasetTimestamp.fromInstant(now, authoritative)) 1104 .setExtendedPanId(newRandomBytes(random, LENGTH_EXTENDED_PAN_ID)) 1105 .setPanId(panId) 1106 .setNetworkName(networkName) 1107 .setChannel(CHANNEL_PAGE_24_GHZ, channel) 1108 .setChannelMask(channelMask) 1109 .setPskc(newRandomBytes(secureRandom, LENGTH_PSKC)) 1110 .setNetworkKey(newRandomBytes(secureRandom, LENGTH_NETWORK_KEY)) 1111 .setMeshLocalPrefix(meshLocalPrefix) 1112 .setSecurityPolicy(new SecurityPolicy(DEFAULT_ROTATION_TIME_HOURS, securityFlags)) 1113 .build(); 1114 } 1115 1116 private static int selectChannel( 1117 int supportedChannelMask, int preferredChannelMask, Random random) { 1118 // Due to radio hardware performance reasons, many Thread radio chips need to reduce their 1119 // transmit power on edge channels to pass regulatory RF certification. Thread edge channel 1120 // 25 and 26 are not preferred here. 1121 // 1122 // If users want to use channel 25 or 26, they can change the channel via the method 1123 // ActiveOperationalDataset.Builder(activeOperationalDataset).setChannel(channel).build(). 1124 preferredChannelMask = preferredChannelMask & CHANNEL_MASK_11_TO_24; 1125 1126 // If the preferred channel mask is not empty, select a random channel from it, otherwise 1127 // choose one from the supported channel mask. 1128 preferredChannelMask = preferredChannelMask & supportedChannelMask; 1129 if (preferredChannelMask == 0) { 1130 preferredChannelMask = supportedChannelMask; 1131 } 1132 1133 return selectRandomChannel(preferredChannelMask, random); 1134 } 1135 1136 private static byte[] newRandomBytes(Random random, int length) { 1137 byte[] result = new byte[length]; 1138 random.nextBytes(result); 1139 return result; 1140 } 1141 1142 private static byte[] channelMaskToByteArray(int channelMask) { 1143 // Per Thread spec, a Channel Mask is: 1144 // A variable-length bit mask that identifies the channels within the channel page 1145 // (1 = selected, 0 = unselected). The channels are represented in most significant bit 1146 // order. For example, the most significant bit of the left-most byte indicates channel 0. 1147 // If channel 0 and channel 10 are selected, the mask would be: 80 20 00 00. For IEEE 1148 // 802.15.4-2006 2.4 GHz PHY, the ChannelMask is 27 bits and MaskLength is 4. 1149 // 1150 // The pass-in channelMask represents a channel K by (channelMask & (1 << K)), so here 1151 // needs to do bit-wise reverse to convert it to the Thread spec format in bytes. 1152 channelMask = Integer.reverse(channelMask); 1153 return new byte[] { 1154 (byte) (channelMask >>> 24), 1155 (byte) (channelMask >>> 16), 1156 (byte) (channelMask >>> 8), 1157 (byte) channelMask 1158 }; 1159 } 1160 1161 private static int selectRandomChannel(int supportedChannelMask, Random random) { 1162 int num = random.nextInt(Integer.bitCount(supportedChannelMask)); 1163 for (int i = 0; i < 32; i++) { 1164 if ((supportedChannelMask & 1) == 1 && (num--) == 0) { 1165 return i; 1166 } 1167 supportedChannelMask >>>= 1; 1168 } 1169 return -1; 1170 } 1171 1172 private void enforceAllPermissionsGranted(String... permissions) { 1173 for (String permission : permissions) { 1174 mContext.enforceCallingOrSelfPermission( 1175 permission, "Permission " + permission + " is missing"); 1176 } 1177 } 1178 1179 @Override 1180 public void registerStateCallback(IStateCallback stateCallback) throws RemoteException { 1181 enforceAllPermissionsGranted(permission.ACCESS_NETWORK_STATE); 1182 boolean hasThreadPrivilegedPermission = 1183 (mContext.checkCallingOrSelfPermission(PERMISSION_THREAD_NETWORK_PRIVILEGED) 1184 == PERMISSION_GRANTED); 1185 1186 mHandler.post( 1187 () -> 1188 mOtDaemonCallbackProxy.registerStateCallback( 1189 stateCallback, hasThreadPrivilegedPermission)); 1190 } 1191 1192 @Override 1193 public void unregisterStateCallback(IStateCallback stateCallback) throws RemoteException { 1194 enforceAllPermissionsGranted(permission.ACCESS_NETWORK_STATE); 1195 mHandler.post(() -> mOtDaemonCallbackProxy.unregisterStateCallback(stateCallback)); 1196 } 1197 1198 @Override 1199 public void registerOperationalDatasetCallback(IOperationalDatasetCallback callback) 1200 throws RemoteException { 1201 enforceAllPermissionsGranted( 1202 permission.ACCESS_NETWORK_STATE, PERMISSION_THREAD_NETWORK_PRIVILEGED); 1203 mHandler.post(() -> mOtDaemonCallbackProxy.registerDatasetCallback(callback)); 1204 } 1205 1206 @Override 1207 public void unregisterOperationalDatasetCallback(IOperationalDatasetCallback callback) 1208 throws RemoteException { 1209 enforceAllPermissionsGranted( 1210 permission.ACCESS_NETWORK_STATE, PERMISSION_THREAD_NETWORK_PRIVILEGED); 1211 mHandler.post(() -> mOtDaemonCallbackProxy.unregisterDatasetCallback(callback)); 1212 } 1213 1214 private void checkOnHandlerThread() { 1215 if (Looper.myLooper() != mHandler.getLooper()) { 1216 throw new IllegalStateException( 1217 "Not running on ThreadNetworkControllerService thread (" 1218 + mHandler.getLooper() 1219 + ") : " 1220 + Looper.myLooper()); 1221 } 1222 } 1223 1224 private IOtStatusReceiver newOtStatusReceiver(OperationReceiverWrapper receiver) { 1225 return new IOtStatusReceiver.Stub() { 1226 @Override 1227 public void onSuccess() { 1228 receiver.onSuccess(); 1229 } 1230 1231 @Override 1232 public void onError(int otError, String message) { 1233 receiver.onError(otErrorToAndroidError(otError), message); 1234 } 1235 }; 1236 } 1237 1238 private IOtOutputReceiver newOtOutputReceiver(OutputReceiverWrapper receiver) { 1239 return new IOtOutputReceiver.Stub() { 1240 @Override 1241 public void onOutput(String output) { 1242 receiver.onOutput(output); 1243 } 1244 1245 @Override 1246 public void onComplete() { 1247 receiver.onComplete(); 1248 } 1249 1250 @Override 1251 public void onError(int otError, String message) { 1252 receiver.onError(otErrorToAndroidError(otError), message); 1253 } 1254 }; 1255 } 1256 1257 @ErrorCode 1258 private static int otErrorToAndroidError(int otError) { 1259 // See external/openthread/include/openthread/error.h for OT error definition 1260 switch (otError) { 1261 case OT_ERROR_ABORT: 1262 return ERROR_ABORTED; 1263 case OT_ERROR_BUSY: 1264 return ERROR_BUSY; 1265 case OT_ERROR_NOT_IMPLEMENTED: 1266 return ERROR_UNSUPPORTED_FEATURE; 1267 case OT_ERROR_NO_BUFS: 1268 return ERROR_RESOURCE_EXHAUSTED; 1269 case OT_ERROR_PARSE: 1270 return ERROR_RESPONSE_BAD_FORMAT; 1271 case OT_ERROR_REASSEMBLY_TIMEOUT: 1272 case OT_ERROR_RESPONSE_TIMEOUT: 1273 return ERROR_TIMEOUT; 1274 case OT_ERROR_REJECTED: 1275 return ERROR_REJECTED_BY_PEER; 1276 case OT_ERROR_UNSUPPORTED_CHANNEL: 1277 return ERROR_UNSUPPORTED_CHANNEL; 1278 case OT_ERROR_THREAD_DISABLED: 1279 return ERROR_THREAD_DISABLED; 1280 case OT_ERROR_FAILED_PRECONDITION: 1281 return ERROR_FAILED_PRECONDITION; 1282 case OT_ERROR_INVALID_STATE: 1283 default: 1284 return ERROR_INTERNAL_ERROR; 1285 } 1286 } 1287 1288 @Override 1289 public void join( 1290 @NonNull ActiveOperationalDataset activeDataset, @NonNull IOperationReceiver receiver) { 1291 enforceAllPermissionsGranted(PERMISSION_THREAD_NETWORK_PRIVILEGED); 1292 1293 OperationReceiverWrapper receiverWrapper = new OperationReceiverWrapper(receiver); 1294 mHandler.post(() -> joinInternal(activeDataset, receiverWrapper)); 1295 } 1296 1297 private void joinInternal( 1298 @NonNull ActiveOperationalDataset activeDataset, 1299 @NonNull OperationReceiverWrapper receiver) { 1300 checkOnHandlerThread(); 1301 1302 try { 1303 // The otDaemon.join() will leave first if this device is currently attached 1304 getOtDaemon().join(activeDataset.toThreadTlvs(), newOtStatusReceiver(receiver)); 1305 } catch (RemoteException | ThreadNetworkException e) { 1306 LOG.e("otDaemon.join failed", e); 1307 receiver.onError(e); 1308 } 1309 } 1310 1311 @Override 1312 public void scheduleMigration( 1313 @NonNull PendingOperationalDataset pendingDataset, 1314 @NonNull IOperationReceiver receiver) { 1315 enforceAllPermissionsGranted(PERMISSION_THREAD_NETWORK_PRIVILEGED); 1316 1317 OperationReceiverWrapper receiverWrapper = new OperationReceiverWrapper(receiver); 1318 mHandler.post(() -> scheduleMigrationInternal(pendingDataset, receiverWrapper)); 1319 } 1320 1321 public void scheduleMigrationInternal( 1322 @NonNull PendingOperationalDataset pendingDataset, 1323 @NonNull OperationReceiverWrapper receiver) { 1324 checkOnHandlerThread(); 1325 1326 try { 1327 getOtDaemon() 1328 .scheduleMigration( 1329 pendingDataset.toThreadTlvs(), newOtStatusReceiver(receiver)); 1330 } catch (RemoteException | ThreadNetworkException e) { 1331 LOG.e("otDaemon.scheduleMigration failed", e); 1332 receiver.onError(e); 1333 } 1334 } 1335 1336 @Override 1337 public void leave(@NonNull IOperationReceiver receiver) { 1338 leave(true /* eraseDataset */, receiver); 1339 } 1340 1341 private void leave(boolean eraseDataset, @NonNull IOperationReceiver receiver) { 1342 enforceAllPermissionsGranted(PERMISSION_THREAD_NETWORK_PRIVILEGED); 1343 1344 mHandler.post(() -> leaveInternal(eraseDataset, new OperationReceiverWrapper(receiver))); 1345 } 1346 1347 private void leaveInternal(boolean eraseDataset, @NonNull OperationReceiverWrapper receiver) { 1348 checkOnHandlerThread(); 1349 1350 try { 1351 getOtDaemon().leave(eraseDataset, newOtStatusReceiver(receiver)); 1352 } catch (RemoteException | ThreadNetworkException e) { 1353 LOG.e("otDaemon.leave failed", e); 1354 receiver.onError(e); 1355 } 1356 } 1357 1358 /** 1359 * Sets the country code. 1360 * 1361 * @param countryCode 2 characters string country code (as defined in ISO 3166) to set. 1362 * @param receiver the receiver to receive result of this operation 1363 */ 1364 @RequiresPermission(PERMISSION_THREAD_NETWORK_PRIVILEGED) 1365 public void setCountryCode(@NonNull String countryCode, @NonNull IOperationReceiver receiver) { 1366 enforceAllPermissionsGranted(PERMISSION_THREAD_NETWORK_PRIVILEGED); 1367 1368 OperationReceiverWrapper receiverWrapper = new OperationReceiverWrapper(receiver); 1369 mHandler.post(() -> setCountryCodeInternal(countryCode, receiverWrapper)); 1370 } 1371 1372 private void setCountryCodeInternal( 1373 String countryCode, @NonNull OperationReceiverWrapper receiver) { 1374 checkOnHandlerThread(); 1375 1376 // Fails early to avoid waking up ot-daemon by the ThreadNetworkCountryCode class 1377 if (!shouldEnableThread()) { 1378 receiver.onError( 1379 ERROR_THREAD_DISABLED, "Can't set country code when Thread is disabled"); 1380 return; 1381 } 1382 1383 try { 1384 getOtDaemon().setCountryCode(countryCode, newOtStatusReceiver(receiver)); 1385 } catch (RemoteException | ThreadNetworkException e) { 1386 LOG.e("otDaemon.setCountryCode failed", e); 1387 receiver.onError(e); 1388 } 1389 } 1390 1391 @Override 1392 public void setTestNetworkAsUpstream( 1393 @Nullable String testNetworkInterfaceName, @NonNull IOperationReceiver receiver) { 1394 enforceAllPermissionsGranted(PERMISSION_THREAD_NETWORK_PRIVILEGED, NETWORK_SETTINGS); 1395 1396 LOG.i("setTestNetworkAsUpstream: " + testNetworkInterfaceName); 1397 mHandler.post(() -> setTestNetworkAsUpstreamInternal(testNetworkInterfaceName, receiver)); 1398 } 1399 1400 private void setTestNetworkAsUpstreamInternal( 1401 @Nullable String testNetworkInterfaceName, @NonNull IOperationReceiver receiver) { 1402 checkOnHandlerThread(); 1403 1404 TestNetworkSpecifier testNetworkSpecifier = null; 1405 if (testNetworkInterfaceName != null) { 1406 testNetworkSpecifier = new TestNetworkSpecifier(testNetworkInterfaceName); 1407 } 1408 1409 if (!Objects.equals(mUpstreamTestNetworkSpecifier, testNetworkSpecifier)) { 1410 cancelRequestUpstreamNetwork(); 1411 mUpstreamTestNetworkSpecifier = testNetworkSpecifier; 1412 mUpstreamNetworkRequest = newUpstreamNetworkRequest(); 1413 requestUpstreamNetwork(); 1414 sendLocalNetworkConfig(); 1415 } 1416 try { 1417 receiver.onSuccess(); 1418 } catch (RemoteException ignored) { 1419 // do nothing if the client is dead 1420 } 1421 } 1422 1423 @RequiresPermission(PERMISSION_THREAD_NETWORK_PRIVILEGED) 1424 public void setChannelMaxPowers( 1425 @NonNull ChannelMaxPower[] channelMaxPowers, @NonNull IOperationReceiver receiver) { 1426 enforceAllPermissionsGranted(PERMISSION_THREAD_NETWORK_PRIVILEGED); 1427 1428 mHandler.post( 1429 () -> 1430 setChannelMaxPowersInternal( 1431 channelMaxPowers, new OperationReceiverWrapper(receiver))); 1432 } 1433 1434 private void setChannelMaxPowersInternal( 1435 @NonNull ChannelMaxPower[] channelMaxPowers, 1436 @NonNull OperationReceiverWrapper receiver) { 1437 checkOnHandlerThread(); 1438 1439 try { 1440 getOtDaemon().setChannelMaxPowers(channelMaxPowers, newOtStatusReceiver(receiver)); 1441 } catch (RemoteException | ThreadNetworkException e) { 1442 LOG.e("otDaemon.setChannelMaxPowers failed", e); 1443 receiver.onError(ERROR_INTERNAL_ERROR, "Thread stack error"); 1444 } 1445 } 1446 1447 private void setInfraLinkState(InfraLinkState newInfraLinkState) { 1448 if (Objects.equals(mInfraLinkState, newInfraLinkState)) { 1449 return; 1450 } 1451 LOG.i("Infra link state changed: " + mInfraLinkState + " -> " + newInfraLinkState); 1452 setInfraLinkInterfaceName(newInfraLinkState.interfaceName); 1453 setInfraLinkNat64Prefix(newInfraLinkState.nat64Prefix); 1454 setInfraLinkDnsServers(newInfraLinkState.dnsServers); 1455 mInfraLinkState = newInfraLinkState; 1456 } 1457 1458 private void setInfraLinkInterfaceName(String newInfraLinkInterfaceName) { 1459 if (Objects.equals(mInfraLinkState.interfaceName, newInfraLinkInterfaceName)) { 1460 return; 1461 } 1462 ParcelFileDescriptor infraIcmp6Socket = null; 1463 if (newInfraLinkInterfaceName != null) { 1464 try { 1465 infraIcmp6Socket = mInfraIfController.createIcmp6Socket(newInfraLinkInterfaceName); 1466 } catch (IOException e) { 1467 LOG.e("Failed to create ICMPv6 socket on infra network interface", e); 1468 } 1469 } 1470 try { 1471 getOtDaemon() 1472 .setInfraLinkInterfaceName( 1473 newInfraLinkInterfaceName, 1474 infraIcmp6Socket, 1475 new LoggingOtStatusReceiver("setInfraLinkInterfaceName")); 1476 } catch (RemoteException | ThreadNetworkException e) { 1477 LOG.e("Failed to set infra link interface name " + newInfraLinkInterfaceName, e); 1478 } 1479 } 1480 1481 private void setInfraLinkNat64Prefix(@Nullable String newNat64Prefix) { 1482 if (Objects.equals(newNat64Prefix, mInfraLinkState.nat64Prefix)) { 1483 return; 1484 } 1485 try { 1486 getOtDaemon() 1487 .setInfraLinkNat64Prefix( 1488 newNat64Prefix, new LoggingOtStatusReceiver("setInfraLinkNat64Prefix")); 1489 } catch (RemoteException | ThreadNetworkException e) { 1490 LOG.e("Failed to set infra link NAT64 prefix " + newNat64Prefix, e); 1491 } 1492 } 1493 1494 private void setInfraLinkDnsServers(List<String> newDnsServers) { 1495 if (Objects.equals(newDnsServers, mInfraLinkState.dnsServers)) { 1496 return; 1497 } 1498 try { 1499 getOtDaemon() 1500 .setInfraLinkDnsServers( 1501 newDnsServers, new LoggingOtStatusReceiver("setInfraLinkDnsServers")); 1502 } catch (RemoteException | ThreadNetworkException e) { 1503 LOG.e("Failed to set infra link DNS servers " + newDnsServers, e); 1504 } 1505 } 1506 1507 private void disableBorderRouting() { 1508 LOG.i("Disabling border routing"); 1509 setInfraLinkState(newInfraLinkStateBuilder().build()); 1510 } 1511 1512 private void handleThreadInterfaceStateChanged(boolean isUp) { 1513 try { 1514 mTunIfController.setInterfaceUp(isUp); 1515 LOG.i("Thread TUN interface becomes " + (isUp ? "up" : "down")); 1516 } catch (IOException e) { 1517 LOG.e("Failed to handle Thread interface state changes", e); 1518 } 1519 } 1520 1521 private void handleDeviceRoleChanged(@DeviceRole int deviceRole) { 1522 if (ThreadNetworkController.isAttached(deviceRole)) { 1523 LOG.i("Attached to the Thread network"); 1524 1525 // This is an idempotent method which can be called for multiple times when the device 1526 // is already attached (e.g. going from Child to Router) 1527 registerThreadNetwork(); 1528 } else { 1529 LOG.i("Detached from the Thread network"); 1530 1531 // This is an idempotent method which can be called for multiple times when the device 1532 // is already detached or stopped 1533 unregisterThreadNetwork(); 1534 } 1535 } 1536 1537 private void handleAddressChanged(List<Ipv6AddressInfo> addressInfoList) { 1538 checkOnHandlerThread(); 1539 1540 mTunIfController.updateAddresses(addressInfoList); 1541 1542 // The OT daemon can send link property updates before the networkAgent is 1543 // registered 1544 maybeSendLinkProperties(); 1545 } 1546 1547 private void handlePrefixChanged(List<OnMeshPrefixConfig> onMeshPrefixConfigList) { 1548 checkOnHandlerThread(); 1549 1550 mTunIfController.updatePrefixes(onMeshPrefixConfigList); 1551 1552 // The OT daemon can send link property updates before the networkAgent is 1553 // registered 1554 maybeSendLinkProperties(); 1555 } 1556 1557 private void maybeSendLinkProperties() { 1558 if (mNetworkAgent == null) { 1559 return; 1560 } 1561 mNetworkAgent.sendLinkProperties(getTunIfLinkProperties()); 1562 } 1563 1564 private LinkProperties getTunIfLinkProperties() { 1565 return mTunIfController.getLinkPropertiesWithNat64Cidr(mNat64CidrController.mNat64Cidr); 1566 } 1567 1568 @RequiresPermission( 1569 allOf = {PERMISSION_THREAD_NETWORK_PRIVILEGED, PERMISSION_THREAD_NETWORK_TESTING}) 1570 public void runOtCtlCommand( 1571 @NonNull String command, boolean isInteractive, @NonNull IOutputReceiver receiver) { 1572 enforceAllPermissionsGranted( 1573 PERMISSION_THREAD_NETWORK_PRIVILEGED, PERMISSION_THREAD_NETWORK_TESTING); 1574 1575 mHandler.post( 1576 () -> 1577 runOtCtlCommandInternal( 1578 command, isInteractive, new OutputReceiverWrapper(receiver))); 1579 } 1580 1581 private void runOtCtlCommandInternal( 1582 String command, boolean isInteractive, @NonNull OutputReceiverWrapper receiver) { 1583 checkOnHandlerThread(); 1584 1585 try { 1586 getOtDaemon().runOtCtlCommand(command, isInteractive, newOtOutputReceiver(receiver)); 1587 } catch (RemoteException | ThreadNetworkException e) { 1588 LOG.e("otDaemon.runOtCtlCommand failed", e); 1589 receiver.onError(ERROR_INTERNAL_ERROR, "Thread stack error"); 1590 } 1591 } 1592 1593 private void sendLocalNetworkConfig() { 1594 if (mNetworkAgent == null) { 1595 return; 1596 } 1597 final LocalNetworkConfig localNetworkConfig = newLocalNetworkConfig(); 1598 mNetworkAgent.sendLocalNetworkConfig(localNetworkConfig); 1599 LOG.v("Sent localNetworkConfig: " + localNetworkConfig); 1600 } 1601 1602 private void handleMulticastForwardingChanged(BackboneRouterState state) { 1603 MulticastRoutingConfig upstreamMulticastRoutingConfig; 1604 MulticastRoutingConfig downstreamMulticastRoutingConfig; 1605 1606 if (state.multicastForwardingEnabled) { 1607 // When multicast forwarding is enabled, setup upstream forwarding to any address 1608 // with minimal scope 4 1609 // setup downstream forwarding with addresses subscribed from Thread network 1610 upstreamMulticastRoutingConfig = 1611 new MulticastRoutingConfig.Builder(FORWARD_WITH_MIN_SCOPE, 4).build(); 1612 downstreamMulticastRoutingConfig = 1613 buildDownstreamMulticastRoutingConfigSelected(state.listeningAddresses); 1614 } else { 1615 // When multicast forwarding is disabled, set both upstream and downstream 1616 // forwarding config to FORWARD_NONE. 1617 upstreamMulticastRoutingConfig = CONFIG_FORWARD_NONE; 1618 downstreamMulticastRoutingConfig = CONFIG_FORWARD_NONE; 1619 } 1620 1621 if (upstreamMulticastRoutingConfig.equals(mUpstreamMulticastRoutingConfig) 1622 && downstreamMulticastRoutingConfig.equals(mDownstreamMulticastRoutingConfig)) { 1623 return; 1624 } 1625 1626 mUpstreamMulticastRoutingConfig = upstreamMulticastRoutingConfig; 1627 mDownstreamMulticastRoutingConfig = downstreamMulticastRoutingConfig; 1628 sendLocalNetworkConfig(); 1629 } 1630 1631 private MulticastRoutingConfig buildDownstreamMulticastRoutingConfigSelected( 1632 List<String> listeningAddresses) { 1633 MulticastRoutingConfig.Builder builder = 1634 new MulticastRoutingConfig.Builder(FORWARD_SELECTED); 1635 for (String addressStr : listeningAddresses) { 1636 Inet6Address address = (Inet6Address) InetAddresses.parseNumericAddress(addressStr); 1637 builder.addListeningAddress(address); 1638 } 1639 return builder.build(); 1640 } 1641 1642 private static InfraLinkState.Builder newInfraLinkStateBuilder() { 1643 return new InfraLinkState.Builder().setInterfaceName(""); 1644 } 1645 1646 private static InfraLinkState.Builder newInfraLinkStateBuilder( 1647 @Nullable LinkProperties linkProperties) { 1648 if (linkProperties == null) { 1649 return newInfraLinkStateBuilder(); 1650 } 1651 String nat64Prefix = null; 1652 if (linkProperties.getNat64Prefix() != null) { 1653 nat64Prefix = linkProperties.getNat64Prefix().toString(); 1654 } 1655 return new InfraLinkState.Builder() 1656 .setInterfaceName(linkProperties.getInterfaceName()) 1657 .setNat64Prefix(nat64Prefix) 1658 .setDnsServers(addressesToStrings(linkProperties.getDnsServers())); 1659 } 1660 1661 private static List<String> addressesToStrings(List<InetAddress> addresses) { 1662 List<String> strings = new ArrayList<>(); 1663 1664 for (InetAddress address : addresses) { 1665 strings.add(address.getHostAddress()); 1666 } 1667 return strings; 1668 } 1669 1670 private static final class CallbackMetadata { 1671 private static long gId = 0; 1672 1673 // The unique ID 1674 final long id; 1675 1676 final IBinder.DeathRecipient deathRecipient; 1677 1678 final boolean hasThreadPrivilegedPermission; 1679 1680 CallbackMetadata( 1681 IBinder.DeathRecipient deathRecipient, boolean hasThreadPrivilegedPermission) { 1682 this.id = allocId(); 1683 this.deathRecipient = deathRecipient; 1684 this.hasThreadPrivilegedPermission = hasThreadPrivilegedPermission; 1685 } 1686 1687 private static long allocId() { 1688 if (gId == Long.MAX_VALUE) { 1689 gId = 0; 1690 } 1691 return gId++; 1692 } 1693 } 1694 1695 /** An implementation of {@link IOperationReceiver} that simply logs the operation result. */ 1696 private static class LoggingOperationReceiver extends IOperationReceiver.Stub { 1697 private final String mOperation; 1698 1699 LoggingOperationReceiver(String operation) { 1700 mOperation = operation; 1701 } 1702 1703 @Override 1704 public void onSuccess() { 1705 LOG.i("The operation " + mOperation + " succeeded"); 1706 } 1707 1708 @Override 1709 public void onError(int errorCode, String errorMessage) { 1710 LOG.w("The operation " + mOperation + " failed: " + errorCode + " " + errorMessage); 1711 } 1712 } 1713 1714 private static class LoggingOtStatusReceiver extends IOtStatusReceiver.Stub { 1715 private final String mAction; 1716 1717 LoggingOtStatusReceiver(String action) { 1718 mAction = action; 1719 } 1720 1721 @Override 1722 public void onSuccess() { 1723 LOG.i("The action " + mAction + " succeeded"); 1724 } 1725 1726 @Override 1727 public void onError(int i, String s) { 1728 LOG.w("The action " + mAction + " failed: " + i + " " + s); 1729 } 1730 } 1731 1732 /** 1733 * Handles and forwards Thread daemon callbacks. This class must be accessed from the thread of 1734 * {@code mHandler}. 1735 */ 1736 private final class OtDaemonCallbackProxy extends IOtDaemonCallback.Stub { 1737 private final Map<IStateCallback, CallbackMetadata> mStateCallbacks = new HashMap<>(); 1738 private final Map<IOperationalDatasetCallback, CallbackMetadata> mOpDatasetCallbacks = 1739 new HashMap<>(); 1740 1741 private OtDaemonState mState; 1742 private ActiveOperationalDataset mActiveDataset; 1743 private PendingOperationalDataset mPendingDataset; 1744 1745 public void registerStateCallback( 1746 IStateCallback callback, boolean hasThreadPrivilegedPermission) { 1747 checkOnHandlerThread(); 1748 if (mStateCallbacks.containsKey(callback)) { 1749 throw new IllegalStateException("Registering the same IStateCallback twice"); 1750 } 1751 1752 IBinder.DeathRecipient deathRecipient = 1753 () -> mHandler.post(() -> unregisterStateCallback(callback)); 1754 CallbackMetadata callbackMetadata = 1755 new CallbackMetadata(deathRecipient, hasThreadPrivilegedPermission); 1756 mStateCallbacks.put(callback, callbackMetadata); 1757 try { 1758 callback.asBinder().linkToDeath(deathRecipient, 0); 1759 } catch (RemoteException e) { 1760 mStateCallbacks.remove(callback); 1761 // This is thrown when the client is dead, do nothing 1762 } 1763 1764 try { 1765 getOtDaemon().registerStateCallback(this, callbackMetadata.id); 1766 } catch (RemoteException | ThreadNetworkException e) { 1767 LOG.e("otDaemon.registerStateCallback failed", e); 1768 } 1769 } 1770 1771 public void unregisterStateCallback(IStateCallback callback) { 1772 checkOnHandlerThread(); 1773 if (!mStateCallbacks.containsKey(callback)) { 1774 return; 1775 } 1776 callback.asBinder().unlinkToDeath(mStateCallbacks.remove(callback).deathRecipient, 0); 1777 } 1778 1779 public void registerDatasetCallback(IOperationalDatasetCallback callback) { 1780 checkOnHandlerThread(); 1781 if (mOpDatasetCallbacks.containsKey(callback)) { 1782 throw new IllegalStateException( 1783 "Registering the same IOperationalDatasetCallback twice"); 1784 } 1785 1786 IBinder.DeathRecipient deathRecipient = 1787 () -> mHandler.post(() -> unregisterDatasetCallback(callback)); 1788 CallbackMetadata callbackMetadata = 1789 new CallbackMetadata(deathRecipient, true /* hasThreadPrivilegedPermission */); 1790 mOpDatasetCallbacks.put(callback, callbackMetadata); 1791 try { 1792 callback.asBinder().linkToDeath(deathRecipient, 0); 1793 } catch (RemoteException e) { 1794 mOpDatasetCallbacks.remove(callback); 1795 } 1796 1797 try { 1798 getOtDaemon().registerStateCallback(this, callbackMetadata.id); 1799 } catch (RemoteException | ThreadNetworkException e) { 1800 LOG.e("otDaemon.registerStateCallback failed", e); 1801 } 1802 } 1803 1804 public void unregisterDatasetCallback(IOperationalDatasetCallback callback) { 1805 checkOnHandlerThread(); 1806 if (!mOpDatasetCallbacks.containsKey(callback)) { 1807 return; 1808 } 1809 callback.asBinder() 1810 .unlinkToDeath(mOpDatasetCallbacks.remove(callback).deathRecipient, 0); 1811 } 1812 1813 public void onOtDaemonDied() { 1814 checkOnHandlerThread(); 1815 if (mState == null) { 1816 return; 1817 } 1818 1819 final int deviceRole = mState.deviceRole; 1820 mState = null; 1821 1822 // If this device is already STOPPED or DETACHED, do nothing 1823 if (!ThreadNetworkController.isAttached(deviceRole)) { 1824 return; 1825 } 1826 1827 // The Thread device role is considered DETACHED when the OT daemon process is dead 1828 handleDeviceRoleChanged(DEVICE_ROLE_DETACHED); 1829 for (IStateCallback callback : mStateCallbacks.keySet()) { 1830 try { 1831 callback.onDeviceRoleChanged(DEVICE_ROLE_DETACHED); 1832 } catch (RemoteException ignored) { 1833 // do nothing if the client is dead 1834 } 1835 } 1836 mInfraLinkState = newInfraLinkStateBuilder().build(); 1837 } 1838 1839 private void onThreadEnabledChanged(int state, long listenerId) { 1840 checkOnHandlerThread(); 1841 boolean stateChanged = (mState == null || mState.threadEnabled != state); 1842 1843 for (var callbackEntry : mStateCallbacks.entrySet()) { 1844 if (!stateChanged && callbackEntry.getValue().id != listenerId) { 1845 continue; 1846 } 1847 try { 1848 callbackEntry.getKey().onThreadEnableStateChanged(otStateToAndroidState(state)); 1849 } catch (RemoteException ignored) { 1850 // do nothing if the client is dead 1851 } 1852 } 1853 } 1854 1855 private static int otStateToAndroidState(int state) { 1856 switch (state) { 1857 case OT_STATE_ENABLED: 1858 return STATE_ENABLED; 1859 case OT_STATE_DISABLED: 1860 return STATE_DISABLED; 1861 case OT_STATE_DISABLING: 1862 return STATE_DISABLING; 1863 default: 1864 throw new IllegalArgumentException("Unknown ot state " + state); 1865 } 1866 } 1867 1868 @Override 1869 public void onStateChanged(@NonNull OtDaemonState newState, long listenerId) { 1870 mHandler.post(() -> onStateChangedInternal(newState, listenerId)); 1871 } 1872 1873 private void onStateChangedInternal(OtDaemonState newState, long listenerId) { 1874 checkOnHandlerThread(); 1875 1876 onInterfaceStateChanged(newState.isInterfaceUp); 1877 onDeviceRoleChanged(newState.deviceRole, listenerId); 1878 onPartitionIdChanged(newState.partitionId, listenerId); 1879 onThreadEnabledChanged(newState.threadEnabled, listenerId); 1880 onEphemeralKeyStateChanged(newState, listenerId); 1881 mState = newState; 1882 1883 ActiveOperationalDataset newActiveDataset; 1884 try { 1885 if (newState.activeDatasetTlvs.length != 0) { 1886 newActiveDataset = 1887 ActiveOperationalDataset.fromThreadTlvs(newState.activeDatasetTlvs); 1888 } else { 1889 newActiveDataset = null; 1890 } 1891 onActiveOperationalDatasetChanged(newActiveDataset, listenerId); 1892 mActiveDataset = newActiveDataset; 1893 } catch (IllegalArgumentException e) { 1894 // Is unlikely that OT will generate invalid Operational Dataset 1895 LOG.wtf("Invalid Active Operational Dataset from OpenThread", e); 1896 } 1897 1898 PendingOperationalDataset newPendingDataset; 1899 try { 1900 if (newState.pendingDatasetTlvs.length != 0) { 1901 newPendingDataset = 1902 PendingOperationalDataset.fromThreadTlvs(newState.pendingDatasetTlvs); 1903 } else { 1904 newPendingDataset = null; 1905 } 1906 onPendingOperationalDatasetChanged(newPendingDataset, listenerId); 1907 mPendingDataset = newPendingDataset; 1908 } catch (IllegalArgumentException e) { 1909 // Is unlikely that OT will generate invalid Operational Dataset 1910 LOG.wtf("Invalid Pending Operational Dataset from OpenThread", e); 1911 } 1912 } 1913 1914 private void onInterfaceStateChanged(boolean isUp) { 1915 checkOnHandlerThread(); 1916 if (mState == null || mState.isInterfaceUp != isUp) { 1917 handleThreadInterfaceStateChanged(isUp); 1918 } 1919 } 1920 1921 private void onDeviceRoleChanged(@DeviceRole int deviceRole, long listenerId) { 1922 checkOnHandlerThread(); 1923 boolean hasChange = (mState == null || mState.deviceRole != deviceRole); 1924 if (hasChange) { 1925 handleDeviceRoleChanged(deviceRole); 1926 } 1927 1928 for (var callbackEntry : mStateCallbacks.entrySet()) { 1929 if (!hasChange && callbackEntry.getValue().id != listenerId) { 1930 continue; 1931 } 1932 try { 1933 callbackEntry.getKey().onDeviceRoleChanged(deviceRole); 1934 } catch (RemoteException ignored) { 1935 // do nothing if the client is dead 1936 } 1937 } 1938 } 1939 1940 private void onPartitionIdChanged(long partitionId, long listenerId) { 1941 checkOnHandlerThread(); 1942 boolean hasChange = (mState == null || mState.partitionId != partitionId); 1943 1944 for (var callbackEntry : mStateCallbacks.entrySet()) { 1945 if (!hasChange && callbackEntry.getValue().id != listenerId) { 1946 continue; 1947 } 1948 try { 1949 callbackEntry.getKey().onPartitionIdChanged(partitionId); 1950 } catch (RemoteException ignored) { 1951 // do nothing if the client is dead 1952 } 1953 } 1954 } 1955 1956 private void onEphemeralKeyStateChanged(OtDaemonState newState, long listenerId) { 1957 checkOnHandlerThread(); 1958 boolean hasChange = isEphemeralKeyStateChanged(mState, newState); 1959 1960 for (var callbackEntry : mStateCallbacks.entrySet()) { 1961 if (!hasChange && callbackEntry.getValue().id != listenerId) { 1962 continue; 1963 } 1964 String passcode = 1965 callbackEntry.getValue().hasThreadPrivilegedPermission 1966 ? newState.ephemeralKeyPasscode 1967 : null; 1968 if (newState.ephemeralKeyState == EPHEMERAL_KEY_DISABLED) { 1969 passcode = null; 1970 } 1971 try { 1972 callbackEntry 1973 .getKey() 1974 .onEphemeralKeyStateChanged( 1975 newState.ephemeralKeyState, 1976 passcode, 1977 newState.ephemeralKeyLifetimeMillis); 1978 } catch (RemoteException ignored) { 1979 // do nothing if the client is dead 1980 } 1981 } 1982 } 1983 1984 private static boolean isEphemeralKeyStateChanged( 1985 OtDaemonState oldState, @NonNull OtDaemonState newState) { 1986 if (oldState == null) return true; 1987 if (oldState.ephemeralKeyState != newState.ephemeralKeyState) return true; 1988 if (oldState.ephemeralKeyState == EPHEMERAL_KEY_DISABLED) return false; 1989 return (!Objects.equals(oldState.ephemeralKeyPasscode, newState.ephemeralKeyPasscode) 1990 || oldState.ephemeralKeyLifetimeMillis != newState.ephemeralKeyLifetimeMillis); 1991 } 1992 1993 private void onActiveOperationalDatasetChanged( 1994 ActiveOperationalDataset activeDataset, long listenerId) { 1995 checkOnHandlerThread(); 1996 boolean hasChange = !Objects.equals(mActiveDataset, activeDataset); 1997 1998 for (var callbackEntry : mOpDatasetCallbacks.entrySet()) { 1999 if (!hasChange && callbackEntry.getValue().id != listenerId) { 2000 continue; 2001 } 2002 try { 2003 callbackEntry.getKey().onActiveOperationalDatasetChanged(activeDataset); 2004 } catch (RemoteException ignored) { 2005 // do nothing if the client is dead 2006 } 2007 } 2008 } 2009 2010 private void onPendingOperationalDatasetChanged( 2011 PendingOperationalDataset pendingDataset, long listenerId) { 2012 checkOnHandlerThread(); 2013 boolean hasChange = !Objects.equals(mPendingDataset, pendingDataset); 2014 for (var callbackEntry : mOpDatasetCallbacks.entrySet()) { 2015 if (!hasChange && callbackEntry.getValue().id != listenerId) { 2016 continue; 2017 } 2018 try { 2019 callbackEntry.getKey().onPendingOperationalDatasetChanged(pendingDataset); 2020 } catch (RemoteException ignored) { 2021 // do nothing if the client is dead 2022 } 2023 } 2024 } 2025 2026 @Override 2027 public void onAddressChanged(List<Ipv6AddressInfo> addressInfoList) { 2028 mHandler.post(() -> handleAddressChanged(addressInfoList)); 2029 } 2030 2031 @Override 2032 public void onBackboneRouterStateChanged(BackboneRouterState state) { 2033 mHandler.post(() -> handleMulticastForwardingChanged(state)); 2034 } 2035 2036 @Override 2037 public void onPrefixChanged(List<OnMeshPrefixConfig> onMeshPrefixConfigList) { 2038 mHandler.post(() -> handlePrefixChanged(onMeshPrefixConfigList)); 2039 } 2040 } 2041 2042 private final class Nat64CidrController extends IIpv4PrefixRequest.Stub { 2043 private static final int RETRY_DELAY_ON_FAILURE_MILLIS = 600_000; // 10 minutes 2044 2045 @Nullable private LinkAddress mNat64Cidr; 2046 2047 @Override 2048 public void onIpv4PrefixConflict(IpPrefix prefix) { 2049 mHandler.post(() -> onIpv4PrefixConflictInternal(prefix)); 2050 } 2051 2052 private void onIpv4PrefixConflictInternal(IpPrefix prefix) { 2053 checkOnHandlerThread(); 2054 2055 LOG.i("Conflict on NAT64 CIDR: " + prefix); 2056 maybeReleaseNat64Cidr(); 2057 maybeUpdateNat64Cidr(); 2058 } 2059 2060 public void maybeUpdateNat64Cidr() { 2061 checkOnHandlerThread(); 2062 2063 if (mPersistentSettings.getConfiguration().isNat64Enabled()) { 2064 maybeRequestNat64Cidr(); 2065 } else { 2066 maybeReleaseNat64Cidr(); 2067 } 2068 try { 2069 getOtDaemon() 2070 .setNat64Cidr( 2071 mNat64Cidr == null ? null : mNat64Cidr.toString(), 2072 new LoggingOtStatusReceiver("setNat64Cidr")); 2073 } catch (RemoteException | ThreadNetworkException e) { 2074 LOG.e("Failed to set NAT64 CIDR at otd-daemon", e); 2075 } 2076 maybeSendLinkProperties(); 2077 } 2078 2079 private void maybeRequestNat64Cidr() { 2080 if (mNat64Cidr != null) { 2081 return; 2082 } 2083 final LinkAddress downstreamAddress = 2084 mRoutingCoordinatorManager.requestDownstreamAddress(this); 2085 if (downstreamAddress == null) { 2086 mHandler.postDelayed(() -> maybeUpdateNat64Cidr(), RETRY_DELAY_ON_FAILURE_MILLIS); 2087 } 2088 mNat64Cidr = downstreamAddress; 2089 LOG.i("Allocated NAT64 CIDR: " + mNat64Cidr); 2090 } 2091 2092 private void maybeReleaseNat64Cidr() { 2093 if (mNat64Cidr == null) { 2094 return; 2095 } 2096 LOG.i("Released NAT64 CIDR: " + mNat64Cidr); 2097 mNat64Cidr = null; 2098 mRoutingCoordinatorManager.releaseDownstream(this); 2099 } 2100 } 2101 } 2102