1 /*
2 * Copyright (c) 2023, The OpenThread Authors.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. Neither the name of the copyright holder nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include <linux/in.h>
30 #define OTBR_LOG_TAG "BINDER"
31
32 #include "android/otdaemon_server.hpp"
33
34 #include <algorithm>
35 #include <net/if.h>
36 #include <random>
37 #include <string.h>
38
39 #include <android/binder_manager.h>
40 #include <android/binder_process.h>
41 #include <openthread/border_agent.h>
42 #include <openthread/border_router.h>
43 #include <openthread/cli.h>
44 #include <openthread/dnssd_server.h>
45 #include <openthread/icmp6.h>
46 #include <openthread/ip6.h>
47 #include <openthread/link.h>
48 #include <openthread/nat64.h>
49 #include <openthread/openthread-system.h>
50 #include <openthread/srp_server.h>
51 #include <openthread/thread_ftd.h>
52 #include <openthread/platform/infra_if.h>
53 #include <openthread/platform/radio.h>
54
55 #include "agent/vendor.hpp"
56 #include "android/android_rcp_host.hpp"
57 #include "android/common_utils.hpp"
58 #include "android/otdaemon_telemetry.hpp"
59 #include "common/code_utils.hpp"
60 #include "host/thread_host.hpp"
61
62 #define BYTE_ARR_END(arr) ((arr) + sizeof(arr))
63
64 namespace otbr {
65
66 namespace vendor {
67
newInstance(Application & aApplication)68 std::shared_ptr<VendorServer> VendorServer::newInstance(Application &aApplication)
69 {
70 return ndk::SharedRefBase::make<Android::OtDaemonServer>(
71 static_cast<otbr::Host::RcpHost &>(aApplication.GetHost()),
72 static_cast<otbr::Android::MdnsPublisher &>(aApplication.GetPublisher()), aApplication.GetBorderAgent(),
73 aApplication.GetAdvertisingProxy(), [&aApplication]() {
74 aApplication.Deinit();
75 aApplication.Init();
76 });
77 }
78
79 } // namespace vendor
80
81 } // namespace otbr
82
83 namespace otbr {
84 namespace Android {
85
86 static const char OTBR_SERVICE_NAME[] = "ot_daemon";
87 static constexpr size_t kMaxIp6Size = 1280;
88
ThreadEnabledStateToString(int enabledState)89 static const char *ThreadEnabledStateToString(int enabledState)
90 {
91 switch (enabledState)
92 {
93 case IOtDaemon::OT_STATE_ENABLED:
94 return "ENABLED";
95 case IOtDaemon::OT_STATE_DISABLED:
96 return "DISABLED";
97 case IOtDaemon::OT_STATE_DISABLING:
98 return "DISABLING";
99 default:
100 assert(false);
101 return "UNKNOWN";
102 }
103 }
104
105 OtDaemonServer *OtDaemonServer::sOtDaemonServer = nullptr;
106
OtDaemonServer(otbr::Host::RcpHost & aRcpHost,otbr::Mdns::Publisher & aMdnsPublisher,otbr::BorderAgent & aBorderAgent,otbr::AdvertisingProxy & aAdvProxy,ResetThreadHandler aResetThreadHandler)107 OtDaemonServer::OtDaemonServer(otbr::Host::RcpHost &aRcpHost,
108 otbr::Mdns::Publisher &aMdnsPublisher,
109 otbr::BorderAgent &aBorderAgent,
110 otbr::AdvertisingProxy &aAdvProxy,
111 ResetThreadHandler aResetThreadHandler)
112 : mHost(aRcpHost)
113 , mAndroidHost(CreateAndroidHost())
114 , mMdnsPublisher(static_cast<MdnsPublisher &>(aMdnsPublisher))
115 , mBorderAgent(aBorderAgent)
116 , mAdvProxy(aAdvProxy)
117 , mResetThreadHandler(aResetThreadHandler)
118 {
119 mClientDeathRecipient =
120 ::ndk::ScopedAIBinder_DeathRecipient(AIBinder_DeathRecipient_new(&OtDaemonServer::BinderDeathCallback));
121 sOtDaemonServer = this;
122 }
123
Init(void)124 void OtDaemonServer::Init(void)
125 {
126 binder_exception_t exp = AServiceManager_registerLazyService(asBinder().get(), OTBR_SERVICE_NAME);
127 SuccessOrDie(exp, "Failed to register OT daemon binder service");
128
129 assert(GetOtInstance() != nullptr);
130
131 mHost.AddThreadStateChangedCallback([this](otChangedFlags aFlags) { StateCallback(aFlags); });
132 otIp6SetAddressCallback(GetOtInstance(), OtDaemonServer::AddressCallback, this);
133 otIp6SetReceiveCallback(GetOtInstance(), OtDaemonServer::ReceiveCallback, this);
134 otBackboneRouterSetMulticastListenerCallback(GetOtInstance(), OtDaemonServer::HandleBackboneMulticastListenerEvent,
135 this);
136 otIcmp6SetEchoMode(GetOtInstance(), OT_ICMP6_ECHO_HANDLER_DISABLED);
137 otIp6SetReceiveFilterEnabled(GetOtInstance(), true);
138 otNat64SetReceiveIp4Callback(GetOtInstance(), &OtDaemonServer::ReceiveCallback, this);
139 mBorderAgent.AddEphemeralKeyChangedCallback([this]() { HandleEpskcStateChanged(); });
140 mBorderAgent.SetEphemeralKeyEnabled(true);
141 otSysUpstreamDnsServerSetResolvConfEnabled(false);
142
143 mTaskRunner.Post(kTelemetryCheckInterval, [this]() { PushTelemetryIfConditionMatch(); });
144 }
145
BinderDeathCallback(void * aBinderServer)146 void OtDaemonServer::BinderDeathCallback(void *aBinderServer)
147 {
148 OtDaemonServer *thisServer = static_cast<OtDaemonServer *>(aBinderServer);
149
150 otbrLogCrit("system_server is dead, removing configs and callbacks...");
151
152 thisServer->mMeshcopTxts = {};
153 thisServer->mINsdPublisher = nullptr;
154
155 // Note that the INsdPublisher reference is held in MdnsPublisher
156 thisServer->mMdnsPublisher.SetINsdPublisher(nullptr);
157
158 thisServer->mCallback = nullptr;
159 thisServer->mTunFd.set(-1); // the original FD will be closed automatically
160 }
161
StateCallback(otChangedFlags aFlags)162 void OtDaemonServer::StateCallback(otChangedFlags aFlags)
163 {
164 std::vector<OnMeshPrefixConfig> onMeshPrefixes;
165
166 assert(GetOtInstance() != nullptr);
167
168 if (RefreshOtDaemonState(aFlags))
169 {
170 if (mCallback == nullptr)
171 {
172 otbrLogWarning("Ignoring OT state changes: callback is not set");
173 }
174 else
175 {
176 NotifyStateChanged(/* aListenerId*/ -1);
177 }
178 }
179
180 if (aFlags & OT_CHANGED_THREAD_BACKBONE_ROUTER_STATE)
181 {
182 if (mCallback == nullptr)
183 {
184 otbrLogWarning("Ignoring OT backbone router state changes: callback is not set");
185 }
186 else
187 {
188 mCallback->onBackboneRouterStateChanged(GetBackboneRouterState());
189 }
190 }
191
192 if ((aFlags & OT_CHANGED_THREAD_NETDATA) && RefreshOnMeshPrefixes())
193 {
194 if (mCallback == nullptr)
195 {
196 otbrLogWarning("Ignoring OT netdata changes: callback is not set");
197 }
198 else
199 {
200 onMeshPrefixes.assign(mOnMeshPrefixes.begin(), mOnMeshPrefixes.end());
201 mCallback->onPrefixChanged(onMeshPrefixes);
202 }
203 }
204 }
205
RefreshOnMeshPrefixes()206 bool OtDaemonServer::RefreshOnMeshPrefixes()
207 {
208 std::set<OnMeshPrefixConfig> onMeshPrefixConfigs;
209 otNetworkDataIterator iterator = OT_NETWORK_DATA_ITERATOR_INIT;
210 otBorderRouterConfig config;
211 bool rv = false;
212
213 VerifyOrExit(GetOtInstance() != nullptr, otbrLogWarning("Can't get on mesh prefixes: OT is not initialized"));
214
215 while (otNetDataGetNextOnMeshPrefix(GetOtInstance(), &iterator, &config) == OT_ERROR_NONE)
216 {
217 OnMeshPrefixConfig onMeshPrefixConfig;
218
219 onMeshPrefixConfig.prefix.assign(std::begin(config.mPrefix.mPrefix.mFields.m8),
220 std::end(config.mPrefix.mPrefix.mFields.m8));
221 onMeshPrefixConfig.prefixLength = config.mPrefix.mLength;
222 onMeshPrefixConfigs.insert(onMeshPrefixConfig);
223 }
224
225 if (mOnMeshPrefixes != onMeshPrefixConfigs)
226 {
227 mOnMeshPrefixes = std::move(onMeshPrefixConfigs);
228 rv = true;
229 }
230 exit:
231 return rv;
232 }
233
ConvertToAddressInfo(const otNetifAddress & aAddress)234 Ipv6AddressInfo OtDaemonServer::ConvertToAddressInfo(const otNetifAddress &aAddress)
235 {
236 Ipv6AddressInfo addrInfo;
237 otIp6Prefix addressPrefix{aAddress.mAddress, aAddress.mPrefixLength};
238
239 addrInfo.address.assign(std::begin(aAddress.mAddress.mFields.m8), std::end(aAddress.mAddress.mFields.m8));
240 addrInfo.prefixLength = aAddress.mPrefixLength;
241 addrInfo.isPreferred = aAddress.mPreferred;
242 addrInfo.isMeshLocal = aAddress.mMeshLocal;
243 addrInfo.isMeshLocalEid =
244 (memcmp(&aAddress.mAddress, otThreadGetMeshLocalEid(GetOtInstance()), sizeof(aAddress.mAddress)) == 0);
245 addrInfo.isActiveOmr = otNetDataContainsOmrPrefix(GetOtInstance(), &addressPrefix);
246 return addrInfo;
247 }
248
ConvertToAddressInfo(const otNetifMulticastAddress & aAddress)249 Ipv6AddressInfo OtDaemonServer::ConvertToAddressInfo(const otNetifMulticastAddress &aAddress)
250 {
251 Ipv6AddressInfo addrInfo;
252
253 addrInfo.address.assign(std::begin(aAddress.mAddress.mFields.m8), std::end(aAddress.mAddress.mFields.m8));
254 return addrInfo;
255 }
256
AddressCallback(const otIp6AddressInfo * aAddressInfo,bool aIsAdded,void * aBinderServer)257 void OtDaemonServer::AddressCallback(const otIp6AddressInfo *aAddressInfo, bool aIsAdded, void *aBinderServer)
258 {
259 OT_UNUSED_VARIABLE(aAddressInfo);
260 OT_UNUSED_VARIABLE(aIsAdded);
261 OtDaemonServer *thisServer = static_cast<OtDaemonServer *>(aBinderServer);
262 std::vector<Ipv6AddressInfo> addrInfoList;
263 const otNetifAddress *unicastAddrs = otIp6GetUnicastAddresses(thisServer->GetOtInstance());
264 const otNetifMulticastAddress *multicastAddrs = otIp6GetMulticastAddresses(thisServer->GetOtInstance());
265
266 for (const otNetifAddress *addr = unicastAddrs; addr != nullptr; addr = addr->mNext)
267 {
268 addrInfoList.push_back(thisServer->ConvertToAddressInfo(*addr));
269 }
270 for (const otNetifMulticastAddress *maddr = multicastAddrs; maddr != nullptr; maddr = maddr->mNext)
271 {
272 addrInfoList.push_back(thisServer->ConvertToAddressInfo(*maddr));
273 }
274 if (thisServer->mCallback != nullptr)
275 {
276 thisServer->mCallback->onAddressChanged(addrInfoList);
277 }
278 else
279 {
280 otbrLogWarning("OT daemon callback is not set");
281 }
282 }
283
ReceiveCallback(otMessage * aMessage,void * aBinderServer)284 void OtDaemonServer::ReceiveCallback(otMessage *aMessage, void *aBinderServer)
285 {
286 static_cast<OtDaemonServer *>(aBinderServer)->ReceiveCallback(aMessage);
287 }
288
289 // TODO: b/291053118 - We should reuse the same code in openthread/src/posix/platform/netif.cpp
ReceiveCallback(otMessage * aMessage)290 void OtDaemonServer::ReceiveCallback(otMessage *aMessage)
291 {
292 char packet[kMaxIp6Size];
293 uint16_t length = otMessageGetLength(aMessage);
294 int fd = mTunFd.get();
295
296 VerifyOrExit(fd != -1, otbrLogWarning("Ignoring egress packet: invalid tunnel FD"));
297
298 if (otMessageRead(aMessage, 0, packet, sizeof(packet)) != length)
299 {
300 otbrLogWarning("Failed to read packet from otMessage");
301 ExitNow();
302 }
303
304 if (write(fd, packet, length) != length)
305 {
306 otbrLogWarning("Failed to send packet over tunnel interface: %s", strerror(errno));
307 }
308
309 exit:
310 otMessageFree(aMessage);
311 }
312
313 static constexpr uint8_t kIpVersion4 = 4;
314 static constexpr uint8_t kIpVersion6 = 6;
315
316 // TODO: b/291053118 - We should reuse the same code in openthread/src/posix/platform/netif.cpp
getIpVersion(const uint8_t * data)317 static uint8_t getIpVersion(const uint8_t *data)
318 {
319 assert(data != nullptr);
320
321 // Mute compiler warnings.
322 OT_UNUSED_VARIABLE(kIpVersion4);
323 OT_UNUSED_VARIABLE(kIpVersion6);
324
325 return (static_cast<uint8_t>(data[0]) >> 4) & 0x0F;
326 }
327
328 // TODO: b/291053118 - we should use a shared library with ot-posix to handle packet translations
329 // between the tunnel interface and Thread.
TransmitCallback(void)330 void OtDaemonServer::TransmitCallback(void)
331 {
332 char packet[kMaxIp6Size];
333 ssize_t length;
334 otMessage *message = nullptr;
335 otError error = OT_ERROR_NONE;
336 otMessageSettings settings;
337 int fd = mTunFd.get();
338 bool isIp4;
339
340 assert(GetOtInstance() != nullptr);
341
342 VerifyOrExit(fd != -1);
343
344 length = read(fd, packet, sizeof(packet));
345
346 if (length == -1)
347 {
348 otbrLogWarning("Failed to read packet from tunnel interface: %s", strerror(errno));
349 ExitNow();
350 }
351 else if (length == 0)
352 {
353 otbrLogWarning("Unexpected EOF on the tunnel FD");
354 ExitNow();
355 }
356
357 VerifyOrExit(GetOtInstance() != nullptr, otbrLogWarning("Ignoring tunnel packet: OT is not initialized"));
358
359 settings.mLinkSecurityEnabled = (otThreadGetDeviceRole(GetOtInstance()) != OT_DEVICE_ROLE_DISABLED);
360 settings.mPriority = OT_MESSAGE_PRIORITY_LOW;
361
362 isIp4 = (getIpVersion(reinterpret_cast<uint8_t *>(packet)) == kIpVersion4);
363 message = isIp4 ? otIp4NewMessage(GetOtInstance(), &settings) : otIp6NewMessage(GetOtInstance(), &settings);
364 VerifyOrExit(message != nullptr, error = OT_ERROR_NO_BUFS);
365 otMessageSetOrigin(message, OT_MESSAGE_ORIGIN_HOST_UNTRUSTED);
366
367 SuccessOrExit(error = otMessageAppend(message, packet, static_cast<uint16_t>(length)));
368
369 error = isIp4 ? otNat64Send(GetOtInstance(), message) : otIp6Send(GetOtInstance(), message);
370 message = nullptr;
371
372 exit:
373 if (message != nullptr)
374 {
375 otMessageFree(message);
376 }
377
378 if (error != OT_ERROR_NONE)
379 {
380 if (error == OT_ERROR_DROP)
381 {
382 otbrLogInfo("Dropped tunnel packet (length=%d)", length);
383 }
384 else
385 {
386 otbrLogWarning("Failed to transmit tunnel packet: %s", otThreadErrorToString(error));
387 }
388 }
389 }
390
HandleEpskcStateChanged(void * aBinderServer)391 void OtDaemonServer::HandleEpskcStateChanged(void *aBinderServer)
392 {
393 static_cast<OtDaemonServer *>(aBinderServer)->HandleEpskcStateChanged();
394 }
395
HandleEpskcStateChanged(void)396 void OtDaemonServer::HandleEpskcStateChanged(void)
397 {
398 mState.ephemeralKeyState = GetEphemeralKeyState();
399 if (mState.ephemeralKeyState == OT_EPHEMERAL_KEY_DISABLED)
400 {
401 mState.ephemeralKeyLifetimeMillis = 0;
402 }
403 else
404 {
405 mState.ephemeralKeyLifetimeMillis =
406 mEphemeralKeyExpiryMillis -
407 std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch())
408 .count();
409 }
410
411 NotifyStateChanged(/* aListenerId*/ -1);
412 }
413
NotifyStateChanged(int64_t aListenerId)414 void OtDaemonServer::NotifyStateChanged(int64_t aListenerId)
415 {
416 if (mCallback != nullptr)
417 {
418 mCallback->onStateChanged(mState, aListenerId);
419 }
420 }
421
GetEphemeralKeyState(void)422 int OtDaemonServer::GetEphemeralKeyState(void)
423 {
424 int ephemeralKeyState;
425
426 switch (otBorderAgentEphemeralKeyGetState(GetOtInstance()))
427 {
428 case OT_BORDER_AGENT_STATE_STARTED:
429 ephemeralKeyState = OT_EPHEMERAL_KEY_ENABLED;
430 break;
431 case OT_BORDER_AGENT_STATE_CONNECTED:
432 case OT_BORDER_AGENT_STATE_ACCEPTED:
433 ephemeralKeyState = OT_EPHEMERAL_KEY_IN_USE;
434 break;
435 case OT_BORDER_AGENT_STATE_DISABLED:
436 case OT_BORDER_AGENT_STATE_STOPPED:
437 ephemeralKeyState = OT_EPHEMERAL_KEY_DISABLED;
438 break;
439 }
440
441 return ephemeralKeyState;
442 }
443
GetBackboneRouterState()444 BackboneRouterState OtDaemonServer::GetBackboneRouterState()
445 {
446 BackboneRouterState state;
447 otBackboneRouterState bbrState;
448 otBackboneRouterMulticastListenerInfo info;
449 otBackboneRouterMulticastListenerIterator iter = OT_BACKBONE_ROUTER_MULTICAST_LISTENER_ITERATOR_INIT;
450 state.listeningAddresses = std::vector<std::string>();
451
452 VerifyOrExit(GetOtInstance() != nullptr, otbrLogWarning("Can't get bbr state: OT is not initialized"));
453
454 bbrState = otBackboneRouterGetState(GetOtInstance());
455 switch (bbrState)
456 {
457 case OT_BACKBONE_ROUTER_STATE_DISABLED:
458 case OT_BACKBONE_ROUTER_STATE_SECONDARY:
459 state.multicastForwardingEnabled = false;
460 break;
461 case OT_BACKBONE_ROUTER_STATE_PRIMARY:
462 state.multicastForwardingEnabled = true;
463 break;
464 }
465
466 while (otBackboneRouterMulticastListenerGetNext(GetOtInstance(), &iter, &info) == OT_ERROR_NONE)
467 {
468 char string[OT_IP6_ADDRESS_STRING_SIZE];
469
470 otIp6AddressToString(&info.mAddress, string, sizeof(string));
471 state.listeningAddresses.push_back(string);
472 }
473
474 exit:
475 return state;
476 }
477
HandleBackboneMulticastListenerEvent(void * aBinderServer,otBackboneRouterMulticastListenerEvent aEvent,const otIp6Address * aAddress)478 void OtDaemonServer::HandleBackboneMulticastListenerEvent(void *aBinderServer,
479 otBackboneRouterMulticastListenerEvent aEvent,
480 const otIp6Address *aAddress)
481 {
482 OtDaemonServer *thisServer = static_cast<OtDaemonServer *>(aBinderServer);
483 char addressString[OT_IP6_ADDRESS_STRING_SIZE];
484
485 otIp6AddressToString(aAddress, addressString, sizeof(addressString));
486
487 otbrLogInfo("Multicast forwarding address changed, %s is %s", addressString,
488 (aEvent == OT_BACKBONE_ROUTER_MULTICAST_LISTENER_ADDED) ? "added" : "removed");
489
490 if (thisServer->mCallback == nullptr)
491 {
492 otbrLogWarning("Ignoring OT multicast listener event: callback is not set");
493 ExitNow();
494 }
495 thisServer->mCallback->onBackboneRouterStateChanged(thisServer->GetBackboneRouterState());
496
497 exit:
498 return;
499 }
500
GetOtInstance()501 otInstance *OtDaemonServer::GetOtInstance()
502 {
503 return mHost.GetInstance();
504 }
505
Update(MainloopContext & aMainloop)506 void OtDaemonServer::Update(MainloopContext &aMainloop)
507 {
508 int fd = mTunFd.get();
509
510 if (fd != -1)
511 {
512 FD_SET(fd, &aMainloop.mReadFdSet);
513 aMainloop.mMaxFd = std::max(aMainloop.mMaxFd, fd);
514 }
515 }
516
Process(const MainloopContext & aMainloop)517 void OtDaemonServer::Process(const MainloopContext &aMainloop)
518 {
519 int fd = mTunFd.get();
520
521 if (fd != -1 && FD_ISSET(fd, &aMainloop.mReadFdSet))
522 {
523 TransmitCallback();
524 }
525 }
526
CreateAndroidHost(void)527 std::unique_ptr<AndroidThreadHost> OtDaemonServer::CreateAndroidHost(void)
528 {
529 std::unique_ptr<AndroidThreadHost> host;
530
531 switch (mHost.GetCoprocessorType())
532 {
533 case OT_COPROCESSOR_RCP:
534 host = std::make_unique<AndroidRcpHost>(static_cast<otbr::Host::RcpHost &>(mHost));
535 break;
536
537 case OT_COPROCESSOR_NCP:
538 default:
539 DieNow("Unknown coprocessor type!");
540 break;
541 }
542
543 return host;
544 }
545
initialize(const bool aEnabled,const OtDaemonConfiguration & aConfiguration,const ScopedFileDescriptor & aTunFd,const std::shared_ptr<INsdPublisher> & aINsdPublisher,const MeshcopTxtAttributes & aMeshcopTxts,const std::string & aCountryCode,const bool aTrelEnabled,const std::shared_ptr<IOtDaemonCallback> & aCallback)546 Status OtDaemonServer::initialize(const bool aEnabled,
547 const OtDaemonConfiguration &aConfiguration,
548 const ScopedFileDescriptor &aTunFd,
549 const std::shared_ptr<INsdPublisher> &aINsdPublisher,
550 const MeshcopTxtAttributes &aMeshcopTxts,
551 const std::string &aCountryCode,
552 const bool aTrelEnabled,
553 const std::shared_ptr<IOtDaemonCallback> &aCallback)
554 {
555 otbrLogInfo("OT daemon is initialized by system server (enabled=%s, tunFd=%d)", (aEnabled ? "true" : "false"),
556 aTunFd.get());
557
558 // The copy constructor of `ScopedFileDescriptor` is deleted. It is unable to pass the `aTunFd`
559 // to the lambda function. The processing method of `aTunFd` doesn't call OpenThread functions,
560 // we can process `aTunFd` directly in front of the task.
561 mTunFd = aTunFd.dup();
562
563 mINsdPublisher = aINsdPublisher;
564 mMeshcopTxts = aMeshcopTxts;
565
566 mTaskRunner.Post(
567 [aEnabled, aConfiguration, aINsdPublisher, aMeshcopTxts, aCallback, aCountryCode, aTrelEnabled, this]() {
568 initializeInternal(aEnabled, aConfiguration, mINsdPublisher, mMeshcopTxts, aCountryCode, aTrelEnabled,
569 aCallback);
570 });
571
572 return Status::ok();
573 }
574
initializeInternal(const bool aEnabled,const OtDaemonConfiguration & aConfiguration,const std::shared_ptr<INsdPublisher> & aINsdPublisher,const MeshcopTxtAttributes & aMeshcopTxts,const std::string & aCountryCode,const bool aTrelEnabled,const std::shared_ptr<IOtDaemonCallback> & aCallback)575 void OtDaemonServer::initializeInternal(const bool aEnabled,
576 const OtDaemonConfiguration &aConfiguration,
577 const std::shared_ptr<INsdPublisher> &aINsdPublisher,
578 const MeshcopTxtAttributes &aMeshcopTxts,
579 const std::string &aCountryCode,
580 const bool aTrelEnabled,
581 const std::shared_ptr<IOtDaemonCallback> &aCallback)
582 {
583 std::string instanceName = aMeshcopTxts.vendorName + " " + aMeshcopTxts.modelName;
584 Mdns::Publisher::TxtList nonStandardTxts;
585 otbrError error;
586
587 mAndroidHost->SetConfiguration(aConfiguration, nullptr /* aReceiver */);
588
589 if (aConfiguration.countryCodeEnabled)
590 {
591 setCountryCodeInternal(aCountryCode, nullptr /* aReceiver */);
592 }
593 registerStateCallbackInternal(aCallback, -1 /* listenerId */);
594
595 mMdnsPublisher.SetINsdPublisher(aINsdPublisher);
596 mAdvProxy.SetAllowMlEid(!aConfiguration.borderRouterEnabled);
597
598 for (const auto &txtAttr : aMeshcopTxts.nonStandardTxtEntries)
599 {
600 nonStandardTxts.emplace_back(txtAttr.name.c_str(), txtAttr.value.data(), txtAttr.value.size());
601 }
602 error = mBorderAgent.SetMeshCopServiceValues(instanceName, aMeshcopTxts.modelName, aMeshcopTxts.vendorName,
603 aMeshcopTxts.vendorOui, nonStandardTxts);
604 if (error != OTBR_ERROR_NONE)
605 {
606 otbrLogCrit("Failed to set MeshCoP values: %d", static_cast<int>(error));
607 }
608
609 mBorderAgent.SetEnabled(aEnabled && aConfiguration.borderRouterEnabled);
610 mAndroidHost->SetTrelEnabled(aTrelEnabled);
611 mTrelEnabled = aTrelEnabled;
612
613 if (aEnabled)
614 {
615 EnableThread(nullptr /* aReceiver */);
616 }
617 else
618 {
619 UpdateThreadEnabledState(OT_STATE_DISABLED, nullptr /* aReceiver */);
620 }
621 }
622
terminate(void)623 Status OtDaemonServer::terminate(void)
624 {
625 mTaskRunner.Post([]() {
626 otbrLogWarning("Terminating ot-daemon process...");
627 exit(0);
628 });
629 return Status::ok();
630 }
631
UpdateThreadEnabledState(const int enabled,const std::shared_ptr<IOtStatusReceiver> & aReceiver)632 void OtDaemonServer::UpdateThreadEnabledState(const int enabled, const std::shared_ptr<IOtStatusReceiver> &aReceiver)
633 {
634 VerifyOrExit(enabled != mState.threadEnabled);
635
636 otbrLogInfo("Thread enabled state changed: %s -> %s", ThreadEnabledStateToString(mState.threadEnabled),
637 ThreadEnabledStateToString(enabled));
638 mState.threadEnabled = enabled;
639
640 if (aReceiver != nullptr)
641 {
642 aReceiver->onSuccess();
643 }
644
645 // Enables the BorderAgent module only when Thread is enabled and configured a Border Router,
646 // so that it won't publish the MeshCoP mDNS service when unnecessary
647 // TODO: b/376217403 - enables / disables OT Border Agent at runtime
648 mBorderAgent.SetEnabled(enabled == OT_STATE_ENABLED && mAndroidHost->GetConfiguration().borderRouterEnabled);
649
650 NotifyStateChanged(/* aListenerId*/ -1);
651
652 exit:
653 return;
654 }
655
EnableThread(const std::shared_ptr<IOtStatusReceiver> & aReceiver)656 void OtDaemonServer::EnableThread(const std::shared_ptr<IOtStatusReceiver> &aReceiver)
657 {
658 otOperationalDatasetTlvs datasetTlvs;
659
660 if ((mAndroidHost->GetConfiguration().borderRouterEnabled &&
661 mAndroidHost->GetConfiguration().borderRouterAutoJoinEnabled) &&
662 (otDatasetGetActiveTlvs(GetOtInstance(), &datasetTlvs) != OT_ERROR_NOT_FOUND && datasetTlvs.mLength > 0) &&
663 !isAttached())
664 {
665 (void)otIp6SetEnabled(GetOtInstance(), true);
666 (void)otThreadSetEnabled(GetOtInstance(), true);
667 }
668 UpdateThreadEnabledState(OT_STATE_ENABLED, aReceiver);
669 }
670
setThreadEnabled(const bool aEnabled,const std::shared_ptr<IOtStatusReceiver> & aReceiver)671 Status OtDaemonServer::setThreadEnabled(const bool aEnabled, const std::shared_ptr<IOtStatusReceiver> &aReceiver)
672 {
673 mTaskRunner.Post([aEnabled, aReceiver, this]() { setThreadEnabledInternal(aEnabled, aReceiver); });
674
675 return Status::ok();
676 }
677
setThreadEnabledInternal(const bool aEnabled,const std::shared_ptr<IOtStatusReceiver> & aReceiver)678 void OtDaemonServer::setThreadEnabledInternal(const bool aEnabled, const std::shared_ptr<IOtStatusReceiver> &aReceiver)
679 {
680 int error = OT_ERROR_NONE;
681 std::string message;
682
683 VerifyOrExit(GetOtInstance() != nullptr, error = OT_ERROR_INVALID_STATE, message = "OT is not initialized");
684
685 VerifyOrExit(mState.threadEnabled != OT_STATE_DISABLING, error = OT_ERROR_BUSY, message = "Thread is disabling");
686
687 if ((mState.threadEnabled == OT_STATE_ENABLED) == aEnabled)
688 {
689 aReceiver->onSuccess();
690 ExitNow();
691 }
692
693 if (aEnabled)
694 {
695 EnableThread(aReceiver);
696 }
697 else
698 {
699 // `aReceiver` should not be set here because the operation isn't finished yet
700 UpdateThreadEnabledState(OT_STATE_DISABLING, nullptr /* aReceiver */);
701
702 LeaveGracefully(false /* aEraseDataset */, "disableThread", [aReceiver, this]() {
703 // Ignore errors as those operations should always succeed
704 (void)otThreadSetEnabled(GetOtInstance(), false);
705 (void)otIp6SetEnabled(GetOtInstance(), false);
706 UpdateThreadEnabledState(OT_STATE_DISABLED, aReceiver);
707 });
708 }
709
710 exit:
711 if (error != OT_ERROR_NONE)
712 {
713 PropagateResult(error, message, aReceiver);
714 }
715 }
716
activateEphemeralKeyMode(const int64_t aLifetimeMillis,const std::shared_ptr<IOtStatusReceiver> & aReceiver)717 Status OtDaemonServer::activateEphemeralKeyMode(const int64_t aLifetimeMillis,
718 const std::shared_ptr<IOtStatusReceiver> &aReceiver)
719 {
720 mTaskRunner.Post(
721 [aLifetimeMillis, aReceiver, this]() { activateEphemeralKeyModeInternal(aLifetimeMillis, aReceiver); });
722
723 return Status::ok();
724 }
725
activateEphemeralKeyModeInternal(const int64_t aLifetimeMillis,const std::shared_ptr<IOtStatusReceiver> & aReceiver)726 void OtDaemonServer::activateEphemeralKeyModeInternal(const int64_t aLifetimeMillis,
727 const std::shared_ptr<IOtStatusReceiver> &aReceiver)
728 {
729 int error = OT_ERROR_NONE;
730 std::string message;
731 std::string passcode;
732
733 VerifyOrExit(GetOtInstance() != nullptr, error = OT_ERROR_INVALID_STATE, message = "OT is not initialized");
734 VerifyOrExit(isAttached(), error = static_cast<int>(IOtDaemon::ErrorCode::OT_ERROR_FAILED_PRECONDITION),
735 message = "Cannot activate ephemeral key mode when this device is not attached to Thread network");
736 VerifyOrExit(otBorderAgentEphemeralKeyGetState(GetOtInstance()) != OT_BORDER_AGENT_STATE_DISABLED,
737 error = OT_ERROR_INVALID_STATE, message = "ephemeral key manager is disabled");
738 VerifyOrExit(otBorderAgentEphemeralKeyGetState(GetOtInstance()) == OT_BORDER_AGENT_STATE_STOPPED,
739 error = OT_ERROR_BUSY, message = "ephemeral key mode is already activated");
740
741 otbrLogInfo("Activating ephemeral key mode with %lldms lifetime.", aLifetimeMillis);
742
743 SuccessOrExit(error = mBorderAgent.CreateEphemeralKey(passcode), message = "Failed to create ephemeral key");
744 SuccessOrExit(error = otBorderAgentEphemeralKeyStart(GetOtInstance(), passcode.c_str(),
745 static_cast<uint32_t>(aLifetimeMillis), 0 /* aUdpPort */),
746 message = "Failed to set ephemeral key");
747
748 exit:
749 if (aReceiver != nullptr)
750 {
751 if (error == OT_ERROR_NONE)
752 {
753 mState.ephemeralKeyState = GetEphemeralKeyState();
754 mState.ephemeralKeyPasscode = passcode;
755 mState.ephemeralKeyLifetimeMillis = aLifetimeMillis;
756 mEphemeralKeyExpiryMillis = std::chrono::duration_cast<std::chrono::milliseconds>(
757 std::chrono::steady_clock::now().time_since_epoch())
758 .count() +
759 aLifetimeMillis;
760 aReceiver->onSuccess();
761 }
762 else
763 {
764 aReceiver->onError(error, message);
765 }
766 }
767 }
768
deactivateEphemeralKeyMode(const std::shared_ptr<IOtStatusReceiver> & aReceiver)769 Status OtDaemonServer::deactivateEphemeralKeyMode(const std::shared_ptr<IOtStatusReceiver> &aReceiver)
770 {
771 mTaskRunner.Post([aReceiver, this]() { deactivateEphemeralKeyModeInternal(aReceiver); });
772
773 return Status::ok();
774 }
775
deactivateEphemeralKeyModeInternal(const std::shared_ptr<IOtStatusReceiver> & aReceiver)776 void OtDaemonServer::deactivateEphemeralKeyModeInternal(const std::shared_ptr<IOtStatusReceiver> &aReceiver)
777 {
778 int error = OT_ERROR_NONE;
779 std::string message;
780
781 VerifyOrExit(GetOtInstance() != nullptr, error = OT_ERROR_INVALID_STATE, message = "OT is not initialized");
782 otbrLogInfo("Deactivating ephemeral key mode.");
783
784 VerifyOrExit(otBorderAgentEphemeralKeyGetState(GetOtInstance()) != OT_BORDER_AGENT_STATE_DISABLED &&
785 otBorderAgentEphemeralKeyGetState(GetOtInstance()) != OT_BORDER_AGENT_STATE_STOPPED,
786 error = OT_ERROR_NONE);
787
788 otBorderAgentEphemeralKeyStop(GetOtInstance());
789
790 exit:
791 PropagateResult(error, message, aReceiver);
792 }
793
registerStateCallback(const std::shared_ptr<IOtDaemonCallback> & aCallback,int64_t aListenerId)794 Status OtDaemonServer::registerStateCallback(const std::shared_ptr<IOtDaemonCallback> &aCallback, int64_t aListenerId)
795 {
796 mTaskRunner.Post([aCallback, aListenerId, this]() { registerStateCallbackInternal(aCallback, aListenerId); });
797
798 return Status::ok();
799 }
800
registerStateCallbackInternal(const std::shared_ptr<IOtDaemonCallback> & aCallback,int64_t aListenerId)801 void OtDaemonServer::registerStateCallbackInternal(const std::shared_ptr<IOtDaemonCallback> &aCallback,
802 int64_t aListenerId)
803 {
804 VerifyOrExit(GetOtInstance() != nullptr, otbrLogWarning("OT is not initialized"));
805
806 mCallback = aCallback;
807 if (mCallback != nullptr)
808 {
809 AIBinder_linkToDeath(mCallback->asBinder().get(), mClientDeathRecipient.get(), this);
810 }
811
812 // To ensure that a client app can get the latest correct state immediately when registering a
813 // state callback, here needs to invoke the callback
814 RefreshOtDaemonState(/* aFlags */ 0xffffffff);
815 NotifyStateChanged(aListenerId);
816 mCallback->onBackboneRouterStateChanged(GetBackboneRouterState());
817
818 exit:
819 return;
820 }
821
RefreshOtDaemonState(otChangedFlags aFlags)822 bool OtDaemonServer::RefreshOtDaemonState(otChangedFlags aFlags)
823 {
824 bool haveUpdates = false;
825
826 if (aFlags & OT_CHANGED_THREAD_NETIF_STATE)
827 {
828 mState.isInterfaceUp = mHost.Ip6IsEnabled();
829 haveUpdates = true;
830 }
831
832 if (aFlags & OT_CHANGED_THREAD_ROLE)
833 {
834 mState.deviceRole = mHost.GetDeviceRole();
835 haveUpdates = true;
836 }
837
838 if (aFlags & OT_CHANGED_THREAD_PARTITION_ID)
839 {
840 mState.partitionId = mHost.GetPartitionId();
841 haveUpdates = true;
842 }
843
844 if (aFlags & OT_CHANGED_ACTIVE_DATASET)
845 {
846 otOperationalDatasetTlvs datasetTlvs;
847 mHost.GetDatasetActiveTlvs(datasetTlvs);
848 mState.activeDatasetTlvs.assign(datasetTlvs.mTlvs, datasetTlvs.mTlvs + datasetTlvs.mLength);
849
850 haveUpdates = true;
851 }
852
853 if (aFlags & OT_CHANGED_PENDING_DATASET)
854 {
855 otOperationalDatasetTlvs datasetTlvs;
856 mHost.GetDatasetPendingTlvs(datasetTlvs);
857 mState.pendingDatasetTlvs.assign(datasetTlvs.mTlvs, datasetTlvs.mTlvs + datasetTlvs.mLength);
858
859 haveUpdates = true;
860 }
861
862 if (isAttached() && !mState.activeDatasetTlvs.empty() && mJoinReceiver != nullptr)
863 {
864 otbrLogInfo("Join succeeded");
865 mJoinReceiver->onSuccess();
866 mJoinReceiver = nullptr;
867 }
868
869 return haveUpdates;
870 }
871
872 /**
873 * Returns `true` if the two TLV lists are representing the same Operational Dataset.
874 *
875 * Note this method works even if TLVs in `aLhs` and `aRhs` are not ordered.
876 */
areDatasetsEqual(const otOperationalDatasetTlvs & aLhs,const otOperationalDatasetTlvs & aRhs)877 static bool areDatasetsEqual(const otOperationalDatasetTlvs &aLhs, const otOperationalDatasetTlvs &aRhs)
878 {
879 bool result = false;
880
881 otOperationalDataset lhsDataset;
882 otOperationalDataset rhsDataset;
883 otOperationalDatasetTlvs lhsNormalizedTlvs;
884 otOperationalDatasetTlvs rhsNormalizedTlvs;
885
886 // Sort the TLVs in the TLV byte arrays by leveraging the deterministic nature of the two OT APIs
887 SuccessOrExit(otDatasetParseTlvs(&aLhs, &lhsDataset));
888 SuccessOrExit(otDatasetParseTlvs(&aRhs, &rhsDataset));
889 otDatasetConvertToTlvs(&lhsDataset, &lhsNormalizedTlvs);
890 otDatasetConvertToTlvs(&rhsDataset, &rhsNormalizedTlvs);
891
892 result = (lhsNormalizedTlvs.mLength == rhsNormalizedTlvs.mLength) &&
893 (memcmp(lhsNormalizedTlvs.mTlvs, rhsNormalizedTlvs.mTlvs, lhsNormalizedTlvs.mLength) == 0);
894
895 exit:
896 return result;
897 }
898
join(const std::vector<uint8_t> & aActiveOpDatasetTlvs,const std::shared_ptr<IOtStatusReceiver> & aReceiver)899 Status OtDaemonServer::join(const std::vector<uint8_t> &aActiveOpDatasetTlvs,
900 const std::shared_ptr<IOtStatusReceiver> &aReceiver)
901 {
902 mTaskRunner.Post([aActiveOpDatasetTlvs, aReceiver, this]() { joinInternal(aActiveOpDatasetTlvs, aReceiver); });
903
904 return Status::ok();
905 }
906
joinInternal(const std::vector<uint8_t> & aActiveOpDatasetTlvs,const std::shared_ptr<IOtStatusReceiver> & aReceiver)907 void OtDaemonServer::joinInternal(const std::vector<uint8_t> &aActiveOpDatasetTlvs,
908 const std::shared_ptr<IOtStatusReceiver> &aReceiver)
909 {
910 int error = OT_ERROR_NONE;
911 std::string message;
912 otOperationalDatasetTlvs newDatasetTlvs;
913 otOperationalDatasetTlvs curDatasetTlvs;
914
915 VerifyOrExit(mState.threadEnabled != OT_STATE_DISABLING, error = OT_ERROR_BUSY, message = "Thread is disabling");
916
917 VerifyOrExit(mState.threadEnabled == OT_STATE_ENABLED,
918 error = static_cast<int>(IOtDaemon::ErrorCode::OT_ERROR_THREAD_DISABLED),
919 message = "Thread is disabled");
920
921 otbrLogInfo("Start joining...");
922
923 VerifyOrExit(GetOtInstance() != nullptr, error = OT_ERROR_INVALID_STATE, message = "OT is not initialized");
924
925 std::copy(aActiveOpDatasetTlvs.begin(), aActiveOpDatasetTlvs.end(), newDatasetTlvs.mTlvs);
926 newDatasetTlvs.mLength = static_cast<uint8_t>(aActiveOpDatasetTlvs.size());
927
928 error = otDatasetGetActiveTlvs(GetOtInstance(), &curDatasetTlvs);
929 if (error == OT_ERROR_NONE && areDatasetsEqual(newDatasetTlvs, curDatasetTlvs) && isAttached())
930 {
931 // Do not leave and re-join if this device has already joined the same network.
932 // This can help elimilate unnecessary connectivity and topology disruption and
933 // save the time for re-joining. It's more useful for use cases where Thread
934 // networks are dynamically brought up and torn down (e.g. Thread on mobile phones).
935 aReceiver->onSuccess();
936 ExitNow();
937 }
938
939 // If this device has ever joined a different network, try to leave from previous
940 // network first. Do this even this device role is detached or disabled, this is for
941 // clearing any in-memory state of the previous network.
942 if (error == OT_ERROR_NONE && !areDatasetsEqual(newDatasetTlvs, curDatasetTlvs))
943 {
944 LeaveGracefully(true /* aEraseDataset */, "join",
945 [aActiveOpDatasetTlvs, aReceiver, this]() { join(aActiveOpDatasetTlvs, aReceiver); });
946 ExitNow();
947 }
948
949 SuccessOrExit(error = otDatasetSetActiveTlvs(GetOtInstance(), &newDatasetTlvs),
950 message = "Failed to set Active Operational Dataset");
951
952 // TODO(b/273160198): check how we can implement join as a child
953
954 // Shouldn't we have an equivalent `otThreadAttach` method vs `otThreadDetachGracefully`?
955 SuccessOrExit(error = otIp6SetEnabled(GetOtInstance(), true), message = "Failed to bring up Thread interface");
956 SuccessOrExit(error = otThreadSetEnabled(GetOtInstance(), true), message = "Failed to bring up Thread stack");
957
958 // Abort an ongoing join()
959 if (mJoinReceiver != nullptr)
960 {
961 mJoinReceiver->onError(OT_ERROR_ABORT, "Aborted by a new join()");
962 }
963 mJoinReceiver = aReceiver;
964
965 exit:
966 if (error != OT_ERROR_NONE)
967 {
968 PropagateResult(error, message, aReceiver);
969 }
970 }
971
leave(bool aEraseDataset,const std::shared_ptr<IOtStatusReceiver> & aReceiver)972 Status OtDaemonServer::leave(bool aEraseDataset, const std::shared_ptr<IOtStatusReceiver> &aReceiver)
973 {
974 mTaskRunner.Post([aEraseDataset, aReceiver, this]() { leaveInternal(aEraseDataset, aReceiver); });
975
976 return Status::ok();
977 }
978
leaveInternal(bool aEraseDataset,const std::shared_ptr<IOtStatusReceiver> & aReceiver)979 void OtDaemonServer::leaveInternal(bool aEraseDataset, const std::shared_ptr<IOtStatusReceiver> &aReceiver)
980 {
981 if (GetOtInstance() == nullptr)
982 {
983 PropagateResult(OT_ERROR_INVALID_STATE, "OT is not initialized", aReceiver);
984 }
985 else
986 {
987 LeaveGracefully(aEraseDataset, "leave", [aReceiver]() { PropagateResult(OT_ERROR_NONE, "", aReceiver); });
988 }
989 }
990
LeaveGracefully(bool aEraseDataset,const std::string & aCallerTag,const LeaveCallback & aCallback)991 void OtDaemonServer::LeaveGracefully(bool aEraseDataset, const std::string &aCallerTag, const LeaveCallback &aCallback)
992 {
993 otOperationalDatasetTlvs curDatasetTlvs;
994
995 VerifyOrDie(GetOtInstance() != nullptr, "OT is not initialized");
996
997 if (otThreadGetDeviceRole(GetOtInstance()) != OT_DEVICE_ROLE_DISABLED)
998 {
999 otbrLogInfo("Start graceful leave...");
1000
1001 mLeaveCallbacks.push_back([aEraseDataset, aCallerTag, aCallback, this]() {
1002 assert(otThreadGetDeviceRole(GetOtInstance()) == OT_DEVICE_ROLE_DISABLED);
1003 LeaveGracefully(aEraseDataset, aCallerTag, aCallback);
1004 });
1005
1006 // Ignores the OT_ERROR_BUSY error if a detach has already been requested.
1007 // `otThreadDetachGracefully()` will invoke the `DetachGracefullyCallback`
1008 // callabck in 0 seconds if this device role is detached or disabled. So
1009 // `DetachGracefullyCallback` is guaranteed to be called in all cases
1010 (void)otThreadDetachGracefully(GetOtInstance(), DetachGracefullyCallback, this);
1011 ExitNow();
1012 }
1013
1014 // Any join() or scheduleMigration() onging requests will be aborted
1015 if (mJoinReceiver != nullptr)
1016 {
1017 mJoinReceiver->onError(OT_ERROR_ABORT, "Aborted by a " + aCallerTag + " operation");
1018 mJoinReceiver = nullptr;
1019 }
1020
1021 if (mMigrationReceiver != nullptr)
1022 {
1023 mMigrationReceiver->onError(OT_ERROR_ABORT, "Aborted by a " + aCallerTag + " operation");
1024 mMigrationReceiver = nullptr;
1025 }
1026
1027 // It's not necessary to reset the OpenThread instance if it has no dataset
1028 if (aEraseDataset && otDatasetGetActiveTlvs(GetOtInstance(), &curDatasetTlvs) == OT_ERROR_NONE)
1029 {
1030 SuccessOrDie(otInstanceErasePersistentInfo(GetOtInstance()), "Failed to erase persistent info");
1031 mResetThreadHandler();
1032
1033 // The OtDaemonServer runtime states are outdated after
1034 // the OT instances has been destroyed in `mResetThreadHandler`
1035 ResetRuntimeStatesAfterLeave();
1036
1037 initializeInternal(mState.threadEnabled, mAndroidHost->GetConfiguration(), mINsdPublisher, mMeshcopTxts,
1038 mCountryCode, mTrelEnabled, mCallback);
1039 }
1040
1041 otbrLogInfo("Leave() is done");
1042
1043 aCallback();
1044
1045 exit:
1046 return;
1047 }
1048
ResetRuntimeStatesAfterLeave()1049 void OtDaemonServer::ResetRuntimeStatesAfterLeave()
1050 {
1051 bool threadEnabled = mState.threadEnabled;
1052
1053 assert(mJoinReceiver == nullptr);
1054 assert(mMigrationReceiver == nullptr);
1055
1056 // The Thread Enabled state survives the leave() API call.
1057 // This indicates that we should move the threadEnabled state
1058 // out of the OtDaemonState class
1059 mState = OtDaemonState();
1060 mState.threadEnabled = threadEnabled;
1061
1062 mOnMeshPrefixes.clear();
1063 mEphemeralKeyExpiryMillis = 0;
1064 }
1065
DetachGracefullyCallback(void * aBinderServer)1066 void OtDaemonServer::DetachGracefullyCallback(void *aBinderServer)
1067 {
1068 OtDaemonServer *thisServer = static_cast<OtDaemonServer *>(aBinderServer);
1069 thisServer->DetachGracefullyCallback();
1070 }
1071
DetachGracefullyCallback(void)1072 void OtDaemonServer::DetachGracefullyCallback(void)
1073 {
1074 otbrLogInfo("DetachGracefully success...");
1075
1076 for (auto &callback : mLeaveCallbacks)
1077 {
1078 callback();
1079 }
1080 mLeaveCallbacks.clear();
1081 }
1082
isAttached()1083 bool OtDaemonServer::isAttached()
1084 {
1085 otDeviceRole role = otThreadGetDeviceRole(GetOtInstance());
1086
1087 return role == OT_DEVICE_ROLE_CHILD || role == OT_DEVICE_ROLE_ROUTER || role == OT_DEVICE_ROLE_LEADER;
1088 }
1089
scheduleMigration(const std::vector<uint8_t> & aPendingOpDatasetTlvs,const std::shared_ptr<IOtStatusReceiver> & aReceiver)1090 Status OtDaemonServer::scheduleMigration(const std::vector<uint8_t> &aPendingOpDatasetTlvs,
1091 const std::shared_ptr<IOtStatusReceiver> &aReceiver)
1092 {
1093 mTaskRunner.Post(
1094 [aPendingOpDatasetTlvs, aReceiver, this]() { scheduleMigrationInternal(aPendingOpDatasetTlvs, aReceiver); });
1095
1096 return Status::ok();
1097 }
1098
scheduleMigrationInternal(const std::vector<uint8_t> & aPendingOpDatasetTlvs,const std::shared_ptr<IOtStatusReceiver> & aReceiver)1099 void OtDaemonServer::scheduleMigrationInternal(const std::vector<uint8_t> &aPendingOpDatasetTlvs,
1100 const std::shared_ptr<IOtStatusReceiver> &aReceiver)
1101 {
1102 int error = OT_ERROR_NONE;
1103 std::string message;
1104 otOperationalDataset emptyDataset;
1105
1106 VerifyOrExit(mState.threadEnabled != OT_STATE_DISABLING, error = OT_ERROR_BUSY, message = "Thread is disabling");
1107
1108 VerifyOrExit(mState.threadEnabled == OT_STATE_ENABLED,
1109 error = static_cast<int>(IOtDaemon::ErrorCode::OT_ERROR_THREAD_DISABLED),
1110 message = "Thread is disabled");
1111
1112 if (GetOtInstance() == nullptr)
1113 {
1114 message = "OT is not initialized";
1115 ExitNow(error = OT_ERROR_INVALID_STATE);
1116 }
1117 if (!isAttached())
1118 {
1119 message = "Cannot schedule migration when this device is detached";
1120 ExitNow(error = static_cast<int>(IOtDaemon::ErrorCode::OT_ERROR_FAILED_PRECONDITION));
1121 }
1122
1123 // TODO: check supported channel mask
1124
1125 error = otDatasetSendMgmtPendingSet(GetOtInstance(), &emptyDataset, aPendingOpDatasetTlvs.data(),
1126 static_cast<uint8_t>(aPendingOpDatasetTlvs.size()), SendMgmtPendingSetCallback,
1127 /* aBinderServer= */ this);
1128 if (error != OT_ERROR_NONE)
1129 {
1130 message = "Failed to send MGMT_PENDING_SET.req";
1131 }
1132
1133 exit:
1134 if (error != OT_ERROR_NONE)
1135 {
1136 PropagateResult(error, message, aReceiver);
1137 }
1138 else
1139 {
1140 // otDatasetSendMgmtPendingSet() returns OT_ERROR_BUSY if it has already been called before but the
1141 // callback hasn't been invoked. So we can guarantee that mMigrationReceiver is always nullptr here
1142 assert(mMigrationReceiver == nullptr);
1143 mMigrationReceiver = aReceiver;
1144 }
1145 }
1146
SendMgmtPendingSetCallback(otError aResult,void * aBinderServer)1147 void OtDaemonServer::SendMgmtPendingSetCallback(otError aResult, void *aBinderServer)
1148 {
1149 OtDaemonServer *thisServer = static_cast<OtDaemonServer *>(aBinderServer);
1150
1151 if (thisServer->mMigrationReceiver != nullptr)
1152 {
1153 PropagateResult(aResult, "Failed to register Pending Dataset to leader", thisServer->mMigrationReceiver);
1154 thisServer->mMigrationReceiver = nullptr;
1155 }
1156 }
1157
setCountryCode(const std::string & aCountryCode,const std::shared_ptr<IOtStatusReceiver> & aReceiver)1158 Status OtDaemonServer::setCountryCode(const std::string &aCountryCode,
1159 const std::shared_ptr<IOtStatusReceiver> &aReceiver)
1160 {
1161 mTaskRunner.Post([aCountryCode, aReceiver, this]() { setCountryCodeInternal(aCountryCode, aReceiver); });
1162
1163 return Status::ok();
1164 }
1165
setCountryCodeInternal(const std::string & aCountryCode,const std::shared_ptr<IOtStatusReceiver> & aReceiver)1166 void OtDaemonServer::setCountryCodeInternal(const std::string &aCountryCode,
1167 const std::shared_ptr<IOtStatusReceiver> &aReceiver)
1168 {
1169 mHost.SetCountryCode(aCountryCode, [aReceiver, aCountryCode, this](otError aError, const std::string &aMessage) {
1170 if (aError == OT_ERROR_NONE)
1171 {
1172 mCountryCode = aCountryCode;
1173 }
1174
1175 PropagateResult(aError, aMessage, aReceiver);
1176 });
1177 }
1178
getChannelMasks(const std::shared_ptr<IChannelMasksReceiver> & aReceiver)1179 Status OtDaemonServer::getChannelMasks(const std::shared_ptr<IChannelMasksReceiver> &aReceiver)
1180 {
1181 mTaskRunner.Post([aReceiver, this]() { getChannelMasksInternal(aReceiver); });
1182
1183 return Status::ok();
1184 }
1185
getChannelMasksInternal(const std::shared_ptr<IChannelMasksReceiver> & aReceiver)1186 void OtDaemonServer::getChannelMasksInternal(const std::shared_ptr<IChannelMasksReceiver> &aReceiver)
1187 {
1188 auto channelMasksReceiver = [aReceiver](uint32_t aSupportedChannelMask, uint32_t aPreferredChannelMask) {
1189 aReceiver->onSuccess(aSupportedChannelMask, aPreferredChannelMask);
1190 };
1191 auto errorReceiver = [aReceiver](otError aError, const std::string &aMessage) {
1192 aReceiver->onError(aError, aMessage);
1193 };
1194 mHost.GetChannelMasks(channelMasksReceiver, errorReceiver);
1195 }
1196
setChannelMaxPowers(const std::vector<ChannelMaxPower> & aChannelMaxPowers,const std::shared_ptr<IOtStatusReceiver> & aReceiver)1197 Status OtDaemonServer::setChannelMaxPowers(const std::vector<ChannelMaxPower> &aChannelMaxPowers,
1198 const std::shared_ptr<IOtStatusReceiver> &aReceiver)
1199 {
1200 mTaskRunner.Post(
1201 [aChannelMaxPowers, aReceiver, this]() { setChannelMaxPowersInternal(aChannelMaxPowers, aReceiver); });
1202
1203 return Status::ok();
1204 }
1205
setChannelMaxPowersInternal(const std::vector<ChannelMaxPower> & aChannelMaxPowers,const std::shared_ptr<IOtStatusReceiver> & aReceiver)1206 Status OtDaemonServer::setChannelMaxPowersInternal(const std::vector<ChannelMaxPower> &aChannelMaxPowers,
1207 const std::shared_ptr<IOtStatusReceiver> &aReceiver)
1208 {
1209 // Transform aidl ChannelMaxPower to ThreadHost::ChannelMaxPower
1210 std::vector<Host::ThreadHost::ChannelMaxPower> channelMaxPowers(aChannelMaxPowers.size());
1211 std::transform(aChannelMaxPowers.begin(), aChannelMaxPowers.end(), channelMaxPowers.begin(),
1212 [](const ChannelMaxPower &aChannelMaxPower) {
1213 // INT_MIN indicates that the corresponding channel is disabled in Thread Android API
1214 // `setChannelMaxPowers()` INT16_MAX indicates that the corresponding channel is disabled in
1215 // OpenThread API `otPlatRadioSetChannelTargetPower()`.
1216 return Host::ThreadHost::ChannelMaxPower(
1217 aChannelMaxPower.channel,
1218 aChannelMaxPower.maxPower == INT_MIN
1219 ? INT16_MAX
1220 : std::clamp(aChannelMaxPower.maxPower, INT16_MIN, INT16_MAX - 1));
1221 });
1222
1223 mHost.SetChannelMaxPowers(channelMaxPowers, [aReceiver](otError aError, const std::string &aMessage) {
1224 PropagateResult(aError, aMessage, aReceiver);
1225 });
1226
1227 return Status::ok();
1228 }
1229
setConfiguration(const OtDaemonConfiguration & aConfiguration,const std::shared_ptr<IOtStatusReceiver> & aReceiver)1230 Status OtDaemonServer::setConfiguration(const OtDaemonConfiguration &aConfiguration,
1231 const std::shared_ptr<IOtStatusReceiver> &aReceiver)
1232 {
1233 mTaskRunner.Post([aConfiguration, aReceiver, this]() {
1234 if (aConfiguration != mAndroidHost->GetConfiguration())
1235 {
1236 mAdvProxy.SetAllowMlEid(!aConfiguration.borderRouterEnabled);
1237 mBorderAgent.SetEnabled(mState.threadEnabled && aConfiguration.borderRouterEnabled);
1238 mAndroidHost->SetConfiguration(aConfiguration, aReceiver);
1239 }
1240 });
1241
1242 return Status::ok();
1243 }
1244
setInfraLinkInterfaceName(const std::optional<std::string> & aInterfaceName,const ScopedFileDescriptor & aIcmp6Socket,const std::shared_ptr<IOtStatusReceiver> & aReceiver)1245 Status OtDaemonServer::setInfraLinkInterfaceName(const std::optional<std::string> &aInterfaceName,
1246 const ScopedFileDescriptor &aIcmp6Socket,
1247 const std::shared_ptr<IOtStatusReceiver> &aReceiver)
1248 {
1249 int icmp6Socket = aIcmp6Socket.dup().release();
1250
1251 mTaskRunner.Post([interfaceName = aInterfaceName.value_or(""), icmp6Socket, aReceiver, this]() {
1252 mAndroidHost->SetInfraLinkInterfaceName(interfaceName, icmp6Socket, aReceiver);
1253 });
1254
1255 return Status::ok();
1256 }
1257
runOtCtlCommand(const std::string & aCommand,const bool aIsInteractive,const std::shared_ptr<IOtOutputReceiver> & aReceiver)1258 Status OtDaemonServer::runOtCtlCommand(const std::string &aCommand,
1259 const bool aIsInteractive,
1260 const std::shared_ptr<IOtOutputReceiver> &aReceiver)
1261 {
1262 mTaskRunner.Post([aCommand, aIsInteractive, aReceiver, this]() {
1263 runOtCtlCommandInternal(aCommand, aIsInteractive, aReceiver);
1264 });
1265
1266 return Status::ok();
1267 }
1268
setInfraLinkNat64Prefix(const std::optional<std::string> & aNat64Prefix,const std::shared_ptr<IOtStatusReceiver> & aReceiver)1269 Status OtDaemonServer::setInfraLinkNat64Prefix(const std::optional<std::string> &aNat64Prefix,
1270 const std::shared_ptr<IOtStatusReceiver> &aReceiver)
1271 {
1272 mTaskRunner.Post([nat64Prefix = aNat64Prefix.value_or(""), aReceiver, this]() {
1273 mAndroidHost->SetInfraLinkNat64Prefix(nat64Prefix, aReceiver);
1274 });
1275
1276 return Status::ok();
1277 }
1278
runOtCtlCommandInternal(const std::string & aCommand,const bool aIsInteractive,const std::shared_ptr<IOtOutputReceiver> & aReceiver)1279 void OtDaemonServer::runOtCtlCommandInternal(const std::string &aCommand,
1280 const bool aIsInteractive,
1281 const std::shared_ptr<IOtOutputReceiver> &aReceiver)
1282 {
1283 mAndroidHost->RunOtCtlCommand(aCommand, aIsInteractive, aReceiver);
1284 }
1285
setInfraLinkDnsServers(const std::vector<std::string> & aDnsServers,const std::shared_ptr<IOtStatusReceiver> & aReceiver)1286 Status OtDaemonServer::setInfraLinkDnsServers(const std::vector<std::string> &aDnsServers,
1287 const std::shared_ptr<IOtStatusReceiver> &aReceiver)
1288 {
1289 mTaskRunner.Post(
1290 [aDnsServers, aReceiver, this]() { mAndroidHost->SetInfraLinkDnsServers(aDnsServers, aReceiver); });
1291
1292 return Status::ok();
1293 }
1294
dump(int aFd,const char ** aArgs,uint32_t aNumArgs)1295 binder_status_t OtDaemonServer::dump(int aFd, const char **aArgs, uint32_t aNumArgs)
1296 {
1297 return mAndroidHost->Dump(aFd, aArgs, aNumArgs);
1298 }
1299
PushTelemetryIfConditionMatch()1300 void OtDaemonServer::PushTelemetryIfConditionMatch()
1301 {
1302 VerifyOrExit(GetOtInstance() != nullptr);
1303
1304 // TODO: Push telemetry per kTelemetryUploadIntervalThreshold instead of on startup.
1305 // TODO: Save unpushed telemetries in local cache to avoid data loss.
1306 RetrieveAndPushAtoms(GetOtInstance());
1307 mTaskRunner.Post(kTelemetryUploadIntervalThreshold, [this]() { PushTelemetryIfConditionMatch(); });
1308
1309 exit:
1310 return;
1311 }
1312
setNat64Cidr(const std::optional<std::string> & aCidr,const std::shared_ptr<IOtStatusReceiver> & aReceiver)1313 Status OtDaemonServer::setNat64Cidr(const std::optional<std::string> &aCidr,
1314 const std::shared_ptr<IOtStatusReceiver> &aReceiver)
1315 {
1316 mTaskRunner.Post([aCidr, aReceiver, this]() { setNat64CidrInternal(aCidr, aReceiver); });
1317
1318 return Status::ok();
1319 }
1320
setNat64CidrInternal(const std::optional<std::string> & aCidr,const std::shared_ptr<IOtStatusReceiver> & aReceiver)1321 void OtDaemonServer::setNat64CidrInternal(const std::optional<std::string> &aCidr,
1322 const std::shared_ptr<IOtStatusReceiver> &aReceiver)
1323 {
1324 otError error = OT_ERROR_NONE;
1325 std::string message;
1326
1327 VerifyOrExit(GetOtInstance() != nullptr, error = OT_ERROR_INVALID_STATE, message = "OT is not initialized");
1328
1329 if (aCidr.has_value())
1330 {
1331 otIp4Cidr nat64Cidr{};
1332
1333 otbrLogInfo("Setting NAT64 CIDR: %s", aCidr->c_str());
1334 SuccessOrExit(error = otIp4CidrFromString(aCidr->c_str(), &nat64Cidr), message = "Failed to parse NAT64 CIDR");
1335 SuccessOrExit(error = otNat64SetIp4Cidr(GetOtInstance(), &nat64Cidr), message = "Failed to set NAT64 CIDR");
1336 }
1337 else
1338 {
1339 otbrLogInfo("Clearing NAT64 CIDR");
1340 otNat64ClearIp4Cidr(GetOtInstance());
1341 }
1342
1343 exit:
1344 PropagateResult(error, message, aReceiver);
1345 }
1346
1347 } // namespace Android
1348 } // namespace otbr
1349