Loading Android.bp +59 −15 Original line number Diff line number Diff line Loading @@ -96,22 +96,63 @@ aidl_interface { min_sdk_version: "30", }, }, versions: [ "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", ], dumpapi: { no_license: true, }, versions_with_info: [ { version: "1", imports: ["netd_event_listener_interface-V1"], }, { version: "2", imports: ["netd_event_listener_interface-V1"], }, { version: "3", imports: ["netd_event_listener_interface-V1"], }, { version: "4", imports: ["netd_event_listener_interface-V1"], }, { version: "5", imports: ["netd_event_listener_interface-V1"], }, { version: "6", imports: ["netd_event_listener_interface-V1"], }, { version: "7", imports: ["netd_event_listener_interface-V1"], }, { version: "8", imports: ["netd_event_listener_interface-V1"], }, { version: "9", imports: ["netd_event_listener_interface-V1"], }, { version: "10", imports: ["netd_event_listener_interface-V1"], }, { version: "11", imports: ["netd_event_listener_interface-V1"], }, { version: "12", imports: ["netd_event_listener_interface-V1"], }, ], frozen: true, } cc_defaults { Loading Loading @@ -154,7 +195,7 @@ cc_defaults { // after the build process. host_required: [ "net-tests-utils-host-common", ] ], } cc_defaults { Loading @@ -176,7 +217,7 @@ cc_defaults { // after the build process. host_required: [ "net-tests-utils-host-common", ] ], } cc_library { Loading Loading @@ -251,6 +292,9 @@ cc_library { "libssl", "libstatssocket", ], runtime_libs: [ "libcom.android.tethering.dns_helper", ], header_libs: [ "libnetdbinder_utils_headers", ], Loading DnsProxyListener.cpp +69 −4 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ #include <arpa/inet.h> #include <dirent.h> #include <dlfcn.h> #include <linux/if.h> #include <math.h> #include <net/if.h> Loading Loading @@ -661,6 +662,54 @@ std::string makeThreadName(unsigned netId, uint32_t uid) { return fmt::format("Dns_{}_{}", netId, multiuser_get_app_id(uid)); } typedef int (*InitFn)(); typedef int (*IsUidBlockedFn)(uid_t, bool); IsUidBlockedFn ADnsHelper_isUidNetworkingBlocked; IsUidBlockedFn resolveIsUidNetworkingBlockedFn() { // Related BPF maps were mainlined from T. if (!isAtLeastT()) return nullptr; // TODO: Check whether it is safe to shared link the .so without using dlopen when the carrier // APEX module (tethering) is fully released. void* handle = dlopen("libcom.android.tethering.dns_helper.so", RTLD_NOW | RTLD_LOCAL); if (!handle) { LOG(WARNING) << __func__ << ": " << dlerror(); return nullptr; } InitFn ADnsHelper_init = reinterpret_cast<InitFn>(dlsym(handle, "ADnsHelper_init")); if (!ADnsHelper_init) { LOG(ERROR) << __func__ << ": " << dlerror(); abort(); } const int ret = (*ADnsHelper_init)(); if (ret) { LOG(ERROR) << __func__ << ": ADnsHelper_init failed " << strerror(-ret); abort(); } IsUidBlockedFn f = reinterpret_cast<IsUidBlockedFn>(dlsym(handle, "ADnsHelper_isUidNetworkingBlocked")); if (!f) { LOG(ERROR) << __func__ << ": " << dlerror(); abort(); } return f; } bool isUidNetworkingBlocked(uid_t uid, unsigned netId) { if (!ADnsHelper_isUidNetworkingBlocked) return false; // The enforceDnsUid is an OEM feature that sets DNS packet with AID_DNS instead of the // application's UID. Its DNS packets are not subject to certain network restriction features. if (resolv_is_enforceDnsUid_enabled_network(netId)) return false; // TODO: Pass metered information from CS to DNS resolver and replace the hardcode value. return (*ADnsHelper_isUidNetworkingBlocked)(uid, /*metered=*/false) == 1; } } // namespace DnsProxyListener::DnsProxyListener() : FrameworkListener(SOCKET_NAME) { Loading @@ -678,6 +727,8 @@ DnsProxyListener::DnsProxyListener() : FrameworkListener(SOCKET_NAME) { mGetDnsNetIdCommand = std::make_unique<GetDnsNetIdCommand>(); registerCmd(mGetDnsNetIdCommand.get()); ADnsHelper_isUidNetworkingBlocked = resolveIsUidNetworkingBlockedFn(); } void DnsProxyListener::Handler::spawn() { Loading Loading @@ -853,7 +904,10 @@ void DnsProxyListener::GetAddrInfoHandler::run() { int32_t rv = 0; NetworkDnsEventReported event; initDnsEvent(&event, mNetContext); if (startQueryLimiter(uid)) { if (isUidNetworkingBlocked(mNetContext.uid, mNetContext.dns_netid)) { LOG(INFO) << "GetAddrInfoHandler::run: network access blocked"; rv = EAI_FAIL; } else if (startQueryLimiter(uid)) { const char* host = mHost.starts_with('^') ? nullptr : mHost.c_str(); const char* service = mService.starts_with('^') ? nullptr : mService.c_str(); if (evaluate_domain_name(mNetContext, host)) { Loading Loading @@ -1062,11 +1116,15 @@ void DnsProxyListener::ResNSendHandler::run() { int ansLen = -1; NetworkDnsEventReported event; initDnsEvent(&event, mNetContext); if (startQueryLimiter(uid)) { if (isUidNetworkingBlocked(mNetContext.uid, mNetContext.dns_netid)) { LOG(INFO) << "ResNSendHandler::run: network access blocked"; ansLen = -ECONNREFUSED; } else if (startQueryLimiter(uid)) { if (evaluate_domain_name(mNetContext, rr_name.c_str())) { ansLen = resolv_res_nsend(&mNetContext, std::span(msg.data(), msgLen), ansBuf, &rcode, static_cast<ResNsendFlags>(mFlags), &event); } else { // TODO(b/307048182): It should return -errno. ansLen = -EAI_SYSTEM; } endQueryLimiter(uid); Loading Loading @@ -1262,7 +1320,10 @@ void DnsProxyListener::GetHostByNameHandler::run() { int32_t rv = 0; NetworkDnsEventReported event; initDnsEvent(&event, mNetContext); if (startQueryLimiter(uid)) { if (isUidNetworkingBlocked(mNetContext.uid, mNetContext.dns_netid)) { LOG(INFO) << "GetHostByNameHandler::run: network access blocked"; rv = EAI_FAIL; } else if (startQueryLimiter(uid)) { const char* name = mName.starts_with('^') ? nullptr : mName.c_str(); if (evaluate_domain_name(mNetContext, name)) { rv = resolv_gethostbyname(name, mAf, &hbuf, tmpbuf, sizeof tmpbuf, &mNetContext, &hp, Loading Loading @@ -1421,7 +1482,11 @@ void DnsProxyListener::GetHostByAddrHandler::run() { int32_t rv = 0; NetworkDnsEventReported event; initDnsEvent(&event, mNetContext); if (startQueryLimiter(uid)) { if (isUidNetworkingBlocked(mNetContext.uid, mNetContext.dns_netid)) { LOG(INFO) << "GetHostByAddrHandler::run: network access blocked"; rv = EAI_FAIL; } else if (startQueryLimiter(uid)) { // From Android U, evaluate_domain_name() is not only for OEM customization, but also tells // DNS resolver whether the UID can send DNS on the specified network. The function needs // to be called even when there is no domain name to evaluate (GetHostByAddr). This is Loading aidl_api/dnsresolver_aidl_interface/12/.hash 0 → 100644 +1 −0 Original line number Diff line number Diff line a65a6755e2e5f5c160e7be2be814019e2d5491b1 aidl_api/dnsresolver_aidl_interface/12/android/net/IDnsResolver.aidl 0 → 100644 +69 −0 Original line number Diff line number Diff line /////////////////////////////////////////////////////////////////////////////// // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // /////////////////////////////////////////////////////////////////////////////// // This file is a snapshot of an AIDL file. Do not edit it manually. There are // two cases: // 1). this is a frozen version file - do not edit this in any case. // 2). this is a 'current' file. If you make a backwards compatible change to // the interface (from the latest frozen version), the build system will // prompt you to update this file with `m <name>-update-api`. // // You must not make a backward incompatible change to any AIDL file built // with the aidl_interface module type with versions property set. The module // type is used to build AIDL files in a way that they can be used across // independently updatable components of the system. If a device is shipped // with such a backward incompatible change, it has a high risk of breaking // later when a module using the interface is updated, e.g., Mainline modules. package android.net; /* @hide */ interface IDnsResolver { boolean isAlive(); void registerEventListener(android.net.metrics.INetdEventListener listener); void setResolverConfiguration(in android.net.ResolverParamsParcel resolverParams); void getResolverInfo(int netId, out @utf8InCpp String[] servers, out @utf8InCpp String[] domains, out @utf8InCpp String[] tlsServers, out int[] params, out int[] stats, out int[] wait_for_pending_req_timeout_count); void startPrefix64Discovery(int netId); void stopPrefix64Discovery(int netId); @utf8InCpp String getPrefix64(int netId); void createNetworkCache(int netId); void destroyNetworkCache(int netId); void setLogSeverity(int logSeverity); void flushNetworkCache(int netId); void setPrefix64(int netId, @utf8InCpp String prefix); void registerUnsolicitedEventListener(android.net.resolv.aidl.IDnsResolverUnsolicitedEventListener listener); void setResolverOptions(int netId, in android.net.ResolverOptionsParcel optionParams); const int RESOLVER_PARAMS_SAMPLE_VALIDITY = 0; const int RESOLVER_PARAMS_SUCCESS_THRESHOLD = 1; const int RESOLVER_PARAMS_MIN_SAMPLES = 2; const int RESOLVER_PARAMS_MAX_SAMPLES = 3; const int RESOLVER_PARAMS_BASE_TIMEOUT_MSEC = 4; const int RESOLVER_PARAMS_RETRY_COUNT = 5; const int RESOLVER_PARAMS_COUNT = 6; const int RESOLVER_STATS_SUCCESSES = 0; const int RESOLVER_STATS_ERRORS = 1; const int RESOLVER_STATS_TIMEOUTS = 2; const int RESOLVER_STATS_INTERNAL_ERRORS = 3; const int RESOLVER_STATS_RTT_AVG = 4; const int RESOLVER_STATS_LAST_SAMPLE_TIME = 5; const int RESOLVER_STATS_USABLE = 6; const int RESOLVER_STATS_COUNT = 7; const int DNS_RESOLVER_LOG_VERBOSE = 0; const int DNS_RESOLVER_LOG_DEBUG = 1; const int DNS_RESOLVER_LOG_INFO = 2; const int DNS_RESOLVER_LOG_WARNING = 3; const int DNS_RESOLVER_LOG_ERROR = 4; const int TC_MODE_DEFAULT = 0; const int TC_MODE_UDP_TCP = 1; const int TRANSPORT_UNKNOWN = (-1) /* -1 */; const int TRANSPORT_CELLULAR = 0; const int TRANSPORT_WIFI = 1; const int TRANSPORT_BLUETOOTH = 2; const int TRANSPORT_ETHERNET = 3; const int TRANSPORT_VPN = 4; const int TRANSPORT_WIFI_AWARE = 5; const int TRANSPORT_LOWPAN = 6; const int TRANSPORT_TEST = 7; const int TRANSPORT_USB = 8; const int TRANSPORT_THREAD = 9; } aidl_api/dnsresolver_aidl_interface/12/android/net/ResolverHostsParcel.aidl 0 → 100644 +24 −0 Original line number Diff line number Diff line /////////////////////////////////////////////////////////////////////////////// // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // /////////////////////////////////////////////////////////////////////////////// // This file is a snapshot of an AIDL file. Do not edit it manually. There are // two cases: // 1). this is a frozen version file - do not edit this in any case. // 2). this is a 'current' file. If you make a backwards compatible change to // the interface (from the latest frozen version), the build system will // prompt you to update this file with `m <name>-update-api`. // // You must not make a backward incompatible change to any AIDL file built // with the aidl_interface module type with versions property set. The module // type is used to build AIDL files in a way that they can be used across // independently updatable components of the system. If a device is shipped // with such a backward incompatible change, it has a high risk of breaking // later when a module using the interface is updated, e.g., Mainline modules. package android.net; /* @hide */ parcelable ResolverHostsParcel { @utf8InCpp String ipAddr; @utf8InCpp String hostName = ""; } Loading
Android.bp +59 −15 Original line number Diff line number Diff line Loading @@ -96,22 +96,63 @@ aidl_interface { min_sdk_version: "30", }, }, versions: [ "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", ], dumpapi: { no_license: true, }, versions_with_info: [ { version: "1", imports: ["netd_event_listener_interface-V1"], }, { version: "2", imports: ["netd_event_listener_interface-V1"], }, { version: "3", imports: ["netd_event_listener_interface-V1"], }, { version: "4", imports: ["netd_event_listener_interface-V1"], }, { version: "5", imports: ["netd_event_listener_interface-V1"], }, { version: "6", imports: ["netd_event_listener_interface-V1"], }, { version: "7", imports: ["netd_event_listener_interface-V1"], }, { version: "8", imports: ["netd_event_listener_interface-V1"], }, { version: "9", imports: ["netd_event_listener_interface-V1"], }, { version: "10", imports: ["netd_event_listener_interface-V1"], }, { version: "11", imports: ["netd_event_listener_interface-V1"], }, { version: "12", imports: ["netd_event_listener_interface-V1"], }, ], frozen: true, } cc_defaults { Loading Loading @@ -154,7 +195,7 @@ cc_defaults { // after the build process. host_required: [ "net-tests-utils-host-common", ] ], } cc_defaults { Loading @@ -176,7 +217,7 @@ cc_defaults { // after the build process. host_required: [ "net-tests-utils-host-common", ] ], } cc_library { Loading Loading @@ -251,6 +292,9 @@ cc_library { "libssl", "libstatssocket", ], runtime_libs: [ "libcom.android.tethering.dns_helper", ], header_libs: [ "libnetdbinder_utils_headers", ], Loading
DnsProxyListener.cpp +69 −4 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ #include <arpa/inet.h> #include <dirent.h> #include <dlfcn.h> #include <linux/if.h> #include <math.h> #include <net/if.h> Loading Loading @@ -661,6 +662,54 @@ std::string makeThreadName(unsigned netId, uint32_t uid) { return fmt::format("Dns_{}_{}", netId, multiuser_get_app_id(uid)); } typedef int (*InitFn)(); typedef int (*IsUidBlockedFn)(uid_t, bool); IsUidBlockedFn ADnsHelper_isUidNetworkingBlocked; IsUidBlockedFn resolveIsUidNetworkingBlockedFn() { // Related BPF maps were mainlined from T. if (!isAtLeastT()) return nullptr; // TODO: Check whether it is safe to shared link the .so without using dlopen when the carrier // APEX module (tethering) is fully released. void* handle = dlopen("libcom.android.tethering.dns_helper.so", RTLD_NOW | RTLD_LOCAL); if (!handle) { LOG(WARNING) << __func__ << ": " << dlerror(); return nullptr; } InitFn ADnsHelper_init = reinterpret_cast<InitFn>(dlsym(handle, "ADnsHelper_init")); if (!ADnsHelper_init) { LOG(ERROR) << __func__ << ": " << dlerror(); abort(); } const int ret = (*ADnsHelper_init)(); if (ret) { LOG(ERROR) << __func__ << ": ADnsHelper_init failed " << strerror(-ret); abort(); } IsUidBlockedFn f = reinterpret_cast<IsUidBlockedFn>(dlsym(handle, "ADnsHelper_isUidNetworkingBlocked")); if (!f) { LOG(ERROR) << __func__ << ": " << dlerror(); abort(); } return f; } bool isUidNetworkingBlocked(uid_t uid, unsigned netId) { if (!ADnsHelper_isUidNetworkingBlocked) return false; // The enforceDnsUid is an OEM feature that sets DNS packet with AID_DNS instead of the // application's UID. Its DNS packets are not subject to certain network restriction features. if (resolv_is_enforceDnsUid_enabled_network(netId)) return false; // TODO: Pass metered information from CS to DNS resolver and replace the hardcode value. return (*ADnsHelper_isUidNetworkingBlocked)(uid, /*metered=*/false) == 1; } } // namespace DnsProxyListener::DnsProxyListener() : FrameworkListener(SOCKET_NAME) { Loading @@ -678,6 +727,8 @@ DnsProxyListener::DnsProxyListener() : FrameworkListener(SOCKET_NAME) { mGetDnsNetIdCommand = std::make_unique<GetDnsNetIdCommand>(); registerCmd(mGetDnsNetIdCommand.get()); ADnsHelper_isUidNetworkingBlocked = resolveIsUidNetworkingBlockedFn(); } void DnsProxyListener::Handler::spawn() { Loading Loading @@ -853,7 +904,10 @@ void DnsProxyListener::GetAddrInfoHandler::run() { int32_t rv = 0; NetworkDnsEventReported event; initDnsEvent(&event, mNetContext); if (startQueryLimiter(uid)) { if (isUidNetworkingBlocked(mNetContext.uid, mNetContext.dns_netid)) { LOG(INFO) << "GetAddrInfoHandler::run: network access blocked"; rv = EAI_FAIL; } else if (startQueryLimiter(uid)) { const char* host = mHost.starts_with('^') ? nullptr : mHost.c_str(); const char* service = mService.starts_with('^') ? nullptr : mService.c_str(); if (evaluate_domain_name(mNetContext, host)) { Loading Loading @@ -1062,11 +1116,15 @@ void DnsProxyListener::ResNSendHandler::run() { int ansLen = -1; NetworkDnsEventReported event; initDnsEvent(&event, mNetContext); if (startQueryLimiter(uid)) { if (isUidNetworkingBlocked(mNetContext.uid, mNetContext.dns_netid)) { LOG(INFO) << "ResNSendHandler::run: network access blocked"; ansLen = -ECONNREFUSED; } else if (startQueryLimiter(uid)) { if (evaluate_domain_name(mNetContext, rr_name.c_str())) { ansLen = resolv_res_nsend(&mNetContext, std::span(msg.data(), msgLen), ansBuf, &rcode, static_cast<ResNsendFlags>(mFlags), &event); } else { // TODO(b/307048182): It should return -errno. ansLen = -EAI_SYSTEM; } endQueryLimiter(uid); Loading Loading @@ -1262,7 +1320,10 @@ void DnsProxyListener::GetHostByNameHandler::run() { int32_t rv = 0; NetworkDnsEventReported event; initDnsEvent(&event, mNetContext); if (startQueryLimiter(uid)) { if (isUidNetworkingBlocked(mNetContext.uid, mNetContext.dns_netid)) { LOG(INFO) << "GetHostByNameHandler::run: network access blocked"; rv = EAI_FAIL; } else if (startQueryLimiter(uid)) { const char* name = mName.starts_with('^') ? nullptr : mName.c_str(); if (evaluate_domain_name(mNetContext, name)) { rv = resolv_gethostbyname(name, mAf, &hbuf, tmpbuf, sizeof tmpbuf, &mNetContext, &hp, Loading Loading @@ -1421,7 +1482,11 @@ void DnsProxyListener::GetHostByAddrHandler::run() { int32_t rv = 0; NetworkDnsEventReported event; initDnsEvent(&event, mNetContext); if (startQueryLimiter(uid)) { if (isUidNetworkingBlocked(mNetContext.uid, mNetContext.dns_netid)) { LOG(INFO) << "GetHostByAddrHandler::run: network access blocked"; rv = EAI_FAIL; } else if (startQueryLimiter(uid)) { // From Android U, evaluate_domain_name() is not only for OEM customization, but also tells // DNS resolver whether the UID can send DNS on the specified network. The function needs // to be called even when there is no domain name to evaluate (GetHostByAddr). This is Loading
aidl_api/dnsresolver_aidl_interface/12/.hash 0 → 100644 +1 −0 Original line number Diff line number Diff line a65a6755e2e5f5c160e7be2be814019e2d5491b1
aidl_api/dnsresolver_aidl_interface/12/android/net/IDnsResolver.aidl 0 → 100644 +69 −0 Original line number Diff line number Diff line /////////////////////////////////////////////////////////////////////////////// // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // /////////////////////////////////////////////////////////////////////////////// // This file is a snapshot of an AIDL file. Do not edit it manually. There are // two cases: // 1). this is a frozen version file - do not edit this in any case. // 2). this is a 'current' file. If you make a backwards compatible change to // the interface (from the latest frozen version), the build system will // prompt you to update this file with `m <name>-update-api`. // // You must not make a backward incompatible change to any AIDL file built // with the aidl_interface module type with versions property set. The module // type is used to build AIDL files in a way that they can be used across // independently updatable components of the system. If a device is shipped // with such a backward incompatible change, it has a high risk of breaking // later when a module using the interface is updated, e.g., Mainline modules. package android.net; /* @hide */ interface IDnsResolver { boolean isAlive(); void registerEventListener(android.net.metrics.INetdEventListener listener); void setResolverConfiguration(in android.net.ResolverParamsParcel resolverParams); void getResolverInfo(int netId, out @utf8InCpp String[] servers, out @utf8InCpp String[] domains, out @utf8InCpp String[] tlsServers, out int[] params, out int[] stats, out int[] wait_for_pending_req_timeout_count); void startPrefix64Discovery(int netId); void stopPrefix64Discovery(int netId); @utf8InCpp String getPrefix64(int netId); void createNetworkCache(int netId); void destroyNetworkCache(int netId); void setLogSeverity(int logSeverity); void flushNetworkCache(int netId); void setPrefix64(int netId, @utf8InCpp String prefix); void registerUnsolicitedEventListener(android.net.resolv.aidl.IDnsResolverUnsolicitedEventListener listener); void setResolverOptions(int netId, in android.net.ResolverOptionsParcel optionParams); const int RESOLVER_PARAMS_SAMPLE_VALIDITY = 0; const int RESOLVER_PARAMS_SUCCESS_THRESHOLD = 1; const int RESOLVER_PARAMS_MIN_SAMPLES = 2; const int RESOLVER_PARAMS_MAX_SAMPLES = 3; const int RESOLVER_PARAMS_BASE_TIMEOUT_MSEC = 4; const int RESOLVER_PARAMS_RETRY_COUNT = 5; const int RESOLVER_PARAMS_COUNT = 6; const int RESOLVER_STATS_SUCCESSES = 0; const int RESOLVER_STATS_ERRORS = 1; const int RESOLVER_STATS_TIMEOUTS = 2; const int RESOLVER_STATS_INTERNAL_ERRORS = 3; const int RESOLVER_STATS_RTT_AVG = 4; const int RESOLVER_STATS_LAST_SAMPLE_TIME = 5; const int RESOLVER_STATS_USABLE = 6; const int RESOLVER_STATS_COUNT = 7; const int DNS_RESOLVER_LOG_VERBOSE = 0; const int DNS_RESOLVER_LOG_DEBUG = 1; const int DNS_RESOLVER_LOG_INFO = 2; const int DNS_RESOLVER_LOG_WARNING = 3; const int DNS_RESOLVER_LOG_ERROR = 4; const int TC_MODE_DEFAULT = 0; const int TC_MODE_UDP_TCP = 1; const int TRANSPORT_UNKNOWN = (-1) /* -1 */; const int TRANSPORT_CELLULAR = 0; const int TRANSPORT_WIFI = 1; const int TRANSPORT_BLUETOOTH = 2; const int TRANSPORT_ETHERNET = 3; const int TRANSPORT_VPN = 4; const int TRANSPORT_WIFI_AWARE = 5; const int TRANSPORT_LOWPAN = 6; const int TRANSPORT_TEST = 7; const int TRANSPORT_USB = 8; const int TRANSPORT_THREAD = 9; }
aidl_api/dnsresolver_aidl_interface/12/android/net/ResolverHostsParcel.aidl 0 → 100644 +24 −0 Original line number Diff line number Diff line /////////////////////////////////////////////////////////////////////////////// // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // /////////////////////////////////////////////////////////////////////////////// // This file is a snapshot of an AIDL file. Do not edit it manually. There are // two cases: // 1). this is a frozen version file - do not edit this in any case. // 2). this is a 'current' file. If you make a backwards compatible change to // the interface (from the latest frozen version), the build system will // prompt you to update this file with `m <name>-update-api`. // // You must not make a backward incompatible change to any AIDL file built // with the aidl_interface module type with versions property set. The module // type is used to build AIDL files in a way that they can be used across // independently updatable components of the system. If a device is shipped // with such a backward incompatible change, it has a high risk of breaking // later when a module using the interface is updated, e.g., Mainline modules. package android.net; /* @hide */ parcelable ResolverHostsParcel { @utf8InCpp String ipAddr; @utf8InCpp String hostName = ""; }