• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #define OTBR_LOG_TAG "BINDER"
30 
31 #include "android/otdaemon_server.hpp"
32 
33 #include <net/if.h>
34 #include <string.h>
35 
36 #include <android-base/file.h>
37 #include <android-base/stringprintf.h>
38 #include <android/binder_manager.h>
39 #include <android/binder_process.h>
40 #include <openthread/border_router.h>
41 #include <openthread/cli.h>
42 #include <openthread/icmp6.h>
43 #include <openthread/ip6.h>
44 #include <openthread/link.h>
45 #include <openthread/openthread-system.h>
46 #include <openthread/platform/infra_if.h>
47 #include <openthread/platform/radio.h>
48 
49 #include "agent/vendor.hpp"
50 #include "android/otdaemon_telemetry.hpp"
51 #include "common/code_utils.hpp"
52 
53 #define BYTE_ARR_END(arr) ((arr) + sizeof(arr))
54 
55 namespace otbr {
56 
57 namespace vendor {
58 
newInstance(Application & aApplication)59 std::shared_ptr<VendorServer> VendorServer::newInstance(Application &aApplication)
60 {
61     return ndk::SharedRefBase::make<Android::OtDaemonServer>(aApplication);
62 }
63 
64 } // namespace vendor
65 
66 } // namespace otbr
67 
68 namespace otbr {
69 namespace Android {
70 
71 static const char       OTBR_SERVICE_NAME[] = "ot_daemon";
72 static constexpr size_t kMaxIp6Size         = 1280;
73 
PropagateResult(int aError,const std::string & aMessage,const std::shared_ptr<IOtStatusReceiver> & aReceiver)74 static void PropagateResult(int                                       aError,
75                             const std::string                        &aMessage,
76                             const std::shared_ptr<IOtStatusReceiver> &aReceiver)
77 {
78     if (aReceiver != nullptr)
79     {
80         // If an operation has already been requested or accepted, consider it succeeded
81         if (aError == OT_ERROR_NONE || aError == OT_ERROR_ALREADY)
82         {
83             aReceiver->onSuccess();
84         }
85         else
86         {
87             aReceiver->onError(aError, aMessage);
88         }
89     }
90 }
91 
ThreadEnabledStateToString(int enabledState)92 static const char *ThreadEnabledStateToString(int enabledState)
93 {
94     switch (enabledState)
95     {
96     case IOtDaemon::OT_STATE_ENABLED:
97         return "ENABLED";
98     case IOtDaemon::OT_STATE_DISABLED:
99         return "DISABLED";
100     case IOtDaemon::OT_STATE_DISABLING:
101         return "DISABLING";
102     default:
103         assert(false);
104         return "UNKNOWN";
105     }
106 }
107 
OtDaemonServer(Application & aApplication)108 OtDaemonServer::OtDaemonServer(Application &aApplication)
109     : mApplication(aApplication)
110     , mNcp(aApplication.GetNcp())
111     , mBorderAgent(aApplication.GetBorderAgent())
112     , mMdnsPublisher(static_cast<MdnsPublisher &>(aApplication.GetPublisher()))
113     , mBorderRouterConfiguration()
114 {
115     mClientDeathRecipient =
116         ::ndk::ScopedAIBinder_DeathRecipient(AIBinder_DeathRecipient_new(&OtDaemonServer::BinderDeathCallback));
117     mBorderRouterConfiguration.infraInterfaceName        = "";
118     mBorderRouterConfiguration.infraInterfaceIcmp6Socket = ScopedFileDescriptor();
119     mBorderRouterConfiguration.isBorderRoutingEnabled    = false;
120 }
121 
Init(void)122 void OtDaemonServer::Init(void)
123 {
124     binder_exception_t exp = AServiceManager_registerLazyService(asBinder().get(), OTBR_SERVICE_NAME);
125     SuccessOrDie(exp, "Failed to register OT daemon binder service");
126 
127     assert(GetOtInstance() != nullptr);
128 
129     mNcp.AddThreadStateChangedCallback([this](otChangedFlags aFlags) { StateCallback(aFlags); });
130     otIp6SetAddressCallback(GetOtInstance(), OtDaemonServer::AddressCallback, this);
131     otIp6SetReceiveCallback(GetOtInstance(), OtDaemonServer::ReceiveCallback, this);
132     otBackboneRouterSetMulticastListenerCallback(GetOtInstance(), OtDaemonServer::HandleBackboneMulticastListenerEvent,
133                                                  this);
134     otIcmp6SetEchoMode(GetOtInstance(), OT_ICMP6_ECHO_HANDLER_DISABLED);
135     otIp6SetReceiveFilterEnabled(GetOtInstance(), true);
136 
137     mTaskRunner.Post(kTelemetryCheckInterval, [this]() { PushTelemetryIfConditionMatch(); });
138 }
139 
BinderDeathCallback(void * aBinderServer)140 void OtDaemonServer::BinderDeathCallback(void *aBinderServer)
141 {
142     OtDaemonServer *thisServer = static_cast<OtDaemonServer *>(aBinderServer);
143 
144     otbrLogCrit("system_server is dead, removing configs and callbacks...");
145 
146     thisServer->mMeshcopTxts   = {};
147     thisServer->mINsdPublisher = nullptr;
148 
149     // Note that the INsdPublisher reference is held in MdnsPublisher
150     thisServer->mMdnsPublisher.SetINsdPublisher(nullptr);
151 
152     thisServer->mCallback = nullptr;
153     thisServer->mTunFd.set(-1); // the original FD will be closed automatically
154 }
155 
StateCallback(otChangedFlags aFlags)156 void OtDaemonServer::StateCallback(otChangedFlags aFlags)
157 {
158     std::vector<OnMeshPrefixConfig> onMeshPrefixes;
159 
160     assert(GetOtInstance() != nullptr);
161 
162     if (RefreshOtDaemonState(aFlags))
163     {
164         if (mCallback == nullptr)
165         {
166             otbrLogWarning("Ignoring OT state changes: callback is not set");
167         }
168         else
169         {
170             mCallback->onStateChanged(mState, -1);
171         }
172     }
173 
174     if (aFlags & OT_CHANGED_THREAD_BACKBONE_ROUTER_STATE)
175     {
176         if (mCallback == nullptr)
177         {
178             otbrLogWarning("Ignoring OT backbone router state changes: callback is not set");
179         }
180         else
181         {
182             mCallback->onBackboneRouterStateChanged(GetBackboneRouterState());
183         }
184     }
185 
186     if ((aFlags & OT_CHANGED_THREAD_NETDATA) && RefreshOnMeshPrefixes())
187     {
188         if (mCallback == nullptr)
189         {
190             otbrLogWarning("Ignoring OT netdata changes: callback is not set");
191         }
192         else
193         {
194             onMeshPrefixes.assign(mOnMeshPrefixes.begin(), mOnMeshPrefixes.end());
195             mCallback->onPrefixChanged(onMeshPrefixes);
196         }
197     }
198 }
199 
RefreshOnMeshPrefixes()200 bool OtDaemonServer::RefreshOnMeshPrefixes()
201 {
202     std::set<OnMeshPrefixConfig> onMeshPrefixConfigs;
203     otNetworkDataIterator        iterator = OT_NETWORK_DATA_ITERATOR_INIT;
204     otBorderRouterConfig         config;
205     bool                         rv = false;
206 
207     VerifyOrExit(GetOtInstance() != nullptr, otbrLogWarning("Can't get on mesh prefixes: OT is not initialized"));
208 
209     while (otNetDataGetNextOnMeshPrefix(GetOtInstance(), &iterator, &config) == OT_ERROR_NONE)
210     {
211         OnMeshPrefixConfig onMeshPrefixConfig;
212 
213         onMeshPrefixConfig.prefix.assign(std::begin(config.mPrefix.mPrefix.mFields.m8),
214                                          std::end(config.mPrefix.mPrefix.mFields.m8));
215         onMeshPrefixConfig.prefixLength = config.mPrefix.mLength;
216         onMeshPrefixConfigs.insert(onMeshPrefixConfig);
217     }
218 
219     if (mOnMeshPrefixes != onMeshPrefixConfigs)
220     {
221         mOnMeshPrefixes = std::move(onMeshPrefixConfigs);
222         rv              = true;
223     }
224 exit:
225     return rv;
226 }
227 
ConvertToAddressInfo(const otNetifAddress & aAddress)228 Ipv6AddressInfo OtDaemonServer::ConvertToAddressInfo(const otNetifAddress &aAddress)
229 {
230     Ipv6AddressInfo addrInfo;
231     otIp6Prefix     addressPrefix{aAddress.mAddress, aAddress.mPrefixLength};
232 
233     addrInfo.address.assign(std::begin(aAddress.mAddress.mFields.m8), std::end(aAddress.mAddress.mFields.m8));
234     addrInfo.prefixLength = aAddress.mPrefixLength;
235     addrInfo.isPreferred  = aAddress.mPreferred;
236     addrInfo.isMeshLocal  = aAddress.mMeshLocal;
237     addrInfo.isActiveOmr  = otNetDataContainsOmrPrefix(GetOtInstance(), &addressPrefix);
238     return addrInfo;
239 }
240 
ConvertToAddressInfo(const otNetifMulticastAddress & aAddress)241 Ipv6AddressInfo OtDaemonServer::ConvertToAddressInfo(const otNetifMulticastAddress &aAddress)
242 {
243     Ipv6AddressInfo addrInfo;
244 
245     addrInfo.address.assign(std::begin(aAddress.mAddress.mFields.m8), std::end(aAddress.mAddress.mFields.m8));
246     return addrInfo;
247 }
248 
AddressCallback(const otIp6AddressInfo * aAddressInfo,bool aIsAdded,void * aBinderServer)249 void OtDaemonServer::AddressCallback(const otIp6AddressInfo *aAddressInfo, bool aIsAdded, void *aBinderServer)
250 {
251     OT_UNUSED_VARIABLE(aAddressInfo);
252     OT_UNUSED_VARIABLE(aIsAdded);
253     OtDaemonServer                *thisServer = static_cast<OtDaemonServer *>(aBinderServer);
254     std::vector<Ipv6AddressInfo>   addrInfoList;
255     const otNetifAddress          *unicastAddrs   = otIp6GetUnicastAddresses(thisServer->GetOtInstance());
256     const otNetifMulticastAddress *multicastAddrs = otIp6GetMulticastAddresses(thisServer->GetOtInstance());
257 
258     for (const otNetifAddress *addr = unicastAddrs; addr != nullptr; addr = addr->mNext)
259     {
260         addrInfoList.push_back(thisServer->ConvertToAddressInfo(*addr));
261     }
262     for (const otNetifMulticastAddress *maddr = multicastAddrs; maddr != nullptr; maddr = maddr->mNext)
263     {
264         addrInfoList.push_back(thisServer->ConvertToAddressInfo(*maddr));
265     }
266     if (thisServer->mCallback != nullptr)
267     {
268         thisServer->mCallback->onAddressChanged(addrInfoList);
269     }
270     else
271     {
272         otbrLogWarning("OT daemon callback is not set");
273     }
274 }
275 
ReceiveCallback(otMessage * aMessage,void * aBinderServer)276 void OtDaemonServer::ReceiveCallback(otMessage *aMessage, void *aBinderServer)
277 {
278     static_cast<OtDaemonServer *>(aBinderServer)->ReceiveCallback(aMessage);
279 }
280 
281 // FIXME(wgtdkp): We should reuse the same code in openthread/src/posix/platform/netif.cp
282 // after the refactor there is done: https://github.com/openthread/openthread/pull/9293
ReceiveCallback(otMessage * aMessage)283 void OtDaemonServer::ReceiveCallback(otMessage *aMessage)
284 {
285     char     packet[kMaxIp6Size];
286     uint16_t length = otMessageGetLength(aMessage);
287     int      fd     = mTunFd.get();
288 
289     VerifyOrExit(fd != -1, otbrLogWarning("Ignoring egress packet: invalid tunnel FD"));
290 
291     if (otMessageRead(aMessage, 0, packet, sizeof(packet)) != length)
292     {
293         otbrLogWarning("Failed to read packet from otMessage");
294         ExitNow();
295     }
296 
297     if (write(fd, packet, length) != length)
298     {
299         otbrLogWarning("Failed to send packet over tunnel interface: %s", strerror(errno));
300     }
301 
302 exit:
303     otMessageFree(aMessage);
304 }
305 
306 // FIXME(wgtdkp): this doesn't support NAT64, we should use a shared library with ot-posix
307 // to handle packet translations between the tunnel interface and Thread.
TransmitCallback(void)308 void OtDaemonServer::TransmitCallback(void)
309 {
310     char              packet[kMaxIp6Size];
311     ssize_t           length;
312     otMessage        *message = nullptr;
313     otError           error   = OT_ERROR_NONE;
314     otMessageSettings settings;
315     int               fd = mTunFd.get();
316 
317     assert(GetOtInstance() != nullptr);
318 
319     VerifyOrExit(fd != -1);
320 
321     length = read(fd, packet, sizeof(packet));
322 
323     if (length == -1)
324     {
325         otbrLogWarning("Failed to read packet from tunnel interface: %s", strerror(errno));
326         ExitNow();
327     }
328     else if (length == 0)
329     {
330         otbrLogWarning("Unexpected EOF on the tunnel FD");
331         ExitNow();
332     }
333 
334     VerifyOrExit(GetOtInstance() != nullptr, otbrLogWarning("Ignoring tunnel packet: OT is not initialized"));
335 
336     settings.mLinkSecurityEnabled = (otThreadGetDeviceRole(GetOtInstance()) != OT_DEVICE_ROLE_DISABLED);
337     settings.mPriority            = OT_MESSAGE_PRIORITY_LOW;
338 
339     message = otIp6NewMessage(GetOtInstance(), &settings);
340     VerifyOrExit(message != nullptr, error = OT_ERROR_NO_BUFS);
341     otMessageSetOrigin(message, OT_MESSAGE_ORIGIN_HOST_UNTRUSTED);
342 
343     SuccessOrExit(error = otMessageAppend(message, packet, static_cast<uint16_t>(length)));
344 
345     error   = otIp6Send(GetOtInstance(), message);
346     message = nullptr;
347 
348 exit:
349     if (message != nullptr)
350     {
351         otMessageFree(message);
352     }
353 
354     if (error != OT_ERROR_NONE)
355     {
356         if (error == OT_ERROR_DROP)
357         {
358             otbrLogInfo("Dropped tunnel packet (length=%d)", length);
359         }
360         else
361         {
362             otbrLogWarning("Failed to transmit tunnel packet: %s", otThreadErrorToString(error));
363         }
364     }
365 }
366 
GetBackboneRouterState()367 BackboneRouterState OtDaemonServer::GetBackboneRouterState()
368 {
369     BackboneRouterState                       state;
370     otBackboneRouterState                     bbrState;
371     otBackboneRouterMulticastListenerInfo     info;
372     otBackboneRouterMulticastListenerIterator iter = OT_BACKBONE_ROUTER_MULTICAST_LISTENER_ITERATOR_INIT;
373     state.listeningAddresses                       = std::vector<std::string>();
374 
375     VerifyOrExit(GetOtInstance() != nullptr, otbrLogWarning("Can't get bbr state: OT is not initialized"));
376 
377     bbrState = otBackboneRouterGetState(GetOtInstance());
378     switch (bbrState)
379     {
380     case OT_BACKBONE_ROUTER_STATE_DISABLED:
381     case OT_BACKBONE_ROUTER_STATE_SECONDARY:
382         state.multicastForwardingEnabled = false;
383         break;
384     case OT_BACKBONE_ROUTER_STATE_PRIMARY:
385         state.multicastForwardingEnabled = true;
386         break;
387     }
388 
389     while (otBackboneRouterMulticastListenerGetNext(GetOtInstance(), &iter, &info) == OT_ERROR_NONE)
390     {
391         char string[OT_IP6_ADDRESS_STRING_SIZE];
392 
393         otIp6AddressToString(&info.mAddress, string, sizeof(string));
394         state.listeningAddresses.push_back(string);
395     }
396 
397 exit:
398     return state;
399 }
400 
HandleBackboneMulticastListenerEvent(void * aBinderServer,otBackboneRouterMulticastListenerEvent aEvent,const otIp6Address * aAddress)401 void OtDaemonServer::HandleBackboneMulticastListenerEvent(void                                  *aBinderServer,
402                                                           otBackboneRouterMulticastListenerEvent aEvent,
403                                                           const otIp6Address                    *aAddress)
404 {
405     OtDaemonServer *thisServer = static_cast<OtDaemonServer *>(aBinderServer);
406     char            addressString[OT_IP6_ADDRESS_STRING_SIZE];
407 
408     otIp6AddressToString(aAddress, addressString, sizeof(addressString));
409 
410     otbrLogInfo("Multicast forwarding address changed, %s is %s", addressString,
411                 (aEvent == OT_BACKBONE_ROUTER_MULTICAST_LISTENER_ADDED) ? "added" : "removed");
412 
413     if (thisServer->mCallback == nullptr)
414     {
415         otbrLogWarning("Ignoring OT multicast listener event: callback is not set");
416         ExitNow();
417     }
418     thisServer->mCallback->onBackboneRouterStateChanged(thisServer->GetBackboneRouterState());
419 
420 exit:
421     return;
422 }
423 
GetOtInstance()424 otInstance *OtDaemonServer::GetOtInstance()
425 {
426     return mNcp.GetInstance();
427 }
428 
Update(MainloopContext & aMainloop)429 void OtDaemonServer::Update(MainloopContext &aMainloop)
430 {
431     int fd = mTunFd.get();
432 
433     if (fd != -1)
434     {
435         FD_SET(fd, &aMainloop.mReadFdSet);
436         aMainloop.mMaxFd = std::max(aMainloop.mMaxFd, fd);
437     }
438 }
439 
Process(const MainloopContext & aMainloop)440 void OtDaemonServer::Process(const MainloopContext &aMainloop)
441 {
442     int fd = mTunFd.get();
443 
444     if (fd != -1 && FD_ISSET(fd, &aMainloop.mReadFdSet))
445     {
446         TransmitCallback();
447     }
448 }
449 
initialize(const ScopedFileDescriptor & aTunFd,const bool enabled,const std::shared_ptr<INsdPublisher> & aINsdPublisher,const MeshcopTxtAttributes & aMeshcopTxts,const std::shared_ptr<IOtDaemonCallback> & aCallback,const std::string & aCountryCode)450 Status OtDaemonServer::initialize(const ScopedFileDescriptor               &aTunFd,
451                                   const bool                                enabled,
452                                   const std::shared_ptr<INsdPublisher>     &aINsdPublisher,
453                                   const MeshcopTxtAttributes               &aMeshcopTxts,
454                                   const std::shared_ptr<IOtDaemonCallback> &aCallback,
455                                   const std::string                        &aCountryCode)
456 {
457     otbrLogInfo("OT daemon is initialized by system server (tunFd=%d, enabled=%s)", aTunFd.get(),
458                 enabled ? "true" : "false");
459     // The copy constructor of `ScopedFileDescriptor` is deleted. It is unable to pass the `aTunFd`
460     // to the lambda function. The processing method of `aTunFd` doesn't call OpenThread functions,
461     // we can process `aTunFd` directly in front of the task.
462     mTunFd = aTunFd.dup();
463 
464     mINsdPublisher = aINsdPublisher;
465     mMeshcopTxts   = aMeshcopTxts;
466 
467     mTaskRunner.Post([enabled, aINsdPublisher, aMeshcopTxts, aCallback, aCountryCode, this]() {
468         initializeInternal(enabled, mINsdPublisher, mMeshcopTxts, aCallback, aCountryCode);
469     });
470 
471     return Status::ok();
472 }
473 
initializeInternal(const bool enabled,const std::shared_ptr<INsdPublisher> & aINsdPublisher,const MeshcopTxtAttributes & aMeshcopTxts,const std::shared_ptr<IOtDaemonCallback> & aCallback,const std::string & aCountryCode)474 void OtDaemonServer::initializeInternal(const bool                                enabled,
475                                         const std::shared_ptr<INsdPublisher>     &aINsdPublisher,
476                                         const MeshcopTxtAttributes               &aMeshcopTxts,
477                                         const std::shared_ptr<IOtDaemonCallback> &aCallback,
478                                         const std::string                        &aCountryCode)
479 {
480     std::string              instanceName = aMeshcopTxts.vendorName + " " + aMeshcopTxts.modelName;
481     Mdns::Publisher::TxtList nonStandardTxts;
482     otbrError                error;
483 
484     setCountryCodeInternal(aCountryCode, nullptr /* aReceiver */);
485     registerStateCallbackInternal(aCallback, -1 /* listenerId */);
486 
487     mMdnsPublisher.SetINsdPublisher(aINsdPublisher);
488 
489     for (const auto &txtAttr : aMeshcopTxts.nonStandardTxtEntries)
490     {
491         nonStandardTxts.emplace_back(txtAttr.name.c_str(), txtAttr.value.data(), txtAttr.value.size());
492     }
493     error = mBorderAgent.SetMeshCopServiceValues(instanceName, aMeshcopTxts.modelName, aMeshcopTxts.vendorName,
494                                                  aMeshcopTxts.vendorOui, nonStandardTxts);
495     if (error != OTBR_ERROR_NONE)
496     {
497         otbrLogCrit("Failed to set MeshCoP values: %d", static_cast<int>(error));
498     }
499 
500     mBorderAgent.SetEnabled(enabled);
501 
502     if (enabled)
503     {
504         EnableThread(nullptr /* aReceiver */);
505     }
506     else
507     {
508         UpdateThreadEnabledState(OT_STATE_DISABLED, nullptr /* aReceiver */);
509     }
510 }
511 
terminate(void)512 Status OtDaemonServer::terminate(void)
513 {
514     mTaskRunner.Post([]() {
515         otbrLogWarning("Terminating ot-daemon process...");
516         exit(0);
517     });
518     return Status::ok();
519 }
520 
UpdateThreadEnabledState(const int enabled,const std::shared_ptr<IOtStatusReceiver> & aReceiver)521 void OtDaemonServer::UpdateThreadEnabledState(const int enabled, const std::shared_ptr<IOtStatusReceiver> &aReceiver)
522 {
523     VerifyOrExit(enabled != mState.threadEnabled);
524 
525     otbrLogInfo("Thread enabled state changed: %s -> %s", ThreadEnabledStateToString(mState.threadEnabled),
526                 ThreadEnabledStateToString(enabled));
527     mState.threadEnabled = enabled;
528 
529     if (aReceiver != nullptr)
530     {
531         aReceiver->onSuccess();
532     }
533 
534     // Enables the BorderAgent module only when Thread is enabled because it always
535     // publishes the MeshCoP service even when no Thread network is provisioned.
536     switch (enabled)
537     {
538     case OT_STATE_ENABLED:
539         mBorderAgent.SetEnabled(true);
540         break;
541     case OT_STATE_DISABLED:
542         mBorderAgent.SetEnabled(false);
543         break;
544     }
545 
546     if (mCallback != nullptr)
547     {
548         mCallback->onStateChanged(mState, -1);
549     }
550 
551 exit:
552     return;
553 }
554 
EnableThread(const std::shared_ptr<IOtStatusReceiver> & aReceiver)555 void OtDaemonServer::EnableThread(const std::shared_ptr<IOtStatusReceiver> &aReceiver)
556 {
557     otOperationalDatasetTlvs datasetTlvs;
558 
559     if (otDatasetGetActiveTlvs(GetOtInstance(), &datasetTlvs) != OT_ERROR_NOT_FOUND && datasetTlvs.mLength > 0 &&
560         !isAttached())
561     {
562         (void)otIp6SetEnabled(GetOtInstance(), true);
563         (void)otThreadSetEnabled(GetOtInstance(), true);
564     }
565     UpdateThreadEnabledState(OT_STATE_ENABLED, aReceiver);
566 }
567 
setThreadEnabled(const bool enabled,const std::shared_ptr<IOtStatusReceiver> & aReceiver)568 Status OtDaemonServer::setThreadEnabled(const bool enabled, const std::shared_ptr<IOtStatusReceiver> &aReceiver)
569 {
570     mTaskRunner.Post([enabled, aReceiver, this]() { setThreadEnabledInternal(enabled, aReceiver); });
571 
572     return Status::ok();
573 }
574 
setThreadEnabledInternal(const bool enabled,const std::shared_ptr<IOtStatusReceiver> & aReceiver)575 void OtDaemonServer::setThreadEnabledInternal(const bool enabled, const std::shared_ptr<IOtStatusReceiver> &aReceiver)
576 {
577     int         error = OT_ERROR_NONE;
578     std::string message;
579 
580     VerifyOrExit(GetOtInstance() != nullptr, error = OT_ERROR_INVALID_STATE, message = "OT is not initialized");
581 
582     VerifyOrExit(mState.threadEnabled != OT_STATE_DISABLING, error = OT_ERROR_BUSY, message = "Thread is disabling");
583 
584     if ((mState.threadEnabled == OT_STATE_ENABLED) == enabled)
585     {
586         aReceiver->onSuccess();
587         ExitNow();
588     }
589 
590     if (enabled)
591     {
592         EnableThread(aReceiver);
593     }
594     else
595     {
596         // `aReceiver` should not be set here because the operation isn't finished yet
597         UpdateThreadEnabledState(OT_STATE_DISABLING, nullptr /* aReceiver */);
598 
599         LeaveGracefully([aReceiver, this]() {
600             // Ignore errors as those operations should always succeed
601             (void)otThreadSetEnabled(GetOtInstance(), false);
602             (void)otIp6SetEnabled(GetOtInstance(), false);
603             UpdateThreadEnabledState(OT_STATE_DISABLED, aReceiver);
604         });
605     }
606 
607 exit:
608     if (error != OT_ERROR_NONE)
609     {
610         PropagateResult(error, message, aReceiver);
611     }
612 }
613 
registerStateCallback(const std::shared_ptr<IOtDaemonCallback> & aCallback,int64_t listenerId)614 Status OtDaemonServer::registerStateCallback(const std::shared_ptr<IOtDaemonCallback> &aCallback, int64_t listenerId)
615 {
616     mTaskRunner.Post([aCallback, listenerId, this]() { registerStateCallbackInternal(aCallback, listenerId); });
617 
618     return Status::ok();
619 }
620 
registerStateCallbackInternal(const std::shared_ptr<IOtDaemonCallback> & aCallback,int64_t listenerId)621 void OtDaemonServer::registerStateCallbackInternal(const std::shared_ptr<IOtDaemonCallback> &aCallback,
622                                                    int64_t                                   listenerId)
623 {
624     VerifyOrExit(GetOtInstance() != nullptr, otbrLogWarning("OT is not initialized"));
625 
626     mCallback = aCallback;
627     if (mCallback != nullptr)
628     {
629         AIBinder_linkToDeath(mCallback->asBinder().get(), mClientDeathRecipient.get(), this);
630     }
631 
632     // To ensure that a client app can get the latest correct state immediately when registering a
633     // state callback, here needs to invoke the callback
634     RefreshOtDaemonState(/* aFlags */ 0xffffffff);
635     mCallback->onStateChanged(mState, listenerId);
636     mCallback->onBackboneRouterStateChanged(GetBackboneRouterState());
637 
638 exit:
639     return;
640 }
641 
RefreshOtDaemonState(otChangedFlags aFlags)642 bool OtDaemonServer::RefreshOtDaemonState(otChangedFlags aFlags)
643 {
644     bool haveUpdates = false;
645 
646     if (aFlags & OT_CHANGED_THREAD_NETIF_STATE)
647     {
648         mState.isInterfaceUp = otIp6IsEnabled(GetOtInstance());
649         haveUpdates          = true;
650     }
651 
652     if (aFlags & OT_CHANGED_THREAD_ROLE)
653     {
654         mState.deviceRole = otThreadGetDeviceRole(GetOtInstance());
655         haveUpdates       = true;
656     }
657 
658     if (aFlags & OT_CHANGED_THREAD_PARTITION_ID)
659     {
660         mState.partitionId = otThreadGetPartitionId(GetOtInstance());
661         haveUpdates        = true;
662     }
663 
664     if (aFlags & OT_CHANGED_ACTIVE_DATASET)
665     {
666         otOperationalDatasetTlvs datasetTlvs;
667         if (otDatasetGetActiveTlvs(GetOtInstance(), &datasetTlvs) == OT_ERROR_NONE)
668         {
669             mState.activeDatasetTlvs.assign(datasetTlvs.mTlvs, datasetTlvs.mTlvs + datasetTlvs.mLength);
670         }
671         else
672         {
673             mState.activeDatasetTlvs.clear();
674         }
675         haveUpdates = true;
676     }
677 
678     if (aFlags & OT_CHANGED_PENDING_DATASET)
679     {
680         otOperationalDatasetTlvs datasetTlvs;
681         if (otDatasetGetPendingTlvs(GetOtInstance(), &datasetTlvs) == OT_ERROR_NONE)
682         {
683             mState.pendingDatasetTlvs.assign(datasetTlvs.mTlvs, datasetTlvs.mTlvs + datasetTlvs.mLength);
684         }
685         else
686         {
687             mState.pendingDatasetTlvs.clear();
688         }
689         haveUpdates = true;
690     }
691 
692     if (isAttached() && !mState.activeDatasetTlvs.empty() && mJoinReceiver != nullptr)
693     {
694         otbrLogInfo("Join succeeded");
695         mJoinReceiver->onSuccess();
696         mJoinReceiver = nullptr;
697     }
698 
699     return haveUpdates;
700 }
701 
join(const std::vector<uint8_t> & aActiveOpDatasetTlvs,const std::shared_ptr<IOtStatusReceiver> & aReceiver)702 Status OtDaemonServer::join(const std::vector<uint8_t>               &aActiveOpDatasetTlvs,
703                             const std::shared_ptr<IOtStatusReceiver> &aReceiver)
704 {
705     mTaskRunner.Post([aActiveOpDatasetTlvs, aReceiver, this]() { joinInternal(aActiveOpDatasetTlvs, aReceiver); });
706 
707     return Status::ok();
708 }
709 
joinInternal(const std::vector<uint8_t> & aActiveOpDatasetTlvs,const std::shared_ptr<IOtStatusReceiver> & aReceiver)710 void OtDaemonServer::joinInternal(const std::vector<uint8_t>               &aActiveOpDatasetTlvs,
711                                   const std::shared_ptr<IOtStatusReceiver> &aReceiver)
712 {
713     int                      error = OT_ERROR_NONE;
714     std::string              message;
715     otOperationalDatasetTlvs datasetTlvs;
716 
717     VerifyOrExit(mState.threadEnabled != OT_STATE_DISABLING, error = OT_ERROR_BUSY, message = "Thread is disabling");
718 
719     VerifyOrExit(mState.threadEnabled == OT_STATE_ENABLED,
720                  error   = static_cast<int>(IOtDaemon::ErrorCode::OT_ERROR_THREAD_DISABLED),
721                  message = "Thread is disabled");
722 
723     otbrLogInfo("Start joining...");
724 
725     VerifyOrExit(GetOtInstance() != nullptr, error = OT_ERROR_INVALID_STATE, message = "OT is not initialized");
726 
727     if (otThreadGetDeviceRole(GetOtInstance()) != OT_DEVICE_ROLE_DISABLED)
728     {
729         LeaveGracefully([aActiveOpDatasetTlvs, aReceiver, this]() {
730             FinishLeave(nullptr);
731             join(aActiveOpDatasetTlvs, aReceiver);
732         });
733         ExitNow();
734     }
735 
736     std::copy(aActiveOpDatasetTlvs.begin(), aActiveOpDatasetTlvs.end(), datasetTlvs.mTlvs);
737     datasetTlvs.mLength = static_cast<uint8_t>(aActiveOpDatasetTlvs.size());
738     SuccessOrExit(error   = otDatasetSetActiveTlvs(GetOtInstance(), &datasetTlvs),
739                   message = "Failed to set Active Operational Dataset");
740 
741     // TODO(b/273160198): check how we can implement join as a child
742 
743     // Shouldn't we have an equivalent `otThreadAttach` method vs `otThreadDetachGracefully`?
744     SuccessOrExit(error = otIp6SetEnabled(GetOtInstance(), true), message = "Failed to bring up Thread interface");
745     SuccessOrExit(error = otThreadSetEnabled(GetOtInstance(), true), message = "Failed to bring up Thread stack");
746 
747     // Abort an ongoing join()
748     if (mJoinReceiver != nullptr)
749     {
750         mJoinReceiver->onError(OT_ERROR_ABORT, "Join() is aborted");
751     }
752     mJoinReceiver = aReceiver;
753 
754 exit:
755     if (error != OT_ERROR_NONE)
756     {
757         PropagateResult(error, message, aReceiver);
758     }
759 }
760 
leave(const std::shared_ptr<IOtStatusReceiver> & aReceiver)761 Status OtDaemonServer::leave(const std::shared_ptr<IOtStatusReceiver> &aReceiver)
762 {
763     mTaskRunner.Post([aReceiver, this]() { leaveInternal(aReceiver); });
764 
765     return Status::ok();
766 }
767 
leaveInternal(const std::shared_ptr<IOtStatusReceiver> & aReceiver)768 void OtDaemonServer::leaveInternal(const std::shared_ptr<IOtStatusReceiver> &aReceiver)
769 {
770     std::string message;
771     int         error = OT_ERROR_NONE;
772 
773     VerifyOrExit(GetOtInstance() != nullptr, error = OT_ERROR_INVALID_STATE, message = "OT is not initialized");
774 
775     VerifyOrExit(mState.threadEnabled != OT_STATE_DISABLING, error = OT_ERROR_BUSY, message = "Thread is disabling");
776 
777     if (mState.threadEnabled == OT_STATE_DISABLED)
778     {
779         FinishLeave(aReceiver);
780         ExitNow();
781     }
782 
783     LeaveGracefully([aReceiver, this]() { FinishLeave(aReceiver); });
784 
785 exit:
786     if (error != OT_ERROR_NONE)
787     {
788         PropagateResult(error, message, aReceiver);
789     }
790 }
791 
FinishLeave(const std::shared_ptr<IOtStatusReceiver> & aReceiver)792 void OtDaemonServer::FinishLeave(const std::shared_ptr<IOtStatusReceiver> &aReceiver)
793 {
794     (void)otInstanceErasePersistentInfo(GetOtInstance());
795     OT_UNUSED_VARIABLE(mApplication); // Avoid the unused-private-field issue.
796     // TODO: b/323301831 - Re-init the Application class.
797     if (aReceiver != nullptr)
798     {
799         aReceiver->onSuccess();
800     }
801 }
802 
LeaveGracefully(const LeaveCallback & aReceiver)803 void OtDaemonServer::LeaveGracefully(const LeaveCallback &aReceiver)
804 {
805     mLeaveCallbacks.push_back(aReceiver);
806 
807     // Ignores the OT_ERROR_BUSY error if a detach has already been requested
808     (void)otThreadDetachGracefully(GetOtInstance(), DetachGracefullyCallback, this);
809 }
810 
DetachGracefullyCallback(void * aBinderServer)811 void OtDaemonServer::DetachGracefullyCallback(void *aBinderServer)
812 {
813     OtDaemonServer *thisServer = static_cast<OtDaemonServer *>(aBinderServer);
814     thisServer->DetachGracefullyCallback();
815 }
816 
DetachGracefullyCallback(void)817 void OtDaemonServer::DetachGracefullyCallback(void)
818 {
819     otbrLogInfo("detach success...");
820 
821     if (mJoinReceiver != nullptr)
822     {
823         mJoinReceiver->onError(OT_ERROR_ABORT, "Aborted by leave/disable operation");
824         mJoinReceiver = nullptr;
825     }
826 
827     if (mMigrationReceiver != nullptr)
828     {
829         mMigrationReceiver->onError(OT_ERROR_ABORT, "Aborted by leave/disable operation");
830         mMigrationReceiver = nullptr;
831     }
832 
833     for (auto &callback : mLeaveCallbacks)
834     {
835         callback();
836     }
837     mLeaveCallbacks.clear();
838 }
839 
isAttached()840 bool OtDaemonServer::isAttached()
841 {
842     otDeviceRole role = otThreadGetDeviceRole(GetOtInstance());
843 
844     return role == OT_DEVICE_ROLE_CHILD || role == OT_DEVICE_ROLE_ROUTER || role == OT_DEVICE_ROLE_LEADER;
845 }
846 
scheduleMigration(const std::vector<uint8_t> & aPendingOpDatasetTlvs,const std::shared_ptr<IOtStatusReceiver> & aReceiver)847 Status OtDaemonServer::scheduleMigration(const std::vector<uint8_t>               &aPendingOpDatasetTlvs,
848                                          const std::shared_ptr<IOtStatusReceiver> &aReceiver)
849 {
850     mTaskRunner.Post(
851         [aPendingOpDatasetTlvs, aReceiver, this]() { scheduleMigrationInternal(aPendingOpDatasetTlvs, aReceiver); });
852 
853     return Status::ok();
854 }
855 
scheduleMigrationInternal(const std::vector<uint8_t> & aPendingOpDatasetTlvs,const std::shared_ptr<IOtStatusReceiver> & aReceiver)856 void OtDaemonServer::scheduleMigrationInternal(const std::vector<uint8_t>               &aPendingOpDatasetTlvs,
857                                                const std::shared_ptr<IOtStatusReceiver> &aReceiver)
858 {
859     int                  error = OT_ERROR_NONE;
860     std::string          message;
861     otOperationalDataset emptyDataset;
862 
863     VerifyOrExit(mState.threadEnabled != OT_STATE_DISABLING, error = OT_ERROR_BUSY, message = "Thread is disabling");
864 
865     VerifyOrExit(mState.threadEnabled == OT_STATE_ENABLED,
866                  error   = static_cast<int>(IOtDaemon::ErrorCode::OT_ERROR_THREAD_DISABLED),
867                  message = "Thread is disabled");
868 
869     if (GetOtInstance() == nullptr)
870     {
871         message = "OT is not initialized";
872         ExitNow(error = OT_ERROR_INVALID_STATE);
873     }
874     if (!isAttached())
875     {
876         message = "Cannot schedule migration when this device is detached";
877         ExitNow(error = static_cast<int>(IOtDaemon::ErrorCode::OT_ERROR_FAILED_PRECONDITION));
878     }
879 
880     // TODO: check supported channel mask
881 
882     error = otDatasetSendMgmtPendingSet(GetOtInstance(), &emptyDataset, aPendingOpDatasetTlvs.data(),
883                                         static_cast<uint8_t>(aPendingOpDatasetTlvs.size()), SendMgmtPendingSetCallback,
884                                         /* aBinderServer= */ this);
885     if (error != OT_ERROR_NONE)
886     {
887         message = "Failed to send MGMT_PENDING_SET.req";
888     }
889 
890 exit:
891     if (error != OT_ERROR_NONE)
892     {
893         PropagateResult(error, message, aReceiver);
894     }
895     else
896     {
897         // otDatasetSendMgmtPendingSet() returns OT_ERROR_BUSY if it has already been called before but the
898         // callback hasn't been invoked. So we can guarantee that mMigrationReceiver is always nullptr here
899         assert(mMigrationReceiver == nullptr);
900         mMigrationReceiver = aReceiver;
901     }
902 }
903 
SendMgmtPendingSetCallback(otError aResult,void * aBinderServer)904 void OtDaemonServer::SendMgmtPendingSetCallback(otError aResult, void *aBinderServer)
905 {
906     OtDaemonServer *thisServer = static_cast<OtDaemonServer *>(aBinderServer);
907 
908     if (thisServer->mMigrationReceiver != nullptr)
909     {
910         PropagateResult(aResult, "Failed to register Pending Dataset to leader", thisServer->mMigrationReceiver);
911         thisServer->mMigrationReceiver = nullptr;
912     }
913 }
914 
setCountryCode(const std::string & aCountryCode,const std::shared_ptr<IOtStatusReceiver> & aReceiver)915 Status OtDaemonServer::setCountryCode(const std::string                        &aCountryCode,
916                                       const std::shared_ptr<IOtStatusReceiver> &aReceiver)
917 {
918     mTaskRunner.Post([aCountryCode, aReceiver, this]() { setCountryCodeInternal(aCountryCode, aReceiver); });
919 
920     return Status::ok();
921 }
922 
setCountryCodeInternal(const std::string & aCountryCode,const std::shared_ptr<IOtStatusReceiver> & aReceiver)923 void OtDaemonServer::setCountryCodeInternal(const std::string                        &aCountryCode,
924                                             const std::shared_ptr<IOtStatusReceiver> &aReceiver)
925 {
926     static constexpr int kCountryCodeLength = 2;
927     otError              error              = OT_ERROR_NONE;
928     std::string          message;
929     uint16_t             countryCode;
930 
931     VerifyOrExit((aCountryCode.length() == kCountryCodeLength) && isalpha(aCountryCode[0]) && isalpha(aCountryCode[1]),
932                  error = OT_ERROR_INVALID_ARGS, message = "The country code is invalid");
933 
934     otbrLogInfo("Set country code: %c%c", aCountryCode[0], aCountryCode[1]);
935     VerifyOrExit(GetOtInstance() != nullptr, error = OT_ERROR_INVALID_STATE, message = "OT is not initialized");
936 
937     countryCode = static_cast<uint16_t>((aCountryCode[0] << 8) | aCountryCode[1]);
938     SuccessOrExit(error = otLinkSetRegion(GetOtInstance(), countryCode), message = "Failed to set the country code");
939 
940 exit:
941     PropagateResult(error, message, aReceiver);
942 }
943 
getChannelMasks(const std::shared_ptr<IChannelMasksReceiver> & aReceiver)944 Status OtDaemonServer::getChannelMasks(const std::shared_ptr<IChannelMasksReceiver> &aReceiver)
945 {
946     mTaskRunner.Post([aReceiver, this]() { getChannelMasksInternal(aReceiver); });
947 
948     return Status::ok();
949 }
950 
getChannelMasksInternal(const std::shared_ptr<IChannelMasksReceiver> & aReceiver)951 void OtDaemonServer::getChannelMasksInternal(const std::shared_ptr<IChannelMasksReceiver> &aReceiver)
952 {
953     otError  error = OT_ERROR_NONE;
954     uint32_t supportedChannelMask;
955     uint32_t preferredChannelMask;
956 
957     VerifyOrExit(GetOtInstance() != nullptr, error = OT_ERROR_INVALID_STATE);
958 
959     supportedChannelMask = otLinkGetSupportedChannelMask(GetOtInstance());
960     preferredChannelMask = otPlatRadioGetPreferredChannelMask(GetOtInstance());
961 
962 exit:
963     if (aReceiver != nullptr)
964     {
965         if (error == OT_ERROR_NONE)
966         {
967             aReceiver->onSuccess(supportedChannelMask, preferredChannelMask);
968         }
969         else
970         {
971             aReceiver->onError(error, "OT is not initialized");
972         }
973     }
974 }
975 
setChannelMaxPowers(const std::vector<ChannelMaxPower> & aChannelMaxPowers,const std::shared_ptr<IOtStatusReceiver> & aReceiver)976 Status OtDaemonServer::setChannelMaxPowers(const std::vector<ChannelMaxPower>       &aChannelMaxPowers,
977                                            const std::shared_ptr<IOtStatusReceiver> &aReceiver)
978 {
979     mTaskRunner.Post(
980         [aChannelMaxPowers, aReceiver, this]() { setChannelMaxPowersInternal(aChannelMaxPowers, aReceiver); });
981 
982     return Status::ok();
983 }
984 
setChannelMaxPowersInternal(const std::vector<ChannelMaxPower> & aChannelMaxPowers,const std::shared_ptr<IOtStatusReceiver> & aReceiver)985 Status OtDaemonServer::setChannelMaxPowersInternal(const std::vector<ChannelMaxPower>       &aChannelMaxPowers,
986                                                    const std::shared_ptr<IOtStatusReceiver> &aReceiver)
987 {
988     otError     error = OT_ERROR_NONE;
989     std::string message;
990     uint8_t     channel;
991     int16_t     maxPower;
992 
993     VerifyOrExit(GetOtInstance() != nullptr, error = OT_ERROR_INVALID_STATE, message = "OT is not initialized");
994 
995     for (ChannelMaxPower channelMaxPower : aChannelMaxPowers)
996     {
997         VerifyOrExit((channelMaxPower.channel >= OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MIN) &&
998                          (channelMaxPower.channel <= OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MAX),
999                      error = OT_ERROR_INVALID_ARGS, message = "The channel is invalid");
1000         VerifyOrExit((channelMaxPower.maxPower >= INT16_MIN) && (channelMaxPower.maxPower <= INT16_MAX),
1001                      error = OT_ERROR_INVALID_ARGS, message = "The max power is invalid");
1002     }
1003 
1004     for (ChannelMaxPower channelMaxPower : aChannelMaxPowers)
1005     {
1006         channel  = static_cast<uint8_t>(channelMaxPower.channel);
1007         maxPower = static_cast<int16_t>(channelMaxPower.maxPower);
1008         otbrLogInfo("Set channel max power: channel=%u, maxPower=%d", channel, maxPower);
1009         SuccessOrExit(error   = otPlatRadioSetChannelTargetPower(GetOtInstance(), channel, maxPower),
1010                       message = "Failed to set channel max power");
1011     }
1012 
1013 exit:
1014     PropagateResult(error, message, aReceiver);
1015     return Status::ok();
1016 }
1017 
configureBorderRouter(const BorderRouterConfigurationParcel & aBorderRouterConfiguration,const std::shared_ptr<IOtStatusReceiver> & aReceiver)1018 Status OtDaemonServer::configureBorderRouter(const BorderRouterConfigurationParcel    &aBorderRouterConfiguration,
1019                                              const std::shared_ptr<IOtStatusReceiver> &aReceiver)
1020 {
1021     int         icmp6SocketFd               = aBorderRouterConfiguration.infraInterfaceIcmp6Socket.dup().release();
1022     std::string infraInterfaceName          = aBorderRouterConfiguration.infraInterfaceName;
1023     bool        isBorderRoutingEnabled      = aBorderRouterConfiguration.isBorderRoutingEnabled;
1024     bool        isBorderRouterConfigChanged = (mBorderRouterConfiguration != aBorderRouterConfiguration);
1025 
1026     otbrLogInfo("Configuring Border Router: %s", aBorderRouterConfiguration.toString().c_str());
1027 
1028     // The copy constructor of `BorderRouterConfigurationParcel` is deleted. It is unable to directly pass the
1029     // `aBorderRouterConfiguration` to the lambda function. Only the necessary parameters of
1030     // `BorderRouterConfigurationParcel` are passed to the lambda function here.
1031     mTaskRunner.Post(
1032         [icmp6SocketFd, infraInterfaceName, isBorderRoutingEnabled, isBorderRouterConfigChanged, aReceiver, this]() {
1033             configureBorderRouterInternal(icmp6SocketFd, infraInterfaceName, isBorderRoutingEnabled,
1034                                           isBorderRouterConfigChanged, aReceiver);
1035         });
1036 
1037     return Status::ok();
1038 }
1039 
configureBorderRouterInternal(int aIcmp6SocketFd,const std::string & aInfraInterfaceName,bool aIsBorderRoutingEnabled,bool aIsBorderRouterConfigChanged,const std::shared_ptr<IOtStatusReceiver> & aReceiver)1040 void OtDaemonServer::configureBorderRouterInternal(int                aIcmp6SocketFd,
1041                                                    const std::string &aInfraInterfaceName,
1042                                                    bool               aIsBorderRoutingEnabled,
1043                                                    bool               aIsBorderRouterConfigChanged,
1044                                                    const std::shared_ptr<IOtStatusReceiver> &aReceiver)
1045 {
1046     int         icmp6SocketFd = aIcmp6SocketFd;
1047     otError     error         = OT_ERROR_NONE;
1048     std::string message;
1049 
1050     VerifyOrExit(GetOtInstance() != nullptr, error = OT_ERROR_INVALID_STATE, message = "OT is not initialized");
1051 
1052     if (aIsBorderRouterConfigChanged)
1053     {
1054         if (aIsBorderRoutingEnabled)
1055         {
1056             unsigned int infraIfIndex = if_nametoindex(aInfraInterfaceName.c_str());
1057             SuccessOrExit(error   = otBorderRoutingSetEnabled(GetOtInstance(), false /* aEnabled */),
1058                           message = "failed to disable border routing");
1059             otSysSetInfraNetif(aInfraInterfaceName.c_str(), icmp6SocketFd);
1060             icmp6SocketFd = -1;
1061             SuccessOrExit(error   = otBorderRoutingInit(GetOtInstance(), infraIfIndex, otSysInfraIfIsRunning()),
1062                           message = "failed to initialize border routing");
1063             SuccessOrExit(error   = otBorderRoutingSetEnabled(GetOtInstance(), true /* aEnabled */),
1064                           message = "failed to enable border routing");
1065             // TODO: b/320836258 - Make BBR independently configurable
1066             otBackboneRouterSetEnabled(GetOtInstance(), true /* aEnabled */);
1067         }
1068         else
1069         {
1070             SuccessOrExit(error   = otBorderRoutingSetEnabled(GetOtInstance(), false /* aEnabled */),
1071                           message = "failed to disable border routing");
1072             otBackboneRouterSetEnabled(GetOtInstance(), false /* aEnabled */);
1073         }
1074     }
1075 
1076     mBorderRouterConfiguration.isBorderRoutingEnabled = aIsBorderRoutingEnabled;
1077     mBorderRouterConfiguration.infraInterfaceName     = aInfraInterfaceName;
1078 
1079 exit:
1080     if (error != OT_ERROR_NONE)
1081     {
1082         close(icmp6SocketFd);
1083     }
1084     PropagateResult(error, message, aReceiver);
1085 }
1086 
OutputCallback(void * aContext,const char * aFormat,va_list aArguments)1087 static int OutputCallback(void *aContext, const char *aFormat, va_list aArguments)
1088 {
1089     std::string output;
1090 
1091     android::base::StringAppendV(&output, aFormat, aArguments);
1092 
1093     int length = output.length();
1094 
1095     VerifyOrExit(android::base::WriteStringToFd(output, *(static_cast<int *>(aContext))), length = 0);
1096 
1097 exit:
1098     return length;
1099 }
1100 
DumpCliCommand(std::string aCommand,int aFd)1101 inline void DumpCliCommand(std::string aCommand, int aFd)
1102 {
1103     android::base::WriteStringToFd(aCommand + '\n', aFd);
1104     otCliInputLine(aCommand.data());
1105 }
1106 
dump(int aFd,const char ** aArgs,uint32_t aNumArgs)1107 binder_status_t OtDaemonServer::dump(int aFd, const char **aArgs, uint32_t aNumArgs)
1108 {
1109     OT_UNUSED_VARIABLE(aArgs);
1110     OT_UNUSED_VARIABLE(aNumArgs);
1111 
1112     otCliInit(GetOtInstance(), OutputCallback, &aFd);
1113 
1114     DumpCliCommand("state", aFd);
1115     DumpCliCommand("srp server state", aFd);
1116     DumpCliCommand("srp server service", aFd);
1117     DumpCliCommand("srp server host", aFd);
1118     DumpCliCommand("dataset active", aFd);
1119     DumpCliCommand("leaderdata", aFd);
1120     DumpCliCommand("eidcache", aFd);
1121     DumpCliCommand("counters mac", aFd);
1122     DumpCliCommand("counters mle", aFd);
1123     DumpCliCommand("counters ip", aFd);
1124     DumpCliCommand("router table", aFd);
1125     DumpCliCommand("neighbor table", aFd);
1126     DumpCliCommand("ipaddr -v", aFd);
1127     DumpCliCommand("netdata show", aFd);
1128 
1129     fsync(aFd);
1130 
1131     otSysCliInitUsingDaemon(GetOtInstance());
1132 
1133     return STATUS_OK;
1134 }
1135 
PushTelemetryIfConditionMatch()1136 void OtDaemonServer::PushTelemetryIfConditionMatch()
1137 {
1138     VerifyOrExit(GetOtInstance() != nullptr);
1139 
1140     // TODO: Push telemetry per kTelemetryUploadIntervalThreshold instead of on startup.
1141     // TODO: Save unpushed telemetries in local cache to avoid data loss.
1142     RetrieveAndPushAtoms(GetOtInstance());
1143     mTaskRunner.Post(kTelemetryUploadIntervalThreshold, [this]() { PushTelemetryIfConditionMatch(); });
1144 
1145 exit:
1146     return;
1147 }
1148 
1149 } // namespace Android
1150 } // namespace otbr
1151