diff options
12 files changed, 294 insertions, 42 deletions
diff --git a/src/android/aidl/com/android/server/thread/openthread/INsdPublisher.aidl b/src/android/aidl/com/android/server/thread/openthread/INsdPublisher.aidl index 84549f9b..74bec2fb 100644 --- a/src/android/aidl/com/android/server/thread/openthread/INsdPublisher.aidl +++ b/src/android/aidl/com/android/server/thread/openthread/INsdPublisher.aidl @@ -32,6 +32,7 @@ import com.android.server.thread.openthread.DnsTxtAttribute; import com.android.server.thread.openthread.INsdStatusReceiver; import com.android.server.thread.openthread.INsdDiscoverServiceCallback; import com.android.server.thread.openthread.INsdResolveServiceCallback; +import com.android.server.thread.openthread.INsdResolveHostCallback; /** * The service which supports mDNS advertising and discovery by {@link NsdManager}. @@ -150,4 +151,29 @@ oneway interface INsdPublisher { * service resolution operation */ void stopServiceResolution(int listenerId); + + /** + * Resolves an mDNS host. + * + * <p>To stop resolving a host, use stopHostResolution. + * + * @param name the hostname + * @param callback the callback when a host is resolved. + * @param listenerId the ID of DnsResolver.Callback which is used to identify the + * host resolution operation + */ + void resolveHost(in String name, + in INsdResolveHostCallback callback, + int listenerId); + + /** + * Stops resolving an mDNS host. + * + * <p>To stop resolving a host, the caller must pass in the same listener ID which was used + * when starting resolving the host. + * + * @param listenerId the ID of the DnsResolver.Callback which is used to identify the + * host resolution operation + */ + void stopHostResolution(int listenerId); } diff --git a/src/android/aidl/com/android/server/thread/openthread/INsdResolveHostCallback.aidl b/src/android/aidl/com/android/server/thread/openthread/INsdResolveHostCallback.aidl new file mode 100644 index 00000000..920a181e --- /dev/null +++ b/src/android/aidl/com/android/server/thread/openthread/INsdResolveHostCallback.aidl @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2024, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +package com.android.server.thread.openthread; + +/** Receives the information of a resolved host. */ +oneway interface INsdResolveHostCallback { + void onHostResolved(in String name, + in List<String> addresses); +} diff --git a/src/android/aidl/com/android/server/thread/openthread/IOtDaemon.aidl b/src/android/aidl/com/android/server/thread/openthread/IOtDaemon.aidl index d07f72a5..60ee87b6 100644 --- a/src/android/aidl/com/android/server/thread/openthread/IOtDaemon.aidl +++ b/src/android/aidl/com/android/server/thread/openthread/IOtDaemon.aidl @@ -140,9 +140,9 @@ oneway interface IOtDaemon { * Leaves from the current network. * * 1. It returns success immediately if this device has already left or disabled - * 2. Else if there is already an onging {@code join} request, no action will be taken but + * 2. Else if there is already an onging {@code leave} request, no action will be taken but * the {@code receiver} will be invoked after the previous request is completed - * 3. Otherwise, OTBR sends Address Release Notification (i.e. ADDR_REL.ntf) to grcefully + * 3. Otherwise, OTBR sends Address Release Notification (i.e. ADDR_REL.ntf) to gracefully * detach from the current network and it takes 1 second to finish * 4. The Operational Dataset will be removed from persistent storage * diff --git a/src/android/aidl/com/android/server/thread/openthread/IOtDaemonCallback.aidl b/src/android/aidl/com/android/server/thread/openthread/IOtDaemonCallback.aidl index 34bdfaef..7bd6fde6 100644 --- a/src/android/aidl/com/android/server/thread/openthread/IOtDaemonCallback.aidl +++ b/src/android/aidl/com/android/server/thread/openthread/IOtDaemonCallback.aidl @@ -31,6 +31,7 @@ package com.android.server.thread.openthread; import com.android.server.thread.openthread.BackboneRouterState; import com.android.server.thread.openthread.Ipv6AddressInfo; import com.android.server.thread.openthread.OtDaemonState; +import com.android.server.thread.openthread.OnMeshPrefixConfig; /** OpenThread daemon callbacks. */ oneway interface IOtDaemonCallback { @@ -60,10 +61,9 @@ oneway interface IOtDaemonCallback { void onBackboneRouterStateChanged(in BackboneRouterState bbrState); /** - * Called when Thread enabled state has changed. Valid values are STATE_* defined in - * {@link ThreadNetworkController}. + * Called when Thread on-mesh prefixes have changed. * - * @param enabled {@code true} if Thread is enabled, {@code false} if Thread is disabled. + * @param onMeshPrefixConfigList the list of IPv6 prefixes. */ - void onThreadEnabledChanged(in int enabled); + void onPrefixChanged(in List<OnMeshPrefixConfig> onMeshPrefixConfigList); } diff --git a/src/android/aidl/com/android/server/thread/openthread/OnMeshPrefixConfig.aidl b/src/android/aidl/com/android/server/thread/openthread/OnMeshPrefixConfig.aidl new file mode 100644 index 00000000..b7ee7194 --- /dev/null +++ b/src/android/aidl/com/android/server/thread/openthread/OnMeshPrefixConfig.aidl @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2024, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +package com.android.server.thread.openthread; + +/** + * On-mesh prefix configuration. + * + * This is a mapping of <a href="https://openthread.io/reference/struct/ot-border-router-config">otBorderRouterConfig</a> + */ +parcelable OnMeshPrefixConfig { + byte[] prefix; // The raw IPv6 prefix bytes, should be 16 bytes + int prefixLength; // The IPv6 prefix length (in bits) + + // More fields of otBorderRouterConfig can be added here when needed. +} diff --git a/src/android/aidl/com/android/server/thread/openthread/OtDaemonState.aidl b/src/android/aidl/com/android/server/thread/openthread/OtDaemonState.aidl index c13a9492..b96baaa5 100644 --- a/src/android/aidl/com/android/server/thread/openthread/OtDaemonState.aidl +++ b/src/android/aidl/com/android/server/thread/openthread/OtDaemonState.aidl @@ -48,4 +48,7 @@ parcelable OtDaemonState { // Active Oprational Dataset encoded as Thread TLVs. Empty array means the dataset doesn't // exist byte[] pendingDatasetTlvs; + + // The Thread enabled state OT_STATE_DISABLED, OT_STATE_ENABLED and OT_STATE_DISABLING. + int threadEnabled; } diff --git a/src/android/java/com/android/server/thread/openthread/testing/FakeOtDaemon.java b/src/android/java/com/android/server/thread/openthread/testing/FakeOtDaemon.java index ce50eba9..931e3735 100644 --- a/src/android/java/com/android/server/thread/openthread/testing/FakeOtDaemon.java +++ b/src/android/java/com/android/server/thread/openthread/testing/FakeOtDaemon.java @@ -72,7 +72,6 @@ public final class FakeOtDaemon extends IOtDaemon.Stub { private OtDaemonState mState; private BackboneRouterState mBbrState; private boolean mIsInitialized = false; - private int mThreadEnabled = OT_STATE_DISABLED; private int mChannelMasksReceiverOtError = OT_ERROR_NONE; private int mSupportedChannelMask = 0x07FFF800; // from channel 11 to 26 private int mPreferredChannelMask = 0; @@ -98,12 +97,12 @@ public final class FakeOtDaemon extends IOtDaemon.Stub { mState.deviceRole = OT_DEVICE_ROLE_DISABLED; mState.activeDatasetTlvs = new byte[0]; mState.pendingDatasetTlvs = new byte[0]; + mState.threadEnabled = OT_STATE_DISABLED; mBbrState = new BackboneRouterState(); mBbrState.multicastForwardingEnabled = false; mBbrState.listeningAddresses = new ArrayList<>(); mTunFd = null; - mThreadEnabled = OT_STATE_DISABLED; mNsdPublisher = null; mIsInitialized = false; @@ -151,7 +150,7 @@ public final class FakeOtDaemon extends IOtDaemon.Stub { throws RemoteException { mIsInitialized = true; mTunFd = tunFd; - mThreadEnabled = enabled ? OT_STATE_ENABLED : OT_STATE_DISABLED; + mState.threadEnabled = enabled ? OT_STATE_ENABLED : OT_STATE_DISABLED; mNsdPublisher = nsdPublisher; mCountryCode = countryCode; @@ -181,7 +180,7 @@ public final class FakeOtDaemon extends IOtDaemon.Stub { } public int getEnabledState() { - return mThreadEnabled; + return mState.threadEnabled; } public OtDaemonState getState() { @@ -228,7 +227,7 @@ public final class FakeOtDaemon extends IOtDaemon.Stub { public void setThreadEnabled(boolean enabled, IOtStatusReceiver receiver) { mHandler.post( () -> { - mThreadEnabled = enabled ? OT_STATE_ENABLED : OT_STATE_DISABLED; + mState.threadEnabled = enabled ? OT_STATE_ENABLED : OT_STATE_DISABLED; try { receiver.onSuccess(); } catch (RemoteException e) { diff --git a/src/android/mdns_publisher.cpp b/src/android/mdns_publisher.cpp index 6febeccb..0bade461 100644 --- a/src/android/mdns_publisher.cpp +++ b/src/android/mdns_publisher.cpp @@ -108,6 +108,30 @@ Status MdnsPublisher::NsdResolveServiceCallback::onServiceResolved(const std::st return Status::ok(); } +Status MdnsPublisher::NsdResolveHostCallback::onHostResolved(const std::string &aName, + const std::vector<std::string> &aAddresses) +{ + DiscoveredHostInfo info; + + info.mTtl = kDefaultResolvedTtl; + for (const auto &addressStr : aAddresses) + { + Ip6Address address; + int error = Ip6Address::FromString(addressStr.c_str(), address); + + if (error != OTBR_ERROR_NONE) + { + otbrLogInfo("Failed to parse resolved IPv6 address: %s", addressStr.c_str()); + continue; + } + info.mAddresses.push_back(address); + } + + mSubscription.mPublisher.OnHostResolved(aName, info); + + return Status::ok(); +} + void MdnsPublisher::SetINsdPublisher(std::shared_ptr<INsdPublisher> aINsdPublisher) { otbrLogInfo("Set INsdPublisher %p", aINsdPublisher.get()); @@ -151,6 +175,12 @@ std::shared_ptr<MdnsPublisher::NsdResolveServiceCallback> CreateNsdResolveServic return ndk::SharedRefBase::make<MdnsPublisher::NsdResolveServiceCallback>(aServiceSubscription); } +std::shared_ptr<MdnsPublisher::NsdResolveHostCallback> CreateNsdResolveHostCallback( + MdnsPublisher::HostSubscription &aHostSubscription) +{ + return ndk::SharedRefBase::make<MdnsPublisher::NsdResolveHostCallback>(aHostSubscription); +} + void DieForNotImplemented(const char *aFuncName) { VerifyOrDie(false, (std::string(aFuncName) + " is not implemented").c_str()); @@ -359,12 +389,42 @@ exit: void MdnsPublisher::SubscribeHost(const std::string &aHostName) { - OTBR_UNUSED_VARIABLE(aHostName); + auto host = MakeUnique<HostSubscription>(aHostName, *this, mNsdPublisher, AllocateListenerId()); + + VerifyOrExit(IsStarted(), otbrLogWarning("No platform mDNS implementation registered!")); + + mNsdPublisher->resolveHost(aHostName, CreateNsdResolveHostCallback(*host), host->mListenerId); + mHostSubscriptions.push_back(std::move(host)); + + otbrLogInfo("Subscribe host %s (total %zu)", aHostName.c_str(), mHostSubscriptions.size()); + +exit: + return; } void MdnsPublisher::UnsubscribeHost(const std::string &aHostName) { - OTBR_UNUSED_VARIABLE(aHostName); + HostSubscriptionList::iterator it; + + VerifyOrExit(IsStarted()); + + it = std::find_if( + mHostSubscriptions.begin(), mHostSubscriptions.end(), + [&aHostName](const std::unique_ptr<HostSubscription> &aHost) { return aHost->mName == aHostName; }); + + VerifyOrExit(it != mHostSubscriptions.end(), + otbrLogWarning("The host %s is already unsubscribed.", aHostName.c_str())); + + { + std::unique_ptr<HostSubscription> host = std::move(*it); + + mHostSubscriptions.erase(it); + } + + otbrLogInfo("Unsubscribe host %s (left %zu)", aHostName.c_str(), mHostSubscriptions.size()); + +exit: + return; } void MdnsPublisher::OnServiceResolveFailedImpl(const std::string &aType, diff --git a/src/android/mdns_publisher.hpp b/src/android/mdns_publisher.hpp index 64793dc5..723532ea 100644 --- a/src/android/mdns_publisher.hpp +++ b/src/android/mdns_publisher.hpp @@ -32,6 +32,7 @@ #include "mdns/mdns.hpp" #include <aidl/com/android/server/thread/openthread/BnNsdDiscoverServiceCallback.h> +#include <aidl/com/android/server/thread/openthread/BnNsdResolveHostCallback.h> #include <aidl/com/android/server/thread/openthread/BnNsdResolveServiceCallback.h> #include <aidl/com/android/server/thread/openthread/BnNsdStatusReceiver.h> #include <aidl/com/android/server/thread/openthread/DnsTxtAttribute.h> @@ -42,6 +43,7 @@ namespace otbr { namespace Android { using Status = ::ndk::ScopedAStatus; using aidl::com::android::server::thread::openthread::BnNsdDiscoverServiceCallback; +using aidl::com::android::server::thread::openthread::BnNsdResolveHostCallback; using aidl::com::android::server::thread::openthread::BnNsdResolveServiceCallback; using aidl::com::android::server::thread::openthread::BnNsdStatusReceiver; using aidl::com::android::server::thread::openthread::DnsTxtAttribute; @@ -157,6 +159,29 @@ public: std::map<std::string, std::set<ServiceResolver *>> mResolvers; }; + struct HostSubscription : private ::NonCopyable + { + explicit HostSubscription(std::string aName, + MdnsPublisher &aPublisher, + std::shared_ptr<INsdPublisher> aNsdPublisher, + int listenerId) + : mName(std::move(aName)) + , mPublisher(aPublisher) + , mNsdPublisher(std::move(aNsdPublisher)) + , mListenerId(listenerId) + { + } + + ~HostSubscription(void) { Release(); } + + void Release(void) { mNsdPublisher->stopHostResolution(mListenerId); } + + std::string mName; + MdnsPublisher &mPublisher; + std::shared_ptr<INsdPublisher> mNsdPublisher; + const int32_t mListenerId; + }; + class NsdDiscoverServiceCallback : public BnNsdDiscoverServiceCallback { public: @@ -191,6 +216,20 @@ public: ServiceSubscription &mSubscription; }; + class NsdResolveHostCallback : public BnNsdResolveHostCallback + { + public: + explicit NsdResolveHostCallback(HostSubscription &aSubscription) + : mSubscription(aSubscription) + { + } + + Status onHostResolved(const std::string &aName, const std::vector<std::string> &aAddresses); + + private: + HostSubscription &mSubscription; + }; + protected: otbrError PublishServiceImpl(const std::string &aHostName, const std::string &aName, @@ -272,9 +311,11 @@ private: }; typedef std::vector<std::unique_ptr<ServiceSubscription>> ServiceSubscriptionList; + typedef std::vector<std::unique_ptr<HostSubscription>> HostSubscriptionList; - static constexpr int kMinResolvedTtl = 1; - static constexpr int kMaxResolvedTtl = 10; + static constexpr int kDefaultResolvedTtl = 10; + static constexpr int kMinResolvedTtl = 1; + static constexpr int kMaxResolvedTtl = 10; int32_t AllocateListenerId(void); @@ -282,6 +323,7 @@ private: int32_t mNextListenerId; std::shared_ptr<INsdPublisher> mNsdPublisher = nullptr; ServiceSubscriptionList mServiceSubscriptions; + HostSubscriptionList mHostSubscriptions; }; } // namespace Android diff --git a/src/android/otdaemon_server.cpp b/src/android/otdaemon_server.cpp index 1401d513..030556eb 100644 --- a/src/android/otdaemon_server.cpp +++ b/src/android/otdaemon_server.cpp @@ -155,6 +155,8 @@ void OtDaemonServer::BinderDeathCallback(void *aBinderServer) void OtDaemonServer::StateCallback(otChangedFlags aFlags) { + std::vector<OnMeshPrefixConfig> onMeshPrefixes; + assert(GetOtInstance() != nullptr); if (RefreshOtDaemonState(aFlags)) @@ -168,6 +170,7 @@ void OtDaemonServer::StateCallback(otChangedFlags aFlags) mCallback->onStateChanged(mState, -1); } } + if (aFlags & OT_CHANGED_THREAD_BACKBONE_ROUTER_STATE) { if (mCallback == nullptr) @@ -179,6 +182,47 @@ void OtDaemonServer::StateCallback(otChangedFlags aFlags) mCallback->onBackboneRouterStateChanged(GetBackboneRouterState()); } } + + if ((aFlags & OT_CHANGED_THREAD_NETDATA) && RefreshOnMeshPrefixes()) + { + if (mCallback == nullptr) + { + otbrLogWarning("Ignoring OT netdata changes: callback is not set"); + } + else + { + onMeshPrefixes.assign(mOnMeshPrefixes.begin(), mOnMeshPrefixes.end()); + mCallback->onPrefixChanged(onMeshPrefixes); + } + } +} + +bool OtDaemonServer::RefreshOnMeshPrefixes() +{ + std::set<OnMeshPrefixConfig> onMeshPrefixConfigs; + otNetworkDataIterator iterator = OT_NETWORK_DATA_ITERATOR_INIT; + otBorderRouterConfig config; + bool rv = false; + + VerifyOrExit(GetOtInstance() != nullptr, otbrLogWarning("Can't get on mesh prefixes: OT is not initialized")); + + while (otNetDataGetNextOnMeshPrefix(GetOtInstance(), &iterator, &config) == OT_ERROR_NONE) + { + OnMeshPrefixConfig onMeshPrefixConfig; + + onMeshPrefixConfig.prefix.assign(std::begin(config.mPrefix.mPrefix.mFields.m8), + std::end(config.mPrefix.mPrefix.mFields.m8)); + onMeshPrefixConfig.prefixLength = config.mPrefix.mLength; + onMeshPrefixConfigs.insert(onMeshPrefixConfig); + } + + if (mOnMeshPrefixes != onMeshPrefixConfigs) + { + mOnMeshPrefixes = std::move(onMeshPrefixConfigs); + rv = true; + } +exit: + return rv; } Ipv6AddressInfo OtDaemonServer::ConvertToAddressInfo(const otNetifAddress &aAddress) @@ -341,7 +385,6 @@ BackboneRouterState OtDaemonServer::GetBackboneRouterState() state.multicastForwardingEnabled = true; break; } - otbrLogInfo("Updating backbone router state (bbr state = %d)", bbrState); while (otBackboneRouterMulticastListenerGetNext(GetOtInstance(), &iter, &info) == OT_ERROR_NONE) { @@ -446,11 +489,11 @@ void OtDaemonServer::initializeInternal(const bool if (enabled) { - enableThread(nullptr /* aReceiver */); + EnableThread(nullptr /* aReceiver */); } else { - updateThreadEnabledState(OT_STATE_DISABLED, nullptr /* aReceiver */); + UpdateThreadEnabledState(OT_STATE_DISABLED, nullptr /* aReceiver */); } } @@ -463,13 +506,13 @@ Status OtDaemonServer::terminate(void) return Status::ok(); } -void OtDaemonServer::updateThreadEnabledState(const int enabled, const std::shared_ptr<IOtStatusReceiver> &aReceiver) +void OtDaemonServer::UpdateThreadEnabledState(const int enabled, const std::shared_ptr<IOtStatusReceiver> &aReceiver) { - VerifyOrExit(enabled != mThreadEnabled); + VerifyOrExit(enabled != mState.threadEnabled); - otbrLogInfo("Thread enabled state changed: %s -> %s", ThreadEnabledStateToString(mThreadEnabled), + otbrLogInfo("Thread enabled state changed: %s -> %s", ThreadEnabledStateToString(mState.threadEnabled), ThreadEnabledStateToString(enabled)); - mThreadEnabled = enabled; + mState.threadEnabled = enabled; if (aReceiver != nullptr) { @@ -490,14 +533,14 @@ void OtDaemonServer::updateThreadEnabledState(const int enabled, const std::shar if (mCallback != nullptr) { - mCallback->onThreadEnabledChanged(mThreadEnabled); + mCallback->onStateChanged(mState, -1); } exit: return; } -void OtDaemonServer::enableThread(const std::shared_ptr<IOtStatusReceiver> &aReceiver) +void OtDaemonServer::EnableThread(const std::shared_ptr<IOtStatusReceiver> &aReceiver) { otOperationalDatasetTlvs datasetTlvs; @@ -507,7 +550,7 @@ void OtDaemonServer::enableThread(const std::shared_ptr<IOtStatusReceiver> &aRec (void)otIp6SetEnabled(GetOtInstance(), true); (void)otThreadSetEnabled(GetOtInstance(), true); } - updateThreadEnabledState(OT_STATE_ENABLED, aReceiver); + UpdateThreadEnabledState(OT_STATE_ENABLED, aReceiver); } Status OtDaemonServer::setThreadEnabled(const bool enabled, const std::shared_ptr<IOtStatusReceiver> &aReceiver) @@ -524,9 +567,9 @@ void OtDaemonServer::setThreadEnabledInternal(const bool enabled, const std::sha VerifyOrExit(GetOtInstance() != nullptr, error = OT_ERROR_INVALID_STATE, message = "OT is not initialized"); - VerifyOrExit(mThreadEnabled != OT_STATE_DISABLING, error = OT_ERROR_BUSY, message = "Thread is disabling"); + VerifyOrExit(mState.threadEnabled != OT_STATE_DISABLING, error = OT_ERROR_BUSY, message = "Thread is disabling"); - if ((mThreadEnabled == OT_STATE_ENABLED) == enabled) + if ((mState.threadEnabled == OT_STATE_ENABLED) == enabled) { aReceiver->onSuccess(); ExitNow(); @@ -534,18 +577,18 @@ void OtDaemonServer::setThreadEnabledInternal(const bool enabled, const std::sha if (enabled) { - enableThread(aReceiver); + EnableThread(aReceiver); } else { // `aReceiver` should not be set here because the operation isn't finished yet - updateThreadEnabledState(OT_STATE_DISABLING, nullptr /* aReceiver */); + UpdateThreadEnabledState(OT_STATE_DISABLING, nullptr /* aReceiver */); LeaveGracefully([aReceiver, this]() { // Ignore errors as those operations should always succeed (void)otThreadSetEnabled(GetOtInstance(), false); (void)otIp6SetEnabled(GetOtInstance(), false); - updateThreadEnabledState(OT_STATE_DISABLED, aReceiver); + UpdateThreadEnabledState(OT_STATE_DISABLED, aReceiver); }); } @@ -578,7 +621,6 @@ void OtDaemonServer::registerStateCallbackInternal(const std::shared_ptr<IOtDaem // state callback, here needs to invoke the callback RefreshOtDaemonState(/* aFlags */ 0xffffffff); mCallback->onStateChanged(mState, listenerId); - mCallback->onThreadEnabledChanged(mThreadEnabled); mCallback->onBackboneRouterStateChanged(GetBackboneRouterState()); exit: @@ -660,9 +702,9 @@ void OtDaemonServer::joinInternal(const std::vector<uint8_t> &aAct std::string message; otOperationalDatasetTlvs datasetTlvs; - VerifyOrExit(mThreadEnabled != OT_STATE_DISABLING, error = OT_ERROR_BUSY, message = "Thread is disabling"); + VerifyOrExit(mState.threadEnabled != OT_STATE_DISABLING, error = OT_ERROR_BUSY, message = "Thread is disabling"); - VerifyOrExit(mThreadEnabled == OT_STATE_ENABLED, + VerifyOrExit(mState.threadEnabled == OT_STATE_ENABLED, error = static_cast<int>(IOtDaemon::ErrorCode::OT_ERROR_THREAD_DISABLED), message = "Thread is disabled"); @@ -718,9 +760,9 @@ void OtDaemonServer::leaveInternal(const std::shared_ptr<IOtStatusReceiver> &aRe VerifyOrExit(GetOtInstance() != nullptr, error = OT_ERROR_INVALID_STATE, message = "OT is not initialized"); - VerifyOrExit(mThreadEnabled != OT_STATE_DISABLING, error = OT_ERROR_BUSY, message = "Thread is disabling"); + VerifyOrExit(mState.threadEnabled != OT_STATE_DISABLING, error = OT_ERROR_BUSY, message = "Thread is disabling"); - if (mThreadEnabled == OT_STATE_DISABLED) + if (mState.threadEnabled == OT_STATE_DISABLED) { FinishLeave(aReceiver); ExitNow(); @@ -806,9 +848,9 @@ void OtDaemonServer::scheduleMigrationInternal(const std::vector<uint8_t> std::string message; otOperationalDataset emptyDataset; - VerifyOrExit(mThreadEnabled != OT_STATE_DISABLING, error = OT_ERROR_BUSY, message = "Thread is disabling"); + VerifyOrExit(mState.threadEnabled != OT_STATE_DISABLING, error = OT_ERROR_BUSY, message = "Thread is disabling"); - VerifyOrExit(mThreadEnabled == OT_STATE_ENABLED, + VerifyOrExit(mState.threadEnabled == OT_STATE_ENABLED, error = static_cast<int>(IOtDaemon::ErrorCode::OT_ERROR_THREAD_DISABLED), message = "Thread is disabled"); diff --git a/src/android/otdaemon_server.hpp b/src/android/otdaemon_server.hpp index 8566ca9b..11d42f36 100644 --- a/src/android/otdaemon_server.hpp +++ b/src/android/otdaemon_server.hpp @@ -62,6 +62,7 @@ using aidl::com::android::server::thread::openthread::IOtDaemonCallback; using aidl::com::android::server::thread::openthread::IOtStatusReceiver; using aidl::com::android::server::thread::openthread::Ipv6AddressInfo; using aidl::com::android::server::thread::openthread::MeshcopTxtAttributes; +using aidl::com::android::server::thread::openthread::OnMeshPrefixConfig; using aidl::com::android::server::thread::openthread::OtDaemonState; class OtDaemonServer : public BnOtDaemon, public MainloopProcessor, public vendor::VendorServer @@ -154,12 +155,12 @@ private: otBackboneRouterMulticastListenerEvent aEvent, const otIp6Address *aAddress); void PushTelemetryIfConditionMatch(); - void updateThreadEnabledState(const int aEnabled, const std::shared_ptr<IOtStatusReceiver> &aReceiver); - void enableThread(const std::shared_ptr<IOtStatusReceiver> &aReceiver); - Ipv6AddressInfo ConvertToAddressInfo(const otNetifAddress &aAddress); - Ipv6AddressInfo ConvertToAddressInfo(const otNetifMulticastAddress &aAddress); + bool RefreshOnMeshPrefixes(); + Ipv6AddressInfo ConvertToAddressInfo(const otNetifAddress &aAddress); + Ipv6AddressInfo ConvertToAddressInfo(const otNetifMulticastAddress &aAddress); + void UpdateThreadEnabledState(const int aEnabled, const std::shared_ptr<IOtStatusReceiver> &aReceiver); + void EnableThread(const std::shared_ptr<IOtStatusReceiver> &aReceiver); - int mThreadEnabled = OT_STATE_DISABLED; otbr::Application &mApplication; otbr::Ncp::ControllerOpenThread &mNcp; otbr::BorderAgent &mBorderAgent; @@ -175,6 +176,7 @@ private: std::shared_ptr<IOtStatusReceiver> mMigrationReceiver; std::vector<LeaveCallback> mLeaveCallbacks; BorderRouterConfigurationParcel mBorderRouterConfiguration; + std::set<OnMeshPrefixConfig> mOnMeshPrefixes; static constexpr Seconds kTelemetryCheckInterval = Seconds(600); // 600 seconds static constexpr Seconds kTelemetryUploadIntervalThreshold = Seconds(60 * 60 * 12); // 12 hours }; diff --git a/tests/android/java/com/android/server/thread/openthread/testing/FakeOtDaemonTest.java b/tests/android/java/com/android/server/thread/openthread/testing/FakeOtDaemonTest.java index b3758ac1..2ee05537 100644 --- a/tests/android/java/com/android/server/thread/openthread/testing/FakeOtDaemonTest.java +++ b/tests/android/java/com/android/server/thread/openthread/testing/FakeOtDaemonTest.java @@ -186,6 +186,7 @@ public final class FakeOtDaemonTest { assertThat(state.deviceRole).isEqualTo(FakeOtDaemon.OT_DEVICE_ROLE_DISABLED); assertThat(state.activeDatasetTlvs).isEmpty(); assertThat(state.pendingDatasetTlvs).isEmpty(); + assertThat(state.threadEnabled).isEqualTo(OT_STATE_DISABLED); assertThat(listenerIdRef.get()).isEqualTo(7); BackboneRouterState bbrState = bbrStateRef.get(); assertThat(bbrState.multicastForwardingEnabled).isFalse(); @@ -345,6 +346,7 @@ public final class FakeOtDaemonTest { assertThat(state.deviceRole).isEqualTo(OT_DEVICE_ROLE_DISABLED); assertThat(state.activeDatasetTlvs).isEqualTo(new byte[0]); assertThat(state.pendingDatasetTlvs).isEqualTo(new byte[0]); + assertThat(state.threadEnabled).isEqualTo(OT_STATE_DISABLED); BackboneRouterState bbrState = mFakeOtDaemon.getBackboneRouterState(); assertThat(bbrState.multicastForwardingEnabled).isFalse(); assertThat(bbrState.listeningAddresses).isEqualTo(new ArrayList<>()); |