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