diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..ccff05290a --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +# Eclipse project +**/.classpath +**/.project + +# IntelliJ project +**/.idea +**/*.iml +**/*.ipr diff --git a/OWNERS b/OWNERS new file mode 100644 index 0000000000..0e1e65df81 --- /dev/null +++ b/OWNERS @@ -0,0 +1,6 @@ +codewiz@google.com +jchalard@google.com +junyulai@google.com +lorenzo@google.com +reminv@google.com +satk@google.com diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg new file mode 100644 index 0000000000..ebc1264c7a --- /dev/null +++ b/PREUPLOAD.cfg @@ -0,0 +1,4 @@ +[Hook Scripts] +checkstyle_hook = ${REPO_ROOT}/prebuilts/checkstyle/checkstyle.py --sha ${PREUPLOAD_COMMIT} + +ktlint_hook = ${REPO_ROOT}/prebuilts/ktlint/ktlint.py -f ${PREUPLOAD_FILES} diff --git a/TEST_MAPPING b/TEST_MAPPING new file mode 100644 index 0000000000..512851905d --- /dev/null +++ b/TEST_MAPPING @@ -0,0 +1,33 @@ +{ + // Run in addition to mainline-presubmit as mainline-presubmit is not + // supported in every branch. + "presubmit": [ + { + "name": "CtsNetTestCasesLatestSdk", + "options": [ + { + "exclude-annotation": "com.android.testutils.SkipPresubmit" + } + ] + } + ], + "mainline-presubmit": [ + { + // TODO: add back the tethering modules when updatable in this branch + "name": "CtsNetTestCasesLatestSdk[CaptivePortalLoginGoogle.apk+NetworkStackGoogle.apk+com.google.android.resolv.apex]", + "options": [ + { + "exclude-annotation": "com.android.testutils.SkipPresubmit" + } + ] + } + ], + // Tests on physical devices with SIM cards: postsubmit only for capacity constraints + "mainline-postsubmit": [ + { + // TODO: add back the tethering module when updatable in this branch + "name": "CtsNetTestCasesLatestSdk[CaptivePortalLoginGoogle.apk+NetworkStackGoogle.apk+com.google.android.resolv.apex]", + "keywords": ["sim"] + } + ] +} diff --git a/Tethering/Android.bp b/Tethering/Android.bp index 0957526125..7427481172 100644 --- a/Tethering/Android.bp +++ b/Tethering/Android.bp @@ -19,6 +19,7 @@ java_defaults { sdk_version: "module_current", min_sdk_version: "30", srcs: [ + "apishim/**/*.java", "src/**/*.java", ":framework-tethering-shared-srcs", ":tethering-module-utils-srcs", @@ -26,13 +27,15 @@ java_defaults { ], static_libs: [ "androidx.annotation_annotation", - "netd_aidl_interface-java", + "modules-utils-build", "netlink-client", - "networkstack-aidl-interfaces-java", + // TODO: use networkstack-client instead of just including the AIDL interface + "networkstack-aidl-interfaces-unstable-java", "android.hardware.tetheroffload.config-V1.0-java", "android.hardware.tetheroffload.control-V1.0-java", "net-utils-framework-common", "net-utils-device-common", + "netd-client", ], libs: [ "framework-statsd.stubs.module_lib", @@ -59,8 +62,9 @@ cc_library { "com.android.tethering", ], min_sdk_version: "30", + header_libs: ["bpf_syscall_wrappers"], srcs: [ - "jni/android_net_util_TetheringUtils.cpp", + "jni/*.cpp", ], shared_libs: [ "liblog", diff --git a/Tethering/apex/Android.bp b/Tethering/apex/Android.bp index a6ea99e9cc..c99121cae7 100644 --- a/Tethering/apex/Android.bp +++ b/Tethering/apex/Android.bp @@ -16,9 +16,18 @@ apex { name: "com.android.tethering", - updatable: true, - min_sdk_version: "30", - java_libs: ["framework-tethering"], + // TODO: make updatable again once this contains only updatable artifacts (in particular, this + // cannot build as updatable unless service-connectivity builds against stable API). + // updatable: true, + // min_sdk_version: "30", + java_libs: [ + "framework-tethering", + "service-connectivity", + ], + jni_libs: [ + "libservice-connectivity", + ], + bpfs: ["offload.o"], apps: ["Tethering"], manifest: "manifest.json", key: "com.android.tethering.key", diff --git a/Tethering/apishim/30/com/android/networkstack/tethering/apishim/api30/BpfCoordinatorShimImpl.java b/Tethering/apishim/30/com/android/networkstack/tethering/apishim/api30/BpfCoordinatorShimImpl.java new file mode 100644 index 0000000000..5cf0384de7 --- /dev/null +++ b/Tethering/apishim/30/com/android/networkstack/tethering/apishim/api30/BpfCoordinatorShimImpl.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.networkstack.tethering.apishim.api30; + +import android.net.INetd; +import android.net.util.SharedLog; +import android.os.RemoteException; +import android.os.ServiceSpecificException; + +import androidx.annotation.NonNull; + +import com.android.networkstack.tethering.BpfCoordinator.Dependencies; +import com.android.networkstack.tethering.BpfCoordinator.Ipv6ForwardingRule; + +/** + * Bpf coordinator class for API shims. + */ +public class BpfCoordinatorShimImpl + extends com.android.networkstack.tethering.apishim.common.BpfCoordinatorShim { + private static final String TAG = "api30.BpfCoordinatorShimImpl"; + + @NonNull + private final SharedLog mLog; + @NonNull + private final INetd mNetd; + + public BpfCoordinatorShimImpl(@NonNull final Dependencies deps) { + mLog = deps.getSharedLog().forSubComponent(TAG); + mNetd = deps.getNetd(); + } + + @Override + public boolean isInitialized() { + return true; + }; + + @Override + public boolean tetherOffloadRuleAdd(@NonNull final Ipv6ForwardingRule rule) { + try { + mNetd.tetherOffloadRuleAdd(rule.toTetherOffloadRuleParcel()); + } catch (RemoteException | ServiceSpecificException e) { + mLog.e("Could not add IPv6 forwarding rule: ", e); + return false; + } + + return true; + }; + + @Override + public String toString() { + return "Netd used"; + } +} diff --git a/Tethering/apishim/31/com/android/networkstack/tethering/apishim/api31/BpfCoordinatorShimImpl.java b/Tethering/apishim/31/com/android/networkstack/tethering/apishim/api31/BpfCoordinatorShimImpl.java new file mode 100644 index 0000000000..03616cab1c --- /dev/null +++ b/Tethering/apishim/31/com/android/networkstack/tethering/apishim/api31/BpfCoordinatorShimImpl.java @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.networkstack.tethering.apishim.api31; + +import android.net.util.SharedLog; +import android.system.ErrnoException; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.android.networkstack.tethering.BpfCoordinator.Dependencies; +import com.android.networkstack.tethering.BpfCoordinator.Ipv6ForwardingRule; +import com.android.networkstack.tethering.BpfMap; +import com.android.networkstack.tethering.TetherIngressKey; +import com.android.networkstack.tethering.TetherIngressValue; + +/** + * Bpf coordinator class for API shims. + */ +public class BpfCoordinatorShimImpl + extends com.android.networkstack.tethering.apishim.common.BpfCoordinatorShim { + private static final String TAG = "api31.BpfCoordinatorShimImpl"; + + @NonNull + private final SharedLog mLog; + + // BPF map of ingress queueing discipline which pre-processes the packets by the IPv6 + // forwarding rules. + @Nullable + private final BpfMap mBpfIngressMap; + + public BpfCoordinatorShimImpl(@NonNull final Dependencies deps) { + mLog = deps.getSharedLog().forSubComponent(TAG); + mBpfIngressMap = deps.getBpfIngressMap(); + } + + @Override + public boolean isInitialized() { + return mBpfIngressMap != null; + } + + @Override + public boolean tetherOffloadRuleAdd(@NonNull final Ipv6ForwardingRule rule) { + if (!isInitialized()) return false; + + final TetherIngressKey key = rule.makeTetherIngressKey(); + final TetherIngressValue value = rule.makeTetherIngressValue(); + + try { + mBpfIngressMap.updateEntry(key, value); + } catch (ErrnoException e) { + mLog.e("Could not update entry: ", e); + return false; + } + + return true; + } + + @Override + public String toString() { + return "mBpfIngressMap{" + + (mBpfIngressMap != null ? "initialized" : "not initialized") + "} " + + "}"; + } +} diff --git a/Tethering/apishim/common/com/android/networkstack/tethering/apishim/common/BpfCoordinatorShim.java b/Tethering/apishim/common/com/android/networkstack/tethering/apishim/common/BpfCoordinatorShim.java new file mode 100644 index 0000000000..bcb644c5a6 --- /dev/null +++ b/Tethering/apishim/common/com/android/networkstack/tethering/apishim/common/BpfCoordinatorShim.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.networkstack.tethering.apishim.common; + +import androidx.annotation.NonNull; + +import com.android.networkstack.tethering.BpfCoordinator.Dependencies; +import com.android.networkstack.tethering.BpfCoordinator.Ipv6ForwardingRule; + +/** + * Bpf coordinator class for API shims. + */ +public abstract class BpfCoordinatorShim { + /** + * Get BpfCoordinatorShim object by OS build version. + */ + @NonNull + public static BpfCoordinatorShim getBpfCoordinatorShim(@NonNull final Dependencies deps) { + if (deps.isAtLeastS()) { + return new com.android.networkstack.tethering.apishim.api31.BpfCoordinatorShimImpl( + deps); + } else { + return new com.android.networkstack.tethering.apishim.api30.BpfCoordinatorShimImpl( + deps); + } + } + + /** + * Return true if this class has been initialized, otherwise return false. + */ + public abstract boolean isInitialized(); + + /** + * Adds a tethering offload rule to BPF map, or updates it if it already exists. + * + * Currently, only downstream /128 IPv6 entries are supported. An existing rule will be updated + * if the input interface and destination prefix match. Otherwise, a new rule will be created. + * Note that this can be only called on handler thread. + * + * @param rule The rule to add or update. + */ + public abstract boolean tetherOffloadRuleAdd(@NonNull Ipv6ForwardingRule rule); +} + diff --git a/Tethering/bpf_progs/Android.bp b/Tethering/bpf_progs/Android.bp new file mode 100644 index 0000000000..d54f861486 --- /dev/null +++ b/Tethering/bpf_progs/Android.bp @@ -0,0 +1,33 @@ +// +// Copyright (C) 2020 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +// +// bpf kernel programs +// +bpf { + name: "offload.o", + srcs: ["offload.c"], + cflags: [ + "-Wall", + "-Werror", + ], + include_dirs: [ + // TODO: get rid of system/netd. + "system/netd/bpf_progs", // for bpf_net_helpers.h + "system/netd/libnetdbpf/include", // for bpf_shared.h + "system/netd/libnetdutils/include", // for UidConstants.h + ], +} diff --git a/Tethering/bpf_progs/offload.c b/Tethering/bpf_progs/offload.c new file mode 100644 index 0000000000..d8dc60dc1a --- /dev/null +++ b/Tethering/bpf_progs/offload.c @@ -0,0 +1,211 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include + +#include "bpf_helpers.h" +#include "bpf_net_helpers.h" +#include "netdbpf/bpf_shared.h" + +DEFINE_BPF_MAP_GRW(tether_ingress_map, HASH, TetherIngressKey, TetherIngressValue, 64, + AID_NETWORK_STACK) + +// Tethering stats, indexed by upstream interface. +DEFINE_BPF_MAP_GRW(tether_stats_map, HASH, uint32_t, TetherStatsValue, 16, AID_NETWORK_STACK) + +// Tethering data limit, indexed by upstream interface. +// (tethering allowed when stats[iif].rxBytes + stats[iif].txBytes < limit[iif]) +DEFINE_BPF_MAP_GRW(tether_limit_map, HASH, uint32_t, uint64_t, 16, AID_NETWORK_STACK) + +// Used only by TetheringPrivilegedTests, not by production code. +DEFINE_BPF_MAP_GRW(tether_ingress_map_TEST, HASH, TetherIngressKey, TetherIngressValue, 16, + AID_NETWORK_STACK) + +static inline __always_inline int do_forward(struct __sk_buff* skb, bool is_ethernet) { + int l2_header_size = is_ethernet ? sizeof(struct ethhdr) : 0; + void* data = (void*)(long)skb->data; + const void* data_end = (void*)(long)skb->data_end; + struct ethhdr* eth = is_ethernet ? data : NULL; // used iff is_ethernet + struct ipv6hdr* ip6 = is_ethernet ? (void*)(eth + 1) : data; + + // Must be meta-ethernet IPv6 frame + if (skb->protocol != htons(ETH_P_IPV6)) return TC_ACT_OK; + + // Must have (ethernet and) ipv6 header + if (data + l2_header_size + sizeof(*ip6) > data_end) return TC_ACT_OK; + + // Ethertype - if present - must be IPv6 + if (is_ethernet && (eth->h_proto != htons(ETH_P_IPV6))) return TC_ACT_OK; + + // IP version must be 6 + if (ip6->version != 6) return TC_ACT_OK; + + // Cannot decrement during forward if already zero or would be zero, + // Let the kernel's stack handle these cases and generate appropriate ICMP errors. + if (ip6->hop_limit <= 1) return TC_ACT_OK; + + // Protect against forwarding packets sourced from ::1 or fe80::/64 or other weirdness. + __be32 src32 = ip6->saddr.s6_addr32[0]; + if (src32 != htonl(0x0064ff9b) && // 64:ff9b:/32 incl. XLAT464 WKP + (src32 & htonl(0xe0000000)) != htonl(0x20000000)) // 2000::/3 Global Unicast + return TC_ACT_OK; + + TetherIngressKey k = { + .iif = skb->ifindex, + .neigh6 = ip6->daddr, + }; + + TetherIngressValue* v = bpf_tether_ingress_map_lookup_elem(&k); + + // If we don't find any offload information then simply let the core stack handle it... + if (!v) return TC_ACT_OK; + + uint32_t stat_and_limit_k = skb->ifindex; + + TetherStatsValue* stat_v = bpf_tether_stats_map_lookup_elem(&stat_and_limit_k); + + // If we don't have anywhere to put stats, then abort... + if (!stat_v) return TC_ACT_OK; + + uint64_t* limit_v = bpf_tether_limit_map_lookup_elem(&stat_and_limit_k); + + // If we don't have a limit, then abort... + if (!limit_v) return TC_ACT_OK; + + // Required IPv6 minimum mtu is 1280, below that not clear what we should do, abort... + const int pmtu = v->pmtu; + if (pmtu < IPV6_MIN_MTU) return TC_ACT_OK; + + // Approximate handling of TCP/IPv6 overhead for incoming LRO/GRO packets: default + // outbound path mtu of 1500 is not necessarily correct, but worst case we simply + // undercount, which is still better then not accounting for this overhead at all. + // Note: this really shouldn't be device/path mtu at all, but rather should be + // derived from this particular connection's mss (ie. from gro segment size). + // This would require a much newer kernel with newer ebpf accessors. + // (This is also blindly assuming 12 bytes of tcp timestamp option in tcp header) + uint64_t packets = 1; + uint64_t bytes = skb->len; + if (bytes > pmtu) { + const int tcp_overhead = sizeof(struct ipv6hdr) + sizeof(struct tcphdr) + 12; + const int mss = pmtu - tcp_overhead; + const uint64_t payload = bytes - tcp_overhead; + packets = (payload + mss - 1) / mss; + bytes = tcp_overhead * packets + payload; + } + + // Are we past the limit? If so, then abort... + // Note: will not overflow since u64 is 936 years even at 5Gbps. + // Do not drop here. Offload is just that, whenever we fail to handle + // a packet we let the core stack deal with things. + // (The core stack needs to handle limits correctly anyway, + // since we don't offload all traffic in both directions) + if (stat_v->rxBytes + stat_v->txBytes + bytes > *limit_v) return TC_ACT_OK; + + if (!is_ethernet) { + is_ethernet = true; + l2_header_size = sizeof(struct ethhdr); + // Try to inject an ethernet header, and simply return if we fail + if (bpf_skb_change_head(skb, l2_header_size, /*flags*/ 0)) { + __sync_fetch_and_add(&stat_v->rxErrors, 1); + return TC_ACT_OK; + } + + // bpf_skb_change_head() invalidates all pointers - reload them + data = (void*)(long)skb->data; + data_end = (void*)(long)skb->data_end; + eth = data; + ip6 = (void*)(eth + 1); + + // I do not believe this can ever happen, but keep the verifier happy... + if (data + l2_header_size + sizeof(*ip6) > data_end) { + __sync_fetch_and_add(&stat_v->rxErrors, 1); + return TC_ACT_SHOT; + } + }; + + // CHECKSUM_COMPLETE is a 16-bit one's complement sum, + // thus corrections for it need to be done in 16-byte chunks at even offsets. + // IPv6 nexthdr is at offset 6, while hop limit is at offset 7 + uint8_t old_hl = ip6->hop_limit; + --ip6->hop_limit; + uint8_t new_hl = ip6->hop_limit; + + // bpf_csum_update() always succeeds if the skb is CHECKSUM_COMPLETE and returns an error + // (-ENOTSUPP) if it isn't. + bpf_csum_update(skb, 0xFFFF - ntohs(old_hl) + ntohs(new_hl)); + + __sync_fetch_and_add(&stat_v->rxPackets, packets); + __sync_fetch_and_add(&stat_v->rxBytes, bytes); + + // Overwrite any mac header with the new one + *eth = v->macHeader; + + // Redirect to forwarded interface. + // + // Note that bpf_redirect() cannot fail unless you pass invalid flags. + // The redirect actually happens after the ebpf program has already terminated, + // and can fail for example for mtu reasons at that point in time, but there's nothing + // we can do about it here. + return bpf_redirect(v->oif, 0 /* this is effectively BPF_F_EGRESS */); +} + +SEC("schedcls/ingress/tether_ether") +int sched_cls_ingress_tether_ether(struct __sk_buff* skb) { + return do_forward(skb, true); +} + +// Note: section names must be unique to prevent programs from appending to each other, +// so instead the bpf loader will strip everything past the final $ symbol when actually +// pinning the program into the filesystem. +// +// bpf_skb_change_head() is only present on 4.14+ and 2 trivial kernel patches are needed: +// ANDROID: net: bpf: Allow TC programs to call BPF_FUNC_skb_change_head +// ANDROID: net: bpf: permit redirect from ingress L3 to egress L2 devices at near max mtu +// (the first of those has already been upstreamed) +// +// 5.4 kernel support was only added to Android Common Kernel in R, +// and thus a 5.4 kernel always supports this. +// +// Hence, this mandatory (must load successfully) implementation for 5.4+ kernels: +DEFINE_BPF_PROG_KVER("schedcls/ingress/tether_rawip$5_4", AID_ROOT, AID_ROOT, + sched_cls_ingress_tether_rawip_5_4, KVER(5, 4, 0)) +(struct __sk_buff* skb) { + return do_forward(skb, false); +} + +// and this identical optional (may fail to load) implementation for [4.14..5.4) patched kernels: +DEFINE_OPTIONAL_BPF_PROG_KVER_RANGE("schedcls/ingress/tether_rawip$4_14", AID_ROOT, AID_ROOT, + sched_cls_ingress_tether_rawip_4_14, KVER(4, 14, 0), + KVER(5, 4, 0)) +(struct __sk_buff* skb) { + return do_forward(skb, false); +} + +// and define a no-op stub for [4.9,4.14) and unpatched [4.14,5.4) kernels. +// (if the above real 4.14+ program loaded successfully, then bpfloader will have already pinned +// it at the same location this one would be pinned at and will thus skip loading this stub) +DEFINE_BPF_PROG_KVER_RANGE("schedcls/ingress/tether_rawip$stub", AID_ROOT, AID_ROOT, + sched_cls_ingress_tether_rawip_stub, KVER_NONE, KVER(5, 4, 0)) +(struct __sk_buff* skb) { + return TC_ACT_OK; +} + +LICENSE("Apache 2.0"); +CRITICAL("netd"); diff --git a/Tethering/common/TetheringLib/Android.bp b/Tethering/common/TetheringLib/Android.bp index 27b17c3667..a10729daff 100644 --- a/Tethering/common/TetheringLib/Android.bp +++ b/Tethering/common/TetheringLib/Android.bp @@ -17,7 +17,8 @@ java_sdk_library { name: "framework-tethering", defaults: ["framework-module-defaults"], impl_library_visibility: [ - "//packages/modules/Connectivity/Tethering:__subpackages__" + "//frameworks/base/packages/Tethering:__subpackages__", + "//packages/modules/Connectivity/Tethering:__subpackages__", ], srcs: [":framework-tethering-srcs"], diff --git a/Tethering/common/TetheringLib/src/android/net/ITetheringConnector.aidl b/Tethering/common/TetheringLib/src/android/net/ITetheringConnector.aidl index 8be79645bd..cf094aac2c 100644 --- a/Tethering/common/TetheringLib/src/android/net/ITetheringConnector.aidl +++ b/Tethering/common/TetheringLib/src/android/net/ITetheringConnector.aidl @@ -22,25 +22,31 @@ import android.os.ResultReceiver; /** @hide */ oneway interface ITetheringConnector { - void tether(String iface, String callerPkg, IIntResultListener receiver); - - void untether(String iface, String callerPkg, IIntResultListener receiver); - - void setUsbTethering(boolean enable, String callerPkg, IIntResultListener receiver); - - void startTethering(in TetheringRequestParcel request, String callerPkg, + void tether(String iface, String callerPkg, String callingAttributionTag, IIntResultListener receiver); - void stopTethering(int type, String callerPkg, IIntResultListener receiver); + void untether(String iface, String callerPkg, String callingAttributionTag, + IIntResultListener receiver); + + void setUsbTethering(boolean enable, String callerPkg, + String callingAttributionTag, IIntResultListener receiver); + + void startTethering(in TetheringRequestParcel request, String callerPkg, + String callingAttributionTag, IIntResultListener receiver); + + void stopTethering(int type, String callerPkg, String callingAttributionTag, + IIntResultListener receiver); void requestLatestTetheringEntitlementResult(int type, in ResultReceiver receiver, - boolean showEntitlementUi, String callerPkg); + boolean showEntitlementUi, String callerPkg, String callingAttributionTag); void registerTetheringEventCallback(ITetheringEventCallback callback, String callerPkg); void unregisterTetheringEventCallback(ITetheringEventCallback callback, String callerPkg); - void isTetheringSupported(String callerPkg, IIntResultListener receiver); + void isTetheringSupported(String callerPkg, String callingAttributionTag, + IIntResultListener receiver); - void stopAllTethering(String callerPkg, IIntResultListener receiver); + void stopAllTethering(String callerPkg, String callingAttributionTag, + IIntResultListener receiver); } diff --git a/Tethering/common/TetheringLib/src/android/net/TetheringManager.java b/Tethering/common/TetheringLib/src/android/net/TetheringManager.java index 3267195d39..13b05a841d 100644 --- a/Tethering/common/TetheringLib/src/android/net/TetheringManager.java +++ b/Tethering/common/TetheringLib/src/android/net/TetheringManager.java @@ -489,13 +489,20 @@ public class TetheringManager { return dispatcher.waitForResult((connector, listener) -> { try { - connector.tether(iface, callerPkg, listener); + connector.tether(iface, callerPkg, getAttributionTag(), listener); } catch (RemoteException e) { throw new IllegalStateException(e); } }); } + /** + * @return the context's attribution tag + */ + private @Nullable String getAttributionTag() { + return mContext.getAttributionTag(); + } + /** * Stop tethering the named interface. * @@ -514,7 +521,7 @@ public class TetheringManager { return dispatcher.waitForResult((connector, listener) -> { try { - connector.untether(iface, callerPkg, listener); + connector.untether(iface, callerPkg, getAttributionTag(), listener); } catch (RemoteException e) { throw new IllegalStateException(e); } @@ -541,7 +548,8 @@ public class TetheringManager { return dispatcher.waitForResult((connector, listener) -> { try { - connector.setUsbTethering(enable, callerPkg, listener); + connector.setUsbTethering(enable, callerPkg, getAttributionTag(), + listener); } catch (RemoteException e) { throw new IllegalStateException(e); } @@ -740,7 +748,8 @@ public class TetheringManager { }); } }; - getConnector(c -> c.startTethering(request.getParcel(), callerPkg, listener)); + getConnector(c -> c.startTethering(request.getParcel(), callerPkg, + getAttributionTag(), listener)); } /** @@ -780,7 +789,8 @@ public class TetheringManager { final String callerPkg = mContext.getOpPackageName(); Log.i(TAG, "stopTethering caller:" + callerPkg); - getConnector(c -> c.stopTethering(type, callerPkg, new IIntResultListener.Stub() { + getConnector(c -> c.stopTethering(type, callerPkg, getAttributionTag(), + new IIntResultListener.Stub() { @Override public void onResult(int resultCode) { // TODO: provide an API to obtain result @@ -866,7 +876,7 @@ public class TetheringManager { Log.i(TAG, "getLatestTetheringEntitlementResult caller:" + callerPkg); getConnector(c -> c.requestLatestTetheringEntitlementResult( - type, receiver, showEntitlementUi, callerPkg)); + type, receiver, showEntitlementUi, callerPkg, getAttributionTag())); } /** @@ -1317,7 +1327,7 @@ public class TetheringManager { final RequestDispatcher dispatcher = new RequestDispatcher(); final int ret = dispatcher.waitForResult((connector, listener) -> { try { - connector.isTetheringSupported(callerPkg, listener); + connector.isTetheringSupported(callerPkg, getAttributionTag(), listener); } catch (RemoteException e) { throw new IllegalStateException(e); } @@ -1340,14 +1350,15 @@ public class TetheringManager { final String callerPkg = mContext.getOpPackageName(); Log.i(TAG, "stopAllTethering caller:" + callerPkg); - getConnector(c -> c.stopAllTethering(callerPkg, new IIntResultListener.Stub() { - @Override - public void onResult(int resultCode) { - // TODO: add an API parameter to send result to caller. - // This has never been possible as stopAllTethering has always been void and never - // taken a callback object. The only indication that callers have is if the call - // results in a TETHER_STATE_CHANGE broadcast. - } - })); + getConnector(c -> c.stopAllTethering(callerPkg, getAttributionTag(), + new IIntResultListener.Stub() { + @Override + public void onResult(int resultCode) { + // TODO: add an API parameter to send result to caller. + // This has never been possible as stopAllTethering has always been void + // and never taken a callback object. The only indication that callers have + // is if the call results in a TETHER_STATE_CHANGE broadcast. + } + })); } } diff --git a/Tethering/jarjar-rules.txt b/Tethering/jarjar-rules.txt index 591861f5b8..d1ad569e0d 100644 --- a/Tethering/jarjar-rules.txt +++ b/Tethering/jarjar-rules.txt @@ -8,4 +8,7 @@ rule android.util.LocalLog* com.android.networkstack.tethering.util.LocalLog@1 rule android.net.shared.Inet4AddressUtils* com.android.networkstack.tethering.shared.Inet4AddressUtils@1 # Classes from net-utils-framework-common -rule com.android.net.module.util.** com.android.networkstack.tethering.util.@1 \ No newline at end of file +rule com.android.net.module.util.** com.android.networkstack.tethering.util.@1 + +# Classes from net-utils-device-common +rule com.android.net.module.util.Struct* com.android.networkstack.tethering.util.Struct@1 diff --git a/Tethering/jni/android_net_util_TetheringUtils.cpp b/Tethering/jni/android_net_util_TetheringUtils.cpp index 7bfb6dab4a..27c84cf280 100644 --- a/Tethering/jni/android_net_util_TetheringUtils.cpp +++ b/Tethering/jni/android_net_util_TetheringUtils.cpp @@ -28,9 +28,6 @@ #include #include -#define LOG_TAG "TetheringUtils" -#include - namespace android { static const uint32_t kIPv6NextHeaderOffset = offsetof(ip6_hdr, ip6_nxt); @@ -184,18 +181,4 @@ int register_android_net_util_TetheringUtils(JNIEnv* env) { gMethods, NELEM(gMethods)); } -extern "C" jint JNI_OnLoad(JavaVM* vm, void*) { - JNIEnv *env; - if (vm->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_6) != JNI_OK) { - __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "ERROR: GetEnv failed"); - return JNI_ERR; - } - - if (register_android_net_util_TetheringUtils(env) < 0) { - return JNI_ERR; - } - - return JNI_VERSION_1_6; -} - }; // namespace android diff --git a/Tethering/jni/com_android_networkstack_tethering_BpfMap.cpp b/Tethering/jni/com_android_networkstack_tethering_BpfMap.cpp new file mode 100644 index 0000000000..eadc210e31 --- /dev/null +++ b/Tethering/jni/com_android_networkstack_tethering_BpfMap.cpp @@ -0,0 +1,175 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include "nativehelper/scoped_primitive_array.h" +#include "nativehelper/scoped_utf_chars.h" + +#define BPF_FD_JUST_USE_INT +#include "BpfSyscallWrappers.h" + +namespace android { + +static jclass sErrnoExceptionClass; +static jmethodID sErrnoExceptionCtor2; +static jmethodID sErrnoExceptionCtor3; + +static void throwErrnoException(JNIEnv* env, const char* functionName, int error) { + if (sErrnoExceptionClass == nullptr || sErrnoExceptionClass == nullptr) return; + + jthrowable cause = nullptr; + if (env->ExceptionCheck()) { + cause = env->ExceptionOccurred(); + env->ExceptionClear(); + } + + ScopedLocalRef msg(env, env->NewStringUTF(functionName)); + + // Not really much we can do here if msg is null, let's try to stumble on... + if (msg.get() == nullptr) env->ExceptionClear(); + + jobject errnoException; + if (cause != nullptr) { + errnoException = env->NewObject(sErrnoExceptionClass, sErrnoExceptionCtor3, msg.get(), + error, cause); + } else { + errnoException = env->NewObject(sErrnoExceptionClass, sErrnoExceptionCtor2, msg.get(), + error); + } + env->Throw(static_cast(errnoException)); +} + +static jint com_android_networkstack_tethering_BpfMap_closeMap(JNIEnv *env, jobject clazz, + jint fd) { + int ret = close(fd); + + if (ret) throwErrnoException(env, "closeMap", errno); + + return ret; +} + +static jint com_android_networkstack_tethering_BpfMap_bpfFdGet(JNIEnv *env, jobject clazz, + jstring path, jint mode) { + ScopedUtfChars pathname(env, path); + + jint fd = bpf::bpfFdGet(pathname.c_str(), static_cast(mode)); + + return fd; +} + +static void com_android_networkstack_tethering_BpfMap_writeToMapEntry(JNIEnv *env, jobject clazz, + jint fd, jbyteArray key, jbyteArray value, jint flags) { + ScopedByteArrayRO keyRO(env, key); + ScopedByteArrayRO valueRO(env, value); + + int ret = bpf::writeToMapEntry(static_cast(fd), keyRO.get(), valueRO.get(), + static_cast(flags)); + + if (ret) throwErrnoException(env, "writeToMapEntry", errno); +} + +static jboolean throwIfNotEnoent(JNIEnv *env, const char* functionName, int ret, int err) { + if (ret == 0) return true; + + if (err != ENOENT) throwErrnoException(env, functionName, err); + return false; +} + +static jboolean com_android_networkstack_tethering_BpfMap_deleteMapEntry(JNIEnv *env, jobject clazz, + jint fd, jbyteArray key) { + ScopedByteArrayRO keyRO(env, key); + + // On success, zero is returned. If the element is not found, -1 is returned and errno is set + // to ENOENT. + int ret = bpf::deleteMapEntry(static_cast(fd), keyRO.get()); + + return throwIfNotEnoent(env, "deleteMapEntry", ret, errno); +} + +static jboolean com_android_networkstack_tethering_BpfMap_getNextMapKey(JNIEnv *env, jobject clazz, + jint fd, jbyteArray key, jbyteArray nextKey) { + // If key is found, the operation returns zero and sets the next key pointer to the key of the + // next element. If key is not found, the operation returns zero and sets the next key pointer + // to the key of the first element. If key is the last element, -1 is returned and errno is + // set to ENOENT. Other possible errno values are ENOMEM, EFAULT, EPERM, and EINVAL. + ScopedByteArrayRW nextKeyRW(env, nextKey); + int ret; + if (key == nullptr) { + // Called by getFirstKey. Find the first key in the map. + ret = bpf::getNextMapKey(static_cast(fd), nullptr, nextKeyRW.get()); + } else { + ScopedByteArrayRO keyRO(env, key); + ret = bpf::getNextMapKey(static_cast(fd), keyRO.get(), nextKeyRW.get()); + } + + return throwIfNotEnoent(env, "getNextMapKey", ret, errno); +} + +static jboolean com_android_networkstack_tethering_BpfMap_findMapEntry(JNIEnv *env, jobject clazz, + jint fd, jbyteArray key, jbyteArray value) { + ScopedByteArrayRO keyRO(env, key); + ScopedByteArrayRW valueRW(env, value); + + // If an element is found, the operation returns zero and stores the element's value into + // "value". If no element is found, the operation returns -1 and sets errno to ENOENT. + int ret = bpf::findMapEntry(static_cast(fd), keyRO.get(), valueRW.get()); + + return throwIfNotEnoent(env, "findMapEntry", ret, errno); +} + +/* + * JNI registration. + */ +static const JNINativeMethod gMethods[] = { + /* name, signature, funcPtr */ + { "closeMap", "(I)I", + (void*) com_android_networkstack_tethering_BpfMap_closeMap }, + { "bpfFdGet", "(Ljava/lang/String;I)I", + (void*) com_android_networkstack_tethering_BpfMap_bpfFdGet }, + { "writeToMapEntry", "(I[B[BI)V", + (void*) com_android_networkstack_tethering_BpfMap_writeToMapEntry }, + { "deleteMapEntry", "(I[B)Z", + (void*) com_android_networkstack_tethering_BpfMap_deleteMapEntry }, + { "getNextMapKey", "(I[B[B)Z", + (void*) com_android_networkstack_tethering_BpfMap_getNextMapKey }, + { "findMapEntry", "(I[B[B)Z", + (void*) com_android_networkstack_tethering_BpfMap_findMapEntry }, + +}; + +int register_com_android_networkstack_tethering_BpfMap(JNIEnv* env) { + sErrnoExceptionClass = static_cast(env->NewGlobalRef( + env->FindClass("android/system/ErrnoException"))); + if (sErrnoExceptionClass == nullptr) return JNI_ERR; + + sErrnoExceptionCtor2 = env->GetMethodID(sErrnoExceptionClass, "", + "(Ljava/lang/String;I)V"); + if (sErrnoExceptionCtor2 == nullptr) return JNI_ERR; + + sErrnoExceptionCtor3 = env->GetMethodID(sErrnoExceptionClass, "", + "(Ljava/lang/String;ILjava/lang/Throwable;)V"); + if (sErrnoExceptionCtor3 == nullptr) return JNI_ERR; + + return jniRegisterNativeMethods(env, + "com/android/networkstack/tethering/BpfMap", + gMethods, NELEM(gMethods)); +} + +}; // namespace android diff --git a/Tethering/jni/onload.cpp b/Tethering/jni/onload.cpp new file mode 100644 index 0000000000..3766de9076 --- /dev/null +++ b/Tethering/jni/onload.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "jni.h" + +#define LOG_TAG "TetheringJni" +#include + +namespace android { + +int register_android_net_util_TetheringUtils(JNIEnv* env); +int register_com_android_networkstack_tethering_BpfMap(JNIEnv* env); + +extern "C" jint JNI_OnLoad(JavaVM* vm, void*) { + JNIEnv *env; + if (vm->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_6) != JNI_OK) { + __android_log_print(ANDROID_LOG_FATAL, LOG_TAG, "ERROR: GetEnv failed"); + return JNI_ERR; + } + + if (register_android_net_util_TetheringUtils(env) < 0) return JNI_ERR; + + if (register_com_android_networkstack_tethering_BpfMap(env) < 0) return JNI_ERR; + + return JNI_VERSION_1_6; +} + +}; // namespace android diff --git a/Tethering/proguard.flags b/Tethering/proguard.flags index 86b903353c..9ab56c2b61 100644 --- a/Tethering/proguard.flags +++ b/Tethering/proguard.flags @@ -4,6 +4,14 @@ static final int EVENT_*; } +-keep class com.android.networkstack.tethering.BpfMap { + native ; +} + +-keepclassmembers public class * extends com.android.networkstack.tethering.util.Struct { + public (...); +} + -keepclassmembers class android.net.ip.IpServer { static final int CMD_*; } diff --git a/Tethering/res/values-mcc204-mnc04-af/strings.xml b/Tethering/res/values-mcc204-mnc04-af/strings.xml new file mode 100644 index 0000000000..052ca091ac --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-af/strings.xml @@ -0,0 +1,25 @@ + + + + + "Warmkol het nie internet nie" + "Toestelle kan nie aan internet koppel nie" + "Skakel warmkol af" + "Warmkol is aan" + "Bykomende heffings kan geld terwyl jy swerf" + "Gaan voort" + diff --git a/Tethering/res/values-mcc204-mnc04-am/strings.xml b/Tethering/res/values-mcc204-mnc04-am/strings.xml new file mode 100644 index 0000000000..0518c5a14f --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-am/strings.xml @@ -0,0 +1,25 @@ + + + + + "መገናኛ ነጥቡ በይነመረብ የለውም" + "መሣሪያዎች ከበይነመረብ ጋር መገናኘት አይችሉም" + "መገናኛ ነጥብ ያጥፉ" + "የመገናኛ ነጥብ በርቷል" + "በሚያንዣብብበት ጊዜ ተጨማሪ ክፍያዎች ተፈጻሚ ሊሆኑ ይችላሉ" + "ቀጥል" + diff --git a/Tethering/res/values-mcc204-mnc04-ar/strings.xml b/Tethering/res/values-mcc204-mnc04-ar/strings.xml new file mode 100644 index 0000000000..e6d8423f46 --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-ar/strings.xml @@ -0,0 +1,25 @@ + + + + + "نقطة الاتصال غير متصلة بالإنترنت." + "لا يمكن للأجهزة الاتصال بالإنترنت." + "إيقاف نقطة الاتصال" + "نقطة الاتصال مفعّلة" + "قد يتم تطبيق رسوم إضافية أثناء التجوال." + "متابعة" + diff --git a/Tethering/res/values-mcc204-mnc04-as/strings.xml b/Tethering/res/values-mcc204-mnc04-as/strings.xml new file mode 100644 index 0000000000..4c57f21eae --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-as/strings.xml @@ -0,0 +1,25 @@ + + + + + "হটস্পটৰ কোনো ইণ্টাৰনেট নাই" + "ডিভাইচসমূহ ইণ্টাৰনেটৰ সৈতে সংযোগ কৰিব নোৱাৰি" + "হটস্পট অফ কৰক" + "হটস্পট অন হৈ আছে" + "ৰ\'মিঙত থাকিলে অতিৰিক্ত মাচুল প্ৰযোজ্য হ’ব পাৰে" + "অব্যাহত ৰাখক" + diff --git a/Tethering/res/values-mcc204-mnc04-az/strings.xml b/Tethering/res/values-mcc204-mnc04-az/strings.xml new file mode 100644 index 0000000000..2610ab1bec --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-az/strings.xml @@ -0,0 +1,25 @@ + + + + + "Hotspotun internetə girişi yoxdur" + "Cihazlar internetə qoşula bilmir" + "Hotspot\'u deaktiv edin" + "Hotspot aktivdir" + "Rouminq zamanı əlavə ödənişlər tətbiq edilə bilər" + "Davam edin" + diff --git a/Tethering/res/values-mcc204-mnc04-b+sr+Latn/strings.xml b/Tethering/res/values-mcc204-mnc04-b+sr+Latn/strings.xml new file mode 100644 index 0000000000..7b032badf0 --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-b+sr+Latn/strings.xml @@ -0,0 +1,25 @@ + + + + + "Hotspot nema pristup internetu" + "Uređaji ne mogu da se povežu na internet" + "Isključi hotspot" + "Hotspot je uključen" + "Možda važe dodatni troškovi u romingu" + "Nastavi" + diff --git a/Tethering/res/values-mcc204-mnc04-be/strings.xml b/Tethering/res/values-mcc204-mnc04-be/strings.xml new file mode 100644 index 0000000000..2362a1e6a5 --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-be/strings.xml @@ -0,0 +1,25 @@ + + + + + "Хот-спот не падключаны да інтэрнэту" + "Прылады не могуць падключацца да інтэрнэту" + "Выключыць хот-спот" + "Хот-спот уключаны" + "Пры выкарыстанні роўмінгу можа спаганяцца дадатковая плата" + "Працягнуць" + diff --git a/Tethering/res/values-mcc204-mnc04-bg/strings.xml b/Tethering/res/values-mcc204-mnc04-bg/strings.xml new file mode 100644 index 0000000000..6ef1b0bbaf --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-bg/strings.xml @@ -0,0 +1,25 @@ + + + + + "Точката за достъп няма връзка с интернет" + "Устройствата не могат да се свържат с интернет" + "Изключване на точката за достъп" + "Точката за достъп е включена" + "Възможно е да ви бъдат начислени допълнителни такси при роуминг" + "Напред" + diff --git a/Tethering/res/values-mcc204-mnc04-bn/strings.xml b/Tethering/res/values-mcc204-mnc04-bn/strings.xml new file mode 100644 index 0000000000..9a3033c94d --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-bn/strings.xml @@ -0,0 +1,25 @@ + + + + + "হটস্পটের সাথে ইন্টারনেট কানেক্ট করা নেই" + "ডিভাইস ইন্টারনেটের সাথে কানেক্ট করতে পারছে না" + "হটস্পট বন্ধ করুন" + "হটস্পট চালু আছে" + "রোমিংয়ের সময় অতিরিক্ত চার্জ করা হতে পারে" + "চালিয়ে যান" + diff --git a/Tethering/res/values-mcc204-mnc04-bs/strings.xml b/Tethering/res/values-mcc204-mnc04-bs/strings.xml new file mode 100644 index 0000000000..57f6d88a4e --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-bs/strings.xml @@ -0,0 +1,25 @@ + + + + + "Pristupna tačka nema internet" + "Uređaji se ne mogu povezati na internet" + "Isključi pristupnu tačku" + "Pristupna tačka je uključena" + "Mogu nastati dodatni troškovi u romingu" + "Nastavi" + diff --git a/Tethering/res/values-mcc204-mnc04-ca/strings.xml b/Tethering/res/values-mcc204-mnc04-ca/strings.xml new file mode 100644 index 0000000000..e3ad666c0b --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-ca/strings.xml @@ -0,0 +1,25 @@ + + + + + "El punt d\'accés Wi‑Fi no té accés a Internet" + "Els dispositius no es poden connectar a Internet" + "Desactiva el punt d\'accés Wi‑Fi" + "El punt d\'accés Wi‑Fi està activat" + "És possible que s\'apliquin costos addicionals en itinerància" + "Continua" + diff --git a/Tethering/res/values-mcc204-mnc04-cs/strings.xml b/Tethering/res/values-mcc204-mnc04-cs/strings.xml new file mode 100644 index 0000000000..f0992814c1 --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-cs/strings.xml @@ -0,0 +1,25 @@ + + + + + "Hotspot nemá připojení k internetu" + "Zařízení se nemohou připojit k internetu" + "Vypnout hotspot" + "Hotspot je aktivní" + "Při roamingu mohou být účtovány dodatečné poplatky" + "Pokračovat" + diff --git a/Tethering/res/values-mcc204-mnc04-da/strings.xml b/Tethering/res/values-mcc204-mnc04-da/strings.xml new file mode 100644 index 0000000000..1fb2374487 --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-da/strings.xml @@ -0,0 +1,25 @@ + + + + + "Hotspottet har intet internet" + "Enheder kan ikke oprette forbindelse til internettet" + "Deaktiver hotspot" + "Hotspottet er aktiveret" + "Der opkræves muligvis yderligere gebyrer ved roaming" + "Fortsæt" + diff --git a/Tethering/res/values-mcc204-mnc04-de/strings.xml b/Tethering/res/values-mcc204-mnc04-de/strings.xml new file mode 100644 index 0000000000..56d1d1df58 --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-de/strings.xml @@ -0,0 +1,25 @@ + + + + + "Hotspot ist nicht mit dem Internet verbunden" + "Geräte können nicht mit dem Internet verbunden werden" + "Hotspot deaktivieren" + "Hotspot aktiviert" + "Für das Roaming können zusätzliche Gebühren anfallen" + "Weiter" + diff --git a/Tethering/res/values-mcc204-mnc04-el/strings.xml b/Tethering/res/values-mcc204-mnc04-el/strings.xml new file mode 100644 index 0000000000..674f1f6798 --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-el/strings.xml @@ -0,0 +1,25 @@ + + + + + "Το σημείο πρόσβασης Wi-Fi δεν έχει πρόσβαση στο διαδίκτυο." + "Δεν είναι η δυνατή η σύνδεση των συσκευών στο διαδίκτυο." + "Απενεργοποίηση σημείου πρόσβασης Wi-Fi" + "Σημείο πρόσβασης Wi-Fi ενεργό" + "Ενδέχεται να ισχύουν επιπλέον χρεώσεις κατά την περιαγωγή." + "Συνέχεια" + diff --git a/Tethering/res/values-mcc204-mnc04-en-rAU/strings.xml b/Tethering/res/values-mcc204-mnc04-en-rAU/strings.xml new file mode 100644 index 0000000000..3046a3725d --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-en-rAU/strings.xml @@ -0,0 +1,25 @@ + + + + + "Hotspot has no Internet" + "Devices can’t connect to Internet" + "Turn off hotspot" + "Hotspot is on" + "Additional charges may apply while roaming" + "Continue" + diff --git a/Tethering/res/values-mcc204-mnc04-en-rCA/strings.xml b/Tethering/res/values-mcc204-mnc04-en-rCA/strings.xml new file mode 100644 index 0000000000..3046a3725d --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-en-rCA/strings.xml @@ -0,0 +1,25 @@ + + + + + "Hotspot has no Internet" + "Devices can’t connect to Internet" + "Turn off hotspot" + "Hotspot is on" + "Additional charges may apply while roaming" + "Continue" + diff --git a/Tethering/res/values-mcc204-mnc04-en-rGB/strings.xml b/Tethering/res/values-mcc204-mnc04-en-rGB/strings.xml new file mode 100644 index 0000000000..3046a3725d --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-en-rGB/strings.xml @@ -0,0 +1,25 @@ + + + + + "Hotspot has no Internet" + "Devices can’t connect to Internet" + "Turn off hotspot" + "Hotspot is on" + "Additional charges may apply while roaming" + "Continue" + diff --git a/Tethering/res/values-mcc204-mnc04-en-rIN/strings.xml b/Tethering/res/values-mcc204-mnc04-en-rIN/strings.xml new file mode 100644 index 0000000000..3046a3725d --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-en-rIN/strings.xml @@ -0,0 +1,25 @@ + + + + + "Hotspot has no Internet" + "Devices can’t connect to Internet" + "Turn off hotspot" + "Hotspot is on" + "Additional charges may apply while roaming" + "Continue" + diff --git a/Tethering/res/values-mcc204-mnc04-en-rXC/strings.xml b/Tethering/res/values-mcc204-mnc04-en-rXC/strings.xml new file mode 100644 index 0000000000..20c9b94cd5 --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-en-rXC/strings.xml @@ -0,0 +1,25 @@ + + + + + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‏‎‏‎‏‎‏‏‏‎‏‏‎‏‏‎‎‎‎‏‎‏‏‏‏‏‏‎‎‏‎‎‎‏‎‎‏‎‏‎‏‎‎‎‏‏‎‏‎‏‏‏‏‏‎‏‎‎‎Hotspot has no internet‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‏‏‎‎‎‎‏‏‏‏‎‏‏‏‎‎‏‏‏‏‎‏‏‎‏‏‏‎‏‎‏‎‎‏‏‏‎‏‎‎‏‏‎‎‏‎‎‏‎‎‏‎‏‏‎‏‏‎Devices can’t connect to internet‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‎‎‏‎‎‎‏‏‎‎‏‎‎‏‏‎‏‎‎‏‎‏‎‎‏‏‎‎‎‎‏‎‎‎‎‎‏‏‏‎‎‏‏‏‏‏‎‎‎‎‏‎‏‎‎‏‏‎Turn off hotspot‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‎‎‏‏‎‏‏‏‎‎‏‎‎‏‏‎‎‎‏‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‎‏‏‎‏‎‏‎‏‏‏‏‏‎‏‎‏‏‏‎‎‎‎‎Hotspot is on‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‏‎‏‏‎‎‎‏‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‏‎‏‏‏‏‏‎‏‏‎‎‎‏‏‏‏‏‏‎‎‏‎‏‎‏‏‏‎‎‏‎‎Additional charges may apply while roaming‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‏‏‏‏‎‎‎‏‏‎‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‏‎‏‏‎‏‎‎‏‏‏‏‏‎‎‎‎‎‏‏‏‎‎‏‎‎‏‏‎‎Continue‎‏‎‎‏‎" + diff --git a/Tethering/res/values-mcc204-mnc04-es-rUS/strings.xml b/Tethering/res/values-mcc204-mnc04-es-rUS/strings.xml new file mode 100644 index 0000000000..956547cc6d --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-es-rUS/strings.xml @@ -0,0 +1,25 @@ + + + + + "El hotspot no tiene conexión a Internet" + "Los dispositivos no pueden conectarse a Internet" + "Desactiva el hotspot" + "El hotspot está activado" + "Es posible que se apliquen cargos adicionales por roaming" + "Continuar" + diff --git a/Tethering/res/values-mcc204-mnc04-es/strings.xml b/Tethering/res/values-mcc204-mnc04-es/strings.xml new file mode 100644 index 0000000000..831ec1fb1e --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-es/strings.xml @@ -0,0 +1,25 @@ + + + + + "El punto de acceso no tiene conexión a Internet" + "Los dispositivos no se pueden conectar a Internet" + "Desactivar punto de acceso" + "Punto de acceso activado" + "Puede que se apliquen cargos adicionales en itinerancia" + "Continuar" + diff --git a/Tethering/res/values-mcc204-mnc04-et/strings.xml b/Tethering/res/values-mcc204-mnc04-et/strings.xml new file mode 100644 index 0000000000..ff8dde5422 --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-et/strings.xml @@ -0,0 +1,25 @@ + + + + + "Kuumkohal puudub Interneti-ühendus" + "Seadmed ei saa Internetiga ühendust luua" + "Lülita kuumkoht välja" + "Kuumkoht on sees" + "Rändluse kasutamisega võivad kaasneda lisatasud" + "Jätka" + diff --git a/Tethering/res/values-mcc204-mnc04-eu/strings.xml b/Tethering/res/values-mcc204-mnc04-eu/strings.xml new file mode 100644 index 0000000000..c4f70a3eb4 --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-eu/strings.xml @@ -0,0 +1,25 @@ + + + + + "Sare publikoak ez du Interneteko konexiorik" + "Gailuak ezin dira konektatu Internetera" + "Desaktibatu sare publikoa" + "Sare publikoa aktibatuta dago" + "Baliteke kostu gehigarriak ordaindu behar izatea ibiltaritzan" + "Egin aurrera" + diff --git a/Tethering/res/values-mcc204-mnc04-fa/strings.xml b/Tethering/res/values-mcc204-mnc04-fa/strings.xml new file mode 100644 index 0000000000..79e3ef11d6 --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-fa/strings.xml @@ -0,0 +1,25 @@ + + + + + "نقطه اتصال به اینترنت دسترسی ندارد" + "دستگاه‌ها به اینترنت متصل نشدند" + "نقطه اتصال را خاموش کنید" + "نقطه اتصال روشن است" + "ممکن است درحین فراگردی تغییرات دیگر اعمال شود" + "ادامه" + diff --git a/Tethering/res/values-mcc204-mnc04-fi/strings.xml b/Tethering/res/values-mcc204-mnc04-fi/strings.xml new file mode 100644 index 0000000000..64921bca9f --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-fi/strings.xml @@ -0,0 +1,25 @@ + + + + + "Hotspotilla ei ole internetyhteyttä" + "Laitteet eivät voi yhdistää internetiin" + "Laita hotspot pois päältä" + "Hotspot on päällä" + "Roaming voi aiheuttaa lisämaksuja" + "Jatka" + diff --git a/Tethering/res/values-mcc204-mnc04-fr-rCA/strings.xml b/Tethering/res/values-mcc204-mnc04-fr-rCA/strings.xml new file mode 100644 index 0000000000..eda7b59761 --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-fr-rCA/strings.xml @@ -0,0 +1,25 @@ + + + + + "Le point d\'accès n\'est pas connecté à Internet" + "Appareils non connectés à Internet" + "Désactiver le point d\'accès" + "Le point d\'accès est activé" + "En itinérance, des frais supplémentaires peuvent s\'appliquer" + "Continuer" + diff --git a/Tethering/res/values-mcc204-mnc04-fr/strings.xml b/Tethering/res/values-mcc204-mnc04-fr/strings.xml new file mode 100644 index 0000000000..eda7b59761 --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-fr/strings.xml @@ -0,0 +1,25 @@ + + + + + "Le point d\'accès n\'est pas connecté à Internet" + "Appareils non connectés à Internet" + "Désactiver le point d\'accès" + "Le point d\'accès est activé" + "En itinérance, des frais supplémentaires peuvent s\'appliquer" + "Continuer" + diff --git a/Tethering/res/values-mcc204-mnc04-gl/strings.xml b/Tethering/res/values-mcc204-mnc04-gl/strings.xml new file mode 100644 index 0000000000..c163c61fbd --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-gl/strings.xml @@ -0,0 +1,25 @@ + + + + + "A zona wifi non ten acceso a Internet" + "Os dispositivos non se poden conectar a Internet" + "Desactivar zona wifi" + "A zona wifi está activada" + "Pódense aplicar cargos adicionais en itinerancia" + "Continuar" + diff --git a/Tethering/res/values-mcc204-mnc04-gu/strings.xml b/Tethering/res/values-mcc204-mnc04-gu/strings.xml new file mode 100644 index 0000000000..796d42ec52 --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-gu/strings.xml @@ -0,0 +1,25 @@ + + + + + "હૉટસ્પૉટથી ઇન્ટરનેટ ચાલી રહ્યું નથી" + "ડિવાઇસ, ઇન્ટરનેટ સાથે કનેક્ટ થઈ શકતા નથી" + "હૉટસ્પૉટ બંધ કરો" + "હૉટસ્પૉટ ચાલુ છે" + "રોમિંગમાં વધારાના શુલ્ક લાગી શકે છે" + "આગળ વધો" + diff --git a/Tethering/res/values-mcc204-mnc04-hi/strings.xml b/Tethering/res/values-mcc204-mnc04-hi/strings.xml new file mode 100644 index 0000000000..a2442009b5 --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-hi/strings.xml @@ -0,0 +1,25 @@ + + + + + "हॉटस्पॉट से इंटरनेट नहीं चल रहा" + "डिवाइस इंटरनेट से कनेक्ट नहीं हो पा रहे" + "हॉटस्पॉट बंद करें" + "हॉटस्पॉट चालू है" + "रोमिंग के दौरान अतिरिक्त शुल्क लग सकता है" + "जारी रखें" + diff --git a/Tethering/res/values-mcc204-mnc04-hr/strings.xml b/Tethering/res/values-mcc204-mnc04-hr/strings.xml new file mode 100644 index 0000000000..41618afb2e --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-hr/strings.xml @@ -0,0 +1,25 @@ + + + + + "Žarišna točka nema pristup internetu" + "Uređaji se ne mogu povezati s internetom" + "Isključi žarišnu točku" + "Žarišna je točka uključena" + "U roamingu su mogući dodatni troškovi" + "Nastavi" + diff --git a/Tethering/res/values-mcc204-mnc04-hu/strings.xml b/Tethering/res/values-mcc204-mnc04-hu/strings.xml new file mode 100644 index 0000000000..39b7a6975b --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-hu/strings.xml @@ -0,0 +1,25 @@ + + + + + "A hotspot nem csatlakozik az internethez" + "Az eszközök nem tudnak csatlakozni az internethez" + "Hotspot kikapcsolása" + "A hotspot be van kapcsolva" + "Roaming során további díjak léphetnek fel" + "Tovább" + diff --git a/Tethering/res/values-mcc204-mnc04-hy/strings.xml b/Tethering/res/values-mcc204-mnc04-hy/strings.xml new file mode 100644 index 0000000000..c14ae10ad1 --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-hy/strings.xml @@ -0,0 +1,25 @@ + + + + + "Թեժ կետը միացված չէ ինտերնետին" + "Սարքերը չեն կարողանում միանալ ինտերնետին" + "Անջատել թեժ կետը" + "Թեժ կետը միացված է" + "Ռոումինգում կարող են լրացուցիչ վճարներ գանձվել" + "Շարունակել" + diff --git a/Tethering/res/values-mcc204-mnc04-in/strings.xml b/Tethering/res/values-mcc204-mnc04-in/strings.xml new file mode 100644 index 0000000000..1243d22d19 --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-in/strings.xml @@ -0,0 +1,25 @@ + + + + + "Hotspot tidak memiliki koneksi internet" + "Perangkat tidak dapat tersambung ke internet" + "Nonaktifkan hotspot" + "Hotspot aktif" + "Biaya tambahan mungkin berlaku saat roaming" + "Lanjutkan" + diff --git a/Tethering/res/values-mcc204-mnc04-is/strings.xml b/Tethering/res/values-mcc204-mnc04-is/strings.xml new file mode 100644 index 0000000000..82a7d01234 --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-is/strings.xml @@ -0,0 +1,25 @@ + + + + + "Heitur reitur er ekki nettengdur" + "Tæki geta ekki tengst við internetið" + "Slökkva á heitum reit" + "Kveikt er á heitum reit" + "Viðbótargjöld kunna að eiga við í reiki" + "Halda áfram" + diff --git a/Tethering/res/values-mcc204-mnc04-it/strings.xml b/Tethering/res/values-mcc204-mnc04-it/strings.xml new file mode 100644 index 0000000000..a0f52dc89b --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-it/strings.xml @@ -0,0 +1,25 @@ + + + + + "L\'hotspot non ha accesso a Internet" + "I dispositivi non possono connettersi a Internet" + "Disattiva l\'hotspot" + "Hotspot attivo" + "Potrebbero essere applicati costi aggiuntivi durante il roaming" + "Continua" + diff --git a/Tethering/res/values-mcc204-mnc04-iw/strings.xml b/Tethering/res/values-mcc204-mnc04-iw/strings.xml new file mode 100644 index 0000000000..80807bc232 --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-iw/strings.xml @@ -0,0 +1,25 @@ + + + + + "לנקודה לשיתוף אינטרנט אין חיבור לאינטרנט" + "המכשירים לא יכולים להתחבר לאינטרנט" + "כיבוי הנקודה לשיתוף אינטרנט" + "הנקודה לשיתוף אינטרנט פועלת" + "ייתכנו חיובים נוספים בעת נדידה" + "המשך" + diff --git a/Tethering/res/values-mcc204-mnc04-ja/strings.xml b/Tethering/res/values-mcc204-mnc04-ja/strings.xml new file mode 100644 index 0000000000..0e21a7f322 --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-ja/strings.xml @@ -0,0 +1,25 @@ + + + + + "アクセス ポイントがインターネットに接続されていません" + "デバイスをインターネットに接続できません" + "アクセス ポイントを OFF にする" + "アクセス ポイント: ON" + "ローミング時に追加料金が発生することがあります" + "続行" + diff --git a/Tethering/res/values-mcc204-mnc04-ka/strings.xml b/Tethering/res/values-mcc204-mnc04-ka/strings.xml new file mode 100644 index 0000000000..6d3b548744 --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-ka/strings.xml @@ -0,0 +1,25 @@ + + + + + "უსადენო ქსელს არ აქვს ინტერნეტზე წვდომა" + "მოწყობილობები ვერ უკავშირდება ინტერნეტს" + "გამორთეთ უსადენო ქსელი" + "უსადენო ქსელი ჩართულია" + "როუმინგის გამოყენებისას შეიძლება ჩამოგეჭრათ დამატებითი საფასური" + "გაგრძელება" + diff --git a/Tethering/res/values-mcc204-mnc04-kk/strings.xml b/Tethering/res/values-mcc204-mnc04-kk/strings.xml new file mode 100644 index 0000000000..985fc3ff99 --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-kk/strings.xml @@ -0,0 +1,25 @@ + + + + + "Хотспотта интернет жоқ" + "Құрылғылар интернетке қосылмайды" + "Хотспотты өшіру" + "Хотспот қосулы" + "Роуминг кезінде қосымша ақы алынуы мүмкін." + "Жалғастыру" + diff --git a/Tethering/res/values-mcc204-mnc04-km/strings.xml b/Tethering/res/values-mcc204-mnc04-km/strings.xml new file mode 100644 index 0000000000..03b5cb6e4b --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-km/strings.xml @@ -0,0 +1,25 @@ + + + + + "ហតស្ប៉ត​មិនមាន​អ៊ីនធឺណិត​ទេ" + "ឧបករណ៍​មិនអាច​ភ្ជាប់​អ៊ីនធឺណិត​បានទេ" + "បិទ​ហតស្ប៉ត" + "ហតស្ប៉ត​ត្រូវបានបើក" + "អាចមាន​ការគិតថ្លៃ​បន្ថែម នៅពេល​រ៉ូមីង" + "បន្ត" + diff --git a/Tethering/res/values-mcc204-mnc04-kn/strings.xml b/Tethering/res/values-mcc204-mnc04-kn/strings.xml new file mode 100644 index 0000000000..f0adad8e21 --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-kn/strings.xml @@ -0,0 +1,25 @@ + + + + + "ಹಾಟ್‌ಸ್ಪಾಟ್ ಯಾವುದೇ ಇಂಟರ್ನೆಟ್ ಸಂಪರ್ಕವನ್ನು ಹೊಂದಿಲ್ಲ" + "ಇಂಟರ್ನೆಟ್‌ಗೆ ಸಂಪರ್ಕಗೊಳ್ಳಲು ಸಾಧನಗಳಿಗೆ ಸಾಧ್ಯವಾಗುತ್ತಿಲ್ಲ" + "ಹಾಟ್‌ಸ್ಪಾಟ್ ಆಫ್‌ ಮಾಡಿ" + "ಹಾಟ್‌ಸ್ಪಾಟ್ ಆನ್ ಆಗಿದೆ" + "ರೋಮಿಂಗ್‌ನಲ್ಲಿರುವಾಗ ಹೆಚ್ಚುವರಿ ಶುಲ್ಕಗಳು ಅನ್ವಯವಾಗಬಹುದು" + "ಮುಂದುವರಿಸಿ" + diff --git a/Tethering/res/values-mcc204-mnc04-ko/strings.xml b/Tethering/res/values-mcc204-mnc04-ko/strings.xml new file mode 100644 index 0000000000..9218e9a09b --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-ko/strings.xml @@ -0,0 +1,25 @@ + + + + + "핫스팟이 인터넷에 연결되지 않음" + "기기를 인터넷에 연결할 수 없음" + "핫스팟 사용 중지" + "핫스팟 사용 중" + "로밍 중에는 추가 요금이 발생할 수 있습니다." + "계속" + diff --git a/Tethering/res/values-mcc204-mnc04-ky/strings.xml b/Tethering/res/values-mcc204-mnc04-ky/strings.xml new file mode 100644 index 0000000000..35a060aa24 --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-ky/strings.xml @@ -0,0 +1,25 @@ + + + + + "Байланыш түйүнүндө Интернет жок" + "Түзмөктөр Интернетке туташпай жатат" + "Туташуу түйүнүн өчүрүү" + "Кошулуу түйүнү күйүк" + "Роумингде кошумча акы алынышы мүмкүн" + "Улантуу" + diff --git a/Tethering/res/values-mcc204-mnc04-lo/strings.xml b/Tethering/res/values-mcc204-mnc04-lo/strings.xml new file mode 100644 index 0000000000..1d9203b369 --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-lo/strings.xml @@ -0,0 +1,25 @@ + + + + + "ຮັອດສະປອດບໍ່ມີອິນເຕີເນັດ" + "ອຸປະກອນບໍ່ສາມາດເຊື່ອມຕໍ່ອິນເຕີເນັດໄດ້" + "ປິດຮັອດສະປອດ" + "ຮັອດສະປອດເປີດຢູ່" + "ອາດມີຄ່າໃຊ້ຈ່າຍເພີ່ມເຕີມໃນລະຫວ່າງການໂຣມມິງ" + "ສືບຕໍ່" + diff --git a/Tethering/res/values-mcc204-mnc04-lt/strings.xml b/Tethering/res/values-mcc204-mnc04-lt/strings.xml new file mode 100644 index 0000000000..db5178bf2d --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-lt/strings.xml @@ -0,0 +1,25 @@ + + + + + "Nėra viešosios interneto prieigos taško interneto ryšio" + "Įrenginiams nepavyksta prisijungti prie interneto" + "Išjungti viešosios interneto prieigos tašką" + "Viešosios interneto prieigos taškas įjungtas" + "Veikiant tarptinkliniam ryšiui gali būti taikomi papildomi mokesčiai" + "Tęsti" + diff --git a/Tethering/res/values-mcc204-mnc04-lv/strings.xml b/Tethering/res/values-mcc204-mnc04-lv/strings.xml new file mode 100644 index 0000000000..c712173ca2 --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-lv/strings.xml @@ -0,0 +1,25 @@ + + + + + "Tīklājam nav interneta savienojuma" + "Ierīces nevar izveidot savienojumu ar internetu" + "Izslēgt tīklāju" + "Tīklājs ir ieslēgts" + "Viesabonēšanas laikā var tikt piemērota papildu samaksa" + "Tālāk" + diff --git a/Tethering/res/values-mcc204-mnc04-mk/strings.xml b/Tethering/res/values-mcc204-mnc04-mk/strings.xml new file mode 100644 index 0000000000..aa4490912b --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-mk/strings.xml @@ -0,0 +1,25 @@ + + + + + "Точката на пристап нема интернет" + "Уредите не може да се поврзат на интернет" + "Исклучи ја точката на пристап" + "Точката на пристап е вклучена" + "При роаминг може да се наплатат дополнителни трошоци" + "Продолжи" + diff --git a/Tethering/res/values-mcc204-mnc04-ml/strings.xml b/Tethering/res/values-mcc204-mnc04-ml/strings.xml new file mode 100644 index 0000000000..d376fe5870 --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-ml/strings.xml @@ -0,0 +1,25 @@ + + + + + "ഹോട്ട്സ്പോട്ടിൽ ഇന്റർനെറ്റ് ലഭ്യമല്ല" + "ഉപകരണങ്ങൾ ഇന്റർനെറ്റിലേക്ക് കണക്റ്റ് ചെയ്യാനാവില്ല" + "ഹോട്ട്‌സ്‌പോട്ട് ഓഫാക്കുക" + "ഹോട്ട്സ്പോട്ട് ഓണാണ്" + "റോമിംഗ് ചെയ്യുമ്പോൾ അധിക നിരക്കുകൾ ബാധകമായേക്കാം" + "തുടരുക" + diff --git a/Tethering/res/values-mcc204-mnc04-mn/strings.xml b/Tethering/res/values-mcc204-mnc04-mn/strings.xml new file mode 100644 index 0000000000..417213f543 --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-mn/strings.xml @@ -0,0 +1,25 @@ + + + + + "Сүлжээний цэг дээр интернэт алга байна" + "Төхөөрөмжүүд нь интернэтэд холбогдох боломжгүй байна" + "Сүлжээний цэгийг унтраах" + "Сүлжээний цэг асаалттай байна" + "Роумингийн үеэр нэмэлт төлбөр нэхэмжилж болзошгүй" + "Үргэлжлүүлэх" + diff --git a/Tethering/res/values-mcc204-mnc04-mr/strings.xml b/Tethering/res/values-mcc204-mnc04-mr/strings.xml new file mode 100644 index 0000000000..2ed153fb17 --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-mr/strings.xml @@ -0,0 +1,25 @@ + + + + + "हॉटस्पॉटला इंटरनेट नाही" + "डिव्हाइस इंटरनेटला कनेक्ट करू शकत नाहीत" + "हॉटस्पॉट बंद करा" + "हॉटस्पॉट सुरू आहे" + "रोमिंगदरम्यान अतिरिक्त शुल्क लागू होऊ शकतात" + "सुरू ठेवा" + diff --git a/Tethering/res/values-mcc204-mnc04-ms/strings.xml b/Tethering/res/values-mcc204-mnc04-ms/strings.xml new file mode 100644 index 0000000000..50817fd4a2 --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-ms/strings.xml @@ -0,0 +1,25 @@ + + + + + "Tempat liputan tiada Internet" + "Peranti tidak dapat menyambung kepada Internet" + "Matikan tempat liputan" + "Tempat liputan dihidupkan" + "Caj tambahan mungkin digunakan semasa perayauan" + "Teruskan" + diff --git a/Tethering/res/values-mcc204-mnc04-my/strings.xml b/Tethering/res/values-mcc204-mnc04-my/strings.xml new file mode 100644 index 0000000000..c0d70e3d5f --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-my/strings.xml @@ -0,0 +1,25 @@ + + + + + "ဟော့စပေါ့တွင် အင်တာနက်မရှိပါ" + "စက်များက အင်တာနက်ချိတ်ဆက်၍ မရပါ" + "ဟော့စပေါ့ ပိတ်ရန်" + "ဟော့စပေါ့ ဖွင့်ထားသည်" + "ပြင်ပကွန်ရက်နှင့် ချိတ်ဆက်သည့်အခါ နောက်ထပ်ကျသင့်မှုများ ရှိနိုင်သည်" + "ရှေ့ဆက်ရန်" + diff --git a/Tethering/res/values-mcc204-mnc04-nb/strings.xml b/Tethering/res/values-mcc204-mnc04-nb/strings.xml new file mode 100644 index 0000000000..1e7f1c6d0a --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-nb/strings.xml @@ -0,0 +1,25 @@ + + + + + "Wi-Fi-sonen har ikke internettilgang" + "Enheter kan ikke koble til internett" + "Slå av Wi-Fi-sonen" + "Wi-Fi-sonen er på" + "Ytterligere kostnader kan påløpe under roaming" + "Fortsett" + diff --git a/Tethering/res/values-mcc204-mnc04-ne/strings.xml b/Tethering/res/values-mcc204-mnc04-ne/strings.xml new file mode 100644 index 0000000000..63ce155034 --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-ne/strings.xml @@ -0,0 +1,25 @@ + + + + + "हटस्पटमा इन्टरनेट छैन" + "यन्त्रहरू इन्टरनेटमा कनेक्ट गर्न सकिएन" + "हटस्पट निष्क्रिय पार्नुहोस्" + "हटस्पट सक्रिय छ" + "रोमिङ सेवा प्रयोग गर्दा अतिरिक्त शुल्क लाग्न सक्छ" + "जारी राख्नुहोस्" + diff --git a/Tethering/res/values-mcc204-mnc04-nl/strings.xml b/Tethering/res/values-mcc204-mnc04-nl/strings.xml new file mode 100644 index 0000000000..bf14a0fced --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-nl/strings.xml @@ -0,0 +1,25 @@ + + + + + "Hotspot heeft geen internet" + "Apparaten kunnen geen verbinding maken met internet" + "Hotspot uitschakelen" + "Hotspot is ingeschakeld" + "Er kunnen extra kosten voor roaming in rekening worden gebracht." + "Doorgaan" + diff --git a/Tethering/res/values-mcc204-mnc04-or/strings.xml b/Tethering/res/values-mcc204-mnc04-or/strings.xml new file mode 100644 index 0000000000..ab87b76caf --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-or/strings.xml @@ -0,0 +1,25 @@ + + + + + "ହଟସ୍ପଟରେ କୌଣସି ଇଣ୍ଟର୍ନେଟ୍ ସଂଯୋଗ ନାହିଁ" + "ଡିଭାଇସଗୁଡ଼ିକ ଇଣ୍ଟର୍ନେଟ୍ ସହ ସଂଯୋଗ କରାଯାଇପାରିବ ନାହିଁ" + "ହଟସ୍ପଟ ବନ୍ଦ କରନ୍ତୁ" + "ହଟସ୍ପଟ ଚାଲୁ ଅଛି" + "ରୋମିଂରେ ଥିବା ସମୟରେ ଅତିରିକ୍ତ ଶୁଳ୍କ ଲାଗୁ ହୋଇପାରେ" + "ଜାରି ରଖନ୍ତୁ" + diff --git a/Tethering/res/values-mcc204-mnc04-pa/strings.xml b/Tethering/res/values-mcc204-mnc04-pa/strings.xml new file mode 100644 index 0000000000..b09f285c2d --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-pa/strings.xml @@ -0,0 +1,25 @@ + + + + + "ਹੌਟਸਪੌਟ ਕੋਲ ਇੰਟਰਨੈੱਟ ਪਹੁੰਚ ਨਹੀਂ ਹੈ" + "ਡੀਵਾਈਸ ਇੰਟਰਨੈੱਟ ਨਾਲ ਕਨੈਕਟ ਨਹੀਂ ਹੋ ਸਕਦੇ" + "ਹੌਟਸਪੌਟ ਬੰਦ ਕਰੋ" + "ਹੌਟਸਪੌਟ ਚਾਲੂ ਹੈ" + "ਰੋਮਿੰਗ ਦੌਰਾਨ ਵਧੀਕ ਖਰਚੇ ਲਾਗੂ ਹੋ ਸਕਦੇ ਹਨ" + "ਜਾਰੀ ਰੱਖੋ" + diff --git a/Tethering/res/values-mcc204-mnc04-pl/strings.xml b/Tethering/res/values-mcc204-mnc04-pl/strings.xml new file mode 100644 index 0000000000..8becd0715f --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-pl/strings.xml @@ -0,0 +1,25 @@ + + + + + "Hotspot nie ma internetu" + "Urządzenia nie mogą połączyć się z internetem" + "Wyłącz hotspot" + "Hotspot jest włączony" + "Podczas korzystania z roamingu mogą zostać naliczone dodatkowe opłaty" + "Dalej" + diff --git a/Tethering/res/values-mcc204-mnc04-pt-rBR/strings.xml b/Tethering/res/values-mcc204-mnc04-pt-rBR/strings.xml new file mode 100644 index 0000000000..8e01736f64 --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-pt-rBR/strings.xml @@ -0,0 +1,25 @@ + + + + + "O ponto de acesso não tem conexão com a Internet" + "Não foi possível conectar os dispositivos à Internet" + "Desativar ponto de acesso" + "O ponto de acesso está ativado" + "Pode haver cobranças extras durante o roaming" + "Continuar" + diff --git a/Tethering/res/values-mcc204-mnc04-pt-rPT/strings.xml b/Tethering/res/values-mcc204-mnc04-pt-rPT/strings.xml new file mode 100644 index 0000000000..2356379e2f --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-pt-rPT/strings.xml @@ -0,0 +1,25 @@ + + + + + "A zona Wi-Fi não tem Internet" + "Não é possível ligar os dispositivos à Internet" + "Desativar zona Wi-Fi" + "A zona Wi-Fi está ativada" + "Podem aplicar-se custos adicionais em roaming." + "Continuar" + diff --git a/Tethering/res/values-mcc204-mnc04-pt/strings.xml b/Tethering/res/values-mcc204-mnc04-pt/strings.xml new file mode 100644 index 0000000000..8e01736f64 --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-pt/strings.xml @@ -0,0 +1,25 @@ + + + + + "O ponto de acesso não tem conexão com a Internet" + "Não foi possível conectar os dispositivos à Internet" + "Desativar ponto de acesso" + "O ponto de acesso está ativado" + "Pode haver cobranças extras durante o roaming" + "Continuar" + diff --git a/Tethering/res/values-mcc204-mnc04-ro/strings.xml b/Tethering/res/values-mcc204-mnc04-ro/strings.xml new file mode 100644 index 0000000000..2e62bd611c --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-ro/strings.xml @@ -0,0 +1,25 @@ + + + + + "Hotspotul nu are internet" + "Dispozitivele nu se pot conecta la internet" + "Dezactivați hotspotul" + "Hotspotul este activ" + "Se pot aplica taxe suplimentare pentru roaming" + "Continuați" + diff --git a/Tethering/res/values-mcc204-mnc04-ru/strings.xml b/Tethering/res/values-mcc204-mnc04-ru/strings.xml new file mode 100644 index 0000000000..a2b1640cb2 --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-ru/strings.xml @@ -0,0 +1,25 @@ + + + + + "Точка доступа не подключена к Интернету" + "Устройства не могут подключаться к Интернету" + "Отключить точку доступа" + "Точка доступа включена" + "За использование услуг связи в роуминге может взиматься дополнительная плата." + "Продолжить" + diff --git a/Tethering/res/values-mcc204-mnc04-si/strings.xml b/Tethering/res/values-mcc204-mnc04-si/strings.xml new file mode 100644 index 0000000000..632748a3e8 --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-si/strings.xml @@ -0,0 +1,25 @@ + + + + + "හොට්ස්පොට් හට අන්තර්ජාලය නැත" + "උපාංගවලට අන්තර්ජාලයට සම්බන්ධ විය නොහැකිය" + "හොට්ස්පොට් ක්‍රියාවිරහිත කරන්න" + "හොට්ස්පොට් ක්‍රියාත්මකයි" + "රෝමිං අතරතුර අමතර ගාස්තු අදාළ විය හැකිය" + "ඉදිරියට යන්න" + diff --git a/Tethering/res/values-mcc204-mnc04-sk/strings.xml b/Tethering/res/values-mcc204-mnc04-sk/strings.xml new file mode 100644 index 0000000000..247fc1b0e7 --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-sk/strings.xml @@ -0,0 +1,25 @@ + + + + + "Hotspot nemá internetové pripojenie" + "Zariadenia sa nedajú pripojiť k internetu" + "Vypnúť hotspot" + "Hotspot je zapnutý" + "Počas roamingu vám môžu byť účtované ďalšie poplatky" + "Pokračovať" + diff --git a/Tethering/res/values-mcc204-mnc04-sl/strings.xml b/Tethering/res/values-mcc204-mnc04-sl/strings.xml new file mode 100644 index 0000000000..ed22372197 --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-sl/strings.xml @@ -0,0 +1,25 @@ + + + + + "Dostopna točka nima internetne povezave" + "Naprave ne morejo vzpostaviti internetne povezave" + "Izklopi dostopno točko" + "Dostopna točka je vklopljena" + "Med gostovanjem lahko nastanejo dodatni stroški" + "Naprej" + diff --git a/Tethering/res/values-mcc204-mnc04-sq/strings.xml b/Tethering/res/values-mcc204-mnc04-sq/strings.xml new file mode 100644 index 0000000000..4bfab6e474 --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-sq/strings.xml @@ -0,0 +1,25 @@ + + + + + "Zona e qasjes për internet nuk ka internet" + "Pajisjet nuk mund të lidhen me internetin" + "Çaktivizo zonën e qasjes për internet" + "Zona e qasjes për internet është aktive" + "Mund të zbatohen tarifime shtesë kur je në roaming" + "Vazhdo" + diff --git a/Tethering/res/values-mcc204-mnc04-sr/strings.xml b/Tethering/res/values-mcc204-mnc04-sr/strings.xml new file mode 100644 index 0000000000..478d53a255 --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-sr/strings.xml @@ -0,0 +1,25 @@ + + + + + "Хотспот нема приступ интернету" + "Уређаји не могу да се повежу на интернет" + "Искључи хотспот" + "Хотспот је укључен" + "Можда важе додатни трошкови у ромингу" + "Настави" + diff --git a/Tethering/res/values-mcc204-mnc04-sv/strings.xml b/Tethering/res/values-mcc204-mnc04-sv/strings.xml new file mode 100644 index 0000000000..a793ed6483 --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-sv/strings.xml @@ -0,0 +1,25 @@ + + + + + "Surfzonen har ingen internetanslutning" + "Enheterna har ingen internetanslutning" + "Inaktivera surfzon" + "Surfzonen är aktiverad" + "Ytterligare avgifter kan tillkomma vid roaming" + "Fortsätt" + diff --git a/Tethering/res/values-mcc204-mnc04-sw/strings.xml b/Tethering/res/values-mcc204-mnc04-sw/strings.xml new file mode 100644 index 0000000000..18ee457d03 --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-sw/strings.xml @@ -0,0 +1,25 @@ + + + + + "Mtandao pepe hauna intaneti" + "Vifaa vimeshindwa kuunganisha kwenye intaneti" + "Zima mtandao pepe" + "Mtandao pepe umewashwa" + "Huenda ukatozwa gharama za ziada ukitumia mitandao ya ng\'ambo" + "Endelea" + diff --git a/Tethering/res/values-mcc204-mnc04-ta/strings.xml b/Tethering/res/values-mcc204-mnc04-ta/strings.xml new file mode 100644 index 0000000000..7eebd6784a --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-ta/strings.xml @@ -0,0 +1,25 @@ + + + + + "ஹாட்ஸ்பாட்டில் இணையம் இல்லை" + "சாதனங்களால் இணையத்தில் இணைய இயலவில்லை" + "ஹாட்ஸ்பாட்டை ஆஃப் செய்" + "ஹாட்ஸ்பாட் ஆன் செய்யப்பட்டுள்ளது" + "ரோமிங்கின்போது கூடுதல் கட்டணங்கள் விதிக்கப்படக்கூடும்" + "தொடர்க" + diff --git a/Tethering/res/values-mcc204-mnc04-te/strings.xml b/Tethering/res/values-mcc204-mnc04-te/strings.xml new file mode 100644 index 0000000000..0986534fc7 --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-te/strings.xml @@ -0,0 +1,25 @@ + + + + + "హాట్‌స్పాట్‌కు ఇంటర్నెట్ యాక్సెస్ లేదు" + "పరికరాలను ఇంటర్నెట్‌కి కనెక్ట్ చేయడం సాధ్యం కాదు" + "హాట్‌స్పాట్‌ని ఆఫ్ చేయండి" + "హాట్‌స్పాట్ ఆన్‌లో ఉంది" + "రోమింగ్‌లో ఉన్నప్పుడు అదనపు ఛార్జీలు వర్తించవచ్చు" + "కొనసాగించు" + diff --git a/Tethering/res/values-mcc204-mnc04-th/strings.xml b/Tethering/res/values-mcc204-mnc04-th/strings.xml new file mode 100644 index 0000000000..3837002b29 --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-th/strings.xml @@ -0,0 +1,25 @@ + + + + + "ฮอตสปอตไม่ได้เชื่อมต่ออินเทอร์เน็ต" + "อุปกรณ์เชื่อมต่ออินเทอร์เน็ตไม่ได้" + "ปิดฮอตสปอต" + "ฮอตสปอตเปิดอยู่" + "อาจมีค่าใช้จ่ายเพิ่มเติมขณะโรมมิ่ง" + "ต่อไป" + diff --git a/Tethering/res/values-mcc204-mnc04-tl/strings.xml b/Tethering/res/values-mcc204-mnc04-tl/strings.xml new file mode 100644 index 0000000000..208f893447 --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-tl/strings.xml @@ -0,0 +1,25 @@ + + + + + "Walang internet ang hotspot" + "Hindi makakonekta sa internet ang mga device" + "I-off ang hotspot" + "Naka-on ang hotspot" + "Posibleng magkaroon ng mga karagdagang singil habang nagro-roam" + "Ituloy" + diff --git a/Tethering/res/values-mcc204-mnc04-tr/strings.xml b/Tethering/res/values-mcc204-mnc04-tr/strings.xml new file mode 100644 index 0000000000..3482fafa2d --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-tr/strings.xml @@ -0,0 +1,25 @@ + + + + + "Hotspot\'un internet bağlantısı yok" + "Cihazlar internete bağlanamıyor" + "Hotspot\'u kapat" + "Hotspot açık" + "Dolaşım sırasında ek ücretler uygulanabilir" + "Devam" + diff --git a/Tethering/res/values-mcc204-mnc04-uk/strings.xml b/Tethering/res/values-mcc204-mnc04-uk/strings.xml new file mode 100644 index 0000000000..dea311443f --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-uk/strings.xml @@ -0,0 +1,25 @@ + + + + + "Точка доступу не підключена до Інтернету" + "Не вдається підключити пристрої до Інтернету" + "Вимкнути точку доступу" + "Точку доступу ввімкнено" + "У роумінгу може стягуватися додаткова плата" + "Продовжити" + diff --git a/Tethering/res/values-mcc204-mnc04-ur/strings.xml b/Tethering/res/values-mcc204-mnc04-ur/strings.xml new file mode 100644 index 0000000000..09bc0c9eab --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-ur/strings.xml @@ -0,0 +1,25 @@ + + + + + "ہاٹ اسپاٹ میں انٹرنیٹ نہیں ہے" + "آلات انٹرنیٹ سے منسلک نہیں ہو سکتے" + "ہاٹ اسپاٹ آف کریں" + "ہاٹ اسپاٹ آن ہے" + "رومنگ کے دوران اضافی چارجز لاگو ہو سکتے ہیں" + "جاری رکھیں" + diff --git a/Tethering/res/values-mcc204-mnc04-uz/strings.xml b/Tethering/res/values-mcc204-mnc04-uz/strings.xml new file mode 100644 index 0000000000..715d34808b --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-uz/strings.xml @@ -0,0 +1,25 @@ + + + + + "Hotspot internetga ulanmagan" + "Qurilmalar internetga ulana olmayapti" + "Hotspotni faolsizlantirish" + "Hotspot yoniq" + "Rouming vaqtida qoʻshimcha haq olinishi mumkin" + "Davom etish" + diff --git a/Tethering/res/values-mcc204-mnc04-vi/strings.xml b/Tethering/res/values-mcc204-mnc04-vi/strings.xml new file mode 100644 index 0000000000..bf4ee1011b --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-vi/strings.xml @@ -0,0 +1,25 @@ + + + + + "Điểm phát sóng không có kết nối Internet" + "Các thiết bị không thể kết nối Internet" + "Tắt điểm phát sóng" + "Điểm phát sóng đang bật" + "Bạn có thể mất thêm phí dữ liệu khi chuyển vùng" + "Tiếp tục" + diff --git a/Tethering/res/values-mcc204-mnc04-zh-rCN/strings.xml b/Tethering/res/values-mcc204-mnc04-zh-rCN/strings.xml new file mode 100644 index 0000000000..cdb4224bf3 --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-zh-rCN/strings.xml @@ -0,0 +1,25 @@ + + + + + "热点没有网络连接" + "设备无法连接到互联网" + "关闭热点" + "热点已开启" + "漫游时可能会产生额外的费用" + "继续" + diff --git a/Tethering/res/values-mcc204-mnc04-zh-rHK/strings.xml b/Tethering/res/values-mcc204-mnc04-zh-rHK/strings.xml new file mode 100644 index 0000000000..3bb52e491f --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-zh-rHK/strings.xml @@ -0,0 +1,25 @@ + + + + + "熱點沒有互聯網連線" + "裝置無法連線至互聯網" + "關閉熱點" + "已開啟熱點" + "漫遊時可能需要支付額外費用" + "繼續" + diff --git a/Tethering/res/values-mcc204-mnc04-zh-rTW/strings.xml b/Tethering/res/values-mcc204-mnc04-zh-rTW/strings.xml new file mode 100644 index 0000000000..298c3eac70 --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-zh-rTW/strings.xml @@ -0,0 +1,25 @@ + + + + + "無線基地台沒有網際網路連線" + "裝置無法連上網際網路" + "關閉無線基地台" + "無線基地台已開啟" + "使用漫遊服務可能須支付額外費用" + "繼續" + diff --git a/Tethering/res/values-mcc204-mnc04-zu/strings.xml b/Tethering/res/values-mcc204-mnc04-zu/strings.xml new file mode 100644 index 0000000000..3dc0078834 --- /dev/null +++ b/Tethering/res/values-mcc204-mnc04-zu/strings.xml @@ -0,0 +1,25 @@ + + + + + "I-Hotspot ayina-inthanethi" + "Amadivayisi awakwazi ukuxhuma ku-inthanethi" + "Vala i-hotspot" + "I-Hotspot ivuliwe" + "Kungaba nezinkokhelo ezengeziwe uma uzula" + "Qhubeka" + diff --git a/Tethering/res/values/config.xml b/Tethering/res/values/config.xml index 5f8d299719..4391006741 100644 --- a/Tethering/res/values/config.xml +++ b/Tethering/res/values/config.xml @@ -40,6 +40,8 @@ "wlan\\d" "softap\\d" + "ap_br_wlan\\d" + "ap_br_softap\\d" + package="com.android.cts.net.hostside"> - - - - - - - + + + + + + + - - - + + + + android:permission="android.permission.BIND_VPN_SERVICE" + android:exported="true"> - + - + - + diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractAppIdleTestCase.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractAppIdleTestCase.java index 219cc3da32..f9e30b6b20 100644 --- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractAppIdleTestCase.java +++ b/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractAppIdleTestCase.java @@ -67,7 +67,7 @@ abstract class AbstractAppIdleTestCase extends AbstractRestrictBackgroundNetwork setAppIdle(true); launchComponentAndAssertNetworkAccess(TYPE_COMPONENT_ACTIVTIY); finishActivity(); - assertAppIdle(false); // Sanity check - not idle anymore, since activity was launched... + assertAppIdle(false); // verify - not idle anymore, since activity was launched... assertBackgroundNetworkAccess(true); setAppIdle(true); assertBackgroundNetworkAccess(false); @@ -78,6 +78,17 @@ abstract class AbstractAppIdleTestCase extends AbstractRestrictBackgroundNetwork stopForegroundService(); assertAppIdle(true); assertBackgroundNetworkAccess(false); + + // Set Idle after foreground service start. + launchComponentAndAssertNetworkAccess(TYPE_COMPONENT_FOREGROUND_SERVICE); + setAppIdle(true); + addPowerSaveModeWhitelist(TEST_PKG); + removePowerSaveModeWhitelist(TEST_PKG); + assertForegroundServiceNetworkAccess(); + stopForegroundService(); + assertAppIdle(true); + assertBackgroundNetworkAccess(false); + } @Test @@ -86,29 +97,29 @@ abstract class AbstractAppIdleTestCase extends AbstractRestrictBackgroundNetwork assertBackgroundNetworkAccess(false); addPowerSaveModeWhitelist(TEST_APP2_PKG); - assertAppIdle(false); // Sanity check - not idle anymore, since whitelisted + assertAppIdle(false); // verify - not idle anymore, since whitelisted assertBackgroundNetworkAccess(true); setAppIdleNoAssert(true); assertAppIdle(false); // app is still whitelisted removePowerSaveModeWhitelist(TEST_APP2_PKG); - assertAppIdle(true); // Sanity check - idle again, once whitelisted was removed + assertAppIdle(true); // verify - idle again, once whitelisted was removed assertBackgroundNetworkAccess(false); setAppIdle(true); addPowerSaveModeExceptIdleWhitelist(TEST_APP2_PKG); - assertAppIdle(false); // Sanity check - not idle anymore, since whitelisted + assertAppIdle(false); // verify - not idle anymore, since whitelisted assertBackgroundNetworkAccess(true); setAppIdleNoAssert(true); assertAppIdle(false); // app is still whitelisted removePowerSaveModeExceptIdleWhitelist(TEST_APP2_PKG); - assertAppIdle(true); // Sanity check - idle again, once whitelisted was removed + assertAppIdle(true); // verify - idle again, once whitelisted was removed assertBackgroundNetworkAccess(false); assertsForegroundAlwaysHasNetworkAccess(); - // Sanity check - no whitelist, no access! + // verify - no whitelist, no access! setAppIdle(true); assertBackgroundNetworkAccess(false); } diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractDozeModeTestCase.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractDozeModeTestCase.java index 6f32c563c1..e0ce4ead39 100644 --- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractDozeModeTestCase.java +++ b/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractDozeModeTestCase.java @@ -101,7 +101,7 @@ abstract class AbstractDozeModeTestCase extends AbstractRestrictBackgroundNetwor @Test public void testBackgroundNetworkAccess_enabledButWhitelistedOnNotificationAction() throws Exception { - setPendingIntentWhitelistDuration(NETWORK_TIMEOUT_MS); + setPendingIntentAllowlistDuration(NETWORK_TIMEOUT_MS); try { registerNotificationListenerService(); setDozeMode(true); diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java index e5fd149aec..e2dc1a1143 100644 --- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java +++ b/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java @@ -25,7 +25,6 @@ import static com.android.cts.net.hostside.NetworkPolicyTestUtils.executeShellCo import static com.android.cts.net.hostside.NetworkPolicyTestUtils.getConnectivityManager; import static com.android.cts.net.hostside.NetworkPolicyTestUtils.getContext; import static com.android.cts.net.hostside.NetworkPolicyTestUtils.getInstrumentation; -import static com.android.cts.net.hostside.NetworkPolicyTestUtils.getWifiManager; import static com.android.cts.net.hostside.NetworkPolicyTestUtils.isDozeModeSupported; import static com.android.cts.net.hostside.NetworkPolicyTestUtils.restrictBackgroundValueToString; @@ -46,15 +45,16 @@ import android.content.IntentFilter; import android.net.ConnectivityManager; import android.net.NetworkInfo.DetailedState; import android.net.NetworkInfo.State; -import android.net.wifi.WifiManager; import android.os.BatteryManager; import android.os.Binder; import android.os.Bundle; import android.os.SystemClock; -import android.provider.Settings; +import android.provider.DeviceConfig; import android.service.notification.NotificationListenerService; import android.util.Log; +import com.android.compatibility.common.util.DeviceConfigStateHelper; + import org.junit.Rule; import org.junit.rules.RuleChain; import org.junit.runner.RunWith; @@ -130,24 +130,24 @@ public abstract class AbstractRestrictBackgroundNetworkTestCase { protected int mUid; private int mMyUid; private MyServiceClient mServiceClient; - private String mDeviceIdleConstantsSetting; + private DeviceConfigStateHelper mDeviceIdleDeviceConfigStateHelper; @Rule public final RuleChain mRuleChain = RuleChain.outerRule(new RequiredPropertiesRule()) .around(new MeterednessConfigurationRule()); protected void setUp() throws Exception { - PROCESS_STATE_FOREGROUND_SERVICE = (Integer) ActivityManager.class .getDeclaredField("PROCESS_STATE_FOREGROUND_SERVICE").get(null); mInstrumentation = getInstrumentation(); mContext = getContext(); mCm = getConnectivityManager(); + mDeviceIdleDeviceConfigStateHelper = + new DeviceConfigStateHelper(DeviceConfig.NAMESPACE_DEVICE_IDLE); mUid = getUid(TEST_APP2_PKG); mMyUid = getUid(mContext.getPackageName()); mServiceClient = new MyServiceClient(mContext); mServiceClient.bind(); - mDeviceIdleConstantsSetting = "device_idle_constants"; executeShellCommand("cmd netpolicy start-watching " + mUid); setAppIdle(false); @@ -229,21 +229,25 @@ public abstract class AbstractRestrictBackgroundNetworkTestCase { } protected void assertBackgroundNetworkAccess(boolean expectAllowed) throws Exception { - assertBackgroundState(); // Sanity check. + assertBackgroundState(); assertNetworkAccess(expectAllowed /* expectAvailable */, false /* needScreenOn */); } protected void assertForegroundNetworkAccess() throws Exception { - assertForegroundState(); // Sanity check. + assertForegroundNetworkAccess(true); + } + + protected void assertForegroundNetworkAccess(boolean expectAllowed) throws Exception { + assertForegroundState(); // We verified that app is in foreground state but if the screen turns-off while // verifying for network access, the app will go into background state (in case app's // foreground status was due to top activity). So, turn the screen on when verifying // network connectivity. - assertNetworkAccess(true /* expectAvailable */, true /* needScreenOn */); + assertNetworkAccess(expectAllowed /* expectAvailable */, true /* needScreenOn */); } protected void assertForegroundServiceNetworkAccess() throws Exception { - assertForegroundServiceState(); // Sanity check. + assertForegroundServiceState(); assertNetworkAccess(true /* expectAvailable */, false /* needScreenOn */); } @@ -374,7 +378,7 @@ public abstract class AbstractRestrictBackgroundNetworkTestCase { } // Network status format is described on MyBroadcastReceiver.checkNetworkStatus() final String[] parts = resultData.split(NETWORK_STATUS_SEPARATOR); - assertEquals("Wrong network status: " + resultData, 5, parts.length); // Sanity check + assertEquals("Wrong network status: " + resultData, 5, parts.length); final State state = parts[0].equals("null") ? null : State.valueOf(parts[0]); final DetailedState detailedState = parts[1].equals("null") ? null : DetailedState.valueOf(parts[1]); @@ -547,7 +551,7 @@ public abstract class AbstractRestrictBackgroundNetworkTestCase { // TODO: currently the power-save mode is behaving like idle, but once it changes, we'll // need to use netpolicy for whitelisting executeShellCommand("dumpsys deviceidle whitelist +" + packageName); - assertPowerSaveModeWhitelist(packageName, true); // Sanity check + assertPowerSaveModeWhitelist(packageName, true); } protected void removePowerSaveModeWhitelist(String packageName) throws Exception { @@ -555,7 +559,7 @@ public abstract class AbstractRestrictBackgroundNetworkTestCase { // TODO: currently the power-save mode is behaving like idle, but once it changes, we'll // need to use netpolicy for whitelisting executeShellCommand("dumpsys deviceidle whitelist -" + packageName); - assertPowerSaveModeWhitelist(packageName, false); // Sanity check + assertPowerSaveModeWhitelist(packageName, false); } protected void assertPowerSaveModeExceptIdleWhitelist(String packageName, boolean expected) @@ -571,7 +575,7 @@ public abstract class AbstractRestrictBackgroundNetworkTestCase { // TODO: currently the power-save mode is behaving like idle, but once it changes, we'll // need to use netpolicy for whitelisting executeShellCommand("dumpsys deviceidle except-idle-whitelist +" + packageName); - assertPowerSaveModeExceptIdleWhitelist(packageName, true); // Sanity check + assertPowerSaveModeExceptIdleWhitelist(packageName, true); } protected void removePowerSaveModeExceptIdleWhitelist(String packageName) throws Exception { @@ -580,7 +584,7 @@ public abstract class AbstractRestrictBackgroundNetworkTestCase { // TODO: currently the power-save mode is behaving like idle, but once it changes, we'll // need to use netpolicy for whitelisting executeShellCommand("dumpsys deviceidle except-idle-whitelist reset"); - assertPowerSaveModeExceptIdleWhitelist(packageName, false); // Sanity check + assertPowerSaveModeExceptIdleWhitelist(packageName, false); } protected void turnBatteryOn() throws Exception { @@ -635,7 +639,7 @@ public abstract class AbstractRestrictBackgroundNetworkTestCase { } protected void setDozeMode(boolean enabled) throws Exception { - // Sanity check, since tests should check beforehand.... + // Check doze mode is supported. assertTrue("Device does not support Doze Mode", isDozeModeSupported()); Log.i(TAG, "Setting Doze Mode to " + enabled); @@ -648,7 +652,6 @@ public abstract class AbstractRestrictBackgroundNetworkTestCase { turnBatteryOff(); executeShellCommand("dumpsys deviceidle unforce"); } - // Sanity check. assertDozeMode(enabled); } @@ -659,7 +662,7 @@ public abstract class AbstractRestrictBackgroundNetworkTestCase { protected void setAppIdle(boolean enabled) throws Exception { Log.i(TAG, "Setting app idle to " + enabled); executeSilentShellCommand("am set-inactive " + TEST_APP2_PKG + " " + enabled ); - assertAppIdle(enabled); // Sanity check + assertAppIdle(enabled); } protected void setAppIdleNoAssert(boolean enabled) throws Exception { @@ -722,15 +725,13 @@ public abstract class AbstractRestrictBackgroundNetworkTestCase { nm.isNotificationListenerAccessGranted(listenerComponent)); } - protected void setPendingIntentWhitelistDuration(int durationMs) throws Exception { - executeSilentShellCommand(String.format( - "settings put global %s %s=%d", mDeviceIdleConstantsSetting, - "notification_whitelist_duration", durationMs)); + protected void setPendingIntentAllowlistDuration(long durationMs) { + mDeviceIdleDeviceConfigStateHelper.set("notification_allowlist_duration_ms", + String.valueOf(durationMs)); } - protected void resetDeviceIdleSettings() throws Exception { - executeShellCommand(String.format("settings delete global %s", - mDeviceIdleConstantsSetting)); + protected void resetDeviceIdleSettings() { + mDeviceIdleDeviceConfigStateHelper.restoreOriginalValues(); } protected void launchComponentAndAssertNetworkAccess(int type) throws Exception { diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/DataSaverModeTest.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/DataSaverModeTest.java index aa2c914e02..604a0b62c6 100644 --- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/DataSaverModeTest.java +++ b/tests/cts/hostside/app/src/com/android/cts/net/hostside/DataSaverModeTest.java @@ -67,7 +67,7 @@ public class DataSaverModeTest extends AbstractRestrictBackgroundNetworkTestCase public void testGetRestrictBackgroundStatus_disabled() throws Exception { assertDataSaverStatusOnBackground(RESTRICT_BACKGROUND_STATUS_DISABLED); - // Sanity check: make sure status is always disabled, never whitelisted + // Verify status is always disabled, never whitelisted addRestrictBackgroundWhitelist(mUid); assertRestrictBackgroundChangedReceived(0); assertDataSaverStatusOnBackground(RESTRICT_BACKGROUND_STATUS_DISABLED); diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/NetworkPolicyTestUtils.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/NetworkPolicyTestUtils.java index 3807d79c35..3041dfa76b 100644 --- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/NetworkPolicyTestUtils.java +++ b/tests/cts/hostside/app/src/com/android/cts/net/hostside/NetworkPolicyTestUtils.java @@ -55,7 +55,7 @@ import androidx.test.platform.app.InstrumentationRegistry; public class NetworkPolicyTestUtils { - private static final int TIMEOUT_CHANGE_METEREDNESS_MS = 5000; + private static final int TIMEOUT_CHANGE_METEREDNESS_MS = 10_000; private static ConnectivityManager mCm; private static WifiManager mWm; diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/RestrictedModeTest.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/RestrictedModeTest.java new file mode 100644 index 0000000000..29d3c6e1ba --- /dev/null +++ b/tests/cts/hostside/app/src/com/android/cts/net/hostside/RestrictedModeTest.java @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.cts.net.hostside; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public final class RestrictedModeTest extends AbstractRestrictBackgroundNetworkTestCase { + @Before + public void setUp() throws Exception { + super.setUp(); + } + + @After + public void tearDown() throws Exception { + setRestrictedMode(false); + super.tearDown(); + } + + private void setRestrictedMode(boolean enabled) throws Exception { + executeSilentShellCommand( + "settings put global restricted_networking_mode " + (enabled ? 1 : 0)); + assertRestrictedModeState(enabled); + } + + private void assertRestrictedModeState(boolean enabled) throws Exception { + assertDelayedShellCommand("cmd netpolicy get restricted-mode", + "Restricted mode status: " + (enabled ? "enabled" : "disabled")); + } + + @Test + public void testNetworkAccess() throws Exception { + setRestrictedMode(false); + + // go to foreground state and enable restricted mode + launchComponentAndAssertNetworkAccess(TYPE_COMPONENT_ACTIVTIY); + setRestrictedMode(true); + assertForegroundNetworkAccess(false); + + // go to background state + finishActivity(); + assertBackgroundNetworkAccess(false); + + // disable restricted mode and assert network access in foreground and background states + setRestrictedMode(false); + launchComponentAndAssertNetworkAccess(TYPE_COMPONENT_ACTIVTIY); + assertForegroundNetworkAccess(true); + + // go to background state + finishActivity(); + assertBackgroundNetworkAccess(true); + } +} diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/VpnTest.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/VpnTest.java index a451ea8585..81a431cfda 100755 --- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/VpnTest.java +++ b/tests/cts/hostside/app/src/com/android/cts/net/hostside/VpnTest.java @@ -17,13 +17,26 @@ package com.android.cts.net.hostside; import static android.os.Process.INVALID_UID; -import static android.system.OsConstants.*; +import static android.system.OsConstants.AF_INET; +import static android.system.OsConstants.AF_INET6; +import static android.system.OsConstants.ECONNABORTED; +import static android.system.OsConstants.IPPROTO_ICMP; +import static android.system.OsConstants.IPPROTO_ICMPV6; +import static android.system.OsConstants.IPPROTO_TCP; +import static android.system.OsConstants.POLLIN; +import static android.system.OsConstants.SOCK_DGRAM; import android.annotation.Nullable; +import android.app.DownloadManager; +import android.app.DownloadManager.Query; +import android.app.DownloadManager.Request; +import android.content.BroadcastReceiver; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.content.pm.PackageManager; +import android.database.Cursor; import android.net.ConnectivityManager; import android.net.ConnectivityManager.NetworkCallback; import android.net.LinkProperties; @@ -32,12 +45,13 @@ import android.net.NetworkCapabilities; import android.net.NetworkRequest; import android.net.Proxy; import android.net.ProxyInfo; +import android.net.Uri; import android.net.VpnService; import android.net.wifi.WifiManager; -import android.provider.Settings; import android.os.ParcelFileDescriptor; import android.os.Process; import android.os.SystemProperties; +import android.provider.Settings; import android.support.test.uiautomator.UiDevice; import android.support.test.uiautomator.UiObject; import android.support.test.uiautomator.UiSelector; @@ -64,12 +78,12 @@ import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.ServerSocket; import java.net.Socket; -import java.net.SocketException; import java.net.UnknownHostException; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Objects; import java.util.Random; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -1009,6 +1023,9 @@ public class VpnTest extends InstrumentationTestCase { } public void testB141603906() throws Exception { + if (!supportedHardware()) { + return; + } final InetSocketAddress src = new InetSocketAddress(0); final InetSocketAddress dst = new InetSocketAddress(0); final int NUM_THREADS = 8; @@ -1087,4 +1104,62 @@ public class VpnTest extends InstrumentationTestCase { received = true; } } + + /** + * Verifies that DownloadManager has CONNECTIVITY_USE_RESTRICTED_NETWORKS permission that can + * bind socket to VPN when it is in VPN disallowed list but requested downloading app is in VPN + * allowed list. + * See b/165774987. + */ + public void testDownloadWithDownloadManagerDisallowed() throws Exception { + if (!supportedHardware()) return; + + // Start a VPN with DownloadManager package in disallowed list. + startVpn(new String[] {"192.0.2.2/32", "2001:db8:1:2::ffe/128"}, + new String[] {"192.0.2.0/24", "2001:db8::/32"}, + "" /* allowedApps */, "com.android.providers.downloads", null /* proxyInfo */, + null /* underlyingNetworks */, false /* isAlwaysMetered */); + + final Context context = VpnTest.this.getInstrumentation().getContext(); + final DownloadManager dm = context.getSystemService(DownloadManager.class); + final DownloadCompleteReceiver receiver = new DownloadCompleteReceiver(); + try { + context.registerReceiver(receiver, + new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)); + + // Enqueue a request and check only one download. + final long id = dm.enqueue(new Request(Uri.parse("https://www.google.com"))); + assertEquals(1, getTotalNumberDownloads(dm, new Query())); + assertEquals(1, getTotalNumberDownloads(dm, new Query().setFilterById(id))); + + // Wait for download complete and check status. + assertEquals(id, receiver.get(TIMEOUT_MS, TimeUnit.MILLISECONDS)); + assertEquals(1, getTotalNumberDownloads(dm, + new Query().setFilterByStatus(DownloadManager.STATUS_SUCCESSFUL))); + + // Remove download. + assertEquals(1, dm.remove(id)); + assertEquals(0, getTotalNumberDownloads(dm, new Query())); + } finally { + context.unregisterReceiver(receiver); + } + } + + private static int getTotalNumberDownloads(final DownloadManager dm, final Query query) { + try (Cursor cursor = dm.query(query)) { return cursor.getCount(); } + } + + private static class DownloadCompleteReceiver extends BroadcastReceiver { + private final CompletableFuture future = new CompletableFuture<>(); + + @Override + public void onReceive(Context context, Intent intent) { + future.complete(intent.getLongExtra( + DownloadManager.EXTRA_DOWNLOAD_ID, -1 /* defaultValue */)); + } + + public long get(long timeout, TimeUnit unit) throws Exception { + return future.get(timeout, unit); + } + } } diff --git a/tests/cts/hostside/app2/Android.bp b/tests/cts/hostside/app2/Android.bp index a6e9b118ff..8e279311a8 100644 --- a/tests/cts/hostside/app2/Android.bp +++ b/tests/cts/hostside/app2/Android.bp @@ -23,7 +23,6 @@ android_test_helper_app { // Tag this module as a cts test artifact test_suites: [ "cts", - "vts10", "general-tests", ], certificate: ":cts-net-app", diff --git a/tests/cts/hostside/app2/AndroidManifest.xml b/tests/cts/hostside/app2/AndroidManifest.xml index ad270b3170..eb777f2e31 100644 --- a/tests/cts/hostside/app2/AndroidManifest.xml +++ b/tests/cts/hostside/app2/AndroidManifest.xml @@ -16,38 +16,43 @@ --> + package="com.android.cts.net.hostside.app2"> - + - + + This application also provides a service, RemoteSocketFactoryService, that the test app can + use to open sockets to remote hosts as a different user ID. + --> - - - - + + + + - + - - - - - - + + + + + + diff --git a/tests/cts/hostside/src/com/android/cts/net/HostsideRestrictBackgroundNetworkTests.java b/tests/cts/hostside/src/com/android/cts/net/HostsideRestrictBackgroundNetworkTests.java index 4598c3936b..0e25d5e8b4 100644 --- a/tests/cts/hostside/src/com/android/cts/net/HostsideRestrictBackgroundNetworkTests.java +++ b/tests/cts/hostside/src/com/android/cts/net/HostsideRestrictBackgroundNetworkTests.java @@ -16,6 +16,8 @@ package com.android.cts.net; +import android.platform.test.annotations.FlakyTest; + import com.android.ddmlib.Log; import com.android.tradefed.device.DeviceNotAvailableException; @@ -146,6 +148,7 @@ public class HostsideRestrictBackgroundNetworkTests extends HostsideNetworkTestC "testBackgroundNetworkAccess_disabled"); } + @FlakyTest(bugId=170180675) public void testAppIdleMetered_whitelisted() throws Exception { runDeviceTests(TEST_PKG, TEST_PKG + ".AppIdleMeteredTest", "testBackgroundNetworkAccess_whitelisted"); @@ -176,6 +179,7 @@ public class HostsideRestrictBackgroundNetworkTests extends HostsideNetworkTestC "testBackgroundNetworkAccess_disabled"); } + @FlakyTest(bugId=170180675) public void testAppIdleNonMetered_whitelisted() throws Exception { runDeviceTests(TEST_PKG, TEST_PKG + ".AppIdleNonMeteredTest", "testBackgroundNetworkAccess_whitelisted"); @@ -311,6 +315,14 @@ public class HostsideRestrictBackgroundNetworkTests extends HostsideNetworkTestC "testAppIdleAndBatterySaver_tempPowerSaveAndAppIdleWhitelists"); } + /************************** + * Restricted mode tests. * + **************************/ + public void testRestrictedMode_networkAccess() throws Exception { + runDeviceTests(TEST_PKG, TEST_PKG + ".RestrictedModeTest", + "testNetworkAccess"); + } + /******************* * Helper methods. * *******************/ @@ -367,7 +379,7 @@ public class HostsideRestrictBackgroundNetworkTests extends HostsideNetworkTestC // TODO: currently the power-save mode is behaving like idle, but once it changes, we'll // need to use netpolicy for whitelisting runCommand("dumpsys deviceidle whitelist +" + packageName); - assertPowerSaveModeWhitelist(packageName, true); // Sanity check + assertPowerSaveModeWhitelist(packageName, true); } protected boolean isDozeModeEnabled() throws Exception { diff --git a/tests/cts/hostside/src/com/android/cts/net/HostsideVpnTests.java b/tests/cts/hostside/src/com/android/cts/net/HostsideVpnTests.java index 62925ad6ab..49b5f9dc96 100644 --- a/tests/cts/hostside/src/com/android/cts/net/HostsideVpnTests.java +++ b/tests/cts/hostside/src/com/android/cts/net/HostsideVpnTests.java @@ -95,4 +95,9 @@ public class HostsideVpnTests extends HostsideNetworkTestCase { public void testB141603906() throws Exception { runDeviceTests(TEST_PKG, TEST_PKG + ".VpnTest", "testB141603906"); } + + public void testDownloadWithDownloadManagerDisallowed() throws Exception { + runDeviceTests(TEST_PKG, TEST_PKG + ".VpnTest", + "testDownloadWithDownloadManagerDisallowed"); + } } diff --git a/tests/cts/net/Android.bp b/tests/cts/net/Android.bp index 3b69602638..528171a036 100644 --- a/tests/cts/net/Android.bp +++ b/tests/cts/net/Android.bp @@ -62,7 +62,6 @@ android_test { defaults: ["CtsNetTestCasesDefaults"], test_suites: [ "cts", - "vts10", "general-tests", ], test_config_template: "AndroidTestTemplate.xml", diff --git a/tests/cts/net/AndroidTestTemplate.xml b/tests/cts/net/AndroidTestTemplate.xml index 4e937512ad..474eefe7bf 100644 --- a/tests/cts/net/AndroidTestTemplate.xml +++ b/tests/cts/net/AndroidTestTemplate.xml @@ -20,7 +20,8 @@