Merge "Apply more generic AIDL package name on jarjar rule."
diff --git a/Android.bp b/Android.bp
index 87b7dc1..35879df 100644
--- a/Android.bp
+++ b/Android.bp
@@ -581,6 +581,7 @@
"//frameworks/base/apex/blobstore/framework",
"//frameworks/base/apex/jobscheduler/framework",
"//frameworks/base/packages/Tethering/tests/unit",
+ "//packages/modules/Connectivity/Tethering/tests/unit",
],
}
@@ -1174,22 +1175,6 @@
}
// Avoid including Parcelable classes as we don't want to have two copies of
-// Parcelable cross the process. This is used by framework-telephony (frameworks/base/telephony).
-filegroup {
- name: "framework-telephony-shared-srcs",
- srcs: [
- "core/java/android/util/RecurrenceRule.java",
- "core/java/com/android/internal/os/SomeArgs.java",
- "core/java/com/android/internal/util/BitwiseInputStream.java",
- "core/java/com/android/internal/util/BitwiseOutputStream.java",
- "core/java/com/android/internal/util/FunctionalUtils.java",
- "core/java/com/android/internal/util/HexDump.java",
- "core/java/com/android/internal/util/IndentingPrintWriter.java",
- "core/java/com/android/internal/util/Preconditions.java",
- ],
-}
-
-// Avoid including Parcelable classes as we don't want to have two copies of
// Parcelable cross the process.
filegroup {
name: "framework-cellbroadcast-shared-srcs",
@@ -1285,43 +1270,3 @@
"StubLibraries.bp",
"ApiDocs.bp",
]
-
-java_library {
- name: "framework-telephony",
- srcs: [
- //":framework-telephony-sources",
- //":framework-telephony-shared-srcs",
- ],
- // TODO: change to framework-system-stub to build against system APIs.
- libs: [
- "framework-minus-apex",
- "unsupportedappusage",
- ],
- static_libs: [
- "libphonenumber-platform",
- "app-compat-annotations",
- ],
- sdk_version: "core_platform",
- aidl: {
- export_include_dirs: ["telephony/java"],
- include_dirs: [
- "frameworks/native/aidl/binder",
- "frameworks/native/aidl/gui",
- ]
- },
- jarjar_rules: ":framework-telephony-jarjar-rules",
- dxflags: [
- "--core-library",
- "--multi-dex",
- ],
- // This is to break the dependency from boot jars.
- dex_preopt: {
- enabled: false,
- },
- installable: true,
-}
-
-filegroup {
- name: "framework-telephony-jarjar-rules",
- srcs: ["telephony/framework-telephony-jarjar-rules.txt"],
-}
diff --git a/StubLibraries.bp b/StubLibraries.bp
index e0c3022..9047df5 100644
--- a/StubLibraries.bp
+++ b/StubLibraries.bp
@@ -148,8 +148,8 @@
args: metalava_framework_docs_args,
check_api: {
current: {
- api_file: "non-updatable-api/current.txt",
- removed_api_file: "non-updatable-api/removed.txt",
+ api_file: "core/api/current.txt",
+ removed_api_file: "core/api/removed.txt",
},
last_released: {
api_file: ":android-non-updatable.api.public.latest",
@@ -208,8 +208,8 @@
args: metalava_framework_docs_args + priv_apps,
check_api: {
current: {
- api_file: "non-updatable-api/system-current.txt",
- removed_api_file: "non-updatable-api/system-removed.txt",
+ api_file: "core/api/system-current.txt",
+ removed_api_file: "core/api/system-removed.txt",
},
last_released: {
api_file: ":android-non-updatable.api.system.latest",
@@ -219,7 +219,7 @@
api_lint: {
enabled: true,
new_since: ":android-non-updatable.api.system.latest",
- baseline_file: "non-updatable-api/system-lint-baseline.txt",
+ baseline_file: "core/api/system-lint-baseline.txt",
},
},
}
@@ -253,46 +253,19 @@
}
/////////////////////////////////////////////////////////////////////
-// Following droidstubs modules are for extra APIs for modules,
+// Following droidstub module for extra APIs for modules,
// namely @SystemApi(client=MODULE_LIBRARIES) APIs.
/////////////////////////////////////////////////////////////////////
droidstubs {
- name: "module-lib-api",
- defaults: ["metalava-full-api-stubs-default"],
- arg_files: ["core/res/AndroidManifest.xml"],
- args: metalava_framework_docs_args + module_libs,
-
- // Do not generate stubs as they are not needed
- generate_stubs: false,
-
- check_api: {
- current: {
- api_file: "api/module-lib-current.txt",
- removed_api_file: "api/module-lib-removed.txt",
- },
- last_released: {
- api_file: ":android.api.module-lib.latest",
- removed_api_file: ":removed.api.module-lib.latest",
- baseline_file: ":module-lib-api-incompatibilities-with-last-released"
- },
- api_lint: {
- enabled: true,
- new_since: ":android.api.module-lib.latest",
- baseline_file: "api/module-lib-lint-baseline.txt",
- },
- },
-}
-
-droidstubs {
name: "module-lib-api-stubs-docs-non-updatable",
defaults: ["metalava-non-updatable-api-stubs-default"],
arg_files: ["core/res/AndroidManifest.xml"],
args: metalava_framework_docs_args + priv_apps + module_libs,
check_api: {
current: {
- api_file: "non-updatable-api/module-lib-current.txt",
- removed_api_file: "non-updatable-api/module-lib-removed.txt",
+ api_file: "core/api/module-lib-current.txt",
+ removed_api_file: "core/api/module-lib-removed.txt",
},
last_released: {
api_file: ":android-non-updatable.api.module-lib.latest",
diff --git a/api/test-current.txt b/api/test-current.txt
index 93f9e2c..9c51729 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -876,6 +876,14 @@
field public static final String SAMPLE_RATE = "android.media.audiotrack.sampleRate";
}
+ public abstract class Image implements java.lang.AutoCloseable {
+ ctor protected Image();
+ }
+
+ public abstract static class Image.Plane {
+ ctor protected Image.Plane();
+ }
+
public final class MediaCas implements java.lang.AutoCloseable {
method public void forceResourceLost();
}
diff --git a/non-updatable-api/Android.bp b/core/api/Android.bp
similarity index 100%
rename from non-updatable-api/Android.bp
rename to core/api/Android.bp
diff --git a/non-updatable-api/current.txt b/core/api/current.txt
similarity index 100%
rename from non-updatable-api/current.txt
rename to core/api/current.txt
diff --git a/non-updatable-api/module-lib-current.txt b/core/api/module-lib-current.txt
similarity index 100%
rename from non-updatable-api/module-lib-current.txt
rename to core/api/module-lib-current.txt
diff --git a/non-updatable-api/module-lib-removed.txt b/core/api/module-lib-removed.txt
similarity index 100%
rename from non-updatable-api/module-lib-removed.txt
rename to core/api/module-lib-removed.txt
diff --git a/non-updatable-api/removed.txt b/core/api/removed.txt
similarity index 100%
rename from non-updatable-api/removed.txt
rename to core/api/removed.txt
diff --git a/non-updatable-api/system-current.txt b/core/api/system-current.txt
similarity index 100%
rename from non-updatable-api/system-current.txt
rename to core/api/system-current.txt
diff --git a/non-updatable-api/system-lint-baseline.txt b/core/api/system-lint-baseline.txt
similarity index 100%
rename from non-updatable-api/system-lint-baseline.txt
rename to core/api/system-lint-baseline.txt
diff --git a/non-updatable-api/system-removed.txt b/core/api/system-removed.txt
similarity index 100%
rename from non-updatable-api/system-removed.txt
rename to core/api/system-removed.txt
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 97ef62b..d10e33f 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -131,6 +131,8 @@
import android.net.lowpan.LowpanManager;
import android.net.nsd.INsdManager;
import android.net.nsd.NsdManager;
+import android.net.vcn.IVcnManagementService;
+import android.net.vcn.VcnManager;
import android.net.wifi.WifiFrameworkInitializer;
import android.net.wifi.nl80211.WifiNl80211Manager;
import android.nfc.NfcManager;
@@ -371,6 +373,14 @@
ctx, () -> ServiceManager.getService(Context.TETHERING_SERVICE));
}});
+ registerService(Context.VCN_MANAGEMENT_SERVICE, VcnManager.class,
+ new CachedServiceFetcher<VcnManager>() {
+ @Override
+ public VcnManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+ IBinder b = ServiceManager.getService(Context.VCN_MANAGEMENT_SERVICE);
+ IVcnManagementService service = IVcnManagementService.Stub.asInterface(b);
+ return new VcnManager(ctx, service);
+ }});
registerService(Context.IPSEC_SERVICE, IpSecManager.class,
new CachedServiceFetcher<IpSecManager>() {
diff --git a/core/java/android/app/backup/OWNERS b/core/java/android/app/backup/OWNERS
index 9c21e8f..7e7710b 100644
--- a/core/java/android/app/backup/OWNERS
+++ b/core/java/android/app/backup/OWNERS
@@ -1,9 +1,4 @@
-alsutton@google.com
-anniemeng@google.com
-brufino@google.com
-bryanmawhinney@google.com
-ctate@google.com
-jorlow@google.com
-nathch@google.com
-rthakohov@google.com
+# Bug component: 656484
+
+include platform/frameworks/base/services/backup:/OWNERS
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 872c377..7047f73 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -18,6 +18,7 @@
package android.bluetooth;
import android.Manifest;
+import android.annotation.CallbackExecutor;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -686,6 +687,8 @@
private final Map<LeScanCallback, ScanCallback> mLeScanClients;
private static final Map<BluetoothDevice, List<Pair<OnMetadataChangedListener, Executor>>>
sMetadataListeners = new HashMap<>();
+ private final Map<BluetoothConnectionCallback, Executor>
+ mBluetoothConnectionCallbackExecutorMap = new HashMap<>();
/**
* Bluetooth metadata listener. Overrides the default BluetoothMetadataListener
@@ -3538,6 +3541,133 @@
@Nullable byte[] value);
}
+ private final IBluetoothConnectionCallback mConnectionCallback =
+ new IBluetoothConnectionCallback.Stub() {
+ @Override
+ public void onDeviceConnected(BluetoothDevice device) {
+ for (Map.Entry<BluetoothConnectionCallback, Executor> callbackExecutorEntry:
+ mBluetoothConnectionCallbackExecutorMap.entrySet()) {
+ BluetoothConnectionCallback callback = callbackExecutorEntry.getKey();
+ Executor executor = callbackExecutorEntry.getValue();
+ executor.execute(() -> callback.onDeviceConnected(device));
+ }
+ }
+
+ @Override
+ public void onDeviceDisconnected(BluetoothDevice device) {
+ for (Map.Entry<BluetoothConnectionCallback, Executor> callbackExecutorEntry:
+ mBluetoothConnectionCallbackExecutorMap.entrySet()) {
+ BluetoothConnectionCallback callback = callbackExecutorEntry.getKey();
+ Executor executor = callbackExecutorEntry.getValue();
+ executor.execute(() -> callback.onDeviceDisconnected(device));
+ }
+ }
+ };
+
+ /**
+ * Registers the BluetoothConnectionCallback to receive callback events when a bluetooth device
+ * (classic or low energy) is connected or disconnected.
+ *
+ * @param executor is the callback executor
+ * @param callback is the connection callback you wish to register
+ * @return true if the callback was registered successfully, false otherwise
+ * @throws IllegalArgumentException if the callback is already registered
+ * @hide
+ */
+ public boolean registerBluetoothConnectionCallback(@NonNull @CallbackExecutor Executor executor,
+ @NonNull BluetoothConnectionCallback callback) {
+ if (DBG) Log.d(TAG, "registerBluetoothConnectionCallback()");
+ if (callback == null) {
+ return false;
+ }
+
+ // If the callback map is empty, we register the service-to-app callback
+ if (mBluetoothConnectionCallbackExecutorMap.isEmpty()) {
+ try {
+ mServiceLock.readLock().lock();
+ if (mService != null) {
+ if (!mService.registerBluetoothConnectionCallback(mConnectionCallback)) {
+ return false;
+ }
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "", e);
+ mBluetoothConnectionCallbackExecutorMap.remove(callback);
+ } finally {
+ mServiceLock.readLock().unlock();
+ }
+ }
+
+ // Adds the passed in callback to our map of callbacks to executors
+ synchronized (mBluetoothConnectionCallbackExecutorMap) {
+ if (mBluetoothConnectionCallbackExecutorMap.containsKey(callback)) {
+ throw new IllegalArgumentException("This callback has already been registered");
+ }
+ mBluetoothConnectionCallbackExecutorMap.put(callback, executor);
+ }
+
+ return true;
+ }
+
+ /**
+ * Unregisters the BluetoothConnectionCallback that was previously registered by the application
+ *
+ * @param callback is the connection callback you wish to unregister
+ * @return true if the callback was unregistered successfully, false otherwise
+ * @hide
+ */
+ public boolean unregisterBluetoothConnectionCallback(
+ @NonNull BluetoothConnectionCallback callback) {
+ if (DBG) Log.d(TAG, "unregisterBluetoothConnectionCallback()");
+ if (callback == null) {
+ return false;
+ }
+
+ synchronized (mBluetoothConnectionCallbackExecutorMap) {
+ if (mBluetoothConnectionCallbackExecutorMap.remove(callback) != null) {
+ return false;
+ }
+ }
+
+ if (!mBluetoothConnectionCallbackExecutorMap.isEmpty()) {
+ return true;
+ }
+
+ // If the callback map is empty, we unregister the service-to-app callback
+ try {
+ mServiceLock.readLock().lock();
+ if (mService != null) {
+ return mService.unregisterBluetoothConnectionCallback(mConnectionCallback);
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "", e);
+ } finally {
+ mServiceLock.readLock().unlock();
+ }
+
+ return false;
+ }
+
+ /**
+ * This abstract class is used to implement callbacks for when a bluetooth classic or Bluetooth
+ * Low Energy (BLE) device is either connected or disconnected.
+ *
+ * @hide
+ */
+ public abstract class BluetoothConnectionCallback {
+ /**
+ * Callback triggered when a bluetooth device (classic or BLE) is connected
+ * @param device is the connected bluetooth device
+ */
+ public void onDeviceConnected(BluetoothDevice device) {}
+
+ /**
+ * Callback triggered when a bluetooth device (classic or BLE) is disconnected
+ * @param device is the disconnected bluetooth device
+ */
+ public void onDeviceDisconnected(BluetoothDevice device) {}
+ }
+
/**
* Converts old constant of priority to the new for connection policy
*
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index e6609ca..392dd64 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -3402,6 +3402,7 @@
VIBRATOR_SERVICE,
//@hide: STATUS_BAR_SERVICE,
CONNECTIVITY_SERVICE,
+ VCN_MANAGEMENT_SERVICE,
//@hide: IP_MEMORY_STORE_SERVICE,
IPSEC_SERVICE,
VPN_MANAGEMENT_SERVICE,
@@ -3966,6 +3967,16 @@
public static final String CONNECTIVITY_SERVICE = "connectivity";
/**
+ * Use with {@link #getSystemService(String)} to retrieve a {@link android.net.vcn.VcnManager}
+ * for managing Virtual Carrier Networks
+ *
+ * @see #getSystemService(String)
+ * @see android.net.vcn.VcnManager
+ * @hide
+ */
+ public static final String VCN_MANAGEMENT_SERVICE = "vcn_management";
+
+ /**
* Use with {@link #getSystemService(String)} to retrieve a
* {@link android.net.INetd} for communicating with the network stack
* @hide
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index 72217a1..267057c 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -189,7 +189,7 @@
* Waits for the event to be delivered to the application and handled.
* @hide
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(trackingBug = 171972397)
public static final int INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH = 2; // see InputDispatcher.h
/** @hide */
diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java
index 327e42b..44ebff9 100644
--- a/core/java/android/net/NetworkAgent.java
+++ b/core/java/android/net/NetworkAgent.java
@@ -353,10 +353,11 @@
private static NetworkInfo getLegacyNetworkInfo(final NetworkAgentConfig config) {
// The subtype can be changed with (TODO) setLegacySubtype, but it starts
- // with the type and an empty description.
+ // with 0 (TelephonyManager.NETWORK_TYPE_UNKNOWN) and an empty description.
final NetworkInfo ni = new NetworkInfo(config.legacyType, 0, config.legacyTypeName, "");
ni.setIsAvailable(true);
- ni.setExtraInfo(config.getLegacyExtraInfo());
+ ni.setDetailedState(NetworkInfo.DetailedState.CONNECTING, null /* reason */,
+ config.getLegacyExtraInfo());
return ni;
}
diff --git a/core/java/android/net/TEST_MAPPING b/core/java/android/net/TEST_MAPPING
index abac811..8c13ef9 100644
--- a/core/java/android/net/TEST_MAPPING
+++ b/core/java/android/net/TEST_MAPPING
@@ -17,4 +17,4 @@
"path": "frameworks/opt/net/wifi"
}
]
-}
\ No newline at end of file
+}
diff --git a/packages/Tethering/common/TetheringLib/src/android/net/TetheredClient.aidl b/core/java/android/net/vcn/IVcnManagementService.aidl
similarity index 80%
rename from packages/Tethering/common/TetheringLib/src/android/net/TetheredClient.aidl
rename to core/java/android/net/vcn/IVcnManagementService.aidl
index 0b279b8..af06906 100644
--- a/packages/Tethering/common/TetheringLib/src/android/net/TetheredClient.aidl
+++ b/core/java/android/net/vcn/IVcnManagementService.aidl
@@ -1,5 +1,5 @@
-/**
- * Copyright (C) 2020 The Android Open Source Project
+/*
+ * Copyright 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.
@@ -13,6 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.net;
-@JavaOnlyStableParcelable parcelable TetheredClient;
\ No newline at end of file
+package android.net.vcn;
+
+/**
+ * @hide
+ */
+interface IVcnManagementService {
+}
diff --git a/core/java/android/net/vcn/VcnManager.java b/core/java/android/net/vcn/VcnManager.java
new file mode 100644
index 0000000..d563b03
--- /dev/null
+++ b/core/java/android/net/vcn/VcnManager.java
@@ -0,0 +1,48 @@
+/*
+ * 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 android.net.vcn;
+
+import static java.util.Objects.requireNonNull;
+
+import android.annotation.NonNull;
+import android.annotation.SystemService;
+import android.content.Context;
+
+/**
+ * VcnManager publishes APIs for applications to configure and manage Virtual Carrier Networks
+ *
+ * @hide
+ */
+@SystemService(Context.VCN_MANAGEMENT_SERVICE)
+public final class VcnManager {
+ @NonNull private static final String TAG = VcnManager.class.getSimpleName();
+
+ @NonNull private final Context mContext;
+ @NonNull private final IVcnManagementService mService;
+
+ /**
+ * Construct an instance of VcnManager within an application context.
+ *
+ * @param ctx the application context for this manager
+ * @param service the VcnManagementService binder backing this manager
+ *
+ * @hide
+ */
+ public VcnManager(@NonNull Context ctx, @NonNull IVcnManagementService service) {
+ mContext = requireNonNull(ctx, "missing context");
+ mService = requireNonNull(service, "missing service");
+ }
+}
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index 3bcef90..136f612 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -348,13 +348,6 @@
void addLegacyRouteForNetId(int netId, in RouteInfo routeInfo, int uid);
/**
- * Set permission for a network.
- * @param permission PERMISSION_NONE to clear permissions.
- * PERMISSION_NETWORK or PERMISSION_SYSTEM to set permission.
- */
- void setNetworkPermission(int netId, int permission);
-
- /**
* Allow UID to call protect().
*/
void allowProtect(int uid);
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 2aa5c13..7a48a2a 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -724,7 +724,7 @@
* Returns the identifier of this process' parent.
* @hide
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(trackingBug = 171962076)
public static final int myPpid() {
return Os.getppid();
}
diff --git a/core/java/android/os/SharedMemory.java b/core/java/android/os/SharedMemory.java
index 7512352..136e3de 100644
--- a/core/java/android/os/SharedMemory.java
+++ b/core/java/android/os/SharedMemory.java
@@ -158,7 +158,7 @@
*
* @hide Exposed for native ASharedMemory_dupFromJava()
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(trackingBug = 171971817)
public int getFd() {
return mFileDescriptor.getInt$();
}
diff --git a/core/java/com/android/internal/net/LegacyVpnInfo.java b/core/java/com/android/internal/net/LegacyVpnInfo.java
index 4eb7ded..43984b5 100644
--- a/core/java/com/android/internal/net/LegacyVpnInfo.java
+++ b/core/java/com/android/internal/net/LegacyVpnInfo.java
@@ -83,8 +83,8 @@
* Return best matching {@link LegacyVpnInfo} state based on given
* {@link NetworkInfo}.
*/
- public static int stateFromNetworkInfo(NetworkInfo info) {
- switch (info.getDetailedState()) {
+ public static int stateFromNetworkInfo(NetworkInfo.DetailedState state) {
+ switch (state) {
case CONNECTING:
return STATE_CONNECTING;
case CONNECTED:
@@ -94,8 +94,7 @@
case FAILED:
return STATE_FAILED;
default:
- Log.w(TAG, "Unhandled state " + info.getDetailedState()
- + " ; treating as disconnected");
+ Log.w(TAG, "Unhandled state " + state + " ; treating as disconnected");
return STATE_DISCONNECTED;
}
}
diff --git a/media/java/android/media/Image.java b/media/java/android/media/Image.java
index 79b8611..610bffe 100644
--- a/media/java/android/media/Image.java
+++ b/media/java/android/media/Image.java
@@ -17,6 +17,7 @@
package android.media;
import android.annotation.Nullable;
+import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Rect;
import android.hardware.HardwareBuffer;
@@ -58,6 +59,7 @@
* @hide
*/
@UnsupportedAppUsage
+ @TestApi
protected Image() {
}
@@ -387,6 +389,7 @@
* @hide
*/
@UnsupportedAppUsage
+ @TestApi
protected Plane() {
}
diff --git a/packages/DynamicSystemInstallationService/res/values/strings.xml b/packages/DynamicSystemInstallationService/res/values/strings.xml
index 719fc73..bfeef0a 100644
--- a/packages/DynamicSystemInstallationService/res/values/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values/strings.xml
@@ -37,6 +37,9 @@
<string name="toast_dynsystem_discarded">Discarded dynamic system</string>
<!-- Toast when we fail to launch into Dynamic System [CHAR LIMIT=128] -->
<string name="toast_failed_to_reboot_to_dynsystem">Can\u2019t restart or load dynamic system</string>
+ <!-- Toast when we fail to disable Dynamic System [CHAR LIMIT=128] -->
+ <string name="toast_failed_to_disable_dynsystem">Failed to disable dynamic system</string>
+
<!-- URL of Dynamic System Key Revocation List [DO NOT TRANSLATE] -->
<string name="key_revocation_list_url" translatable="false">https://dl.google.com/developers/android/gsi/gsi-keyblacklist.json</string>
diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java
index 12505bc..ac27580 100644
--- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java
+++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java
@@ -375,8 +375,17 @@
return;
}
- // Per current design, we don't have disable() API. AOT is disabled on next reboot.
- // TODO: Use better status query when b/125079548 is done.
+ if (!mDynSystem.setEnable(/* enable = */ false, /* oneShot = */ false)) {
+ Log.e(TAG, "Failed to disable DynamicSystem.");
+
+ // Dismiss status bar and show a toast.
+ sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
+ Toast.makeText(this,
+ getString(R.string.toast_failed_to_disable_dynsystem),
+ Toast.LENGTH_LONG).show();
+ return;
+ }
+
PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
if (powerManager != null) {
diff --git a/packages/SettingsProvider/src/android/provider/settings/OWNERS b/packages/SettingsProvider/src/android/provider/settings/OWNERS
index 541dd878..7e7710b 100644
--- a/packages/SettingsProvider/src/android/provider/settings/OWNERS
+++ b/packages/SettingsProvider/src/android/provider/settings/OWNERS
@@ -1,5 +1,4 @@
-# Please reach out to Android B&R when making Settings backup changes
-alsutton@google.com
-nathch@google.com
-rthakohov@google.com
+# Bug component: 656484
+
+include platform/frameworks/base/services/backup:/OWNERS
diff --git a/packages/SettingsProvider/test/src/android/provider/OWNERS b/packages/SettingsProvider/test/src/android/provider/OWNERS
index f3241ea..7e7710b 100644
--- a/packages/SettingsProvider/test/src/android/provider/OWNERS
+++ b/packages/SettingsProvider/test/src/android/provider/OWNERS
@@ -1,4 +1,4 @@
-per-file * = *
+# Bug component: 656484
-# Please reach out to the Android B&R team for settings backup changes
-per-file SettingsBackupTest.java = alsutton@google.com, nathch@google.com, rthakohov@google.com
+include platform/frameworks/base/services/backup:/OWNERS
+
diff --git a/packages/Tethering/Android.bp b/packages/Tethering/Android.bp
deleted file mode 100644
index 5526c65..0000000
--- a/packages/Tethering/Android.bp
+++ /dev/null
@@ -1,137 +0,0 @@
-//
-// Copyright (C) 2019 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.
-//
-
-java_defaults {
- name: "TetheringAndroidLibraryDefaults",
- sdk_version: "module_current",
- srcs: [
- "src/**/*.java",
- ":framework-tethering-shared-srcs",
- ":tethering-module-utils-srcs",
- ":services-tethering-shared-srcs",
- ],
- static_libs: [
- "androidx.annotation_annotation",
- "netd_aidl_interface-unstable-java",
- "netlink-client",
- // 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",
- ],
- libs: [
- "framework-statsd.stubs.module_lib",
- "framework-tethering.impl",
- "framework-wifi",
- "unsupportedappusage",
- ],
- plugins: ["java_api_finder"],
- manifest: "AndroidManifestBase.xml",
-}
-
-// Build tethering static library, used to compile both variants of the tethering.
-android_library {
- name: "TetheringApiCurrentLib",
- defaults: ["TetheringAndroidLibraryDefaults"],
-}
-
-// Due to b/143733063, APK can't access a jni lib that is in APEX (but not in the APK).
-cc_library {
- name: "libtetherutilsjni",
- sdk_version: "current",
- apex_available: [
- "//apex_available:platform", // Used by InProcessTethering
- "com.android.tethering",
- ],
- min_sdk_version: "current",
- srcs: [
- "jni/android_net_util_TetheringUtils.cpp",
- ],
- shared_libs: [
- "liblog",
- "libnativehelper_compat_libc++",
- ],
-
- // We cannot use plain "libc++" here to link libc++ dynamically because it results in:
- // java.lang.UnsatisfiedLinkError: dlopen failed: library "libc++_shared.so" not found
- // even if "libc++" is added into jni_libs below. Adding "libc++_shared" into jni_libs doesn't
- // build because soong complains of:
- // module Tethering missing dependencies: libc++_shared
- //
- // So, link libc++ statically. This means that we also need to ensure that all the C++ libraries
- // we depend on do not dynamically link libc++. This is currently the case, because liblog is
- // C-only and libnativehelper_compat_libc also uses stl: "c++_static".
- stl: "c++_static",
-
- cflags: [
- "-Wall",
- "-Werror",
- "-Wno-unused-parameter",
- "-Wthread-safety",
- ],
-
- ldflags: ["-Wl,--exclude-libs=ALL,-error-limit=0"],
-}
-
-// Common defaults for compiling the actual APK.
-java_defaults {
- name: "TetheringAppDefaults",
- sdk_version: "module_current",
- privileged: true,
- jni_libs: [
- "libtetherutilsjni",
- ],
- resource_dirs: [
- "res",
- ],
- libs: [
- "framework-tethering",
- "framework-wifi",
- ],
- jarjar_rules: "jarjar-rules.txt",
- optimize: {
- proguard_flags_files: ["proguard.flags"],
- },
-}
-
-// Non-updatable tethering running in the system server process for devices not using the module
-android_app {
- name: "InProcessTethering",
- defaults: ["TetheringAppDefaults"],
- static_libs: ["TetheringApiCurrentLib"],
- certificate: "platform",
- manifest: "AndroidManifest_InProcess.xml",
- // InProcessTethering is a replacement for Tethering
- overrides: ["Tethering"],
- apex_available: ["com.android.tethering"],
- min_sdk_version: "current",
-}
-
-// Updatable tethering packaged as an application
-android_app {
- name: "Tethering",
- defaults: ["TetheringAppDefaults"],
- static_libs: ["TetheringApiCurrentLib"],
- certificate: "networkstack",
- manifest: "AndroidManifest.xml",
- use_embedded_native_libs: true,
- // The permission configuration *must* be included to ensure security of the device
- required: ["NetworkPermissionConfig"],
- apex_available: ["com.android.tethering"],
- min_sdk_version: "current",
-}
diff --git a/packages/Tethering/AndroidManifest.xml b/packages/Tethering/AndroidManifest.xml
deleted file mode 100644
index e6444f3..0000000
--- a/packages/Tethering/AndroidManifest.xml
+++ /dev/null
@@ -1,57 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
- * Copyright (C) 2019 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.
- */
--->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.networkstack.tethering"
- android:sharedUserId="android.uid.networkstack">
- <uses-sdk android:minSdkVersion="29" android:targetSdkVersion="29" />
-
- <!-- Permissions must be defined here, and not in the base manifest, as the tethering
- running in the system server process does not need any permission, and having
- privileged permissions added would cause crashes on startup unless they are also
- added to the privileged permissions allowlist for that package. -->
- <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
- <uses-permission android:name="android.permission.BLUETOOTH" />
- <uses-permission android:name="android.permission.BLUETOOTH_PRIVILEGED" />
- <uses-permission android:name="android.permission.BROADCAST_STICKY" />
- <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
- <uses-permission android:name="android.permission.MANAGE_USB" />
- <uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />
- <uses-permission android:name="android.permission.READ_DEVICE_CONFIG" />
- <uses-permission android:name="android.permission.READ_NETWORK_USAGE_HISTORY" />
- <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
- <uses-permission android:name="android.permission.TETHER_PRIVILEGED" />
- <uses-permission android:name="android.permission.UPDATE_APP_OPS_STATS" />
- <uses-permission android:name="android.permission.UPDATE_DEVICE_STATS" />
- <uses-permission android:name="android.permission.WRITE_SETTINGS" />
-
- <protected-broadcast android:name="com.android.server.connectivity.tethering.DISABLE_TETHERING" />
-
- <application
- android:process="com.android.networkstack.process"
- android:extractNativeLibs="false"
- android:persistent="true">
- <service android:name="com.android.networkstack.tethering.TetheringService"
- android:permission="android.permission.MAINLINE_NETWORK_STACK"
- android:exported="true">
- <intent-filter>
- <action android:name="android.net.ITetheringConnector"/>
- </intent-filter>
- </service>
- </application>
-</manifest>
diff --git a/packages/Tethering/AndroidManifestBase.xml b/packages/Tethering/AndroidManifestBase.xml
deleted file mode 100644
index 97c3988..0000000
--- a/packages/Tethering/AndroidManifestBase.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
- * Copyright (C) 2019 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.
- */
--->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.networkstack.tethering"
- android:versionCode="1"
- android:versionName="R-initial">
- <application
- android:label="Tethering"
- android:defaultToDeviceProtectedStorage="true"
- android:directBootAware="true"
- android:usesCleartextTraffic="true">
- </application>
-</manifest>
diff --git a/packages/Tethering/AndroidManifest_InProcess.xml b/packages/Tethering/AndroidManifest_InProcess.xml
deleted file mode 100644
index b1f1240..0000000
--- a/packages/Tethering/AndroidManifest_InProcess.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
- * Copyright (C) 2019 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.
- */
--->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.networkstack.tethering.inprocess"
- android:sharedUserId="android.uid.system"
- android:process="system">
- <uses-sdk android:minSdkVersion="29" android:targetSdkVersion="29" />
- <application>
- <service android:name="com.android.networkstack.tethering.TetheringService"
- android:process="system"
- android:permission="android.permission.MAINLINE_NETWORK_STACK"
- android:exported="true">
- <intent-filter>
- <action android:name="android.net.ITetheringConnector.InProcess"/>
- </intent-filter>
- </service>
- </application>
-</manifest>
diff --git a/packages/Tethering/OWNERS b/packages/Tethering/OWNERS
deleted file mode 100644
index 5b42d49..0000000
--- a/packages/Tethering/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-include platform/packages/modules/NetworkStack/:/OWNERS
-markchien@google.com
diff --git a/packages/Tethering/TEST_MAPPING b/packages/Tethering/TEST_MAPPING
deleted file mode 100644
index 5617b0c..0000000
--- a/packages/Tethering/TEST_MAPPING
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "presubmit": [
- {
- "name": "TetheringTests"
- }
- ],
- "postsubmit": [
- {
- "name": "TetheringIntegrationTests"
- }
- ]
-}
diff --git a/packages/Tethering/apex/Android.bp b/packages/Tethering/apex/Android.bp
deleted file mode 100644
index 0524374..0000000
--- a/packages/Tethering/apex/Android.bp
+++ /dev/null
@@ -1,48 +0,0 @@
-//
-// Copyright (C) 2019 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.
-//
-
-apex {
- name: "com.android.tethering",
- updatable: true,
- min_sdk_version: "current",
- java_libs: ["framework-tethering"],
- bpfs: ["offload.o"],
- apps: ["Tethering"],
- manifest: "manifest.json",
- key: "com.android.tethering.key",
-
- androidManifest: "AndroidManifest.xml",
-}
-
-apex_key {
- name: "com.android.tethering.key",
- public_key: "com.android.tethering.avbpubkey",
- private_key: "com.android.tethering.pem",
-}
-
-android_app_certificate {
- name: "com.android.tethering.certificate",
- certificate: "com.android.tethering",
-}
-
-override_apex {
- name: "com.android.tethering.inprocess",
- base: "com.android.tethering",
- package_name: "com.android.tethering.inprocess",
- apps: [
- "InProcessTethering",
- ],
-}
diff --git a/packages/Tethering/apex/AndroidManifest.xml b/packages/Tethering/apex/AndroidManifest.xml
deleted file mode 100644
index 4aae3cc..0000000
--- a/packages/Tethering/apex/AndroidManifest.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (C) 2019 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.
- -->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.tethering">
- <!-- APEX does not have classes.dex -->
- <application android:hasCode="false" />
- <!-- b/145383354: Current minSdk is locked to Q for development cycle, lock it to next version
- before ship. -->
- <!-- TODO: Uncomment this when the R API level is fixed. b/148281152 -->
- <!--uses-sdk
- android:minSdkVersion="29"
- android:targetSdkVersion="29"
- />
- -->
-</manifest>
diff --git a/packages/Tethering/apex/com.android.tethering.avbpubkey b/packages/Tethering/apex/com.android.tethering.avbpubkey
deleted file mode 100644
index 9a2c017..0000000
--- a/packages/Tethering/apex/com.android.tethering.avbpubkey
+++ /dev/null
Binary files differ
diff --git a/packages/Tethering/apex/com.android.tethering.pem b/packages/Tethering/apex/com.android.tethering.pem
deleted file mode 100644
index d4f39ab..0000000
--- a/packages/Tethering/apex/com.android.tethering.pem
+++ /dev/null
@@ -1,51 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIIJKgIBAAKCAgEA+AWTp03PBRMGt4mVNLt5PDoFFSfmFOVTM7jt5AJXnQMIDsAM
-1cyWGWRridGIpoHAaCALVgW5aRySgi8yV5xP4w0YHcKbfh9M6I9oz4RUo4GQBZfX
-+lFIGaLjb6I3tEJxPuxps4sW26Io63ihwTnKeGyADHdHGWDUs9WU0Ml+QTvKrdjy
-qC03M0dehYXILGiA9m+UXwKoKxhWgfDUhWLhDBUtLJLPL4WeqKc9sG9h+zzVqE+8
-LzJsfrodKhTTrLpWOXi6YLRTk8dzsuPz/Nu98sJd1w3fHd20DrmkqsxVhgN1h+nk
-zcPpxyGYIP6qYVZCmIXCwZZNtPeb7y/tOs967VHoZ4Qj7p2tE0CAWFMZFGjA/pcZ
-7fi6CsIuMOYBbj4+wRlJwpG1g5zSJBCjzhv7dZp8S5oXmLShNYOMYEdsPfaZbm08
-3pVY+k8DVf7idcANXNw1lM+sPbE2hp5VuEuVpK+ca5x8hIMpTqJ84wDAjnC1kCwm
-X2xfNvYPKNF58SvqlNCPN8X7hQjoeaEb7w24vCdZMRqeGBmu1GNQvCyzbBO0huQm
-f5CQPrZjPcnoImlP879VPxY4YB6tAjsA/ZLiub9VdT108lCjb5r8criMzpMAA/AQ
-NqQLWFI3M43xPemGBTiIguTYgpRgGcdRZf7XuTgTY5qzQZZuZMVuwaqSD2cCAwEA
-AQKCAgEA0jMvw3BPTrakT7Lb8JgelKt7mUV6WyVMUZ6eh0pw5JIoJxAfEKfWYmjY
-NzKNRMjcv6LA2MP7MplTld/YI6ZHkl+Lm9VOISL39HVuV8mIThbFb+gT1INEvu1t
-IjRyT2SsQ67rmo377mLNmVtgg7mt3kfecjI44MpPGqad/CF4zmKVUKd4aI4BpYUM
-F8+dKf3bpoBEWA2RZwy2bGQmSXHW132vDoLR8y2knL04rCqJ+PrC/WWuULXEe9bS
-VtLV3yMBZq3qD4Fk/+7fILLPGvNFVdPi4htQiChYrM4rP9HzfaO63VieYMF0hR70
-pqoOznXj9Q4QVC9FZmUgFCQjQ1+KhqJw3OldIo0SnvpsLdTO/inKkhQWKC5HlPyh
-/rqvro2j3pTHWPAziuBr+oQPcdVCOlCBZ+B99L1tO7aGktVPEIVQG7G7jlFMBiJ1
-j/kRGk2RTX8RaPQJTnwUqp8mWUV2fwxHiXNadjejA5ZU3eQT2eAOhXl1w6Lv2jEl
-0wMOwPMJGcF77CcqnnWHON8fkxCbAfyy5Uo6Pm9g/Zzecn+ji2sabG7Ge5t0gzdL
-LKRcGoyakN2CrbQ8pxlCTgE4HX5oPY+VuqOf8L3AIWIJBsyLbXHVkL1mqQ/Ed2uz
-zaaSFYUZw81+m/5bl8JLPaIFNPyikZrXTD0YRer3V06XiyP/kYECggEBAP033xeF
-OhgRwkRTjd68hwRJpyHsZDWxHiUqQf6l6yFv5mEE355G2IGI7cZmR2+tUDjQdxLv
-tAZIszTK4PFCdVTeWfGVFbVF84eNWLB124pHDMM79GN/AMcuHnQPR756a8IO1hIy
-4KxIUE1a1PKN5b9IgE5Lu4TZM96HDpFcUAmCT5urdYDmg3++IWT9PYQlGS7Hhiar
-r+Hh646waM8Qx619CwXBqy+Y37+WHVbYqJClr6AcpVMrGA+6cgpskFpZAPLsoy7G
-RSsVfyV8pH2JKm/hzk7XCwIpczxeWQSfpJWZ+oOPFHu+zM60Cdj2UrQyKrNHwew8
-+WYe9eCA+MiNBcECggEBAPq/F1vdqROiLv9uzhKb8ybgdL7CmREELiqwK+MvNE9t
-W7lQz7lcWzav+b2n0M+VJBxUWB3XClgoIvA/AllgTgsYXfKAxNakhKLSBoMmvKCW
-HtWcGr/D3RcmacK+DTMWlVS/LuueAFLuH6UmBIUFKc+qA5x7oQecAFALBFupE3G4
-LtAspLBI6P8gRtRav5p2whs9H8qjYcyf2f6liWpkmFITcXvPvAxFHicR6ZJdwZ/S
-PiX2LJQnOpT7L3+2PWnYwzFStb4MkMGlFKcscU9CvS53JcP/J4Asjk0I4zDB2gri
-xzFHPlVzCr2IVVGptKCQ3sdYiMIzQKzEXQHCU8h37ycCggEBAJu8aC48Fz3Edlm1
-ldS+2L9vWSaJEBzhoSu0cMBgZVu8SdGzwKDE69XHVI4oS5lI28UFmaaA3JTc07MN
-cAmSGT2oP2NQkPhbXGsrKLfm1K6YAiZ1Ulp7OwxFth8lYreo7Wt92nV46yuqkhDx
-Y3UGhp39xkPhWiRbvgYHxJLsVqFyjumsK2mq3IeNdVZ6VgJXGsTlnAFeqJ7hZxHs
-N5natSRjeosA0PtGJ57agZLvT8Ue0gREef3LzFGoFwmIOcQHZ4kAt2BGOzZDU17H
-6Rb4bKxBEbT1l2St/5zKXi90zDHicOvG7Q8qiyY6HrBc1wLSs+ZtpLxZx/3h3tFE
-IT6fVUECggEBAMSAQm8Ey76OJ+SXUjk1K50442SnHcs/Cmr7urkEQitImUwl71Pk
-87pst/uP6szypOTqmE9yOTIS6iZ6Sn3+QcriIqWrkhZfwW3Tx7S6A7KZUrq15iSH
-+thsiw9JXxC9TvOmC8AsBzb2U6hZncsc28JZCxFztSNAduJDb/vhCVLiMxWDFuDr
-kmR1R+yc3XDQRpeQFDz6QudYEj9EPOc6xD/16sZLaqP2+oVFvVSt0tJLsdaQECle
-gMNGAdhE2eX8MCOUHMc+E6cdlozYAEhMFfO2/cqWR79jq3TlVR3dnOFRDScqHMhc
-KnuTvsELjHkUbvGsCSiff7yk+fop7vy4OJsCggEAPemJdItO2rhib8EofrZdY72I
-oifX1jhPZ1BWD2GKgcx+eVyJGbONBbJVexvvskTfZBvCcAegmgp+sngP6MO6yZkr
-cHMfAJeApYZnshsgXksHGMDtSB50/w1JLrc/nqpxdpy/aTazt0Eu1pLWpze1HFZ/
-Xyu4PcmrU+4P1vN7c396slHMktEvly6QqOn4nfBbGDJ17Ow6X1XFvGjAxQPIDTB+
-6loV14AHymwmqwMrGn84O72rzqyw+41GxW5+oXhOZ4MeXF3u89TBLWvXDpPy/YQU
-EiKpodN0YeEn6Ghzplan8rUha+7TP7AYnS5pCszsCHKd03Py0lMLkF+uAfVsDA==
------END RSA PRIVATE KEY-----
diff --git a/packages/Tethering/apex/com.android.tethering.pk8 b/packages/Tethering/apex/com.android.tethering.pk8
deleted file mode 100644
index 3b94405..0000000
--- a/packages/Tethering/apex/com.android.tethering.pk8
+++ /dev/null
Binary files differ
diff --git a/packages/Tethering/apex/com.android.tethering.x509.pem b/packages/Tethering/apex/com.android.tethering.x509.pem
deleted file mode 100644
index a1786e3..0000000
--- a/packages/Tethering/apex/com.android.tethering.x509.pem
+++ /dev/null
@@ -1,35 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIGKTCCBBGgAwIBAgIUNiSs5EMqxCZ31gWWCcRJVp9HffAwDQYJKoZIhvcNAQEL
-BQAwgaIxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQH
-DA1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKDAdBbmRyb2lkMRAwDgYDVQQLDAdBbmRy
-b2lkMR4wHAYDVQQDDBVjb20uYW5kcm9pZC50ZXRoZXJpbmcxIjAgBgkqhkiG9w0B
-CQEWE2FuZHJvaWRAYW5kcm9pZC5jb20wIBcNMTkxMjE4MDcwMDQ4WhgPNDc1NzEx
-MTMwNzAwNDhaMIGiMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEW
-MBQGA1UEBwwNTW91bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UE
-CwwHQW5kcm9pZDEeMBwGA1UEAwwVY29tLmFuZHJvaWQudGV0aGVyaW5nMSIwIAYJ
-KoZIhvcNAQkBFhNhbmRyb2lkQGFuZHJvaWQuY29tMIICIjANBgkqhkiG9w0BAQEF
-AAOCAg8AMIICCgKCAgEAxvTUA4seblYjZLfTVNwZuJH914QVNFTj+vD94pWmt5Aq
-sH1DVTpBvpXXegc/P5HI2XF/71poSBib1WaQSuXG0fU5K75T18bOGL0qF+fhMtBO
-wUyvulcjO0h4XE/xf0txY54exUjAA4JS9ERGJOgb4GOwSbPyzekfmzIyCZ2Yawwu
-+oGwD2ZNzZRaPOoWxjwohBWQ6mySuvF9RRRb300qmxxUGFM9Ki3aqrWlYlHEOwOC
-M+gIXxYFO7S+yUzf6/gMZLOz2YqfcTOup4hAxtExR7niutxJSsRLPBL237exAJoz
-OupoXjtWAlPK4ZwZ/Nl1jdTWauJ+Kv3WqzhHGEb2gn3ZpeO3IdOjJhDgFJ6m1OT/
-kjRbW1LCuKGrKaoqsEDT2X3a7Izfripn65hSNTfR5gNLtgELaI3/vXi8Fmzw1AfH
-+qi6ulElZvSwx0qm+S0QiPyGFlxrsdnHoGJl1tzjJW8KdNZRvzRLUQtbphPp+VkL
-5i0bNKum+AwbfdUkLkNLfw9XdbujgBkZTZDQbZGsNjgrvyXcPO2KiJee0hVCZRs0
-rhDi5Pfm7BnN/I2vaTRz/W4mdct9H2RWMuqlSH90JvmKtWcND8ahmOJ3sggrvzfO
-QNs3k4JTRecamMzqIkylhlnEC4FjWc6Bx4wsEpwBMZOkF/tGGMZYf2C09a8tpP0C
-AwEAAaNTMFEwHQYDVR0OBBYEFNP5gIpNWmq0xa411M1GaRPbEijvMB8GA1UdIwQY
-MBaAFNP5gIpNWmq0xa411M1GaRPbEijvMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZI
-hvcNAQELBQADggIBADJGmU3QP4EGbt6eBhVPeo/efsqrHsuB2fvFzvIobJbfkSob
-cmvjbzIikOlPAgFWj8lT5SDcIWRorFf1u2JylClJ0nSDcqJMHVKmT7wseV/KtX//
-1yUyJFRQVzmjC89dp8OIc00GmItivKLer3NbJdkR3rTUjg7+bNUO27Qp3AFREmiJ
-P+M7ouvcQRvByUWbp/LOrJpMdJLysRBO562RwrtwTjltdvufyYswbBZOKEiUh1Jc
-Ged+3+SJdhwq3Wy+R3Uj7YE7mUMu1QNbANIMrwF8W93EA53eoL2+cKmuaVU6ZURL
-xgSJaY6TrunnSI9XTROLtjsFlJorYWy2tvG7Q5Hw3OkO2Xdz/mm85VTkiusg9DMB
-WWTv607YtsIO0FhKmcV4bp3q/EkRj3t/zLvL9uFJrWDGkuShZq6fQvqbCvaokOPY
-+M0ZRIwgwa9UpEE0BMklVWqR6BGyap614gOgcOjYM70WRNl59Qne+g128ZN7g9nz
-61F70i7kUngV0ZUz1/Fu/NCG+6wGF85ZbFmQl60YHPDw1FtjVUuKyBblaDzdJunx
-yQr2t9RUokzFBFK0lGW3+yf0WDQ5fqTMs5h8bz1FCq8/HzWmpdOfqePLe4zsld3b
-1nFuSohaIfbn/HDdTNtTBGQPgz8ZswQ6ejJJqTLz9D/odbqn9LeIhDZXcQTf
------END CERTIFICATE-----
diff --git a/packages/Tethering/apex/manifest.json b/packages/Tethering/apex/manifest.json
deleted file mode 100644
index 8836c4e..0000000
--- a/packages/Tethering/apex/manifest.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "name": "com.android.tethering",
- "version": 300900700
-}
diff --git a/packages/Tethering/bpf_progs/Android.bp b/packages/Tethering/bpf_progs/Android.bp
deleted file mode 100644
index d54f861..0000000
--- a/packages/Tethering/bpf_progs/Android.bp
+++ /dev/null
@@ -1,33 +0,0 @@
-//
-// 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/packages/Tethering/bpf_progs/offload.c b/packages/Tethering/bpf_progs/offload.c
deleted file mode 100644
index cc5af31..0000000
--- a/packages/Tethering/bpf_progs/offload.c
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * 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 <linux/if.h>
-#include <linux/ip.h>
-#include <linux/ipv6.h>
-#include <linux/pkt_cls.h>
-#include <linux/tcp.h>
-
-#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)
-
-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/packages/Tethering/common/TetheringLib/Android.bp b/packages/Tethering/common/TetheringLib/Android.bp
deleted file mode 100644
index bf643cd..0000000
--- a/packages/Tethering/common/TetheringLib/Android.bp
+++ /dev/null
@@ -1,47 +0,0 @@
-//
-// Copyright (C) 2019 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.
-
-java_sdk_library {
- name: "framework-tethering",
- defaults: ["framework-module-defaults"],
- impl_library_visibility: ["//frameworks/base/packages/Tethering:__subpackages__"],
-
- srcs: [":framework-tethering-srcs"],
-
- jarjar_rules: "jarjar-rules.txt",
- installable: true,
-
- hostdex: true, // for hiddenapi check
- apex_available: ["com.android.tethering"],
- permitted_packages: ["android.net"],
-}
-
-filegroup {
- name: "framework-tethering-srcs",
- srcs: [
- "src/android/net/TetheredClient.aidl",
- "src/android/net/TetheredClient.java",
- "src/android/net/TetheringManager.java",
- "src/android/net/TetheringConstants.java",
- "src/android/net/IIntResultListener.aidl",
- "src/android/net/ITetheringEventCallback.aidl",
- "src/android/net/ITetheringConnector.aidl",
- "src/android/net/TetheringCallbackStartedParcel.aidl",
- "src/android/net/TetheringConfigurationParcel.aidl",
- "src/android/net/TetheringRequestParcel.aidl",
- "src/android/net/TetherStatesParcel.aidl",
- ],
- path: "src"
-}
diff --git a/packages/Tethering/common/TetheringLib/api/current.txt b/packages/Tethering/common/TetheringLib/api/current.txt
deleted file mode 100644
index d802177..0000000
--- a/packages/Tethering/common/TetheringLib/api/current.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 2.0
diff --git a/packages/Tethering/common/TetheringLib/api/module-lib-current.txt b/packages/Tethering/common/TetheringLib/api/module-lib-current.txt
deleted file mode 100644
index 6ddb122..0000000
--- a/packages/Tethering/common/TetheringLib/api/module-lib-current.txt
+++ /dev/null
@@ -1,41 +0,0 @@
-// Signature format: 2.0
-package android.net {
-
- public final class TetheringConstants {
- field public static final String EXTRA_ADD_TETHER_TYPE = "extraAddTetherType";
- field public static final String EXTRA_PROVISION_CALLBACK = "extraProvisionCallback";
- field public static final String EXTRA_REM_TETHER_TYPE = "extraRemTetherType";
- field public static final String EXTRA_RUN_PROVISION = "extraRunProvision";
- field public static final String EXTRA_SET_ALARM = "extraSetAlarm";
- }
-
- public class TetheringManager {
- ctor public TetheringManager(@NonNull android.content.Context, @NonNull java.util.function.Supplier<android.os.IBinder>);
- method public int getLastTetherError(@NonNull String);
- method @NonNull public String[] getTetherableBluetoothRegexs();
- method @NonNull public String[] getTetherableIfaces();
- method @NonNull public String[] getTetherableUsbRegexs();
- method @NonNull public String[] getTetherableWifiRegexs();
- method @NonNull public String[] getTetheredIfaces();
- method @NonNull public String[] getTetheringErroredIfaces();
- method public boolean isTetheringSupported();
- method public boolean isTetheringSupported(@NonNull String);
- method public void requestLatestTetheringEntitlementResult(int, @NonNull android.os.ResultReceiver, boolean);
- method @Deprecated public int setUsbTethering(boolean);
- method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public void startTethering(int, @NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.StartTetheringCallback);
- method @Deprecated public int tether(@NonNull String);
- method @Deprecated public int untether(@NonNull String);
- }
-
- public static interface TetheringManager.TetheringEventCallback {
- method public default void onTetherableInterfaceRegexpsChanged(@NonNull android.net.TetheringManager.TetheringInterfaceRegexps);
- }
-
- public static class TetheringManager.TetheringInterfaceRegexps {
- method @NonNull public java.util.List<java.lang.String> getTetherableBluetoothRegexs();
- method @NonNull public java.util.List<java.lang.String> getTetherableUsbRegexs();
- method @NonNull public java.util.List<java.lang.String> getTetherableWifiRegexs();
- }
-
-}
-
diff --git a/packages/Tethering/common/TetheringLib/api/module-lib-removed.txt b/packages/Tethering/common/TetheringLib/api/module-lib-removed.txt
deleted file mode 100644
index d802177..0000000
--- a/packages/Tethering/common/TetheringLib/api/module-lib-removed.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 2.0
diff --git a/packages/Tethering/common/TetheringLib/api/removed.txt b/packages/Tethering/common/TetheringLib/api/removed.txt
deleted file mode 100644
index d802177..0000000
--- a/packages/Tethering/common/TetheringLib/api/removed.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 2.0
diff --git a/packages/Tethering/common/TetheringLib/api/system-current.txt b/packages/Tethering/common/TetheringLib/api/system-current.txt
deleted file mode 100644
index edd1ebb5..0000000
--- a/packages/Tethering/common/TetheringLib/api/system-current.txt
+++ /dev/null
@@ -1,99 +0,0 @@
-// Signature format: 2.0
-package android.net {
-
- public final class TetheredClient implements android.os.Parcelable {
- ctor public TetheredClient(@NonNull android.net.MacAddress, @NonNull java.util.Collection<android.net.TetheredClient.AddressInfo>, int);
- method public int describeContents();
- method @NonNull public java.util.List<android.net.TetheredClient.AddressInfo> getAddresses();
- method @NonNull public android.net.MacAddress getMacAddress();
- method public int getTetheringType();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.net.TetheredClient> CREATOR;
- }
-
- public static final class TetheredClient.AddressInfo implements android.os.Parcelable {
- method public int describeContents();
- method @NonNull public android.net.LinkAddress getAddress();
- method @Nullable public String getHostname();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.net.TetheredClient.AddressInfo> CREATOR;
- }
-
- public class TetheringManager {
- method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerTetheringEventCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.TetheringEventCallback);
- method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public void requestLatestTetheringEntitlementResult(int, boolean, @NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.OnTetheringEntitlementResultListener);
- method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public void startTethering(@NonNull android.net.TetheringManager.TetheringRequest, @NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.StartTetheringCallback);
- method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public void stopAllTethering();
- method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public void stopTethering(int);
- method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.ACCESS_NETWORK_STATE}) public void unregisterTetheringEventCallback(@NonNull android.net.TetheringManager.TetheringEventCallback);
- field public static final String ACTION_TETHER_STATE_CHANGED = "android.net.conn.TETHER_STATE_CHANGED";
- field public static final String EXTRA_ACTIVE_LOCAL_ONLY = "android.net.extra.ACTIVE_LOCAL_ONLY";
- field public static final String EXTRA_ACTIVE_TETHER = "tetherArray";
- field public static final String EXTRA_AVAILABLE_TETHER = "availableArray";
- field public static final String EXTRA_ERRORED_TETHER = "erroredArray";
- field public static final int TETHERING_BLUETOOTH = 2; // 0x2
- field public static final int TETHERING_ETHERNET = 5; // 0x5
- field public static final int TETHERING_INVALID = -1; // 0xffffffff
- field public static final int TETHERING_NCM = 4; // 0x4
- field public static final int TETHERING_USB = 1; // 0x1
- field public static final int TETHERING_WIFI = 0; // 0x0
- field public static final int TETHERING_WIFI_P2P = 3; // 0x3
- field public static final int TETHER_ERROR_DHCPSERVER_ERROR = 12; // 0xc
- field public static final int TETHER_ERROR_DISABLE_FORWARDING_ERROR = 9; // 0x9
- field public static final int TETHER_ERROR_ENABLE_FORWARDING_ERROR = 8; // 0x8
- field public static final int TETHER_ERROR_ENTITLEMENT_UNKNOWN = 13; // 0xd
- field public static final int TETHER_ERROR_IFACE_CFG_ERROR = 10; // 0xa
- field public static final int TETHER_ERROR_INTERNAL_ERROR = 5; // 0x5
- field public static final int TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION = 15; // 0xf
- field public static final int TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION = 14; // 0xe
- field public static final int TETHER_ERROR_NO_ERROR = 0; // 0x0
- field public static final int TETHER_ERROR_PROVISIONING_FAILED = 11; // 0xb
- field public static final int TETHER_ERROR_SERVICE_UNAVAIL = 2; // 0x2
- field public static final int TETHER_ERROR_TETHER_IFACE_ERROR = 6; // 0x6
- field public static final int TETHER_ERROR_UNAVAIL_IFACE = 4; // 0x4
- field public static final int TETHER_ERROR_UNKNOWN_IFACE = 1; // 0x1
- field public static final int TETHER_ERROR_UNKNOWN_TYPE = 16; // 0x10
- field public static final int TETHER_ERROR_UNSUPPORTED = 3; // 0x3
- field public static final int TETHER_ERROR_UNTETHER_IFACE_ERROR = 7; // 0x7
- field public static final int TETHER_HARDWARE_OFFLOAD_FAILED = 2; // 0x2
- field public static final int TETHER_HARDWARE_OFFLOAD_STARTED = 1; // 0x1
- field public static final int TETHER_HARDWARE_OFFLOAD_STOPPED = 0; // 0x0
- }
-
- public static interface TetheringManager.OnTetheringEntitlementResultListener {
- method public void onTetheringEntitlementResult(int);
- }
-
- public static interface TetheringManager.StartTetheringCallback {
- method public default void onTetheringFailed(int);
- method public default void onTetheringStarted();
- }
-
- public static interface TetheringManager.TetheringEventCallback {
- method public default void onClientsChanged(@NonNull java.util.Collection<android.net.TetheredClient>);
- method public default void onError(@NonNull String, int);
- method public default void onOffloadStatusChanged(int);
- method public default void onTetherableInterfacesChanged(@NonNull java.util.List<java.lang.String>);
- method public default void onTetheredInterfacesChanged(@NonNull java.util.List<java.lang.String>);
- method public default void onTetheringSupported(boolean);
- method public default void onUpstreamChanged(@Nullable android.net.Network);
- }
-
- public static class TetheringManager.TetheringRequest {
- method @Nullable public android.net.LinkAddress getClientStaticIpv4Address();
- method @Nullable public android.net.LinkAddress getLocalIpv4Address();
- method public boolean getShouldShowEntitlementUi();
- method public int getTetheringType();
- method public boolean isExemptFromEntitlementCheck();
- }
-
- public static class TetheringManager.TetheringRequest.Builder {
- ctor public TetheringManager.TetheringRequest.Builder(int);
- method @NonNull public android.net.TetheringManager.TetheringRequest build();
- method @NonNull @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public android.net.TetheringManager.TetheringRequest.Builder setExemptFromEntitlementCheck(boolean);
- method @NonNull @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public android.net.TetheringManager.TetheringRequest.Builder setShouldShowEntitlementUi(boolean);
- method @NonNull @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public android.net.TetheringManager.TetheringRequest.Builder setStaticIpv4Addresses(@NonNull android.net.LinkAddress, @NonNull android.net.LinkAddress);
- }
-
-}
-
diff --git a/packages/Tethering/common/TetheringLib/api/system-removed.txt b/packages/Tethering/common/TetheringLib/api/system-removed.txt
deleted file mode 100644
index d802177..0000000
--- a/packages/Tethering/common/TetheringLib/api/system-removed.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 2.0
diff --git a/packages/Tethering/common/TetheringLib/jarjar-rules.txt b/packages/Tethering/common/TetheringLib/jarjar-rules.txt
deleted file mode 100644
index e459fad..0000000
--- a/packages/Tethering/common/TetheringLib/jarjar-rules.txt
+++ /dev/null
@@ -1 +0,0 @@
-# jarjar rules for the bootclasspath tethering framework library here
\ No newline at end of file
diff --git a/packages/Tethering/common/TetheringLib/src/android/net/IIntResultListener.aidl b/packages/Tethering/common/TetheringLib/src/android/net/IIntResultListener.aidl
deleted file mode 100644
index c3d66ee..0000000
--- a/packages/Tethering/common/TetheringLib/src/android/net/IIntResultListener.aidl
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2019 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 android.net;
-
-/**
- * Listener interface allowing objects to listen to various module event.
- * {@hide}
- */
-oneway interface IIntResultListener {
- void onResult(int resultCode);
-}
diff --git a/packages/Tethering/common/TetheringLib/src/android/net/ITetheringConnector.aidl b/packages/Tethering/common/TetheringLib/src/android/net/ITetheringConnector.aidl
deleted file mode 100644
index cf094aa..0000000
--- a/packages/Tethering/common/TetheringLib/src/android/net/ITetheringConnector.aidl
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * 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 android.net;
-
-import android.net.IIntResultListener;
-import android.net.ITetheringEventCallback;
-import android.net.TetheringRequestParcel;
-import android.os.ResultReceiver;
-
-/** @hide */
-oneway interface ITetheringConnector {
- void tether(String iface, String callerPkg, String callingAttributionTag,
- 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, String callingAttributionTag);
-
- void registerTetheringEventCallback(ITetheringEventCallback callback, String callerPkg);
-
- void unregisterTetheringEventCallback(ITetheringEventCallback callback, String callerPkg);
-
- void isTetheringSupported(String callerPkg, String callingAttributionTag,
- IIntResultListener receiver);
-
- void stopAllTethering(String callerPkg, String callingAttributionTag,
- IIntResultListener receiver);
-}
diff --git a/packages/Tethering/common/TetheringLib/src/android/net/ITetheringEventCallback.aidl b/packages/Tethering/common/TetheringLib/src/android/net/ITetheringEventCallback.aidl
deleted file mode 100644
index b4e3ba4..0000000
--- a/packages/Tethering/common/TetheringLib/src/android/net/ITetheringEventCallback.aidl
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2019 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 android.net;
-
-import android.net.Network;
-import android.net.TetheredClient;
-import android.net.TetheringConfigurationParcel;
-import android.net.TetheringCallbackStartedParcel;
-import android.net.TetherStatesParcel;
-
-/**
- * Callback class for receiving tethering changed events.
- * @hide
- */
-oneway interface ITetheringEventCallback
-{
- /** Called immediately after the callbacks are registered */
- void onCallbackStarted(in TetheringCallbackStartedParcel parcel);
- void onCallbackStopped(int errorCode);
- void onUpstreamChanged(in Network network);
- void onConfigurationChanged(in TetheringConfigurationParcel config);
- void onTetherStatesChanged(in TetherStatesParcel states);
- void onTetherClientsChanged(in List<TetheredClient> clients);
- void onOffloadStatusChanged(int status);
-}
diff --git a/packages/Tethering/common/TetheringLib/src/android/net/TetherStatesParcel.aidl b/packages/Tethering/common/TetheringLib/src/android/net/TetherStatesParcel.aidl
deleted file mode 100644
index 3d842b3..0000000
--- a/packages/Tethering/common/TetheringLib/src/android/net/TetherStatesParcel.aidl
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2019 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 android.net;
-
-/**
- * Status details for tethering downstream interfaces.
- * {@hide}
- */
-parcelable TetherStatesParcel {
- String[] availableList;
- String[] tetheredList;
- String[] localOnlyList;
- String[] erroredIfaceList;
- // List of Last error code corresponding to each errored iface in erroredIfaceList. */
- // TODO: Improve this as b/143122247.
- int[] lastErrorList;
-}
diff --git a/packages/Tethering/common/TetheringLib/src/android/net/TetheredClient.java b/packages/Tethering/common/TetheringLib/src/android/net/TetheredClient.java
deleted file mode 100644
index 0b223f4..0000000
--- a/packages/Tethering/common/TetheringLib/src/android/net/TetheredClient.java
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- * 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 android.net;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SystemApi;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Objects;
-
-/**
- * Information on a tethered downstream client.
- * @hide
- */
-@SystemApi
-public final class TetheredClient implements Parcelable {
- @NonNull
- private final MacAddress mMacAddress;
- @NonNull
- private final List<AddressInfo> mAddresses;
- // TODO: use an @IntDef here
- private final int mTetheringType;
-
- public TetheredClient(@NonNull MacAddress macAddress,
- @NonNull Collection<AddressInfo> addresses, int tetheringType) {
- mMacAddress = macAddress;
- mAddresses = new ArrayList<>(addresses);
- mTetheringType = tetheringType;
- }
-
- private TetheredClient(@NonNull Parcel in) {
- this(in.readParcelable(null), in.createTypedArrayList(AddressInfo.CREATOR), in.readInt());
- }
-
- @Override
- public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeParcelable(mMacAddress, flags);
- dest.writeTypedList(mAddresses);
- dest.writeInt(mTetheringType);
- }
-
- /**
- * Get the MAC address used to identify the client.
- */
- @NonNull
- public MacAddress getMacAddress() {
- return mMacAddress;
- }
-
- /**
- * Get information on the list of addresses that are associated with the client.
- */
- @NonNull
- public List<AddressInfo> getAddresses() {
- return new ArrayList<>(mAddresses);
- }
-
- /**
- * Get the type of tethering used by the client.
- * @return one of the {@code TetheringManager#TETHERING_*} constants.
- */
- public int getTetheringType() {
- return mTetheringType;
- }
-
- /**
- * Return a new {@link TetheredClient} that has all the attributes of this instance, plus the
- * {@link AddressInfo} of the provided {@link TetheredClient}.
- *
- * <p>Duplicate addresses are removed.
- * @hide
- */
- public TetheredClient addAddresses(@NonNull TetheredClient other) {
- final LinkedHashSet<AddressInfo> newAddresses = new LinkedHashSet<>(
- mAddresses.size() + other.mAddresses.size());
- newAddresses.addAll(mAddresses);
- newAddresses.addAll(other.mAddresses);
- return new TetheredClient(mMacAddress, newAddresses, mTetheringType);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(mMacAddress, mAddresses, mTetheringType);
- }
-
- @Override
- public boolean equals(@Nullable Object obj) {
- if (!(obj instanceof TetheredClient)) return false;
- final TetheredClient other = (TetheredClient) obj;
- return mMacAddress.equals(other.mMacAddress)
- && mAddresses.equals(other.mAddresses)
- && mTetheringType == other.mTetheringType;
- }
-
- /**
- * Information on an lease assigned to a tethered client.
- */
- public static final class AddressInfo implements Parcelable {
- @NonNull
- private final LinkAddress mAddress;
- @Nullable
- private final String mHostname;
-
- /** @hide */
- public AddressInfo(@NonNull LinkAddress address, @Nullable String hostname) {
- this.mAddress = address;
- this.mHostname = hostname;
- }
-
- private AddressInfo(Parcel in) {
- this(in.readParcelable(null), in.readString());
- }
-
- @Override
- public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeParcelable(mAddress, flags);
- dest.writeString(mHostname);
- }
-
- /**
- * Get the link address (including prefix length and lifetime) used by the client.
- *
- * This may be an IPv4 or IPv6 address.
- */
- @NonNull
- public LinkAddress getAddress() {
- return mAddress;
- }
-
- /**
- * Get the hostname that was advertised by the client when obtaining its address, if any.
- */
- @Nullable
- public String getHostname() {
- return mHostname;
- }
-
- /**
- * Get the expiration time of the address assigned to the client.
- * @hide
- */
- public long getExpirationTime() {
- return mAddress.getExpirationTime();
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(mAddress, mHostname);
- }
-
- @Override
- public boolean equals(@Nullable Object obj) {
- if (!(obj instanceof AddressInfo)) return false;
- final AddressInfo other = (AddressInfo) obj;
- // Use .equals() for addresses as all changes, including address expiry changes,
- // should be included.
- return other.mAddress.equals(mAddress)
- && Objects.equals(mHostname, other.mHostname);
- }
-
- @NonNull
- public static final Creator<AddressInfo> CREATOR = new Creator<AddressInfo>() {
- @NonNull
- @Override
- public AddressInfo createFromParcel(@NonNull Parcel in) {
- return new AddressInfo(in);
- }
-
- @NonNull
- @Override
- public AddressInfo[] newArray(int size) {
- return new AddressInfo[size];
- }
- };
-
- @NonNull
- @Override
- public String toString() {
- return "AddressInfo {"
- + mAddress
- + (mHostname != null ? ", hostname " + mHostname : "")
- + "}";
- }
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @NonNull
- public static final Creator<TetheredClient> CREATOR = new Creator<TetheredClient>() {
- @NonNull
- @Override
- public TetheredClient createFromParcel(@NonNull Parcel in) {
- return new TetheredClient(in);
- }
-
- @NonNull
- @Override
- public TetheredClient[] newArray(int size) {
- return new TetheredClient[size];
- }
- };
-
- @NonNull
- @Override
- public String toString() {
- return "TetheredClient {hwAddr " + mMacAddress
- + ", addresses " + mAddresses
- + ", tetheringType " + mTetheringType
- + "}";
- }
-}
diff --git a/packages/Tethering/common/TetheringLib/src/android/net/TetheringCallbackStartedParcel.aidl b/packages/Tethering/common/TetheringLib/src/android/net/TetheringCallbackStartedParcel.aidl
deleted file mode 100644
index 253eacb..0000000
--- a/packages/Tethering/common/TetheringLib/src/android/net/TetheringCallbackStartedParcel.aidl
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * 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 android.net;
-
-import android.net.Network;
-import android.net.TetheredClient;
-import android.net.TetheringConfigurationParcel;
-import android.net.TetherStatesParcel;
-
-/**
- * Initial information reported by tethering upon callback registration.
- * @hide
- */
-parcelable TetheringCallbackStartedParcel {
- boolean tetheringSupported;
- Network upstreamNetwork;
- TetheringConfigurationParcel config;
- TetherStatesParcel states;
- List<TetheredClient> tetheredClients;
- int offloadStatus;
-}
diff --git a/packages/Tethering/common/TetheringLib/src/android/net/TetheringConfigurationParcel.aidl b/packages/Tethering/common/TetheringLib/src/android/net/TetheringConfigurationParcel.aidl
deleted file mode 100644
index 89f3813..0000000
--- a/packages/Tethering/common/TetheringLib/src/android/net/TetheringConfigurationParcel.aidl
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2019 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 android.net;
-
-/**
- * Configuration details for tethering.
- * @hide
- */
-parcelable TetheringConfigurationParcel {
- int subId;
- String[] tetherableUsbRegexs;
- String[] tetherableWifiRegexs;
- String[] tetherableBluetoothRegexs;
- boolean isDunRequired;
- boolean chooseUpstreamAutomatically;
- int[] preferredUpstreamIfaceTypes;
- String[] legacyDhcpRanges;
- String[] defaultIPv4DNS;
- boolean enableLegacyDhcpServer;
- String[] provisioningApp;
- String provisioningAppNoUi;
- int provisioningCheckPeriod;
-}
diff --git a/packages/Tethering/common/TetheringLib/src/android/net/TetheringConstants.java b/packages/Tethering/common/TetheringLib/src/android/net/TetheringConstants.java
deleted file mode 100644
index f14def6a..0000000
--- a/packages/Tethering/common/TetheringLib/src/android/net/TetheringConstants.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * 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 android.net;
-
-import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
-
-import android.annotation.SystemApi;
-import android.os.ResultReceiver;
-
-/**
- * Collections of constants for internal tethering usage.
- *
- * <p>These hidden constants are not in TetheringManager as they are not part of the API stubs
- * generated for TetheringManager, which prevents the tethering module from linking them at
- * build time.
- * TODO: investigate changing the tethering build rules so that Tethering can reference hidden
- * symbols from framework-tethering even when they are in a non-hidden class.
- * @hide
- */
-@SystemApi(client = MODULE_LIBRARIES)
-public final class TetheringConstants {
- /** An explicit private class to avoid exposing constructor.*/
- private TetheringConstants() { }
-
- /**
- * Extra used for communicating with the TetherService and TetherProvisioningActivity.
- * Includes the type of tethering to enable if any.
- */
- public static final String EXTRA_ADD_TETHER_TYPE = "extraAddTetherType";
- /**
- * Extra used for communicating with the TetherService. Includes the type of tethering for
- * which to cancel provisioning.
- */
- public static final String EXTRA_REM_TETHER_TYPE = "extraRemTetherType";
- /**
- * Extra used for communicating with the TetherService. True to schedule a recheck of tether
- * provisioning.
- */
- public static final String EXTRA_SET_ALARM = "extraSetAlarm";
- /**
- * Tells the TetherService to run a provision check now.
- */
- public static final String EXTRA_RUN_PROVISION = "extraRunProvision";
- /**
- * Extra used for communicating with the TetherService and TetherProvisioningActivity.
- * Contains the {@link ResultReceiver} which will receive provisioning results.
- * Can not be empty.
- */
- public static final String EXTRA_PROVISION_CALLBACK = "extraProvisionCallback";
-
- /**
- * Extra used for communicating with the TetherService and TetherProvisioningActivity.
- * Contains the subId of current active cellular upstream.
- * @hide
- */
- public static final String EXTRA_TETHER_SUBID = "android.net.extra.TETHER_SUBID";
-
- /**
- * Extra used for telling TetherProvisioningActivity the entitlement package name and class
- * name to start UI entitlement check.
- * @hide
- */
- public static final String EXTRA_TETHER_UI_PROVISIONING_APP_NAME =
- "android.net.extra.TETHER_UI_PROVISIONING_APP_NAME";
-
- /**
- * Extra used for telling TetherService the intent action to start silent entitlement check.
- * @hide
- */
- public static final String EXTRA_TETHER_SILENT_PROVISIONING_ACTION =
- "android.net.extra.TETHER_SILENT_PROVISIONING_ACTION";
-
- /**
- * Extra used for TetherService to receive the response of provisioning check.
- * @hide
- */
- public static final String EXTRA_TETHER_PROVISIONING_RESPONSE =
- "android.net.extra.TETHER_PROVISIONING_RESPONSE";
-}
diff --git a/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java b/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java
deleted file mode 100644
index 97fb497..0000000
--- a/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java
+++ /dev/null
@@ -1,1364 +0,0 @@
-/*
- * Copyright (C) 2019 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 android.net;
-
-import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
-
-import android.Manifest;
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.RequiresPermission;
-import android.annotation.SystemApi;
-import android.content.Context;
-import android.os.Bundle;
-import android.os.ConditionVariable;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.os.ResultReceiver;
-import android.util.ArrayMap;
-import android.util.Log;
-
-import com.android.internal.annotations.GuardedBy;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Objects;
-import java.util.concurrent.Executor;
-import java.util.function.Supplier;
-
-/**
- * This class provides the APIs to control the tethering service.
- * <p> The primary responsibilities of this class are to provide the APIs for applications to
- * start tethering, stop tethering, query configuration and query status.
- *
- * @hide
- */
-@SystemApi
-public class TetheringManager {
- private static final String TAG = TetheringManager.class.getSimpleName();
- private static final int DEFAULT_TIMEOUT_MS = 60_000;
- private static final long CONNECTOR_POLL_INTERVAL_MILLIS = 200L;
-
- @GuardedBy("mConnectorWaitQueue")
- @Nullable
- private ITetheringConnector mConnector;
- @GuardedBy("mConnectorWaitQueue")
- @NonNull
- private final List<ConnectorConsumer> mConnectorWaitQueue = new ArrayList<>();
- private final Supplier<IBinder> mConnectorSupplier;
-
- private final TetheringCallbackInternal mCallback;
- private final Context mContext;
- private final ArrayMap<TetheringEventCallback, ITetheringEventCallback>
- mTetheringEventCallbacks = new ArrayMap<>();
-
- private volatile TetheringConfigurationParcel mTetheringConfiguration;
- private volatile TetherStatesParcel mTetherStatesParcel;
-
- /**
- * Broadcast Action: A tetherable connection has come or gone.
- * Uses {@code TetheringManager.EXTRA_AVAILABLE_TETHER},
- * {@code TetheringManager.EXTRA_ACTIVE_LOCAL_ONLY},
- * {@code TetheringManager.EXTRA_ACTIVE_TETHER}, and
- * {@code TetheringManager.EXTRA_ERRORED_TETHER} to indicate
- * the current state of tethering. Each include a list of
- * interface names in that state (may be empty).
- */
- public static final String ACTION_TETHER_STATE_CHANGED =
- "android.net.conn.TETHER_STATE_CHANGED";
-
- /**
- * gives a String[] listing all the interfaces configured for
- * tethering and currently available for tethering.
- */
- public static final String EXTRA_AVAILABLE_TETHER = "availableArray";
-
- /**
- * gives a String[] listing all the interfaces currently in local-only
- * mode (ie, has DHCPv4+IPv6-ULA support and no packet forwarding)
- */
- public static final String EXTRA_ACTIVE_LOCAL_ONLY = "android.net.extra.ACTIVE_LOCAL_ONLY";
-
- /**
- * gives a String[] listing all the interfaces currently tethered
- * (ie, has DHCPv4 support and packets potentially forwarded/NATed)
- */
- public static final String EXTRA_ACTIVE_TETHER = "tetherArray";
-
- /**
- * gives a String[] listing all the interfaces we tried to tether and
- * failed. Use {@link #getLastTetherError} to find the error code
- * for any interfaces listed here.
- */
- public static final String EXTRA_ERRORED_TETHER = "erroredArray";
-
- /** @hide */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(flag = false, value = {
- TETHERING_WIFI,
- TETHERING_USB,
- TETHERING_BLUETOOTH,
- TETHERING_WIFI_P2P,
- TETHERING_NCM,
- TETHERING_ETHERNET,
- })
- public @interface TetheringType {
- }
-
- /**
- * Invalid tethering type.
- * @see #startTethering.
- */
- public static final int TETHERING_INVALID = -1;
-
- /**
- * Wifi tethering type.
- * @see #startTethering.
- */
- public static final int TETHERING_WIFI = 0;
-
- /**
- * USB tethering type.
- * @see #startTethering.
- */
- public static final int TETHERING_USB = 1;
-
- /**
- * Bluetooth tethering type.
- * @see #startTethering.
- */
- public static final int TETHERING_BLUETOOTH = 2;
-
- /**
- * Wifi P2p tethering type.
- * Wifi P2p tethering is set through events automatically, and don't
- * need to start from #startTethering.
- */
- public static final int TETHERING_WIFI_P2P = 3;
-
- /**
- * Ncm local tethering type.
- * @see #startTethering(TetheringRequest, Executor, StartTetheringCallback)
- */
- public static final int TETHERING_NCM = 4;
-
- /**
- * Ethernet tethering type.
- * @see #startTethering(TetheringRequest, Executor, StartTetheringCallback)
- */
- public static final int TETHERING_ETHERNET = 5;
-
- /**
- * WIGIG tethering type. Use a separate type to prevent
- * conflicts with TETHERING_WIFI
- * This type is only used internally by the tethering module
- * @hide
- */
- public static final int TETHERING_WIGIG = 6;
-
- /** @hide */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(value = {
- TETHER_ERROR_NO_ERROR,
- TETHER_ERROR_PROVISIONING_FAILED,
- TETHER_ERROR_ENTITLEMENT_UNKNOWN,
- })
- public @interface EntitlementResult {
- }
-
- /** @hide */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(value = {
- TETHER_ERROR_NO_ERROR,
- TETHER_ERROR_UNKNOWN_IFACE,
- TETHER_ERROR_SERVICE_UNAVAIL,
- TETHER_ERROR_INTERNAL_ERROR,
- TETHER_ERROR_TETHER_IFACE_ERROR,
- TETHER_ERROR_ENABLE_FORWARDING_ERROR,
- TETHER_ERROR_DISABLE_FORWARDING_ERROR,
- TETHER_ERROR_IFACE_CFG_ERROR,
- TETHER_ERROR_DHCPSERVER_ERROR,
- })
- public @interface TetheringIfaceError {
- }
-
- /** @hide */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(value = {
- TETHER_ERROR_SERVICE_UNAVAIL,
- TETHER_ERROR_INTERNAL_ERROR,
- TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION,
- TETHER_ERROR_UNKNOWN_TYPE,
- })
- public @interface StartTetheringError {
- }
-
- public static final int TETHER_ERROR_NO_ERROR = 0;
- public static final int TETHER_ERROR_UNKNOWN_IFACE = 1;
- public static final int TETHER_ERROR_SERVICE_UNAVAIL = 2;
- public static final int TETHER_ERROR_UNSUPPORTED = 3;
- public static final int TETHER_ERROR_UNAVAIL_IFACE = 4;
- public static final int TETHER_ERROR_INTERNAL_ERROR = 5;
- public static final int TETHER_ERROR_TETHER_IFACE_ERROR = 6;
- public static final int TETHER_ERROR_UNTETHER_IFACE_ERROR = 7;
- public static final int TETHER_ERROR_ENABLE_FORWARDING_ERROR = 8;
- public static final int TETHER_ERROR_DISABLE_FORWARDING_ERROR = 9;
- public static final int TETHER_ERROR_IFACE_CFG_ERROR = 10;
- public static final int TETHER_ERROR_PROVISIONING_FAILED = 11;
- public static final int TETHER_ERROR_DHCPSERVER_ERROR = 12;
- public static final int TETHER_ERROR_ENTITLEMENT_UNKNOWN = 13;
- public static final int TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION = 14;
- public static final int TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION = 15;
- public static final int TETHER_ERROR_UNKNOWN_TYPE = 16;
-
- /** @hide */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(flag = false, value = {
- TETHER_HARDWARE_OFFLOAD_STOPPED,
- TETHER_HARDWARE_OFFLOAD_STARTED,
- TETHER_HARDWARE_OFFLOAD_FAILED,
- })
- public @interface TetherOffloadStatus {
- }
-
- /** Tethering offload status is stopped. */
- public static final int TETHER_HARDWARE_OFFLOAD_STOPPED = 0;
- /** Tethering offload status is started. */
- public static final int TETHER_HARDWARE_OFFLOAD_STARTED = 1;
- /** Fail to start tethering offload. */
- public static final int TETHER_HARDWARE_OFFLOAD_FAILED = 2;
-
- /**
- * Create a TetheringManager object for interacting with the tethering service.
- *
- * @param context Context for the manager.
- * @param connectorSupplier Supplier for the manager connector; may return null while the
- * service is not connected.
- * {@hide}
- */
- @SystemApi(client = MODULE_LIBRARIES)
- public TetheringManager(@NonNull final Context context,
- @NonNull Supplier<IBinder> connectorSupplier) {
- mContext = context;
- mCallback = new TetheringCallbackInternal();
- mConnectorSupplier = connectorSupplier;
-
- final String pkgName = mContext.getOpPackageName();
-
- final IBinder connector = mConnectorSupplier.get();
- // If the connector is available on start, do not start a polling thread. This introduces
- // differences in the thread that sends the oneway binder calls to the service between the
- // first few seconds after boot and later, but it avoids always having differences between
- // the first usage of TetheringManager from a process and subsequent usages (so the
- // difference is only on boot). On boot binder calls may be queued until the service comes
- // up and be sent from a worker thread; later, they are always sent from the caller thread.
- // Considering that it's just oneway binder calls, and ordering is preserved, this seems
- // better than inconsistent behavior persisting after boot.
- if (connector != null) {
- mConnector = ITetheringConnector.Stub.asInterface(connector);
- } else {
- startPollingForConnector();
- }
-
- Log.i(TAG, "registerTetheringEventCallback:" + pkgName);
- getConnector(c -> c.registerTetheringEventCallback(mCallback, pkgName));
- }
-
- private void startPollingForConnector() {
- new Thread(() -> {
- while (true) {
- try {
- Thread.sleep(CONNECTOR_POLL_INTERVAL_MILLIS);
- } catch (InterruptedException e) {
- // Not much to do here, the system needs to wait for the connector
- }
-
- final IBinder connector = mConnectorSupplier.get();
- if (connector != null) {
- onTetheringConnected(ITetheringConnector.Stub.asInterface(connector));
- return;
- }
- }
- }).start();
- }
-
- private interface ConnectorConsumer {
- void onConnectorAvailable(ITetheringConnector connector) throws RemoteException;
- }
-
- private void onTetheringConnected(ITetheringConnector connector) {
- // Process the connector wait queue in order, including any items that are added
- // while processing.
- //
- // 1. Copy the queue to a local variable under lock.
- // 2. Drain the local queue with the lock released (otherwise, enqueuing future commands
- // would block on the lock).
- // 3. Acquire the lock again. If any new tasks were queued during step 2, goto 1.
- // If not, set mConnector to non-null so future tasks are run immediately, not queued.
- //
- // For this to work, all calls to the tethering service must use getConnector(), which
- // ensures that tasks are added to the queue with the lock held.
- //
- // Once mConnector is set to non-null, it will never be null again. If the network stack
- // process crashes, no recovery is possible.
- // TODO: evaluate whether it is possible to recover from network stack process crashes
- // (though in most cases the system will have crashed when the network stack process
- // crashes).
- do {
- final List<ConnectorConsumer> localWaitQueue;
- synchronized (mConnectorWaitQueue) {
- localWaitQueue = new ArrayList<>(mConnectorWaitQueue);
- mConnectorWaitQueue.clear();
- }
-
- // Allow more tasks to be added at the end without blocking while draining the queue.
- for (ConnectorConsumer task : localWaitQueue) {
- try {
- task.onConnectorAvailable(connector);
- } catch (RemoteException e) {
- // Most likely the network stack process crashed, which is likely to crash the
- // system. Keep processing other requests but report the error loudly.
- Log.wtf(TAG, "Error processing request for the tethering connector", e);
- }
- }
-
- synchronized (mConnectorWaitQueue) {
- if (mConnectorWaitQueue.size() == 0) {
- mConnector = connector;
- return;
- }
- }
- } while (true);
- }
-
- /**
- * Asynchronously get the ITetheringConnector to execute some operation.
- *
- * <p>If the connector is already available, the operation will be executed on the caller's
- * thread. Otherwise it will be queued and executed on a worker thread. The operation should be
- * limited to performing oneway binder calls to minimize differences due to threading.
- */
- private void getConnector(ConnectorConsumer consumer) {
- final ITetheringConnector connector;
- synchronized (mConnectorWaitQueue) {
- connector = mConnector;
- if (connector == null) {
- mConnectorWaitQueue.add(consumer);
- return;
- }
- }
-
- try {
- consumer.onConnectorAvailable(connector);
- } catch (RemoteException e) {
- throw new IllegalStateException(e);
- }
- }
-
- private interface RequestHelper {
- void runRequest(ITetheringConnector connector, IIntResultListener listener);
- }
-
- // Used to dispatch legacy ConnectivityManager methods that expect tethering to be able to
- // return results and perform operations synchronously.
- // TODO: remove once there are no callers of these legacy methods.
- private class RequestDispatcher {
- private final ConditionVariable mWaiting;
- public volatile int mRemoteResult;
-
- private final IIntResultListener mListener = new IIntResultListener.Stub() {
- @Override
- public void onResult(final int resultCode) {
- mRemoteResult = resultCode;
- mWaiting.open();
- }
- };
-
- RequestDispatcher() {
- mWaiting = new ConditionVariable();
- }
-
- int waitForResult(final RequestHelper request) {
- getConnector(c -> request.runRequest(c, mListener));
- if (!mWaiting.block(DEFAULT_TIMEOUT_MS)) {
- throw new IllegalStateException("Callback timeout");
- }
-
- throwIfPermissionFailure(mRemoteResult);
-
- return mRemoteResult;
- }
- }
-
- private void throwIfPermissionFailure(final int errorCode) {
- switch (errorCode) {
- case TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION:
- throw new SecurityException("No android.permission.TETHER_PRIVILEGED"
- + " or android.permission.WRITE_SETTINGS permission");
- case TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION:
- throw new SecurityException(
- "No android.permission.ACCESS_NETWORK_STATE permission");
- }
- }
-
- private class TetheringCallbackInternal extends ITetheringEventCallback.Stub {
- private volatile int mError = TETHER_ERROR_NO_ERROR;
- private final ConditionVariable mWaitForCallback = new ConditionVariable();
-
- @Override
- public void onCallbackStarted(TetheringCallbackStartedParcel parcel) {
- mTetheringConfiguration = parcel.config;
- mTetherStatesParcel = parcel.states;
- mWaitForCallback.open();
- }
-
- @Override
- public void onCallbackStopped(int errorCode) {
- mError = errorCode;
- mWaitForCallback.open();
- }
-
- @Override
- public void onUpstreamChanged(Network network) { }
-
- @Override
- public void onConfigurationChanged(TetheringConfigurationParcel config) {
- mTetheringConfiguration = config;
- }
-
- @Override
- public void onTetherStatesChanged(TetherStatesParcel states) {
- mTetherStatesParcel = states;
- }
-
- @Override
- public void onTetherClientsChanged(List<TetheredClient> clients) { }
-
- @Override
- public void onOffloadStatusChanged(int status) { }
-
- public void waitForStarted() {
- mWaitForCallback.block(DEFAULT_TIMEOUT_MS);
- throwIfPermissionFailure(mError);
- }
- }
-
- /**
- * Attempt to tether the named interface. This will setup a dhcp server
- * on the interface, forward and NAT IP v4 packets and forward DNS requests
- * to the best active upstream network interface. Note that if no upstream
- * IP network interface is available, dhcp will still run and traffic will be
- * allowed between the tethered devices and this device, though upstream net
- * access will of course fail until an upstream network interface becomes
- * active.
- *
- * @deprecated The only usages is PanService. It uses this for legacy reasons
- * and will migrate away as soon as possible.
- *
- * @param iface the interface name to tether.
- * @return error a {@code TETHER_ERROR} value indicating success or failure type
- *
- * {@hide}
- */
- @Deprecated
- @SystemApi(client = MODULE_LIBRARIES)
- public int tether(@NonNull final String iface) {
- final String callerPkg = mContext.getOpPackageName();
- Log.i(TAG, "tether caller:" + callerPkg);
- final RequestDispatcher dispatcher = new RequestDispatcher();
-
- return dispatcher.waitForResult((connector, listener) -> {
- try {
- connector.tether(iface, callerPkg, getAttributionTag(), listener);
- } catch (RemoteException e) {
- throw new IllegalStateException(e);
- }
- });
- }
-
- /**
- * @return the context's attribution tag
- */
- private @Nullable String getAttributionTag() {
- return null;
- }
-
- /**
- * Stop tethering the named interface.
- *
- * @deprecated The only usages is PanService. It uses this for legacy reasons
- * and will migrate away as soon as possible.
- *
- * {@hide}
- */
- @Deprecated
- @SystemApi(client = MODULE_LIBRARIES)
- public int untether(@NonNull final String iface) {
- final String callerPkg = mContext.getOpPackageName();
- Log.i(TAG, "untether caller:" + callerPkg);
-
- final RequestDispatcher dispatcher = new RequestDispatcher();
-
- return dispatcher.waitForResult((connector, listener) -> {
- try {
- connector.untether(iface, callerPkg, getAttributionTag(), listener);
- } catch (RemoteException e) {
- throw new IllegalStateException(e);
- }
- });
- }
-
- /**
- * Attempt to both alter the mode of USB and Tethering of USB.
- *
- * @deprecated New client should not use this API anymore. All clients should use
- * #startTethering or #stopTethering which encapsulate proper entitlement logic. If the API is
- * used and an entitlement check is needed, downstream USB tethering will be enabled but will
- * not have any upstream.
- *
- * {@hide}
- */
- @Deprecated
- @SystemApi(client = MODULE_LIBRARIES)
- public int setUsbTethering(final boolean enable) {
- final String callerPkg = mContext.getOpPackageName();
- Log.i(TAG, "setUsbTethering caller:" + callerPkg);
-
- final RequestDispatcher dispatcher = new RequestDispatcher();
-
- return dispatcher.waitForResult((connector, listener) -> {
- try {
- connector.setUsbTethering(enable, callerPkg, getAttributionTag(),
- listener);
- } catch (RemoteException e) {
- throw new IllegalStateException(e);
- }
- });
- }
-
- /**
- * Use with {@link #startTethering} to specify additional parameters when starting tethering.
- */
- public static class TetheringRequest {
- /** A configuration set for TetheringRequest. */
- private final TetheringRequestParcel mRequestParcel;
-
- private TetheringRequest(final TetheringRequestParcel request) {
- mRequestParcel = request;
- }
-
- /** Builder used to create TetheringRequest. */
- public static class Builder {
- private final TetheringRequestParcel mBuilderParcel;
-
- /** Default constructor of Builder. */
- public Builder(@TetheringType final int type) {
- mBuilderParcel = new TetheringRequestParcel();
- mBuilderParcel.tetheringType = type;
- mBuilderParcel.localIPv4Address = null;
- mBuilderParcel.staticClientAddress = null;
- mBuilderParcel.exemptFromEntitlementCheck = false;
- mBuilderParcel.showProvisioningUi = true;
- }
-
- /**
- * Configure tethering with static IPv4 assignment.
- *
- * A DHCP server will be started, but will only be able to offer the client address.
- * The two addresses must be in the same prefix.
- *
- * @param localIPv4Address The preferred local IPv4 link address to use.
- * @param clientAddress The static client address.
- */
- @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
- @NonNull
- public Builder setStaticIpv4Addresses(@NonNull final LinkAddress localIPv4Address,
- @NonNull final LinkAddress clientAddress) {
- Objects.requireNonNull(localIPv4Address);
- Objects.requireNonNull(clientAddress);
- if (!checkStaticAddressConfiguration(localIPv4Address, clientAddress)) {
- throw new IllegalArgumentException("Invalid server or client addresses");
- }
-
- mBuilderParcel.localIPv4Address = localIPv4Address;
- mBuilderParcel.staticClientAddress = clientAddress;
- return this;
- }
-
- /** Start tethering without entitlement checks. */
- @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
- @NonNull
- public Builder setExemptFromEntitlementCheck(boolean exempt) {
- mBuilderParcel.exemptFromEntitlementCheck = exempt;
- return this;
- }
-
- /**
- * If an entitlement check is needed, sets whether to show the entitlement UI or to
- * perform a silent entitlement check. By default, the entitlement UI is shown.
- */
- @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
- @NonNull
- public Builder setShouldShowEntitlementUi(boolean showUi) {
- mBuilderParcel.showProvisioningUi = showUi;
- return this;
- }
-
- /** Build {@link TetheringRequest] with the currently set configuration. */
- @NonNull
- public TetheringRequest build() {
- return new TetheringRequest(mBuilderParcel);
- }
- }
-
- /**
- * Get the local IPv4 address, if one was configured with
- * {@link Builder#setStaticIpv4Addresses}.
- */
- @Nullable
- public LinkAddress getLocalIpv4Address() {
- return mRequestParcel.localIPv4Address;
- }
-
- /**
- * Get the static IPv4 address of the client, if one was configured with
- * {@link Builder#setStaticIpv4Addresses}.
- */
- @Nullable
- public LinkAddress getClientStaticIpv4Address() {
- return mRequestParcel.staticClientAddress;
- }
-
- /** Get tethering type. */
- @TetheringType
- public int getTetheringType() {
- return mRequestParcel.tetheringType;
- }
-
- /** Check if exempt from entitlement check. */
- public boolean isExemptFromEntitlementCheck() {
- return mRequestParcel.exemptFromEntitlementCheck;
- }
-
- /** Check if show entitlement ui. */
- public boolean getShouldShowEntitlementUi() {
- return mRequestParcel.showProvisioningUi;
- }
-
- /**
- * Check whether the two addresses are ipv4 and in the same prefix.
- * @hide
- */
- public static boolean checkStaticAddressConfiguration(
- @NonNull final LinkAddress localIPv4Address,
- @NonNull final LinkAddress clientAddress) {
- return localIPv4Address.getPrefixLength() == clientAddress.getPrefixLength()
- && localIPv4Address.isIpv4() && clientAddress.isIpv4()
- && new IpPrefix(localIPv4Address.toString()).equals(
- new IpPrefix(clientAddress.toString()));
- }
-
- /**
- * Get a TetheringRequestParcel from the configuration
- * @hide
- */
- public TetheringRequestParcel getParcel() {
- return mRequestParcel;
- }
-
- /** String of TetheringRequest detail. */
- public String toString() {
- return "TetheringRequest [ type= " + mRequestParcel.tetheringType
- + ", localIPv4Address= " + mRequestParcel.localIPv4Address
- + ", staticClientAddress= " + mRequestParcel.staticClientAddress
- + ", exemptFromEntitlementCheck= "
- + mRequestParcel.exemptFromEntitlementCheck + ", showProvisioningUi= "
- + mRequestParcel.showProvisioningUi + " ]";
- }
- }
-
- /**
- * Callback for use with {@link #startTethering} to find out whether tethering succeeded.
- */
- public interface StartTetheringCallback {
- /**
- * Called when tethering has been successfully started.
- */
- default void onTetheringStarted() {}
-
- /**
- * Called when starting tethering failed.
- *
- * @param error The error that caused the failure.
- */
- default void onTetheringFailed(@StartTetheringError final int error) {}
- }
-
- /**
- * Starts tethering and runs tether provisioning for the given type if needed. If provisioning
- * fails, stopTethering will be called automatically.
- *
- * <p>Without {@link android.Manifest.permission.TETHER_PRIVILEGED} permission, the call will
- * fail if a tethering entitlement check is required.
- *
- * @param request a {@link TetheringRequest} which can specify the preferred configuration.
- * @param executor {@link Executor} to specify the thread upon which the callback of
- * TetheringRequest will be invoked.
- * @param callback A callback that will be called to indicate the success status of the
- * tethering start request.
- */
- @RequiresPermission(anyOf = {
- android.Manifest.permission.TETHER_PRIVILEGED,
- android.Manifest.permission.WRITE_SETTINGS
- })
- public void startTethering(@NonNull final TetheringRequest request,
- @NonNull final Executor executor, @NonNull final StartTetheringCallback callback) {
- final String callerPkg = mContext.getOpPackageName();
- Log.i(TAG, "startTethering caller:" + callerPkg);
-
- final IIntResultListener listener = new IIntResultListener.Stub() {
- @Override
- public void onResult(final int resultCode) {
- executor.execute(() -> {
- if (resultCode == TETHER_ERROR_NO_ERROR) {
- callback.onTetheringStarted();
- } else {
- callback.onTetheringFailed(resultCode);
- }
- });
- }
- };
- getConnector(c -> c.startTethering(request.getParcel(), callerPkg,
- getAttributionTag(), listener));
- }
-
- /**
- * Starts tethering and runs tether provisioning for the given type if needed. If provisioning
- * fails, stopTethering will be called automatically.
- *
- * <p>Without {@link android.Manifest.permission.TETHER_PRIVILEGED} permission, the call will
- * fail if a tethering entitlement check is required.
- *
- * @param type The tethering type, on of the {@code TetheringManager#TETHERING_*} constants.
- * @param executor {@link Executor} to specify the thread upon which the callback of
- * TetheringRequest will be invoked.
- * @hide
- */
- @RequiresPermission(anyOf = {
- android.Manifest.permission.TETHER_PRIVILEGED,
- android.Manifest.permission.WRITE_SETTINGS
- })
- @SystemApi(client = MODULE_LIBRARIES)
- public void startTethering(int type, @NonNull final Executor executor,
- @NonNull final StartTetheringCallback callback) {
- startTethering(new TetheringRequest.Builder(type).build(), executor, callback);
- }
-
- /**
- * Stops tethering for the given type. Also cancels any provisioning rechecks for that type if
- * applicable.
- *
- * <p>Without {@link android.Manifest.permission.TETHER_PRIVILEGED} permission, the call will
- * fail if a tethering entitlement check is required.
- */
- @RequiresPermission(anyOf = {
- android.Manifest.permission.TETHER_PRIVILEGED,
- android.Manifest.permission.WRITE_SETTINGS
- })
- public void stopTethering(@TetheringType final int type) {
- final String callerPkg = mContext.getOpPackageName();
- Log.i(TAG, "stopTethering caller:" + callerPkg);
-
- getConnector(c -> c.stopTethering(type, callerPkg, getAttributionTag(),
- new IIntResultListener.Stub() {
- @Override
- public void onResult(int resultCode) {
- // TODO: provide an API to obtain result
- // This has never been possible as stopTethering 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.
- }
- }));
- }
-
- /**
- * Callback for use with {@link #getLatestTetheringEntitlementResult} to find out whether
- * entitlement succeeded.
- */
- public interface OnTetheringEntitlementResultListener {
- /**
- * Called to notify entitlement result.
- *
- * @param resultCode an int value of entitlement result. It may be one of
- * {@link #TETHER_ERROR_NO_ERROR},
- * {@link #TETHER_ERROR_PROVISIONING_FAILED}, or
- * {@link #TETHER_ERROR_ENTITLEMENT_UNKNOWN}.
- */
- void onTetheringEntitlementResult(@EntitlementResult int result);
- }
-
- /**
- * Request the latest value of the tethering entitlement check.
- *
- * <p>This method will only return the latest entitlement result if it is available. If no
- * cached entitlement result is available, and {@code showEntitlementUi} is false,
- * {@link #TETHER_ERROR_ENTITLEMENT_UNKNOWN} will be returned. If {@code showEntitlementUi} is
- * true, entitlement will be run.
- *
- * <p>Without {@link android.Manifest.permission.TETHER_PRIVILEGED} permission, the call will
- * fail if a tethering entitlement check is required.
- *
- * @param type the downstream type of tethering. Must be one of {@code #TETHERING_*} constants.
- * @param showEntitlementUi a boolean indicating whether to check result for the UI-based
- * entitlement check or the silent entitlement check.
- * @param executor the executor on which callback will be invoked.
- * @param listener an {@link OnTetheringEntitlementResultListener} which will be called to
- * notify the caller of the result of entitlement check. The listener may be called zero
- * or one time.
- */
- @RequiresPermission(anyOf = {
- android.Manifest.permission.TETHER_PRIVILEGED,
- android.Manifest.permission.WRITE_SETTINGS
- })
- public void requestLatestTetheringEntitlementResult(@TetheringType int type,
- boolean showEntitlementUi,
- @NonNull Executor executor,
- @NonNull final OnTetheringEntitlementResultListener listener) {
- if (listener == null) {
- throw new IllegalArgumentException(
- "OnTetheringEntitlementResultListener cannot be null.");
- }
-
- ResultReceiver wrappedListener = new ResultReceiver(null /* handler */) {
- @Override
- protected void onReceiveResult(int resultCode, Bundle resultData) {
- executor.execute(() -> {
- listener.onTetheringEntitlementResult(resultCode);
- });
- }
- };
-
- requestLatestTetheringEntitlementResult(type, wrappedListener,
- showEntitlementUi);
- }
-
- /**
- * Helper function of #requestLatestTetheringEntitlementResult to remain backwards compatible
- * with ConnectivityManager#getLatestTetheringEntitlementResult
- *
- * {@hide}
- */
- // TODO: improve the usage of ResultReceiver, b/145096122
- @SystemApi(client = MODULE_LIBRARIES)
- public void requestLatestTetheringEntitlementResult(@TetheringType final int type,
- @NonNull final ResultReceiver receiver, final boolean showEntitlementUi) {
- final String callerPkg = mContext.getOpPackageName();
- Log.i(TAG, "getLatestTetheringEntitlementResult caller:" + callerPkg);
-
- getConnector(c -> c.requestLatestTetheringEntitlementResult(
- type, receiver, showEntitlementUi, callerPkg, getAttributionTag()));
- }
-
- /**
- * Callback for use with {@link registerTetheringEventCallback} to find out tethering
- * upstream status.
- */
- public interface TetheringEventCallback {
- /**
- * Called when tethering supported status changed.
- *
- * <p>This will be called immediately after the callback is registered, and may be called
- * multiple times later upon changes.
- *
- * <p>Tethering may be disabled via system properties, device configuration, or device
- * policy restrictions.
- *
- * @param supported The new supported status
- */
- default void onTetheringSupported(boolean supported) {}
-
- /**
- * Called when tethering upstream changed.
- *
- * <p>This will be called immediately after the callback is registered, and may be called
- * multiple times later upon changes.
- *
- * @param network the {@link Network} of tethering upstream. Null means tethering doesn't
- * have any upstream.
- */
- default void onUpstreamChanged(@Nullable Network network) {}
-
- /**
- * Called when there was a change in tethering interface regular expressions.
- *
- * <p>This will be called immediately after the callback is registered, and may be called
- * multiple times later upon changes.
- * @param reg The new regular expressions.
- *
- * @hide
- */
- @SystemApi(client = MODULE_LIBRARIES)
- default void onTetherableInterfaceRegexpsChanged(@NonNull TetheringInterfaceRegexps reg) {}
-
- /**
- * Called when there was a change in the list of tetherable interfaces. Tetherable
- * interface means this interface is available and can be used for tethering.
- *
- * <p>This will be called immediately after the callback is registered, and may be called
- * multiple times later upon changes.
- * @param interfaces The list of tetherable interface names.
- */
- default void onTetherableInterfacesChanged(@NonNull List<String> interfaces) {}
-
- /**
- * Called when there was a change in the list of tethered interfaces.
- *
- * <p>This will be called immediately after the callback is registered, and may be called
- * multiple times later upon changes.
- * @param interfaces The list of 0 or more String of currently tethered interface names.
- */
- default void onTetheredInterfacesChanged(@NonNull List<String> interfaces) {}
-
- /**
- * Called when an error occurred configuring tethering.
- *
- * <p>This will be called immediately after the callback is registered if the latest status
- * on the interface is an error, and may be called multiple times later upon changes.
- * @param ifName Name of the interface.
- * @param error One of {@code TetheringManager#TETHER_ERROR_*}.
- */
- default void onError(@NonNull String ifName, @TetheringIfaceError int error) {}
-
- /**
- * Called when the list of tethered clients changes.
- *
- * <p>This callback provides best-effort information on connected clients based on state
- * known to the system, however the list cannot be completely accurate (and should not be
- * used for security purposes). For example, clients behind a bridge and using static IP
- * assignments are not visible to the tethering device; or even when using DHCP, such
- * clients may still be reported by this callback after disconnection as the system cannot
- * determine if they are still connected.
- * @param clients The new set of tethered clients; the collection is not ordered.
- */
- default void onClientsChanged(@NonNull Collection<TetheredClient> clients) {}
-
- /**
- * Called when tethering offload status changes.
- *
- * <p>This will be called immediately after the callback is registered.
- * @param status The offload status.
- */
- default void onOffloadStatusChanged(@TetherOffloadStatus int status) {}
- }
-
- /**
- * Regular expressions used to identify tethering interfaces.
- * @hide
- */
- @SystemApi(client = MODULE_LIBRARIES)
- public static class TetheringInterfaceRegexps {
- private final String[] mTetherableBluetoothRegexs;
- private final String[] mTetherableUsbRegexs;
- private final String[] mTetherableWifiRegexs;
-
- /** @hide */
- public TetheringInterfaceRegexps(@NonNull String[] tetherableBluetoothRegexs,
- @NonNull String[] tetherableUsbRegexs, @NonNull String[] tetherableWifiRegexs) {
- mTetherableBluetoothRegexs = tetherableBluetoothRegexs.clone();
- mTetherableUsbRegexs = tetherableUsbRegexs.clone();
- mTetherableWifiRegexs = tetherableWifiRegexs.clone();
- }
-
- @NonNull
- public List<String> getTetherableBluetoothRegexs() {
- return Collections.unmodifiableList(Arrays.asList(mTetherableBluetoothRegexs));
- }
-
- @NonNull
- public List<String> getTetherableUsbRegexs() {
- return Collections.unmodifiableList(Arrays.asList(mTetherableUsbRegexs));
- }
-
- @NonNull
- public List<String> getTetherableWifiRegexs() {
- return Collections.unmodifiableList(Arrays.asList(mTetherableWifiRegexs));
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(mTetherableBluetoothRegexs, mTetherableUsbRegexs,
- mTetherableWifiRegexs);
- }
-
- @Override
- public boolean equals(@Nullable Object obj) {
- if (!(obj instanceof TetheringInterfaceRegexps)) return false;
- final TetheringInterfaceRegexps other = (TetheringInterfaceRegexps) obj;
- return Arrays.equals(mTetherableBluetoothRegexs, other.mTetherableBluetoothRegexs)
- && Arrays.equals(mTetherableUsbRegexs, other.mTetherableUsbRegexs)
- && Arrays.equals(mTetherableWifiRegexs, other.mTetherableWifiRegexs);
- }
- }
-
- /**
- * Start listening to tethering change events. Any new added callback will receive the last
- * tethering status right away. If callback is registered,
- * {@link TetheringEventCallback#onUpstreamChanged} will immediately be called. If tethering
- * has no upstream or disabled, the argument of callback will be null. The same callback object
- * cannot be registered twice.
- *
- * @param executor the executor on which callback will be invoked.
- * @param callback the callback to be called when tethering has change events.
- */
- @RequiresPermission(Manifest.permission.ACCESS_NETWORK_STATE)
- public void registerTetheringEventCallback(@NonNull Executor executor,
- @NonNull TetheringEventCallback callback) {
- final String callerPkg = mContext.getOpPackageName();
- Log.i(TAG, "registerTetheringEventCallback caller:" + callerPkg);
-
- synchronized (mTetheringEventCallbacks) {
- if (mTetheringEventCallbacks.containsKey(callback)) {
- throw new IllegalArgumentException("callback was already registered.");
- }
- final ITetheringEventCallback remoteCallback = new ITetheringEventCallback.Stub() {
- // Only accessed with a lock on this object
- private final HashMap<String, Integer> mErrorStates = new HashMap<>();
- private String[] mLastTetherableInterfaces = null;
- private String[] mLastTetheredInterfaces = null;
-
- @Override
- public void onUpstreamChanged(Network network) throws RemoteException {
- executor.execute(() -> {
- callback.onUpstreamChanged(network);
- });
- }
-
- private synchronized void sendErrorCallbacks(final TetherStatesParcel newStates) {
- for (int i = 0; i < newStates.erroredIfaceList.length; i++) {
- final String iface = newStates.erroredIfaceList[i];
- final Integer lastError = mErrorStates.get(iface);
- final int newError = newStates.lastErrorList[i];
- if (newError != TETHER_ERROR_NO_ERROR
- && !Objects.equals(lastError, newError)) {
- callback.onError(iface, newError);
- }
- mErrorStates.put(iface, newError);
- }
- }
-
- private synchronized void maybeSendTetherableIfacesChangedCallback(
- final TetherStatesParcel newStates) {
- if (Arrays.equals(mLastTetherableInterfaces, newStates.availableList)) return;
- mLastTetherableInterfaces = newStates.availableList.clone();
- callback.onTetherableInterfacesChanged(
- Collections.unmodifiableList(Arrays.asList(mLastTetherableInterfaces)));
- }
-
- private synchronized void maybeSendTetheredIfacesChangedCallback(
- final TetherStatesParcel newStates) {
- if (Arrays.equals(mLastTetheredInterfaces, newStates.tetheredList)) return;
- mLastTetheredInterfaces = newStates.tetheredList.clone();
- callback.onTetheredInterfacesChanged(
- Collections.unmodifiableList(Arrays.asList(mLastTetheredInterfaces)));
- }
-
- // Called immediately after the callbacks are registered.
- @Override
- public void onCallbackStarted(TetheringCallbackStartedParcel parcel) {
- executor.execute(() -> {
- callback.onTetheringSupported(parcel.tetheringSupported);
- callback.onUpstreamChanged(parcel.upstreamNetwork);
- sendErrorCallbacks(parcel.states);
- sendRegexpsChanged(parcel.config);
- maybeSendTetherableIfacesChangedCallback(parcel.states);
- maybeSendTetheredIfacesChangedCallback(parcel.states);
- callback.onClientsChanged(parcel.tetheredClients);
- callback.onOffloadStatusChanged(parcel.offloadStatus);
- });
- }
-
- @Override
- public void onCallbackStopped(int errorCode) {
- executor.execute(() -> {
- throwIfPermissionFailure(errorCode);
- });
- }
-
- private void sendRegexpsChanged(TetheringConfigurationParcel parcel) {
- callback.onTetherableInterfaceRegexpsChanged(new TetheringInterfaceRegexps(
- parcel.tetherableBluetoothRegexs,
- parcel.tetherableUsbRegexs,
- parcel.tetherableWifiRegexs));
- }
-
- @Override
- public void onConfigurationChanged(TetheringConfigurationParcel config) {
- executor.execute(() -> sendRegexpsChanged(config));
- }
-
- @Override
- public void onTetherStatesChanged(TetherStatesParcel states) {
- executor.execute(() -> {
- sendErrorCallbacks(states);
- maybeSendTetherableIfacesChangedCallback(states);
- maybeSendTetheredIfacesChangedCallback(states);
- });
- }
-
- @Override
- public void onTetherClientsChanged(final List<TetheredClient> clients) {
- executor.execute(() -> callback.onClientsChanged(clients));
- }
-
- @Override
- public void onOffloadStatusChanged(final int status) {
- executor.execute(() -> callback.onOffloadStatusChanged(status));
- }
- };
- getConnector(c -> c.registerTetheringEventCallback(remoteCallback, callerPkg));
- mTetheringEventCallbacks.put(callback, remoteCallback);
- }
- }
-
- /**
- * Remove tethering event callback previously registered with
- * {@link #registerTetheringEventCallback}.
- *
- * @param callback previously registered callback.
- */
- @RequiresPermission(anyOf = {
- Manifest.permission.TETHER_PRIVILEGED,
- Manifest.permission.ACCESS_NETWORK_STATE
- })
- public void unregisterTetheringEventCallback(@NonNull final TetheringEventCallback callback) {
- final String callerPkg = mContext.getOpPackageName();
- Log.i(TAG, "unregisterTetheringEventCallback caller:" + callerPkg);
-
- synchronized (mTetheringEventCallbacks) {
- ITetheringEventCallback remoteCallback = mTetheringEventCallbacks.remove(callback);
- if (remoteCallback == null) {
- throw new IllegalArgumentException("callback was not registered.");
- }
-
- getConnector(c -> c.unregisterTetheringEventCallback(remoteCallback, callerPkg));
- }
- }
-
- /**
- * Get a more detailed error code after a Tethering or Untethering
- * request asynchronously failed.
- *
- * @param iface The name of the interface of interest
- * @return error The error code of the last error tethering or untethering the named
- * interface
- * @hide
- */
- @SystemApi(client = MODULE_LIBRARIES)
- public int getLastTetherError(@NonNull final String iface) {
- mCallback.waitForStarted();
- if (mTetherStatesParcel == null) return TETHER_ERROR_NO_ERROR;
-
- int i = 0;
- for (String errored : mTetherStatesParcel.erroredIfaceList) {
- if (iface.equals(errored)) return mTetherStatesParcel.lastErrorList[i];
-
- i++;
- }
- return TETHER_ERROR_NO_ERROR;
- }
-
- /**
- * Get the list of regular expressions that define any tetherable
- * USB network interfaces. If USB tethering is not supported by the
- * device, this list should be empty.
- *
- * @return an array of 0 or more regular expression Strings defining
- * what interfaces are considered tetherable usb interfaces.
- * @hide
- */
- @SystemApi(client = MODULE_LIBRARIES)
- public @NonNull String[] getTetherableUsbRegexs() {
- mCallback.waitForStarted();
- return mTetheringConfiguration.tetherableUsbRegexs;
- }
-
- /**
- * Get the list of regular expressions that define any tetherable
- * Wifi network interfaces. If Wifi tethering is not supported by the
- * device, this list should be empty.
- *
- * @return an array of 0 or more regular expression Strings defining
- * what interfaces are considered tetherable wifi interfaces.
- * @hide
- */
- @SystemApi(client = MODULE_LIBRARIES)
- public @NonNull String[] getTetherableWifiRegexs() {
- mCallback.waitForStarted();
- return mTetheringConfiguration.tetherableWifiRegexs;
- }
-
- /**
- * Get the list of regular expressions that define any tetherable
- * Bluetooth network interfaces. If Bluetooth tethering is not supported by the
- * device, this list should be empty.
- *
- * @return an array of 0 or more regular expression Strings defining
- * what interfaces are considered tetherable bluetooth interfaces.
- * @hide
- */
- @SystemApi(client = MODULE_LIBRARIES)
- public @NonNull String[] getTetherableBluetoothRegexs() {
- mCallback.waitForStarted();
- return mTetheringConfiguration.tetherableBluetoothRegexs;
- }
-
- /**
- * Get the set of tetherable, available interfaces. This list is limited by
- * device configuration and current interface existence.
- *
- * @return an array of 0 or more Strings of tetherable interface names.
- * @hide
- */
- @SystemApi(client = MODULE_LIBRARIES)
- public @NonNull String[] getTetherableIfaces() {
- mCallback.waitForStarted();
- if (mTetherStatesParcel == null) return new String[0];
-
- return mTetherStatesParcel.availableList;
- }
-
- /**
- * Get the set of tethered interfaces.
- *
- * @return an array of 0 or more String of currently tethered interface names.
- * @hide
- */
- @SystemApi(client = MODULE_LIBRARIES)
- public @NonNull String[] getTetheredIfaces() {
- mCallback.waitForStarted();
- if (mTetherStatesParcel == null) return new String[0];
-
- return mTetherStatesParcel.tetheredList;
- }
-
- /**
- * Get the set of interface names which attempted to tether but
- * failed. Re-attempting to tether may cause them to reset to the Tethered
- * state. Alternatively, causing the interface to be destroyed and recreated
- * may cause them to reset to the available state.
- * {@link TetheringManager#getLastTetherError} can be used to get more
- * information on the cause of the errors.
- *
- * @return an array of 0 or more String indicating the interface names
- * which failed to tether.
- * @hide
- */
- @SystemApi(client = MODULE_LIBRARIES)
- public @NonNull String[] getTetheringErroredIfaces() {
- mCallback.waitForStarted();
- if (mTetherStatesParcel == null) return new String[0];
-
- return mTetherStatesParcel.erroredIfaceList;
- }
-
- /**
- * Get the set of tethered dhcp ranges.
- *
- * @deprecated This API just return the default value which is not used in DhcpServer.
- * @hide
- */
- @Deprecated
- public @NonNull String[] getTetheredDhcpRanges() {
- mCallback.waitForStarted();
- return mTetheringConfiguration.legacyDhcpRanges;
- }
-
- /**
- * Check if the device allows for tethering. It may be disabled via
- * {@code ro.tether.denied} system property, Settings.TETHER_SUPPORTED or
- * due to device configuration.
- *
- * @return a boolean - {@code true} indicating Tethering is supported.
- * @hide
- */
- @SystemApi(client = MODULE_LIBRARIES)
- public boolean isTetheringSupported() {
- final String callerPkg = mContext.getOpPackageName();
-
- return isTetheringSupported(callerPkg);
- }
-
- /**
- * Check if the device allows for tethering. It may be disabled via {@code ro.tether.denied}
- * system property, Settings.TETHER_SUPPORTED or due to device configuration. This is useful
- * for system components that query this API on behalf of an app. In particular, Bluetooth
- * has @UnsupportedAppUsage calls that will let apps turn on bluetooth tethering if they have
- * the right permissions, but such an app needs to know whether it can (permissions as well
- * as support from the device) turn on tethering in the first place to show the appropriate UI.
- *
- * @param callerPkg The caller package name, if it is not matching the calling uid,
- * SecurityException would be thrown.
- * @return a boolean - {@code true} indicating Tethering is supported.
- * @hide
- */
- @SystemApi(client = MODULE_LIBRARIES)
- public boolean isTetheringSupported(@NonNull final String callerPkg) {
-
- final RequestDispatcher dispatcher = new RequestDispatcher();
- final int ret = dispatcher.waitForResult((connector, listener) -> {
- try {
- connector.isTetheringSupported(callerPkg, getAttributionTag(), listener);
- } catch (RemoteException e) {
- throw new IllegalStateException(e);
- }
- });
-
- return ret == TETHER_ERROR_NO_ERROR;
- }
-
- /**
- * Stop all active tethering.
- *
- * <p>Without {@link android.Manifest.permission.TETHER_PRIVILEGED} permission, the call will
- * fail if a tethering entitlement check is required.
- */
- @RequiresPermission(anyOf = {
- android.Manifest.permission.TETHER_PRIVILEGED,
- android.Manifest.permission.WRITE_SETTINGS
- })
- public void stopAllTethering() {
- final String callerPkg = mContext.getOpPackageName();
- Log.i(TAG, "stopAllTethering caller:" + callerPkg);
-
- 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/packages/Tethering/common/TetheringLib/src/android/net/TetheringRequestParcel.aidl b/packages/Tethering/common/TetheringLib/src/android/net/TetheringRequestParcel.aidl
deleted file mode 100644
index c0280d3..0000000
--- a/packages/Tethering/common/TetheringLib/src/android/net/TetheringRequestParcel.aidl
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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 android.net;
-
-import android.net.LinkAddress;
-
-/**
- * Configuration details for requesting tethering.
- * @hide
- */
-parcelable TetheringRequestParcel {
- int tetheringType;
- LinkAddress localIPv4Address;
- LinkAddress staticClientAddress;
- boolean exemptFromEntitlementCheck;
- boolean showProvisioningUi;
-}
diff --git a/packages/Tethering/jarjar-rules.txt b/packages/Tethering/jarjar-rules.txt
deleted file mode 100644
index 591861f..0000000
--- a/packages/Tethering/jarjar-rules.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-# These must be kept in sync with the framework-tethering-shared-srcs filegroup.
-# Classes from the framework-tethering-shared-srcs filegroup.
-# If there are files in that filegroup that are not covered below, the classes in the
-# module will be overwritten by the ones in the framework.
-rule com.android.internal.util.** com.android.networkstack.tethering.util.@1
-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
diff --git a/packages/Tethering/jni/android_net_util_TetheringUtils.cpp b/packages/Tethering/jni/android_net_util_TetheringUtils.cpp
deleted file mode 100644
index 94c871d..0000000
--- a/packages/Tethering/jni/android_net_util_TetheringUtils.cpp
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * Copyright (C) 2017 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 <errno.h>
-#include <error.h>
-#include <jni.h>
-#include <linux/filter.h>
-#include <nativehelper/JNIHelp.h>
-#include <nativehelper/JNIHelpCompat.h>
-#include <nativehelper/ScopedUtfChars.h>
-#include <net/if.h>
-#include <netinet/ether.h>
-#include <netinet/ip6.h>
-#include <netinet/icmp6.h>
-#include <sys/socket.h>
-#include <stdio.h>
-
-#define LOG_TAG "TetheringUtils"
-#include <android/log.h>
-
-namespace android {
-
-static const uint32_t kIPv6NextHeaderOffset = offsetof(ip6_hdr, ip6_nxt);
-static const uint32_t kIPv6PayloadStart = sizeof(ip6_hdr);
-static const uint32_t kICMPv6TypeOffset = kIPv6PayloadStart + offsetof(icmp6_hdr, icmp6_type);
-
-static void android_net_util_setupIcmpFilter(JNIEnv *env, jobject javaFd, uint32_t type) {
- sock_filter filter_code[] = {
- // Check header is ICMPv6.
- BPF_STMT(BPF_LD | BPF_B | BPF_ABS, kIPv6NextHeaderOffset),
- BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, IPPROTO_ICMPV6, 0, 3),
-
- // Check ICMPv6 type.
- BPF_STMT(BPF_LD | BPF_B | BPF_ABS, kICMPv6TypeOffset),
- BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, type, 0, 1),
-
- // Accept or reject.
- BPF_STMT(BPF_RET | BPF_K, 0xffff),
- BPF_STMT(BPF_RET | BPF_K, 0)
- };
-
- const sock_fprog filter = {
- sizeof(filter_code) / sizeof(filter_code[0]),
- filter_code,
- };
-
- int fd = jniGetFDFromFileDescriptor(env, javaFd);
- if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter)) != 0) {
- jniThrowExceptionFmt(env, "java/net/SocketException",
- "setsockopt(SO_ATTACH_FILTER): %s", strerror(errno));
- }
-}
-
-static void android_net_util_setupNaSocket(JNIEnv *env, jobject clazz, jobject javaFd)
-{
- android_net_util_setupIcmpFilter(env, javaFd, ND_NEIGHBOR_ADVERT);
-}
-
-static void android_net_util_setupNsSocket(JNIEnv *env, jobject clazz, jobject javaFd)
-{
- android_net_util_setupIcmpFilter(env, javaFd, ND_NEIGHBOR_SOLICIT);
-}
-
-static void android_net_util_setupRaSocket(JNIEnv *env, jobject clazz, jobject javaFd,
- jint ifIndex)
-{
- static const int kLinkLocalHopLimit = 255;
-
- int fd = jniGetFDFromFileDescriptor(env, javaFd);
-
- // Set an ICMPv6 filter that only passes Router Solicitations.
- struct icmp6_filter rs_only;
- ICMP6_FILTER_SETBLOCKALL(&rs_only);
- ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT, &rs_only);
- socklen_t len = sizeof(rs_only);
- if (setsockopt(fd, IPPROTO_ICMPV6, ICMP6_FILTER, &rs_only, len) != 0) {
- jniThrowExceptionFmt(env, "java/net/SocketException",
- "setsockopt(ICMP6_FILTER): %s", strerror(errno));
- return;
- }
-
- // Most/all of the rest of these options can be set via Java code, but
- // because we're here on account of setting an icmp6_filter go ahead
- // and do it all natively for now.
-
- // Set the multicast hoplimit to 255 (link-local only).
- int hops = kLinkLocalHopLimit;
- len = sizeof(hops);
- if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &hops, len) != 0) {
- jniThrowExceptionFmt(env, "java/net/SocketException",
- "setsockopt(IPV6_MULTICAST_HOPS): %s", strerror(errno));
- return;
- }
-
- // Set the unicast hoplimit to 255 (link-local only).
- hops = kLinkLocalHopLimit;
- len = sizeof(hops);
- if (setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &hops, len) != 0) {
- jniThrowExceptionFmt(env, "java/net/SocketException",
- "setsockopt(IPV6_UNICAST_HOPS): %s", strerror(errno));
- return;
- }
-
- // Explicitly disable multicast loopback.
- int off = 0;
- len = sizeof(off);
- if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &off, len) != 0) {
- jniThrowExceptionFmt(env, "java/net/SocketException",
- "setsockopt(IPV6_MULTICAST_LOOP): %s", strerror(errno));
- return;
- }
-
- // Specify the IPv6 interface to use for outbound multicast.
- len = sizeof(ifIndex);
- if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifIndex, len) != 0) {
- jniThrowExceptionFmt(env, "java/net/SocketException",
- "setsockopt(IPV6_MULTICAST_IF): %s", strerror(errno));
- return;
- }
-
- // Additional options to be considered:
- // - IPV6_TCLASS
- // - IPV6_RECVPKTINFO
- // - IPV6_RECVHOPLIMIT
-
- // Bind to [::].
- const struct sockaddr_in6 sin6 = {
- .sin6_family = AF_INET6,
- .sin6_port = 0,
- .sin6_flowinfo = 0,
- .sin6_addr = IN6ADDR_ANY_INIT,
- .sin6_scope_id = 0,
- };
- auto sa = reinterpret_cast<const struct sockaddr *>(&sin6);
- len = sizeof(sin6);
- if (bind(fd, sa, len) != 0) {
- jniThrowExceptionFmt(env, "java/net/SocketException",
- "bind(IN6ADDR_ANY): %s", strerror(errno));
- return;
- }
-
- // Join the all-routers multicast group, ff02::2%index.
- struct ipv6_mreq all_rtrs = {
- .ipv6mr_multiaddr = {{{0xff,2,0,0,0,0,0,0,0,0,0,0,0,0,0,2}}},
- .ipv6mr_interface = ifIndex,
- };
- len = sizeof(all_rtrs);
- if (setsockopt(fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &all_rtrs, len) != 0) {
- jniThrowExceptionFmt(env, "java/net/SocketException",
- "setsockopt(IPV6_JOIN_GROUP): %s", strerror(errno));
- return;
- }
-}
-
-/*
- * JNI registration.
- */
-static const JNINativeMethod gMethods[] = {
- /* name, signature, funcPtr */
- { "setupNaSocket", "(Ljava/io/FileDescriptor;)V",
- (void*) android_net_util_setupNaSocket },
- { "setupNsSocket", "(Ljava/io/FileDescriptor;)V",
- (void*) android_net_util_setupNsSocket },
- { "setupRaSocket", "(Ljava/io/FileDescriptor;I)V",
- (void*) android_net_util_setupRaSocket },
-};
-
-int register_android_net_util_TetheringUtils(JNIEnv* env) {
- return jniRegisterNativeMethods(env,
- "android/net/util/TetheringUtils",
- gMethods, NELEM(gMethods));
-}
-
-extern "C" jint JNI_OnLoad(JavaVM* vm, void*) {
- JNIEnv *env;
- if (vm->GetEnv(reinterpret_cast<void**>(&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/packages/Tethering/proguard.flags b/packages/Tethering/proguard.flags
deleted file mode 100644
index 86b9033..0000000
--- a/packages/Tethering/proguard.flags
+++ /dev/null
@@ -1,9 +0,0 @@
-# Keep class's integer static field for MessageUtils to parsing their name.
--keep class com.android.networkstack.tethering.Tethering$TetherMainSM {
- static final int CMD_*;
- static final int EVENT_*;
-}
-
--keepclassmembers class android.net.ip.IpServer {
- static final int CMD_*;
-}
diff --git a/packages/Tethering/res/drawable-hdpi/stat_sys_tether_bluetooth.png b/packages/Tethering/res/drawable-hdpi/stat_sys_tether_bluetooth.png
deleted file mode 100644
index 9451174..0000000
--- a/packages/Tethering/res/drawable-hdpi/stat_sys_tether_bluetooth.png
+++ /dev/null
Binary files differ
diff --git a/packages/Tethering/res/drawable-hdpi/stat_sys_tether_general.png b/packages/Tethering/res/drawable-hdpi/stat_sys_tether_general.png
deleted file mode 100644
index 79d5756..0000000
--- a/packages/Tethering/res/drawable-hdpi/stat_sys_tether_general.png
+++ /dev/null
Binary files differ
diff --git a/packages/Tethering/res/drawable-hdpi/stat_sys_tether_usb.png b/packages/Tethering/res/drawable-hdpi/stat_sys_tether_usb.png
deleted file mode 100644
index cae1bd1..0000000
--- a/packages/Tethering/res/drawable-hdpi/stat_sys_tether_usb.png
+++ /dev/null
Binary files differ
diff --git a/packages/Tethering/res/drawable-ldpi/stat_sys_tether_bluetooth.png b/packages/Tethering/res/drawable-ldpi/stat_sys_tether_bluetooth.png
deleted file mode 100644
index ffe8e8c..0000000
--- a/packages/Tethering/res/drawable-ldpi/stat_sys_tether_bluetooth.png
+++ /dev/null
Binary files differ
diff --git a/packages/Tethering/res/drawable-ldpi/stat_sys_tether_general.png b/packages/Tethering/res/drawable-ldpi/stat_sys_tether_general.png
deleted file mode 100644
index ca20f73..0000000
--- a/packages/Tethering/res/drawable-ldpi/stat_sys_tether_general.png
+++ /dev/null
Binary files differ
diff --git a/packages/Tethering/res/drawable-ldpi/stat_sys_tether_usb.png b/packages/Tethering/res/drawable-ldpi/stat_sys_tether_usb.png
deleted file mode 100644
index 65e9075..0000000
--- a/packages/Tethering/res/drawable-ldpi/stat_sys_tether_usb.png
+++ /dev/null
Binary files differ
diff --git a/packages/Tethering/res/drawable-mdpi/stat_sys_tether_bluetooth.png b/packages/Tethering/res/drawable-mdpi/stat_sys_tether_bluetooth.png
deleted file mode 100644
index f42dae0..0000000
--- a/packages/Tethering/res/drawable-mdpi/stat_sys_tether_bluetooth.png
+++ /dev/null
Binary files differ
diff --git a/packages/Tethering/res/drawable-mdpi/stat_sys_tether_general.png b/packages/Tethering/res/drawable-mdpi/stat_sys_tether_general.png
deleted file mode 100644
index 0655161..0000000
--- a/packages/Tethering/res/drawable-mdpi/stat_sys_tether_general.png
+++ /dev/null
Binary files differ
diff --git a/packages/Tethering/res/drawable-mdpi/stat_sys_tether_usb.png b/packages/Tethering/res/drawable-mdpi/stat_sys_tether_usb.png
deleted file mode 100644
index 2e2b8ca..0000000
--- a/packages/Tethering/res/drawable-mdpi/stat_sys_tether_usb.png
+++ /dev/null
Binary files differ
diff --git a/packages/Tethering/res/drawable-xhdpi/stat_sys_tether_bluetooth.png b/packages/Tethering/res/drawable-xhdpi/stat_sys_tether_bluetooth.png
deleted file mode 100644
index 3f57d1c..0000000
--- a/packages/Tethering/res/drawable-xhdpi/stat_sys_tether_bluetooth.png
+++ /dev/null
Binary files differ
diff --git a/packages/Tethering/res/drawable-xhdpi/stat_sys_tether_general.png b/packages/Tethering/res/drawable-xhdpi/stat_sys_tether_general.png
deleted file mode 100644
index 34b0cb3..0000000
--- a/packages/Tethering/res/drawable-xhdpi/stat_sys_tether_general.png
+++ /dev/null
Binary files differ
diff --git a/packages/Tethering/res/drawable-xhdpi/stat_sys_tether_usb.png b/packages/Tethering/res/drawable-xhdpi/stat_sys_tether_usb.png
deleted file mode 100644
index 36afe48..0000000
--- a/packages/Tethering/res/drawable-xhdpi/stat_sys_tether_usb.png
+++ /dev/null
Binary files differ
diff --git a/packages/Tethering/res/drawable-xxhdpi/stat_sys_tether_bluetooth.png b/packages/Tethering/res/drawable-xxhdpi/stat_sys_tether_bluetooth.png
deleted file mode 100644
index 25acfbb..0000000
--- a/packages/Tethering/res/drawable-xxhdpi/stat_sys_tether_bluetooth.png
+++ /dev/null
Binary files differ
diff --git a/packages/Tethering/res/drawable-xxhdpi/stat_sys_tether_general.png b/packages/Tethering/res/drawable-xxhdpi/stat_sys_tether_general.png
deleted file mode 100644
index 5c65601..0000000
--- a/packages/Tethering/res/drawable-xxhdpi/stat_sys_tether_general.png
+++ /dev/null
Binary files differ
diff --git a/packages/Tethering/res/drawable-xxhdpi/stat_sys_tether_usb.png b/packages/Tethering/res/drawable-xxhdpi/stat_sys_tether_usb.png
deleted file mode 100644
index 28b4b54..0000000
--- a/packages/Tethering/res/drawable-xxhdpi/stat_sys_tether_usb.png
+++ /dev/null
Binary files differ
diff --git a/packages/Tethering/res/values-af/strings.xml b/packages/Tethering/res/values-af/strings.xml
deleted file mode 100644
index 056168b..0000000
--- a/packages/Tethering/res/values-af/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"Verbinding of warmkol is aktief"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"Tik om op te stel."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"Verbinding is gedeaktiveer"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"Kontak jou administrateur vir besonderhede"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Warmkol- en verbindingstatus"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-am/strings.xml b/packages/Tethering/res/values-am/strings.xml
deleted file mode 100644
index ac468dd..0000000
--- a/packages/Tethering/res/values-am/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"እንደ ሞደም መሰካት ወይም መገናኛ ነጥብ ገባሪ"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"ለማዋቀር መታ ያድርጉ።"</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"እንደ ሞደም መሰካት ተሰናክሏል"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"ለዝርዝሮች የእርስዎን አስተዳዳሪ ያነጋግሩ"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"መገናኛ ነጥብ እና እንደ ሞደም የመሰካት ሁኔታ"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-ar/strings.xml b/packages/Tethering/res/values-ar/strings.xml
deleted file mode 100644
index 7d5bad3..0000000
--- a/packages/Tethering/res/values-ar/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"النطاق نشط أو نقطة الاتصال نشطة"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"انقر للإعداد."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"التوصيل متوقف."</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"تواصَل مع المشرف للحصول على التفاصيل."</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"حالة نقطة الاتصال والتوصيل"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-as/strings.xml b/packages/Tethering/res/values-as/strings.xml
deleted file mode 100644
index 0913504..0000000
--- a/packages/Tethering/res/values-as/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"টে\'ডাৰিং অথবা হ\'টস্প\'ট সক্ৰিয় অৱস্থাত আছে"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"ছেট আপ কৰিবলৈ টিপক।"</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"টে\'ডাৰিঙৰ সুবিধাটো অক্ষম কৰি থোৱা হৈছে"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"সবিশেষ জানিবলৈ আপোনাৰ প্ৰশাসকৰ সৈতে যোগাযোগ কৰক"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"হ’টস্প\'ট আৰু টে\'ডাৰিঙৰ স্থিতি"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-az/strings.xml b/packages/Tethering/res/values-az/strings.xml
deleted file mode 100644
index dce70da..0000000
--- a/packages/Tethering/res/values-az/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"Birləşmə və ya hotspot aktivdir"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"Ayarlamaq üçün toxunun."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"Birləşmə deaktivdir"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"Detallar üçün adminlə əlaqə saxlayın"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Hotspot & birləşmə statusu"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-b+sr+Latn/strings.xml b/packages/Tethering/res/values-b+sr+Latn/strings.xml
deleted file mode 100644
index b0774ec..0000000
--- a/packages/Tethering/res/values-b+sr+Latn/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"Privezivanje ili hotspot je aktivan"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"Dodirnite da biste podesili."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"Privezivanje je onemogućeno"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"Potražite detalje od administratora"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Status hotspota i privezivanja"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-be/strings.xml b/packages/Tethering/res/values-be/strings.xml
deleted file mode 100644
index a8acebe..0000000
--- a/packages/Tethering/res/values-be/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"Мадэм або хот-спот актыўныя"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"Дакраніцеся, каб наладзіць."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"Рэжым мадэма выключаны"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"Звярніцеся да адміністратара па падрабязную інфармацыю"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Стан \"Хот-спот і мадэм\""</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-bg/strings.xml b/packages/Tethering/res/values-bg/strings.xml
deleted file mode 100644
index 94fb2d8..0000000
--- a/packages/Tethering/res/values-bg/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"Има активна споделена връзка или точка за достъп"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"Докоснете, за да настроите."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"Функцията за тетъринг е деактивирана"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"Свържете се с администратора си за подробности"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Състояние на функцията за точка за достъп и тетъринг"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-bn/strings.xml b/packages/Tethering/res/values-bn/strings.xml
deleted file mode 100644
index aea02b9..0000000
--- a/packages/Tethering/res/values-bn/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"টিথারিং বা হটস্পট চালু আছে"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"সেট-আপ করতে ট্যাপ করুন।"</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"টিথারিং বন্ধ করা আছে"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"বিশদে জানতে অ্যাডমিনের সাথে যোগাযোগ করুন"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"হটস্পট ও টিথারিং স্ট্যাটাস"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-bs/strings.xml b/packages/Tethering/res/values-bs/strings.xml
deleted file mode 100644
index de23272..0000000
--- a/packages/Tethering/res/values-bs/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"Aktivno je povezivanje putem mobitela ili pristupna tačka"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"Dodirnite da postavite."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"Povezivanje putem mobitela je onemogućeno"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"Kontaktirajte svog administratora za detalje"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Status pristupne tačke i povezivanja putem mobitela"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-ca/strings.xml b/packages/Tethering/res/values-ca/strings.xml
deleted file mode 100644
index 88b795c..0000000
--- a/packages/Tethering/res/values-ca/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"Compartició de xarxa o punt d\'accés Wi‑Fi actius"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"Toca per configurar."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"La compartició de xarxa està desactivada"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"Contacta amb el teu administrador per obtenir més informació"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Estat del punt d\'accés Wi‑Fi i de la compartició de xarxa"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-cs/strings.xml b/packages/Tethering/res/values-cs/strings.xml
deleted file mode 100644
index 8c1b83b..0000000
--- a/packages/Tethering/res/values-cs/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"Tethering nebo hotspot je aktivní"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"Klepnutím zahájíte nastavení."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"Tethering je zakázán"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"O podrobnosti požádejte administrátora"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Stav hotspotu a tetheringu"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-da/strings.xml b/packages/Tethering/res/values-da/strings.xml
deleted file mode 100644
index f413e70..0000000
--- a/packages/Tethering/res/values-da/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"Netdeling eller hotspot er aktivt"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"Tryk for at konfigurere."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"Netdeling er deaktiveret"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"Kontakt din administrator for at få oplysninger"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Status for hotspot og netdeling"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-de/strings.xml b/packages/Tethering/res/values-de/strings.xml
deleted file mode 100644
index f057d78..0000000
--- a/packages/Tethering/res/values-de/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"Tethering oder Hotspot aktiv"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"Zum Einrichten tippen."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"Tethering ist deaktiviert"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"Bitte wende dich für weitere Informationen an den Administrator"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Hotspot- und Tethering-Status"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-el/strings.xml b/packages/Tethering/res/values-el/strings.xml
deleted file mode 100644
index b3c986b..0000000
--- a/packages/Tethering/res/values-el/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"Πρόσδεση ή σύνδεση σημείου πρόσβασης ενεργή"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"Πατήστε για ρύθμιση."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"Η σύνδεση είναι απενεργοποιημένη"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"Επικοινωνήστε με τον διαχειριστή σας για λεπτομέρειες"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Κατάσταση σημείου πρόσβασης Wi-Fi και σύνδεσης"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-en-rAU/strings.xml b/packages/Tethering/res/values-en-rAU/strings.xml
deleted file mode 100644
index 769e0120..0000000
--- a/packages/Tethering/res/values-en-rAU/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"Tethering or hotspot active"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"Tap to set up."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"Tethering is disabled"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"Contact your admin for details"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Hotspot and tethering status"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-en-rCA/strings.xml b/packages/Tethering/res/values-en-rCA/strings.xml
deleted file mode 100644
index 769e0120..0000000
--- a/packages/Tethering/res/values-en-rCA/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"Tethering or hotspot active"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"Tap to set up."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"Tethering is disabled"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"Contact your admin for details"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Hotspot and tethering status"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-en-rGB/strings.xml b/packages/Tethering/res/values-en-rGB/strings.xml
deleted file mode 100644
index 769e0120..0000000
--- a/packages/Tethering/res/values-en-rGB/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"Tethering or hotspot active"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"Tap to set up."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"Tethering is disabled"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"Contact your admin for details"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Hotspot and tethering status"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-en-rIN/strings.xml b/packages/Tethering/res/values-en-rIN/strings.xml
deleted file mode 100644
index 769e0120..0000000
--- a/packages/Tethering/res/values-en-rIN/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"Tethering or hotspot active"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"Tap to set up."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"Tethering is disabled"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"Contact your admin for details"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Hotspot and tethering status"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-en-rXC/strings.xml b/packages/Tethering/res/values-en-rXC/strings.xml
deleted file mode 100644
index f1674be..0000000
--- a/packages/Tethering/res/values-en-rXC/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"Tethering or hotspot active"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"Tap to set up."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"Tethering is disabled"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"Contact your admin for details"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Hotspot & tethering status"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-es-rUS/strings.xml b/packages/Tethering/res/values-es-rUS/strings.xml
deleted file mode 100644
index 63689f4..0000000
--- a/packages/Tethering/res/values-es-rUS/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"Conexión a red o hotspot conectados"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"Presiona para configurar esta opción."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"Se inhabilitó la conexión mediante dispositivo portátil"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"Para obtener más información, comunícate con el administrador"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Estado del hotspot y la conexión mediante dispositivo portátil"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-es/strings.xml b/packages/Tethering/res/values-es/strings.xml
deleted file mode 100644
index 9a34ed5..0000000
--- a/packages/Tethering/res/values-es/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"Conexión compartida o punto de acceso activos"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"Toca para configurar."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"La conexión compartida está inhabilitada"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"Solicita más información a tu administrador"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Estado del punto de acceso y de la conexión compartida"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-et/strings.xml b/packages/Tethering/res/values-et/strings.xml
deleted file mode 100644
index 0970341..0000000
--- a/packages/Tethering/res/values-et/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"Jagamine või kuumkoht on aktiivne"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"Puudutage seadistamiseks."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"Jagamine on keelatud"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"Lisateabe saamiseks võtke ühendust oma administraatoriga"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Kuumkoha ja jagamise olek"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-eu/strings.xml b/packages/Tethering/res/values-eu/strings.xml
deleted file mode 100644
index 632019e..0000000
--- a/packages/Tethering/res/values-eu/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"Konexioa partekatzea edo wifi-gunea aktibo dago"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"Sakatu konfiguratzeko."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"Desgaituta dago konexioa partekatzeko aukera"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"Xehetasunak lortzeko, jarri administratzailearekin harremanetan"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Wifi-gunearen eta konexioa partekatzeko eginbidearen egoera"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-fa/strings.xml b/packages/Tethering/res/values-fa/strings.xml
deleted file mode 100644
index 2e21c85..0000000
--- a/packages/Tethering/res/values-fa/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"اشتراکگذاری اینترنت یا نقطه اتصال فعال"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"برای راهاندازی ضربه بزنید."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"اشتراکگذاری اینترنت غیرفعال است"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"برای جزئیات، با سرپرستتان تماس بگیرید"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"وضعیت نقطه اتصال و اشتراکگذاری اینترنت"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-fi/strings.xml b/packages/Tethering/res/values-fi/strings.xml
deleted file mode 100644
index 413db3f..0000000
--- a/packages/Tethering/res/values-fi/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"Yhteyden jakaminen tai hotspot käytössä"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"Ota käyttöön napauttamalla."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"Yhteyden jakaminen on poistettu käytöstä"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"Pyydä lisätietoja järjestelmänvalvojalta"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Hotspotin ja yhteyden jakamisen tila"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-fr-rCA/strings.xml b/packages/Tethering/res/values-fr-rCA/strings.xml
deleted file mode 100644
index eb2e4ba..0000000
--- a/packages/Tethering/res/values-fr-rCA/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"Partage de connexion ou point d\'accès sans fil activé"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"Touchez pour configurer."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"Le partage de connexion est désactivé"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"Communiquez avec votre administrateur pour obtenir plus de détails"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Point d\'accès et partage de connexion"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-fr/strings.xml b/packages/Tethering/res/values-fr/strings.xml
deleted file mode 100644
index 22259c5..0000000
--- a/packages/Tethering/res/values-fr/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"Partage de connexion ou point d\'accès activé"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"Appuyez pour effectuer la configuration."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"Le partage de connexion est désactivé"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"Pour en savoir plus, contactez votre administrateur"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"État du point d\'accès et du partage de connexion"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-gl/strings.xml b/packages/Tethering/res/values-gl/strings.xml
deleted file mode 100644
index ded82fc..0000000
--- a/packages/Tethering/res/values-gl/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"Conexión compartida ou zona wifi activada"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"Toca para configurar."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"A conexión compartida está desactivada"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"Contacta co administrador para obter información"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Estado da zona wifi e da conexión compartida"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-gu/strings.xml b/packages/Tethering/res/values-gu/strings.xml
deleted file mode 100644
index 7cbbc2d..0000000
--- a/packages/Tethering/res/values-gu/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"ઇન્ટરનેટ શેર કરવાની સુવિધા અથવા હૉટસ્પૉટ સક્રિય છે"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"સેટઅપ કરવા માટે ટૅપ કરો."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"ઇન્ટરનેટ શેર કરવાની સુવિધા બંધ કરી છે"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"વિગતો માટે તમારા વ્યવસ્થાપકનો સંપર્ક કરો"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"હૉટસ્પૉટ અને ઇન્ટરનેટ શેર કરવાની સુવિધાનું સ્ટેટસ"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-hi/strings.xml b/packages/Tethering/res/values-hi/strings.xml
deleted file mode 100644
index 08af81b..0000000
--- a/packages/Tethering/res/values-hi/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"टेदरिंग या हॉटस्पॉट चालू है"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"सेट अप करने के लिए टैप करें."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"टेदरिंग बंद है"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"जानकारी के लिए अपने एडमिन से संपर्क करें"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"हॉटस्पॉट और टेदरिंग की स्थिति"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-hr/strings.xml b/packages/Tethering/res/values-hr/strings.xml
deleted file mode 100644
index 827c135..0000000
--- a/packages/Tethering/res/values-hr/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"Modemsko povezivanje ili žarišna točka aktivni"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"Dodirnite da biste postavili."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"Modemsko je povezivanje onemogućeno"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"Obratite se administratoru da biste saznali pojedinosti"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Status žarišne točke i modemskog povezivanja"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-hu/strings.xml b/packages/Tethering/res/values-hu/strings.xml
deleted file mode 100644
index eb68d6b..0000000
--- a/packages/Tethering/res/values-hu/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"Megosztás vagy aktív hotspot"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"Koppintson a beállításhoz."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"Az internetmegosztás le van tiltva"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"A részletekért forduljon rendszergazdájához"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Hotspot és internetmegosztás állapota"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-hy/strings.xml b/packages/Tethering/res/values-hy/strings.xml
deleted file mode 100644
index 912941e..0000000
--- a/packages/Tethering/res/values-hy/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"Մոդեմի ռեժիմը միացված է"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"Հպեք՝ կարգավորելու համար։"</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"Մոդեմի ռեժիմն անջատված է"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"Մանրամասների համար դիմեք ձեր ադմինիստրատորին"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Թեժ կետի և մոդեմի ռեժիմի կարգավիճակը"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-in/strings.xml b/packages/Tethering/res/values-in/strings.xml
deleted file mode 100644
index a4e175a..0000000
--- a/packages/Tethering/res/values-in/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"Tethering atau hotspot aktif"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"Ketuk untuk menyiapkan."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"Tethering dinonaktifkan"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"Hubungi admin untuk mengetahui detailnya"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Status hotspot & tethering"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-is/strings.xml b/packages/Tethering/res/values-is/strings.xml
deleted file mode 100644
index e9f6670..0000000
--- a/packages/Tethering/res/values-is/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"Kveikt á tjóðrun eða aðgangsstað"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"Ýttu til að setja upp."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"Slökkt er á tjóðrun"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"Hafðu samband við kerfisstjórann til að fá upplýsingar"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Staða heits reits og tjóðrunar"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-it/strings.xml b/packages/Tethering/res/values-it/strings.xml
deleted file mode 100644
index ffb9196..0000000
--- a/packages/Tethering/res/values-it/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"Hotspot o tethering attivo"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"Tocca per impostare."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"Tethering disattivato"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"Contatta il tuo amministratore per avere informazioni dettagliate"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Stato hotspot e tethering"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-iw/strings.xml b/packages/Tethering/res/values-iw/strings.xml
deleted file mode 100644
index 7adcb47..0000000
--- a/packages/Tethering/res/values-iw/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"נקודה לשיתוף אינטרנט או שיתוף אינטרנט בין מכשירים: בסטטוס פעיל"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"יש להקיש כדי להגדיר."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"שיתוף האינטרנט בין מכשירים מושבת"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"לפרטים, יש לפנות למנהל המערכת"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"סטטוס של נקודה לשיתוף אינטרנט ושיתוף אינטרנט בין מכשירים"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-ja/strings.xml b/packages/Tethering/res/values-ja/strings.xml
deleted file mode 100644
index f68a730..0000000
--- a/packages/Tethering/res/values-ja/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"テザリングまたはアクセス ポイントが有効です"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"タップしてセットアップします。"</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"テザリングは無効に設定されています"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"詳しくは、管理者にお問い合わせください"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"アクセス ポイントとテザリングのステータス"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-ka/strings.xml b/packages/Tethering/res/values-ka/strings.xml
deleted file mode 100644
index 7c22e82..0000000
--- a/packages/Tethering/res/values-ka/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"ტეტერინგი ან უსადენო ქსელი აქტიურია"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"შეეხეთ დასაყენებლად."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"ტეტერინგი გათიშულია"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"დამატებითი ინფორმაციისთვის დაუკავშირდით თქვენს ადმინისტრატორს"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"უსადენო ქსელის და ტეტერინგის სტატუსი"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-kk/strings.xml b/packages/Tethering/res/values-kk/strings.xml
deleted file mode 100644
index 0857d06..0000000
--- a/packages/Tethering/res/values-kk/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"Тетеринг немесе хотспот қосулы"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"Реттеу үшін түртіңіз."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"Тетеринг өшірілді."</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"Мәліметтерді әкімшіден алыңыз."</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Хотспот және тетеринг күйі"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-km/strings.xml b/packages/Tethering/res/values-km/strings.xml
deleted file mode 100644
index 536e3d1..0000000
--- a/packages/Tethering/res/values-km/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"ការភ្ជាប់ ឬហតស្ប៉តកំពុងដំណើរការ"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"ចុចដើម្បីរៀបចំ។"</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"ការភ្ជាប់ត្រូវបានបិទ"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"ទាក់ទងអ្នកគ្រប់គ្រងរបស់អ្នក ដើម្បីទទួលបានព័ត៌មានលម្អិត"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"ស្ថានភាពនៃការភ្ជាប់ និងហតស្ប៉ត"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-kn/strings.xml b/packages/Tethering/res/values-kn/strings.xml
deleted file mode 100644
index 32f5492..0000000
--- a/packages/Tethering/res/values-kn/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"ಟೆಥರಿಂಗ್ ಅಥವಾ ಹಾಟ್ಸ್ಪಾಟ್ ಸಕ್ರಿಯವಾಗಿದೆ"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"ಸೆಟಪ್ ಮಾಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"ಟೆಥರಿಂಗ್ ಅನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"ವಿವರಗಳಿಗಾಗಿ ನಿಮ್ಮ ನಿರ್ವಾಹಕರನ್ನು ಸಂಪರ್ಕಿಸಿ"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"ಹಾಟ್ಸ್ಪಾಟ್ ಮತ್ತು ಟೆಥರಿಂಗ್ ಸ್ಥಿತಿ"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-ko/strings.xml b/packages/Tethering/res/values-ko/strings.xml
deleted file mode 100644
index 156b247..0000000
--- a/packages/Tethering/res/values-ko/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"테더링 또는 핫스팟 사용"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"설정하려면 탭하세요."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"테더링이 사용 중지됨"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"자세한 정보는 관리자에게 문의하세요."</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"핫스팟 및 테더링 상태"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-ky/strings.xml b/packages/Tethering/res/values-ky/strings.xml
deleted file mode 100644
index 18ee5fd..0000000
--- a/packages/Tethering/res/values-ky/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"Модем режими күйүп турат"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"Жөндөө үчүн таптап коюңуз."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"Телефонду модем катары колдонууга болбойт"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"Кеңири маалымат үчүн администраторуңузга кайрылыңыз"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Байланыш түйүнүнүн жана модем режиминин статусу"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-lo/strings.xml b/packages/Tethering/res/values-lo/strings.xml
deleted file mode 100644
index b127670..0000000
--- a/packages/Tethering/res/values-lo/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"ເປີດການປ່ອຍສັນຍານ ຫຼື ຮັອດສະປອດແລ້ວ"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"ແຕະເພື່ອຕັ້ງຄ່າ."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"ການປ່ອຍສັນຍານຖືກປິດໄວ້"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"ຕິດຕໍ່ຜູ້ເບິ່ງແຍງລະບົບສຳລັບລາຍລະອຽດ"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"ສະຖານະຮັອດສະປອດ ແລະ ການປ່ອຍສັນຍານ"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-lt/strings.xml b/packages/Tethering/res/values-lt/strings.xml
deleted file mode 100644
index 8427baf..0000000
--- a/packages/Tethering/res/values-lt/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"Įrenginys naudojamas kaip modemas arba įjungtas viešosios interneto prieigos taškas"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"Palieskite, kad nustatytumėte."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"Įrenginio kaip modemo naudojimas išjungtas"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"Jei reikia išsamios informacijos, susisiekite su administratoriumi"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Viešosios interneto prieigos taško ir įrenginio kaip modemo naudojimo būsena"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-lv/strings.xml b/packages/Tethering/res/values-lv/strings.xml
deleted file mode 100644
index aa2d699..0000000
--- a/packages/Tethering/res/values-lv/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"Piesaiste vai tīklājs ir aktīvs."</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"Pieskarieties, lai to iestatītu."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"Piesaiste ir atspējota"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"Lai iegūtu detalizētu informāciju, sazinieties ar savu administratoru."</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Tīklāja un piesaistes statuss"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-af/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-af/strings.xml
deleted file mode 100644
index 19d659c..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-af/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"Verbinding het nie internet nie"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"Toestelle kan nie koppel nie"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Skakel verbinding af"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Warmkol of verbinding is aan"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Bykomende heffings kan geld terwyl jy swerf"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-am/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-am/strings.xml
deleted file mode 100644
index 8995430..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-am/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"ማስተሳሰር ምንም በይነመረብ የለውም"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"መሣሪያዎችን ማገናኘት አይቻልም"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"ማስተሳሰርን አጥፋ"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"መገናኛ ነጥብ ወይም ማስተሳሰር በርቷል"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"በሚያንዣብብበት ጊዜ ተጨማሪ ክፍያዎች ተፈጻሚ ሊሆኑ ይችላሉ"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-ar/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-ar/strings.xml
deleted file mode 100644
index 54f3b53..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-ar/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"ما مِن اتصال بالإنترنت خلال التوصيل"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"تعذّر اتصال الأجهزة"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"إيقاف التوصيل"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"نقطة الاتصال أو التوصيل مفعّلان"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"قد يتم تطبيق رسوم إضافية أثناء التجوال."</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-as/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-as/strings.xml
deleted file mode 100644
index e215141c..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-as/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"টে\'ডাৰিঙৰ ইণ্টাৰনেট নাই"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"ডিভাইচসমূহ সংযোগ কৰিব নোৱাৰি"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"টে\'ডাৰিং অফ কৰক"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"হটস্পট অথবা টে\'ডাৰিং অন আছে"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"ৰ\'মিঙত থাকিলে অতিৰিক্ত মাচুল প্ৰযোজ্য হ’ব পাৰে"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-az/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-az/strings.xml
deleted file mode 100644
index 1fd8e4c..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-az/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"Modemin internetə girişi yoxdur"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"Cihazları qoşmaq mümkün deyil"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Modemi deaktiv edin"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Hotspot və ya modem aktivdir"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Rouminq zamanı əlavə ödənişlər tətbiq edilə bilər"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-b+sr+Latn/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-b+sr+Latn/strings.xml
deleted file mode 100644
index 1abe4f3..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-b+sr+Latn/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"Privezivanje nema pristup internetu"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"Povezivanje uređaja nije uspelo"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Isključi privezivanje"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Uključen je hotspot ili privezivanje"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Možda važe dodatni troškovi u romingu"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-be/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-be/strings.xml
deleted file mode 100644
index 38dbd1e..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-be/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"Рэжым мадэма выкарыстоўваецца без доступу да інтэрнэту"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"Не ўдалося падключыць прылады"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Выключыць рэжым мадэма"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Хот-спот або рэжым мадэма ўключаны"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Пры выкарыстанні роўмінгу можа спаганяцца дадатковая плата"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-bg/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-bg/strings.xml
deleted file mode 100644
index 04b44db..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-bg/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"Тетърингът няма връзка с интернет"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"Устройствата не могат да установят връзка"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Изключване на тетъринга"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Точката за достъп или тетърингът са включени"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Възможно е да ви бъдат начислени допълнителни такси при роуминг"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-bn/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-bn/strings.xml
deleted file mode 100644
index 579d1be..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-bn/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"টিথারিং করার জন্য কোনও ইন্টারনেট কানেকশন নেই"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"ডিভাইস কানেক্ট করতে পারছে না"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"টিথারিং বন্ধ করুন"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"হটস্পট বা টিথারিং চালু আছে"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"রোমিংয়ের সময় অতিরিক্ত চার্জ করা হতে পারে"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-bs/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-bs/strings.xml
deleted file mode 100644
index 9ce3efe..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-bs/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"Povezivanje putem mobitela nema internet"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"Uređaji se ne mogu povezati"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Isključi povezivanje putem mobitela"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Pristupna tačka ili povezivanje putem mobitela je uključeno"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Mogu nastati dodatni troškovi u romingu"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-ca/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-ca/strings.xml
deleted file mode 100644
index 46d4c35..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-ca/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"La compartició de xarxa no té accés a Internet"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"No es poden connectar els dispositius"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Desactiva la compartició de xarxa"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"S\'ha activat el punt d\'accés Wi‑Fi o la compartició de xarxa"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"És possible que s\'apliquin costos addicionals en itinerància"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-cs/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-cs/strings.xml
deleted file mode 100644
index cc13860..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-cs/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"Tethering nemá připojení k internetu"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"Zařízení se nemůžou připojit"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Vypnout tethering"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Je zapnutý hotspot nebo tethering"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Při roamingu mohou být účtovány dodatečné poplatky"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-da/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-da/strings.xml
deleted file mode 100644
index 92c3ae1..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-da/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"Netdeling har ingen internetforbindelse"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"Enheder kan ikke oprette forbindelse"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Deaktiver netdeling"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Hotspot eller netdeling er aktiveret"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Der opkræves muligvis yderligere gebyrer ved roaming"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-de/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-de/strings.xml
deleted file mode 100644
index 967eb4d..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-de/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"Tethering hat keinen Internetzugriff"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"Geräte können sich nicht verbinden"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Tethering deaktivieren"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Hotspot oder Tethering ist aktiviert"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Für das Roaming können zusätzliche Gebühren anfallen"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-el/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-el/strings.xml
deleted file mode 100644
index 5fb4974..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-el/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"Η σύνδεση δεν έχει πρόσβαση στο διαδίκτυο"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"Δεν είναι δυνατή η σύνδεση των συσκευών"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Απενεργοποιήστε τη σύνδεση"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Ενεργό σημείο πρόσβασης Wi-Fi ή ενεργή σύνδεση"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Ενδέχεται να ισχύουν επιπλέον χρεώσεις κατά την περιαγωγή."</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-en-rAU/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-en-rAU/strings.xml
deleted file mode 100644
index 45647f9..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-en-rAU/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"Tethering has no Internet"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"Devices can’t connect"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Turn off tethering"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Hotspot or tethering is on"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Additional charges may apply while roaming"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-en-rCA/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-en-rCA/strings.xml
deleted file mode 100644
index 45647f9..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-en-rCA/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"Tethering has no Internet"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"Devices can’t connect"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Turn off tethering"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Hotspot or tethering is on"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Additional charges may apply while roaming"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-en-rGB/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-en-rGB/strings.xml
deleted file mode 100644
index 45647f9..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-en-rGB/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"Tethering has no Internet"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"Devices can’t connect"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Turn off tethering"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Hotspot or tethering is on"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Additional charges may apply while roaming"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-en-rIN/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-en-rIN/strings.xml
deleted file mode 100644
index 45647f9..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-en-rIN/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"Tethering has no Internet"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"Devices can’t connect"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Turn off tethering"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Hotspot or tethering is on"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Additional charges may apply while roaming"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-en-rXC/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-en-rXC/strings.xml
deleted file mode 100644
index 7877074..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-en-rXC/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"Tethering has no internet"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"Devices can’t connect"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Turn off tethering"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Hotspot or tethering is on"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Additional charges may apply while roaming"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-es-rUS/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-es-rUS/strings.xml
deleted file mode 100644
index 08edd81..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-es-rUS/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"La conexión mediante dispositivo móvil no tiene Internet"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"No se pueden conectar los dispositivos"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Desactivar conexión mediante dispositivo móvil"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Se activó el hotspot o la conexión mediante dispositivo móvil"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Es posible que se apliquen cargos adicionales por roaming"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-es/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-es/strings.xml
deleted file mode 100644
index 79f51d0..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-es/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"La conexión no se puede compartir, porque no hay acceso a Internet"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"Los dispositivos no se pueden conectar"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Desactivar conexión compartida"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Punto de acceso o conexión compartida activados"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Puede que se apliquen cargos adicionales en itinerancia"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-et/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-et/strings.xml
deleted file mode 100644
index 2da5f8a..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-et/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"Jagamisel puudub internetiühendus"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"Seadmed ei saa ühendust luua"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Lülita jagamine välja"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Kuumkoht või jagamine on sisse lülitatud"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Rändluse kasutamisega võivad kaasneda lisatasud"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-eu/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-eu/strings.xml
deleted file mode 100644
index 2073f28..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-eu/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"Konexioa partekatzeko aukerak ez du Interneteko konexiorik"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"Ezin dira konektatu gailuak"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Desaktibatu konexioa partekatzeko aukera"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Wifi-gunea edo konexioa partekatzeko aukera aktibatuta dago"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Baliteke kostu gehigarriak ordaindu behar izatea ibiltaritzan"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-fa/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-fa/strings.xml
deleted file mode 100644
index e21b2a0..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-fa/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"«اشتراکگذاری اینترنت» به اینترنت دسترسی ندارد"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"دستگاهها متصل نمیشوند"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"خاموش کردن «اشتراکگذاری اینترنت»"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"«نقطه اتصال» یا «اشتراکگذاری اینترنت» روشن است"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"ممکن است درحین فراگردی تغییرات دیگر اعمال شود"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-fi/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-fi/strings.xml
deleted file mode 100644
index 88b0b13..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-fi/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"Ei jaettavaa internetyhteyttä"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"Laitteet eivät voi muodostaa yhteyttä"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Laita yhteyden jakaminen pois päältä"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Hotspot tai yhteyden jakaminen on päällä"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Roaming voi aiheuttaa lisämaksuja"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-fr-rCA/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-fr-rCA/strings.xml
deleted file mode 100644
index 3b781bc..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-fr-rCA/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"Le partage de connexion n\'est pas connecté à Internet"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"Impossible de connecter les appareils"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Désactiver le partage de connexion"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Le point d\'accès ou le partage de connexion est activé"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"En itinérance, des frais supplémentaires peuvent s\'appliquer"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-fr/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-fr/strings.xml
deleted file mode 100644
index 51d7203..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-fr/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"Aucune connexion à Internet n\'est disponible pour le partage de connexion"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"Impossible de connecter les appareils"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Désactiver le partage de connexion"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Le point d\'accès ou le partage de connexion est activé"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"En itinérance, des frais supplémentaires peuvent s\'appliquer"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-gl/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-gl/strings.xml
deleted file mode 100644
index 008ccb4..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-gl/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"A conexión compartida non ten Internet"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"Non se puideron conectar os dispositivos"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Desactivar conexión compartida"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Está activada a zona wifi ou a conexión compartida"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Pódense aplicar cargos adicionais en itinerancia"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-gu/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-gu/strings.xml
deleted file mode 100644
index f2e3b4d..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-gu/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"ઇન્ટરનેટ શેર કરવાની સુવિધામાં ઇન્ટરનેટ નથી"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"ડિવાઇસ કનેક્ટ કરી શકાતા નથી"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"ઇન્ટરનેટ શેર કરવાની સુવિધા બંધ કરો"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"હૉટસ્પૉટ અથવા ઇન્ટરનેટ શેર કરવાની સુવિધા ચાલુ છે"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"રોમિંગમાં વધારાના શુલ્ક લાગી શકે છે"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-hi/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-hi/strings.xml
deleted file mode 100644
index b11839d..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-hi/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"टेदरिंग से इंटरनेट नहीं चल रहा"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"डिवाइस कनेक्ट नहीं हो पा रहे"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"टेदरिंग बंद करें"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"हॉटस्पॉट या टेदरिंग चालू है"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"रोमिंग के दौरान अतिरिक्त शुल्क लग सकता है"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-hr/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-hr/strings.xml
deleted file mode 100644
index 0a5aca2..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-hr/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"Modemsko povezivanje nema internet"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"Uređaji se ne mogu povezati"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Isključivanje modemskog povezivanja"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Uključena je žarišna točka ili modemsko povezivanje"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"U roamingu su mogući dodatni troškovi"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-hu/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-hu/strings.xml
deleted file mode 100644
index 21c689a4..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-hu/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"Nincs internetkapcsolat az internet megosztásához"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"Az eszközök nem tudnak csatlakozni"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Internetmegosztás kikapcsolása"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"A hotspot vagy az internetmegosztás be van kapcsolva"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Roaming során további díjak léphetnek fel"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-hy/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-hy/strings.xml
deleted file mode 100644
index 689d9287..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-hy/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"Մոդեմի ռեժիմի կապը բացակայում է"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"Չհաջողվեց միացնել սարքը"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Անջատել մոդեմի ռեժիմը"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Թեժ կետը կամ մոդեմի ռեժիմը միացված է"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Ռոումինգում կարող են լրացուցիչ վճարներ գանձվել"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-in/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-in/strings.xml
deleted file mode 100644
index a5f4d19..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-in/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"Tidak ada koneksi internet di tethering"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"Perangkat tidak dapat terhubung"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Nonaktifkan tethering"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Hotspot atau tethering aktif"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Biaya tambahan mungkin berlaku saat roaming"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-is/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-is/strings.xml
deleted file mode 100644
index fc7e8aa..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-is/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"Tjóðrun er ekki með internettengingu"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"Tæki geta ekki tengst"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Slökkva á tjóðrun"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Kveikt er á heitum reit eða tjóðrun"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Viðbótargjöld kunna að eiga við í reiki"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-it/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-it/strings.xml
deleted file mode 100644
index 6456dd1..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-it/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"Nessuna connessione a Internet per il tethering"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"Impossibile connettere i dispositivi"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Disattiva il tethering"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Hotspot o tethering attivi"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Potrebbero essere applicati costi aggiuntivi durante il roaming"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-iw/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-iw/strings.xml
deleted file mode 100644
index 46b24bd..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-iw/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"אי אפשר להפעיל את תכונת שיתוף האינטרנט בין מכשירים כי אין חיבור לאינטרנט"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"למכשירים אין אפשרות להתחבר"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"השבתה של שיתוף האינטרנט בין מכשירים"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"תכונת הנקודה לשיתוף אינטרנט או תכונת שיתוף האינטרנט בין מכשירים פועלת"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"ייתכנו חיובים נוספים בעת נדידה"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-ja/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-ja/strings.xml
deleted file mode 100644
index e6eb277..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-ja/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"テザリングがインターネットに接続されていません"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"デバイスを接続できません"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"テザリングを OFF にする"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"アクセス ポイントまたはテザリングが ON です"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"ローミング時に追加料金が発生することがあります"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-ka/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-ka/strings.xml
deleted file mode 100644
index aeddd71..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-ka/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"ტეტერინგს არ აქვს ინტერნეტზე წვდომა"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"მოწყობილობები ვერ ახერხებენ დაკავშირებას"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"ტეტერინგის გამორთვა"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"ჩართულია უსადენო ქსელი ან ტეტერინგი"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"როუმინგის გამოყენებისას შეიძლება ჩამოგეჭრათ დამატებითი საფასური"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-kk/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-kk/strings.xml
deleted file mode 100644
index 255f0a2..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-kk/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"Тетеринг режимі интернет байланысынсыз пайдаланылуда"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"Құрылғыларды байланыстыру мүмкін емес"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Тетерингіні өшіру"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Хотспот немесе тетеринг қосулы"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Роуминг кезінде қосымша ақы алынуы мүмкін."</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-km/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-km/strings.xml
deleted file mode 100644
index 2bceb1c..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-km/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"ការភ្ជាប់មិនមានអ៊ីនធឺណិតទេ"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"មិនអាចភ្ជាប់ឧបករណ៍បានទេ"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"បិទការភ្ជាប់"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"ហតស្ប៉ត ឬការភ្ជាប់ត្រូវបានបើក"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"អាចមានការគិតថ្លៃបន្ថែម នៅពេលរ៉ូមីង"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-kn/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-kn/strings.xml
deleted file mode 100644
index ed76930..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-kn/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"ಟೆಥರಿಂಗ್ ಯಾವುದೇ ಇಂಟರ್ನೆಟ್ ಕನೆಕ್ಷನ್ ಹೊಂದಿಲ್ಲ"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"ಸಾಧನಗಳನ್ನು ಕನೆಕ್ಟ್ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"ಟೆಥರಿಂಗ್ ಆಫ್ ಮಾಡಿ"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"ಹಾಟ್ಸ್ಪಾಟ್ ಅಥವಾ ಟೆಥರಿಂಗ್ ಆನ್ ಆಗಿದೆ"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"ರೋಮಿಂಗ್ನಲ್ಲಿರುವಾಗ ಹೆಚ್ಚುವರಿ ಶುಲ್ಕಗಳು ಅನ್ವಯವಾಗಬಹುದು"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-ko/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-ko/strings.xml
deleted file mode 100644
index 6e50494..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-ko/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"테더링으로 인터넷을 사용할 수 없음"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"기기에서 연결할 수 없음"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"테더링 사용 중지"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"핫스팟 또는 테더링 켜짐"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"로밍 중에는 추가 요금이 발생할 수 있습니다."</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-ky/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-ky/strings.xml
deleted file mode 100644
index d68128b..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-ky/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"Модем режими Интернети жок колдонулууда"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"Түзмөктөр туташпай жатат"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Модем режимин өчүрүү"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Байланыш түйүнү же модем режими күйүк"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Роумингде кошумча акы алынышы мүмкүн"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-lo/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-lo/strings.xml
deleted file mode 100644
index 03e134a..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-lo/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"ການປ່ອຍສັນຍານບໍ່ມີອິນເຕີເນັດ"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"ອຸປະກອນບໍ່ສາມາດເຊື່ອມຕໍ່ໄດ້"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"ປິດການປ່ອຍສັນຍານ"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"ເປີດໃຊ້ຮັອດສະປອດ ຫຼື ການປ່ອຍສັນຍານຢູ່"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"ອາດມີຄ່າໃຊ້ຈ່າຍເພີ່ມເຕີມໃນລະຫວ່າງການໂຣມມິງ"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-lt/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-lt/strings.xml
deleted file mode 100644
index 652cedc..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-lt/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"Nėra įrenginio kaip modemo naudojimo interneto ryšio"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"Nepavyko susieti įrenginių"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Išjungti įrenginio kaip modemo naudojimą"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Įjungtas viešosios interneto prieigos taškas arba įrenginio kaip modemo naudojimas"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Veikiant tarptinkliniam ryšiui gali būti taikomi papildomi mokesčiai"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-lv/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-lv/strings.xml
deleted file mode 100644
index 2219722..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-lv/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"Piesaistei nav interneta savienojuma"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"Nevar savienot ierīces"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Izslēgt piesaisti"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Ir ieslēgts tīklājs vai piesaiste"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Viesabonēšanas laikā var tikt piemērota papildu samaksa"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-mk/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-mk/strings.xml
deleted file mode 100644
index 227f9e3..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-mk/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"Нема интернет преку мобилен"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"Уредите не може да се поврзат"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Исклучи интернет преку мобилен"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Точката на пристап или интернетот преку мобилен е вклучен"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"При роаминг може да се наплатат дополнителни трошоци"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-ml/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-ml/strings.xml
deleted file mode 100644
index ec43885..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-ml/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"ടെതറിംഗിന് ഇന്റർനെറ്റ് ഇല്ല"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"ഉപകരണങ്ങൾ കണക്റ്റ് ചെയ്യാനാവില്ല"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"ടെതറിംഗ് ഓഫാക്കുക"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"ഹോട്ട്സ്പോട്ട് അല്ലെങ്കിൽ ടെതറിംഗ് ഓണാണ്"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"റോമിംഗ് ചെയ്യുമ്പോൾ അധിക നിരക്കുകൾ ബാധകമായേക്കാം"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-mn/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-mn/strings.xml
deleted file mode 100644
index e263573..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-mn/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"Модемд интернэт алга байна"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"Төхөөрөмжүүд холбогдох боломжгүй байна"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Модем болгохыг унтраах"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Сүлжээний цэг эсвэл модем болгох асаалттай байна"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Роумингийн үеэр нэмэлт төлбөр нэхэмжилж болзошгүй"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-mr/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-mr/strings.xml
deleted file mode 100644
index adf845d..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-mr/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"टेदरिंगला इंटरनेट नाही"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"डिव्हाइस कनेक्ट होऊ शकत नाहीत"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"टेदरिंग बंद करा"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"हॉटस्पॉट किंवा टेदरिंग सुरू आहे"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"रोमिंगदरम्यान अतिरिक्त शुल्क लागू होऊ शकतात"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-ms/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-ms/strings.xml
deleted file mode 100644
index f65c451..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-ms/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"Penambatan tiada Internet"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"Peranti tidak dapat disambungkan"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Matikan penambatan"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Tempat liputan atau penambatan dihidupkan"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Caj tambahan mungkin digunakan semasa perayauan"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-my/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-my/strings.xml
deleted file mode 100644
index 4118e77..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-my/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"မိုဘိုင်းဖုန်းသုံး ချိတ်ဆက်မျှဝေခြင်းတွင် အင်တာနက် မရှိပါ"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"စက်များ ချိတ်ဆက်၍ မရပါ"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"မိုဘိုင်းဖုန်းသုံး ချိတ်ဆက်မျှဝေခြင်း ပိတ်ရန်"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"ဟော့စပေါ့ (သို့) မိုဘိုင်းဖုန်းသုံး ချိတ်ဆက်မျှဝေခြင်း ဖွင့်ထားသည်"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"ပြင်ပကွန်ရက်နှင့် ချိတ်ဆက်သည့်အခါ နောက်ထပ်ကျသင့်မှုများ ရှိနိုင်သည်"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-nb/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-nb/strings.xml
deleted file mode 100644
index 3685358..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-nb/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"Internettdeling har ikke internettilgang"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"Enhetene kan ikke koble til"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Slå av internettdeling"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Wi-Fi-sone eller internettdeling er på"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Ytterligere kostnader kan påløpe under roaming"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-ne/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-ne/strings.xml
deleted file mode 100644
index d074f15..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-ne/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"टेदरिङमार्फत इन्टरनेट कनेक्सन प्राप्त हुन सकेन"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"यन्त्रहरू कनेक्ट गर्न सकिएन"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"टेदरिङ निष्क्रिय पार्नुहोस्"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"हटस्पट वा टेदरिङ सक्रिय छ"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"रोमिङ सेवा प्रयोग गर्दा अतिरिक्त शुल्क लाग्न सक्छ"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-nl/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-nl/strings.xml
deleted file mode 100644
index 1d88894..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-nl/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"Tethering heeft geen internet"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"Apparaten kunnen niet worden verbonden"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Tethering uitschakelen"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Hotspot of tethering is ingeschakeld"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Er kunnen extra kosten voor roaming in rekening worden gebracht."</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-or/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-or/strings.xml
deleted file mode 100644
index 8038815..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-or/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"ଟିଥରିଂ ପାଇଁ କୌଣସି ଇଣ୍ଟର୍ନେଟ୍ ସଂଯୋଗ ନାହିଁ"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"ଡିଭାଇସଗୁଡ଼ିକ ସଂଯୋଗ କରାଯାଇପାରିବ ନାହିଁ"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"ଟିଥରିଂ ବନ୍ଦ କରନ୍ତୁ"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"ହଟସ୍ପଟ୍ କିମ୍ବା ଟିଥରିଂ ଚାଲୁ ଅଛି"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"ରୋମିଂରେ ଥିବା ସମୟରେ ଅତିରିକ୍ତ ଶୁଳ୍କ ଲାଗୁ ହୋଇପାରେ"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-pa/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-pa/strings.xml
deleted file mode 100644
index 819833e..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-pa/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"ਟੈਦਰਿੰਗ ਕੋਲ ਇੰਟਰਨੈੱਟ ਪਹੁੰਚ ਨਹੀਂ ਹੈ"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"ਡੀਵਾਈਸ ਕਨੈਕਟ ਨਹੀਂ ਕੀਤੇ ਜਾ ਸਕਦੇ"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"ਟੈਦਰਿੰਗ ਬੰਦ ਕਰੋ"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"ਹੌਟਸਪੌਟ ਜਾਂ ਟੈਦਰਿੰਗ ਚਾਲੂ ਹੈ"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"ਰੋਮਿੰਗ ਦੌਰਾਨ ਵਧੀਕ ਖਰਚੇ ਲਾਗੂ ਹੋ ਸਕਦੇ ਹਨ"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-pl/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-pl/strings.xml
deleted file mode 100644
index 65e4380..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-pl/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"Tethering nie ma internetu"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"Urządzenia nie mogą się połączyć"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Wyłącz tethering"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Hotspot lub tethering jest włączony"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Podczas korzystania z roamingu mogą zostać naliczone dodatkowe opłaty"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-pt-rBR/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-pt-rBR/strings.xml
deleted file mode 100644
index d886617..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-pt-rBR/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"O tethering não tem Internet"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"Não é possível conectar os dispositivos"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Desativar o tethering"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Ponto de acesso ou tethering ativado"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Pode haver cobranças extras durante o roaming"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-pt-rPT/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-pt-rPT/strings.xml
deleted file mode 100644
index bfd45ca..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-pt-rPT/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"A ligação (à Internet) via telemóvel não tem Internet"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"Não é possível ligar os dispositivos"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Desativar ligação (à Internet) via telemóvel"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"A zona Wi-Fi ou a ligação (à Internet) via telemóvel está ativada"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Podem aplicar-se custos adicionais em roaming."</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-pt/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-pt/strings.xml
deleted file mode 100644
index d886617..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-pt/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"O tethering não tem Internet"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"Não é possível conectar os dispositivos"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Desativar o tethering"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Ponto de acesso ou tethering ativado"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Pode haver cobranças extras durante o roaming"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-ro/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-ro/strings.xml
deleted file mode 100644
index 8d87a9e5..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-ro/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"Procesul de tethering nu are internet"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"Dispozitivele nu se pot conecta"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Dezactivați procesul de tethering"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"S-a activat hotspotul sau tethering"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Se pot aplica taxe suplimentare pentru roaming"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-ru/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-ru/strings.xml
deleted file mode 100644
index dbdb9eb..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-ru/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"Режим модема используется без доступа к Интернету"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"Невозможно подключить устройства."</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Отключить режим модема"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Включены точка доступа или режим модема"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"За использование услуг связи в роуминге может взиматься дополнительная плата."</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-si/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-si/strings.xml
deleted file mode 100644
index d8301e4..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-si/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"ටෙදරින් හට අන්තර්ජාලය නැත"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"උපාංගවලට සම්බන්ධ විය නොහැකිය"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"ටෙදරින් ක්රියාවිරහිත කරන්න"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"හොට්ස්පොට් හෝ ටෙදරින් ක්රියාත්මකයි"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"රෝමිං අතරතුර අමතර ගාස්තු අදාළ විය හැකිය"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-sk/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-sk/strings.xml
deleted file mode 100644
index bef7136..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-sk/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"Tethering nemá internetové pripojenie"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"Zariadenia sa nemôžu pripojiť"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Vypnúť tethering"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Je zapnutý hotspot alebo tethering"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Počas roamingu vám môžu byť účtované ďalšie poplatky"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-sl/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-sl/strings.xml
deleted file mode 100644
index 3202c62..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-sl/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"Internetna povezava prek mobilnega telefona ni vzpostavljena"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"Napravi se ne moreta povezati"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Izklopi internetno povezavo prek mobilnega telefona"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Dostopna točka ali internetna povezava prek mobilnega telefona je vklopljena"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Med gostovanjem lahko nastanejo dodatni stroški"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-sq/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-sq/strings.xml
deleted file mode 100644
index 37f6ad2..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-sq/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"Ndarja e internetit nuk ka internet"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"Pajisjet nuk mund të lidhen"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Çaktivizo ndarjen e internetit"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Zona e qasjes për internet ose ndarja e internetit është aktive"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Mund të zbatohen tarifime shtesë kur je në roaming"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-sr/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-sr/strings.xml
deleted file mode 100644
index 5566d03..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-sr/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"Привезивање нема приступ интернету"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"Повезивање уређаја није успело"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Искључи привезивање"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Укључен је хотспот или привезивање"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Можда важе додатни трошкови у ромингу"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-sv/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-sv/strings.xml
deleted file mode 100644
index 9765acd..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-sv/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"Det finns ingen internetanslutning för internetdelningen"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"Enheterna kan inte anslutas"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Inaktivera internetdelning"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Surfzon eller internetdelning har aktiverats"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Ytterligare avgifter kan tillkomma vid roaming"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-sw/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-sw/strings.xml
deleted file mode 100644
index cf850c9..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-sw/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"Kipengele cha kusambaza mtandao hakina intaneti"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"Imeshindwa kuunganisha vifaa"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Zima kipengele cha kusambaza mtandao"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Umewasha kipengele cha kusambaza mtandao au mtandao pepe"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Huenda ukatozwa gharama za ziada ukitumia mitandao ya ng\'ambo"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-ta/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-ta/strings.xml
deleted file mode 100644
index f4b15aa..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-ta/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"இணைப்பு முறைக்கு இணைய இணைப்பு இல்லை"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"சாதனங்களால் இணைய முடியவில்லை"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"இணைப்பு முறையை ஆஃப் செய்"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"ஹாட்ஸ்பாட் அல்லது இணைப்பு முறை ஆன் செய்யப்பட்டுள்ளது"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"ரோமிங்கின்போது கூடுதல் கட்டணங்கள் விதிக்கப்படக்கூடும்"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-te/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-te/strings.xml
deleted file mode 100644
index 937d34d..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-te/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"టెథరింగ్ చేయడానికి ఇంటర్నెట్ కనెక్షన్ లేదు"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"పరికరాలు కనెక్ట్ అవ్వడం లేదు"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"టెథరింగ్ను ఆఫ్ చేయండి"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"హాట్స్పాట్ లేదా టెథరింగ్ ఆన్లో ఉంది"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"రోమింగ్లో ఉన్నప్పుడు అదనపు ఛార్జీలు వర్తించవచ్చు"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-th/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-th/strings.xml
deleted file mode 100644
index f781fae..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-th/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"การเชื่อมต่ออินเทอร์เน็ตผ่านมือถือไม่มีอินเทอร์เน็ต"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"อุปกรณ์เชื่อมต่อไม่ได้"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"ปิดการเชื่อมต่ออินเทอร์เน็ตผ่านมือถือ"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"ฮอตสปอตหรือการเชื่อมต่ออินเทอร์เน็ตผ่านมือถือเปิดอยู่"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"อาจมีค่าใช้จ่ายเพิ่มเติมขณะโรมมิ่ง"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-tl/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-tl/strings.xml
deleted file mode 100644
index 8d5d4653..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-tl/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"Walang internet ang pag-tether"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"Hindi makakonekta ang mga device"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"I-off ang pag-tether"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Naka-on ang Hotspot o pag-tether"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Posibleng magkaroon ng mga karagdagang singil habang nagro-roam"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-tr/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-tr/strings.xml
deleted file mode 100644
index 80cab33..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-tr/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"Tethering\'in internet bağlantısı yok"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"Cihazlar bağlanamıyor"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Tethering\'i kapat"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Hotspot veya tethering açık"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Dolaşım sırasında ek ücretler uygulanabilir"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-uk/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-uk/strings.xml
deleted file mode 100644
index c05932a..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-uk/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"Телефон, який використовується як модем, не підключений до Інтернету"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"Не вдається підключити пристрої"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Вимкнути використання телефона як модема"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Увімкнено точку доступу або використання телефона як модема"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"У роумінгу може стягуватися додаткова плата"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-ur/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-ur/strings.xml
deleted file mode 100644
index d820eee..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-ur/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"ٹیدرنگ میں انٹرنیٹ نہیں ہے"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"آلات منسلک نہیں ہو سکتے"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"ٹیدرنگ آف کریں"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"ہاٹ اسپاٹ یا ٹیدرنگ آن ہے"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"رومنگ کے دوران اضافی چارجز لاگو ہو سکتے ہیں"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-uz/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-uz/strings.xml
deleted file mode 100644
index 726148a..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-uz/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"Modem internetga ulanmagan"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"Qurilmalar ulanmadi"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Modem rejimini faolsizlantirish"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Hotspot yoki modem rejimi yoniq"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Rouming vaqtida qoʻshimcha haq olinishi mumkin"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-vi/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-vi/strings.xml
deleted file mode 100644
index b7cb045..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-vi/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"Không có Internet để chia sẻ kết Internet"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"Các thiết bị không thể kết nối"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Tắt tính năng chia sẻ Internet"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"Điểm phát sóng hoặc tính năng chia sẻ Internet đang bật"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Bạn có thể mất thêm phí dữ liệu khi chuyển vùng"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-zh-rCN/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-zh-rCN/strings.xml
deleted file mode 100644
index af91aff..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-zh-rCN/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"共享网络未连接到互联网"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"设备无法连接"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"关闭网络共享"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"热点或网络共享已开启"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"漫游时可能会产生额外的费用"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-zh-rHK/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-zh-rHK/strings.xml
deleted file mode 100644
index 28e6b80..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-zh-rHK/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"無法透過網絡共享連線至互聯網"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"裝置無法連接"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"關閉網絡共享"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"熱點或網絡共享已開啟"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"漫遊時可能需要支付額外費用"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-zh-rTW/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-zh-rTW/strings.xml
deleted file mode 100644
index 528a1e5..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-zh-rTW/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"無法透過網路共用連上網際網路"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"裝置無法連線"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"關閉網路共用"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"無線基地台或網路共用已開啟"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"使用漫遊服務可能須支付額外費用"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-zu/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-zu/strings.xml
deleted file mode 100644
index 11eb666..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004-zu/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"Ukusebenzisa ifoni njengemodemu akunayo i-inthanethi"</string>
- <string name="no_upstream_notification_message" msgid="3843613362272973447">"Amadivayisi awakwazi ukuxhumeka"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"Vala ukusebenzisa ifoni njengemodemu"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"I-hotspot noma ukusebenzisa ifoni njengemodemu kuvuliwe"</string>
- <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"Kungaba nezinkokhelo ezengeziwe uma uzula"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004/config.xml b/packages/Tethering/res/values-mcc310-mnc004/config.xml
deleted file mode 100644
index 5c5be04..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004/config.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-<resources>
- <!-- Delay(millisecond) to show no upstream notification after there's no Backhaul. Set delay to
- "0" for disable this feature. -->
- <integer name="delay_to_show_no_upstream_after_no_backhaul">5000</integer>
-
- <!-- Config for showing upstream roaming notification. -->
- <bool name="config_upstream_roaming_notification">true</bool>
-</resources>
\ No newline at end of file
diff --git a/packages/Tethering/res/values-mcc310-mnc004/strings.xml b/packages/Tethering/res/values-mcc310-mnc004/strings.xml
deleted file mode 100644
index ce9ff60..0000000
--- a/packages/Tethering/res/values-mcc310-mnc004/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-<resources>
- <!-- String for no upstream notification title [CHAR LIMIT=200] -->
- <string name="no_upstream_notification_title">Tethering has no internet</string>
- <!-- String for no upstream notification title [CHAR LIMIT=200] -->
- <string name="no_upstream_notification_message">Devices can\u2019t connect</string>
- <!-- String for no upstream notification disable button [CHAR LIMIT=200] -->
- <string name="no_upstream_notification_disable_button">Turn off tethering</string>
-
- <!-- String for cellular roaming notification title [CHAR LIMIT=200] -->
- <string name="upstream_roaming_notification_title">Hotspot or tethering is on</string>
- <!-- String for cellular roaming notification message [CHAR LIMIT=500] -->
- <string name="upstream_roaming_notification_message">Additional charges may apply while roaming</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-af/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-af/strings.xml
deleted file mode 100644
index 9bfa531..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-af/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"Verbinding het nie internet nie"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"Toestelle kan nie koppel nie"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Skakel verbinding af"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Warmkol of verbinding is aan"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Bykomende heffings kan geld terwyl jy swerf"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-am/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-am/strings.xml
deleted file mode 100644
index 5949dfa..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-am/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"ማስተሳሰር ምንም በይነመረብ የለውም"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"መሣሪያዎችን ማገናኘት አይቻልም"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"ማስተሳሰርን አጥፋ"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"መገናኛ ነጥብ ወይም ማስተሳሰር በርቷል"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"በሚያንዣብብበት ጊዜ ተጨማሪ ክፍያዎች ተፈጻሚ ሊሆኑ ይችላሉ"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-ar/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-ar/strings.xml
deleted file mode 100644
index 8467f9b..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-ar/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"ما مِن اتصال بالإنترنت خلال التوصيل"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"تعذّر اتصال الأجهزة"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"إيقاف التوصيل"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"نقطة الاتصال أو التوصيل مفعّلان"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"قد يتم تطبيق رسوم إضافية أثناء التجوال."</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-as/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-as/strings.xml
deleted file mode 100644
index 9776bd8..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-as/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"টে\'ডাৰিঙৰ ইণ্টাৰনেট নাই"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"ডিভাইচসমূহ সংযোগ কৰিব নোৱাৰি"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"টে\'ডাৰিং অফ কৰক"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"হটস্পট অথবা টে\'ডাৰিং অন আছে"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"ৰ\'মিঙত থাকিলে অতিৰিক্ত মাচুল প্ৰযোজ্য হ’ব পাৰে"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-az/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-az/strings.xml
deleted file mode 100644
index e6d3eaf..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-az/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"Modemin internetə girişi yoxdur"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"Cihazları qoşmaq mümkün deyil"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Modemi deaktiv edin"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Hotspot və ya modem aktivdir"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Rouminq zamanı əlavə ödənişlər tətbiq edilə bilər"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-b+sr+Latn/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-b+sr+Latn/strings.xml
deleted file mode 100644
index 4c8a1df..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-b+sr+Latn/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"Privezivanje nema pristup internetu"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"Povezivanje uređaja nije uspelo"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Isključi privezivanje"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Uključen je hotspot ili privezivanje"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Možda važe dodatni troškovi u romingu"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-be/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-be/strings.xml
deleted file mode 100644
index edfa41e..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-be/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"Рэжым мадэма выкарыстоўваецца без доступу да інтэрнэту"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"Не ўдалося падключыць прылады"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Выключыць рэжым мадэма"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Хот-спот або рэжым мадэма ўключаны"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Пры выкарыстанні роўмінгу можа спаганяцца дадатковая плата"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-bg/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-bg/strings.xml
deleted file mode 100644
index f563981..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-bg/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"Тетърингът няма връзка с интернет"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"Устройствата не могат да установят връзка"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Изключване на тетъринга"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Точката за достъп или тетърингът са включени"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Възможно е да ви бъдат начислени допълнителни такси при роуминг"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-bn/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-bn/strings.xml
deleted file mode 100644
index d8ecd2e..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-bn/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"টিথারিং করার জন্য কোনও ইন্টারনেট কানেকশন নেই"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"ডিভাইস কানেক্ট করতে পারছে না"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"টিথারিং বন্ধ করুন"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"হটস্পট বা টিথারিং চালু আছে"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"রোমিংয়ের সময় অতিরিক্ত চার্জ করা হতে পারে"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-bs/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-bs/strings.xml
deleted file mode 100644
index b85fd5e..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-bs/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"Povezivanje putem mobitela nema internet"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"Uređaji se ne mogu povezati"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Isključi povezivanje putem mobitela"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Pristupna tačka ili povezivanje putem mobitela je uključeno"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Mogu nastati dodatni troškovi u romingu"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-ca/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-ca/strings.xml
deleted file mode 100644
index a357215..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-ca/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"La compartició de xarxa no té accés a Internet"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"No es poden connectar els dispositius"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Desactiva la compartició de xarxa"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"S\'ha activat el punt d\'accés Wi‑Fi o la compartició de xarxa"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"És possible que s\'apliquin costos addicionals en itinerància"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-cs/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-cs/strings.xml
deleted file mode 100644
index 91196be..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-cs/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"Tethering nemá připojení k internetu"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"Zařízení se nemůžou připojit"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Vypnout tethering"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Je zapnutý hotspot nebo tethering"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Při roamingu mohou být účtovány dodatečné poplatky"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-da/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-da/strings.xml
deleted file mode 100644
index 1968900..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-da/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"Netdeling har ingen internetforbindelse"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"Enheder kan ikke oprette forbindelse"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Deaktiver netdeling"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Hotspot eller netdeling er aktiveret"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Der opkræves muligvis yderligere gebyrer ved roaming"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-de/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-de/strings.xml
deleted file mode 100644
index eb3f8c5..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-de/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"Tethering hat keinen Internetzugriff"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"Geräte können sich nicht verbinden"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Tethering deaktivieren"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Hotspot oder Tethering ist aktiviert"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Für das Roaming können zusätzliche Gebühren anfallen"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-el/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-el/strings.xml
deleted file mode 100644
index 56c3d81..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-el/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"Η σύνδεση δεν έχει πρόσβαση στο διαδίκτυο"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"Δεν είναι δυνατή η σύνδεση των συσκευών"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Απενεργοποιήστε τη σύνδεση"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Ενεργό σημείο πρόσβασης Wi-Fi ή ενεργή σύνδεση"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Ενδέχεται να ισχύουν επιπλέον χρεώσεις κατά την περιαγωγή."</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-en-rAU/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-en-rAU/strings.xml
deleted file mode 100644
index dd1a197..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-en-rAU/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"Tethering has no Internet"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"Devices can’t connect"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Turn off tethering"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Hotspot or tethering is on"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Additional charges may apply while roaming"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-en-rCA/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-en-rCA/strings.xml
deleted file mode 100644
index dd1a197..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-en-rCA/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"Tethering has no Internet"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"Devices can’t connect"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Turn off tethering"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Hotspot or tethering is on"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Additional charges may apply while roaming"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-en-rGB/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-en-rGB/strings.xml
deleted file mode 100644
index dd1a197..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-en-rGB/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"Tethering has no Internet"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"Devices can’t connect"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Turn off tethering"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Hotspot or tethering is on"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Additional charges may apply while roaming"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-en-rIN/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-en-rIN/strings.xml
deleted file mode 100644
index dd1a197..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-en-rIN/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"Tethering has no Internet"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"Devices can’t connect"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Turn off tethering"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Hotspot or tethering is on"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Additional charges may apply while roaming"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-en-rXC/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-en-rXC/strings.xml
deleted file mode 100644
index d3347aa..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-en-rXC/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"Tethering has no internet"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"Devices can’t connect"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Turn off tethering"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Hotspot or tethering is on"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Additional charges may apply while roaming"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-es-rUS/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-es-rUS/strings.xml
deleted file mode 100644
index 2f0504f..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-es-rUS/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"La conexión mediante dispositivo móvil no tiene Internet"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"No se pueden conectar los dispositivos"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Desactivar conexión mediante dispositivo móvil"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Se activó el hotspot o la conexión mediante dispositivo móvil"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Es posible que se apliquen cargos adicionales por roaming"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-es/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-es/strings.xml
deleted file mode 100644
index 2d8f882..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-es/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"La conexión no se puede compartir, porque no hay acceso a Internet"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"Los dispositivos no se pueden conectar"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Desactivar conexión compartida"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Punto de acceso o conexión compartida activados"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Puede que se apliquen cargos adicionales en itinerancia"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-et/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-et/strings.xml
deleted file mode 100644
index 8493c470..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-et/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"Jagamisel puudub internetiühendus"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"Seadmed ei saa ühendust luua"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Lülita jagamine välja"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Kuumkoht või jagamine on sisse lülitatud"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Rändluse kasutamisega võivad kaasneda lisatasud"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-eu/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-eu/strings.xml
deleted file mode 100644
index 33bccab..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-eu/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"Konexioa partekatzeko aukerak ez du Interneteko konexiorik"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"Ezin dira konektatu gailuak"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Desaktibatu konexioa partekatzeko aukera"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Wifi-gunea edo konexioa partekatzeko aukera aktibatuta dago"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Baliteke kostu gehigarriak ordaindu behar izatea ibiltaritzan"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-fa/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-fa/strings.xml
deleted file mode 100644
index cf8a0cc..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-fa/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"«اشتراکگذاری اینترنت» به اینترنت دسترسی ندارد"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"دستگاهها متصل نمیشوند"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"خاموش کردن «اشتراکگذاری اینترنت»"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"«نقطه اتصال» یا «اشتراکگذاری اینترنت» روشن است"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"ممکن است درحین فراگردی تغییرات دیگر اعمال شود"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-fi/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-fi/strings.xml
deleted file mode 100644
index 6a3ab80..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-fi/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"Ei jaettavaa internetyhteyttä"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"Laitteet eivät voi muodostaa yhteyttä"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Laita yhteyden jakaminen pois päältä"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Hotspot tai yhteyden jakaminen on päällä"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Roaming voi aiheuttaa lisämaksuja"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-fr-rCA/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-fr-rCA/strings.xml
deleted file mode 100644
index ffb9bf60..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-fr-rCA/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"Le partage de connexion n\'est pas connecté à Internet"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"Impossible de connecter les appareils"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Désactiver le partage de connexion"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Le point d\'accès ou le partage de connexion est activé"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"En itinérance, des frais supplémentaires peuvent s\'appliquer"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-fr/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-fr/strings.xml
deleted file mode 100644
index 768bce3..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-fr/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"Aucune connexion à Internet n\'est disponible pour le partage de connexion"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"Impossible de connecter les appareils"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Désactiver le partage de connexion"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Le point d\'accès ou le partage de connexion est activé"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"En itinérance, des frais supplémentaires peuvent s\'appliquer"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-gl/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-gl/strings.xml
deleted file mode 100644
index 0c4195a..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-gl/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"A conexión compartida non ten Internet"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"Non se puideron conectar os dispositivos"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Desactivar conexión compartida"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Está activada a zona wifi ou a conexión compartida"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Pódense aplicar cargos adicionais en itinerancia"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-gu/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-gu/strings.xml
deleted file mode 100644
index e9d33a7..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-gu/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"ઇન્ટરનેટ શેર કરવાની સુવિધામાં ઇન્ટરનેટ નથી"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"ડિવાઇસ કનેક્ટ કરી શકાતા નથી"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"ઇન્ટરનેટ શેર કરવાની સુવિધા બંધ કરો"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"હૉટસ્પૉટ અથવા ઇન્ટરનેટ શેર કરવાની સુવિધા ચાલુ છે"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"રોમિંગમાં વધારાના શુલ્ક લાગી શકે છે"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-hi/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-hi/strings.xml
deleted file mode 100644
index aa418ac..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-hi/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"टेदरिंग से इंटरनेट नहीं चल रहा"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"डिवाइस कनेक्ट नहीं हो पा रहे"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"टेदरिंग बंद करें"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"हॉटस्पॉट या टेदरिंग चालू है"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"रोमिंग के दौरान अतिरिक्त शुल्क लग सकता है"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-hr/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-hr/strings.xml
deleted file mode 100644
index 51c524a..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-hr/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"Modemsko povezivanje nema internet"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"Uređaji se ne mogu povezati"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Isključivanje modemskog povezivanja"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Uključena je žarišna točka ili modemsko povezivanje"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"U roamingu su mogući dodatni troškovi"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-hu/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-hu/strings.xml
deleted file mode 100644
index 164e45e..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-hu/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"Nincs internetkapcsolat az internet megosztásához"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"Az eszközök nem tudnak csatlakozni"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Internetmegosztás kikapcsolása"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"A hotspot vagy az internetmegosztás be van kapcsolva"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Roaming során további díjak léphetnek fel"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-hy/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-hy/strings.xml
deleted file mode 100644
index e76c0a4..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-hy/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"Մոդեմի ռեժիմի կապը բացակայում է"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"Չհաջողվեց միացնել սարքը"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Անջատել մոդեմի ռեժիմը"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Թեժ կետը կամ մոդեմի ռեժիմը միացված է"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Ռոումինգում կարող են լրացուցիչ վճարներ գանձվել"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-in/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-in/strings.xml
deleted file mode 100644
index 2b817f8..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-in/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"Tidak ada koneksi internet di tethering"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"Perangkat tidak dapat terhubung"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Nonaktifkan tethering"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Hotspot atau tethering aktif"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Biaya tambahan mungkin berlaku saat roaming"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-is/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-is/strings.xml
deleted file mode 100644
index a338d9c..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-is/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"Tjóðrun er ekki með internettengingu"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"Tæki geta ekki tengst"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Slökkva á tjóðrun"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Kveikt er á heitum reit eða tjóðrun"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Viðbótargjöld kunna að eiga við í reiki"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-it/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-it/strings.xml
deleted file mode 100644
index 77769c2..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-it/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"Nessuna connessione a Internet per il tethering"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"Impossibile connettere i dispositivi"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Disattiva il tethering"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Hotspot o tethering attivi"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Potrebbero essere applicati costi aggiuntivi durante il roaming"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-iw/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-iw/strings.xml
deleted file mode 100644
index 5267b51..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-iw/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"אי אפשר להפעיל את תכונת שיתוף האינטרנט בין מכשירים כי אין חיבור לאינטרנט"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"למכשירים אין אפשרות להתחבר"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"השבתה של שיתוף האינטרנט בין מכשירים"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"תכונת הנקודה לשיתוף אינטרנט או תכונת שיתוף האינטרנט בין מכשירים פועלת"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"ייתכנו חיובים נוספים בעת נדידה"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-ja/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-ja/strings.xml
deleted file mode 100644
index 66a9a6d..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-ja/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"テザリングがインターネットに接続されていません"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"デバイスを接続できません"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"テザリングを OFF にする"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"アクセス ポイントまたはテザリングが ON です"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"ローミング時に追加料金が発生することがあります"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-ka/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-ka/strings.xml
deleted file mode 100644
index d8ad880..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-ka/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"ტეტერინგს არ აქვს ინტერნეტზე წვდომა"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"მოწყობილობები ვერ ახერხებენ დაკავშირებას"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"ტეტერინგის გამორთვა"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"ჩართულია უსადენო ქსელი ან ტეტერინგი"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"როუმინგის გამოყენებისას შეიძლება ჩამოგეჭრათ დამატებითი საფასური"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-kk/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-kk/strings.xml
deleted file mode 100644
index 1ddd6b4..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-kk/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"Тетеринг режимі интернет байланысынсыз пайдаланылуда"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"Құрылғыларды байланыстыру мүмкін емес"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Тетерингіні өшіру"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Хотспот немесе тетеринг қосулы"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Роуминг кезінде қосымша ақы алынуы мүмкін."</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-km/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-km/strings.xml
deleted file mode 100644
index cf5a137..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-km/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"ការភ្ជាប់មិនមានអ៊ីនធឺណិតទេ"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"មិនអាចភ្ជាប់ឧបករណ៍បានទេ"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"បិទការភ្ជាប់"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"ហតស្ប៉ត ឬការភ្ជាប់ត្រូវបានបើក"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"អាចមានការគិតថ្លៃបន្ថែម នៅពេលរ៉ូមីង"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-kn/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-kn/strings.xml
deleted file mode 100644
index 68ae68b..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-kn/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"ಟೆಥರಿಂಗ್ ಯಾವುದೇ ಇಂಟರ್ನೆಟ್ ಕನೆಕ್ಷನ್ ಹೊಂದಿಲ್ಲ"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"ಸಾಧನಗಳನ್ನು ಕನೆಕ್ಟ್ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"ಟೆಥರಿಂಗ್ ಆಫ್ ಮಾಡಿ"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"ಹಾಟ್ಸ್ಪಾಟ್ ಅಥವಾ ಟೆಥರಿಂಗ್ ಆನ್ ಆಗಿದೆ"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"ರೋಮಿಂಗ್ನಲ್ಲಿರುವಾಗ ಹೆಚ್ಚುವರಿ ಶುಲ್ಕಗಳು ಅನ್ವಯವಾಗಬಹುದು"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-ko/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-ko/strings.xml
deleted file mode 100644
index 17185ba..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-ko/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"테더링으로 인터넷을 사용할 수 없음"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"기기에서 연결할 수 없음"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"테더링 사용 중지"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"핫스팟 또는 테더링 켜짐"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"로밍 중에는 추가 요금이 발생할 수 있습니다."</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-ky/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-ky/strings.xml
deleted file mode 100644
index 6a9fb98..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-ky/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"Модем режими Интернети жок колдонулууда"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"Түзмөктөр туташпай жатат"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Модем режимин өчүрүү"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Байланыш түйүнү же модем режими күйүк"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Роумингде кошумча акы алынышы мүмкүн"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-lo/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-lo/strings.xml
deleted file mode 100644
index bcc4b57..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-lo/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"ການປ່ອຍສັນຍານບໍ່ມີອິນເຕີເນັດ"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"ອຸປະກອນບໍ່ສາມາດເຊື່ອມຕໍ່ໄດ້"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"ປິດການປ່ອຍສັນຍານ"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"ເປີດໃຊ້ຮັອດສະປອດ ຫຼື ການປ່ອຍສັນຍານຢູ່"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"ອາດມີຄ່າໃຊ້ຈ່າຍເພີ່ມເຕີມໃນລະຫວ່າງການໂຣມມິງ"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-lt/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-lt/strings.xml
deleted file mode 100644
index 011c2c1..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-lt/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"Nėra įrenginio kaip modemo naudojimo interneto ryšio"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"Nepavyko susieti įrenginių"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Išjungti įrenginio kaip modemo naudojimą"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Įjungtas viešosios interneto prieigos taškas arba įrenginio kaip modemo naudojimas"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Veikiant tarptinkliniam ryšiui gali būti taikomi papildomi mokesčiai"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-lv/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-lv/strings.xml
deleted file mode 100644
index 5cb2f3b..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-lv/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"Piesaistei nav interneta savienojuma"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"Nevar savienot ierīces"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Izslēgt piesaisti"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Ir ieslēgts tīklājs vai piesaiste"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Viesabonēšanas laikā var tikt piemērota papildu samaksa"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-mk/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-mk/strings.xml
deleted file mode 100644
index 4cbfd88..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-mk/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"Нема интернет преку мобилен"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"Уредите не може да се поврзат"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Исклучи интернет преку мобилен"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Точката на пристап или интернетот преку мобилен е вклучен"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"При роаминг може да се наплатат дополнителни трошоци"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-ml/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-ml/strings.xml
deleted file mode 100644
index 9cf4eaf..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-ml/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"ടെതറിംഗിന് ഇന്റർനെറ്റ് ഇല്ല"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"ഉപകരണങ്ങൾ കണക്റ്റ് ചെയ്യാനാവില്ല"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"ടെതറിംഗ് ഓഫാക്കുക"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"ഹോട്ട്സ്പോട്ട് അല്ലെങ്കിൽ ടെതറിംഗ് ഓണാണ്"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"റോമിംഗ് ചെയ്യുമ്പോൾ അധിക നിരക്കുകൾ ബാധകമായേക്കാം"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-mn/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-mn/strings.xml
deleted file mode 100644
index 47c82c1..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-mn/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"Модемд интернэт алга байна"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"Төхөөрөмжүүд холбогдох боломжгүй байна"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Модем болгохыг унтраах"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Сүлжээний цэг эсвэл модем болгох асаалттай байна"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Роумингийн үеэр нэмэлт төлбөр нэхэмжилж болзошгүй"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-mr/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-mr/strings.xml
deleted file mode 100644
index ad9e809..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-mr/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"टेदरिंगला इंटरनेट नाही"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"डिव्हाइस कनेक्ट होऊ शकत नाहीत"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"टेदरिंग बंद करा"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"हॉटस्पॉट किंवा टेदरिंग सुरू आहे"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"रोमिंगदरम्यान अतिरिक्त शुल्क लागू होऊ शकतात"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-ms/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-ms/strings.xml
deleted file mode 100644
index e708cb8..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-ms/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"Penambatan tiada Internet"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"Peranti tidak dapat disambungkan"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Matikan penambatan"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Tempat liputan atau penambatan dihidupkan"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Caj tambahan mungkin digunakan semasa perayauan"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-my/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-my/strings.xml
deleted file mode 100644
index ba54622..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-my/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"မိုဘိုင်းဖုန်းသုံး ချိတ်ဆက်မျှဝေခြင်းတွင် အင်တာနက် မရှိပါ"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"စက်များ ချိတ်ဆက်၍ မရပါ"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"မိုဘိုင်းဖုန်းသုံး ချိတ်ဆက်မျှဝေခြင်း ပိတ်ရန်"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"ဟော့စပေါ့ (သို့) မိုဘိုင်းဖုန်းသုံး ချိတ်ဆက်မျှဝေခြင်း ဖွင့်ထားသည်"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"ပြင်ပကွန်ရက်နှင့် ချိတ်ဆက်သည့်အခါ နောက်ထပ်ကျသင့်မှုများ ရှိနိုင်သည်"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-nb/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-nb/strings.xml
deleted file mode 100644
index 57db484a2..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-nb/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"Internettdeling har ikke internettilgang"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"Enhetene kan ikke koble til"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Slå av internettdeling"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Wi-Fi-sone eller internettdeling er på"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Ytterligere kostnader kan påløpe under roaming"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-ne/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-ne/strings.xml
deleted file mode 100644
index 1503244..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-ne/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"टेदरिङमार्फत इन्टरनेट कनेक्सन प्राप्त हुन सकेन"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"यन्त्रहरू कनेक्ट गर्न सकिएन"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"टेदरिङ निष्क्रिय पार्नुहोस्"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"हटस्पट वा टेदरिङ सक्रिय छ"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"रोमिङ सेवा प्रयोग गर्दा अतिरिक्त शुल्क लाग्न सक्छ"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-nl/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-nl/strings.xml
deleted file mode 100644
index b08133f..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-nl/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"Tethering heeft geen internet"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"Apparaten kunnen niet worden verbonden"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Tethering uitschakelen"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Hotspot of tethering is ingeschakeld"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Er kunnen extra kosten voor roaming in rekening worden gebracht."</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-or/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-or/strings.xml
deleted file mode 100644
index 1ad4ca3..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-or/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"ଟିଥରିଂ ପାଇଁ କୌଣସି ଇଣ୍ଟର୍ନେଟ୍ ସଂଯୋଗ ନାହିଁ"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"ଡିଭାଇସଗୁଡ଼ିକ ସଂଯୋଗ କରାଯାଇପାରିବ ନାହିଁ"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"ଟିଥରିଂ ବନ୍ଦ କରନ୍ତୁ"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"ହଟସ୍ପଟ୍ କିମ୍ବା ଟିଥରିଂ ଚାଲୁ ଅଛି"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"ରୋମିଂରେ ଥିବା ସମୟରେ ଅତିରିକ୍ତ ଶୁଳ୍କ ଲାଗୁ ହୋଇପାରେ"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-pa/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-pa/strings.xml
deleted file mode 100644
index 88def56..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-pa/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"ਟੈਦਰਿੰਗ ਕੋਲ ਇੰਟਰਨੈੱਟ ਪਹੁੰਚ ਨਹੀਂ ਹੈ"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"ਡੀਵਾਈਸ ਕਨੈਕਟ ਨਹੀਂ ਕੀਤੇ ਜਾ ਸਕਦੇ"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"ਟੈਦਰਿੰਗ ਬੰਦ ਕਰੋ"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"ਹੌਟਸਪੌਟ ਜਾਂ ਟੈਦਰਿੰਗ ਚਾਲੂ ਹੈ"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"ਰੋਮਿੰਗ ਦੌਰਾਨ ਵਧੀਕ ਖਰਚੇ ਲਾਗੂ ਹੋ ਸਕਦੇ ਹਨ"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-pl/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-pl/strings.xml
deleted file mode 100644
index f9890ab..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-pl/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"Tethering nie ma internetu"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"Urządzenia nie mogą się połączyć"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Wyłącz tethering"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Hotspot lub tethering jest włączony"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Podczas korzystania z roamingu mogą zostać naliczone dodatkowe opłaty"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-pt-rBR/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-pt-rBR/strings.xml
deleted file mode 100644
index ce3b884..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-pt-rBR/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"O tethering não tem Internet"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"Não é possível conectar os dispositivos"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Desativar o tethering"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Ponto de acesso ou tethering ativado"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Pode haver cobranças extras durante o roaming"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-pt-rPT/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-pt-rPT/strings.xml
deleted file mode 100644
index 7e883ea..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-pt-rPT/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"A ligação (à Internet) via telemóvel não tem Internet"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"Não é possível ligar os dispositivos"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Desativar ligação (à Internet) via telemóvel"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"A zona Wi-Fi ou a ligação (à Internet) via telemóvel está ativada"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Podem aplicar-se custos adicionais em roaming."</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-pt/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-pt/strings.xml
deleted file mode 100644
index ce3b884..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-pt/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"O tethering não tem Internet"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"Não é possível conectar os dispositivos"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Desativar o tethering"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Ponto de acesso ou tethering ativado"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Pode haver cobranças extras durante o roaming"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-ro/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-ro/strings.xml
deleted file mode 100644
index 1009417..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-ro/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"Procesul de tethering nu are internet"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"Dispozitivele nu se pot conecta"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Dezactivați procesul de tethering"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"S-a activat hotspotul sau tethering"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Se pot aplica taxe suplimentare pentru roaming"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-ru/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-ru/strings.xml
deleted file mode 100644
index 88683be..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-ru/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"Режим модема используется без доступа к Интернету"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"Невозможно подключить устройства."</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Отключить режим модема"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Включены точка доступа или режим модема"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"За использование услуг связи в роуминге может взиматься дополнительная плата."</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-si/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-si/strings.xml
deleted file mode 100644
index 176bcdb..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-si/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"ටෙදරින් හට අන්තර්ජාලය නැත"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"උපාංගවලට සම්බන්ධ විය නොහැකිය"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"ටෙදරින් ක්රියාවිරහිත කරන්න"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"හොට්ස්පොට් හෝ ටෙදරින් ක්රියාත්මකයි"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"රෝමිං අතරතුර අමතර ගාස්තු අදාළ විය හැකිය"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-sk/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-sk/strings.xml
deleted file mode 100644
index b9e2127..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-sk/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"Tethering nemá internetové pripojenie"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"Zariadenia sa nemôžu pripojiť"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Vypnúť tethering"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Je zapnutý hotspot alebo tethering"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Počas roamingu vám môžu byť účtované ďalšie poplatky"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-sl/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-sl/strings.xml
deleted file mode 100644
index e8140e6..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-sl/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"Internetna povezava prek mobilnega telefona ni vzpostavljena"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"Napravi se ne moreta povezati"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Izklopi internetno povezavo prek mobilnega telefona"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Dostopna točka ali internetna povezava prek mobilnega telefona je vklopljena"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Med gostovanjem lahko nastanejo dodatni stroški"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-sq/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-sq/strings.xml
deleted file mode 100644
index 61e698d..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-sq/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"Ndarja e internetit nuk ka internet"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"Pajisjet nuk mund të lidhen"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Çaktivizo ndarjen e internetit"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Zona e qasjes për internet ose ndarja e internetit është aktive"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Mund të zbatohen tarifime shtesë kur je në roaming"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-sr/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-sr/strings.xml
deleted file mode 100644
index b4c411c..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-sr/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"Привезивање нема приступ интернету"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"Повезивање уређаја није успело"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Искључи привезивање"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Укључен је хотспот или привезивање"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Можда важе додатни трошкови у ромингу"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-sv/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-sv/strings.xml
deleted file mode 100644
index 4f543e4..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-sv/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"Det finns ingen internetanslutning för internetdelningen"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"Enheterna kan inte anslutas"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Inaktivera internetdelning"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Surfzon eller internetdelning har aktiverats"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Ytterligare avgifter kan tillkomma vid roaming"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-sw/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-sw/strings.xml
deleted file mode 100644
index ac347ab..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-sw/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"Kipengele cha kusambaza mtandao hakina intaneti"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"Imeshindwa kuunganisha vifaa"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Zima kipengele cha kusambaza mtandao"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Umewasha kipengele cha kusambaza mtandao au mtandao pepe"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Huenda ukatozwa gharama za ziada ukitumia mitandao ya ng\'ambo"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-ta/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-ta/strings.xml
deleted file mode 100644
index 2ea2467..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-ta/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"இணைப்பு முறைக்கு இணைய இணைப்பு இல்லை"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"சாதனங்களால் இணைய முடியவில்லை"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"இணைப்பு முறையை ஆஃப் செய்"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"ஹாட்ஸ்பாட் அல்லது இணைப்பு முறை ஆன் செய்யப்பட்டுள்ளது"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"ரோமிங்கின்போது கூடுதல் கட்டணங்கள் விதிக்கப்படக்கூடும்"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-te/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-te/strings.xml
deleted file mode 100644
index 9360297..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-te/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"టెథరింగ్ చేయడానికి ఇంటర్నెట్ కనెక్షన్ లేదు"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"పరికరాలు కనెక్ట్ అవ్వడం లేదు"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"టెథరింగ్ను ఆఫ్ చేయండి"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"హాట్స్పాట్ లేదా టెథరింగ్ ఆన్లో ఉంది"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"రోమింగ్లో ఉన్నప్పుడు అదనపు ఛార్జీలు వర్తించవచ్చు"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-th/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-th/strings.xml
deleted file mode 100644
index 9c4d7e0..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-th/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"การเชื่อมต่ออินเทอร์เน็ตผ่านมือถือไม่มีอินเทอร์เน็ต"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"อุปกรณ์เชื่อมต่อไม่ได้"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"ปิดการเชื่อมต่ออินเทอร์เน็ตผ่านมือถือ"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"ฮอตสปอตหรือการเชื่อมต่ออินเทอร์เน็ตผ่านมือถือเปิดอยู่"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"อาจมีค่าใช้จ่ายเพิ่มเติมขณะโรมมิ่ง"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-tl/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-tl/strings.xml
deleted file mode 100644
index a7c78a5..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-tl/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"Walang internet ang pag-tether"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"Hindi makakonekta ang mga device"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"I-off ang pag-tether"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Naka-on ang Hotspot o pag-tether"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Posibleng magkaroon ng mga karagdagang singil habang nagro-roam"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-tr/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-tr/strings.xml
deleted file mode 100644
index 93da2c3..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-tr/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"Tethering\'in internet bağlantısı yok"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"Cihazlar bağlanamıyor"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Tethering\'i kapat"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Hotspot veya tethering açık"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Dolaşım sırasında ek ücretler uygulanabilir"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-uk/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-uk/strings.xml
deleted file mode 100644
index ee0dcd2..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-uk/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"Телефон, який використовується як модем, не підключений до Інтернету"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"Не вдається підключити пристрої"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Вимкнути використання телефона як модема"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Увімкнено точку доступу або використання телефона як модема"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"У роумінгу може стягуватися додаткова плата"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-ur/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-ur/strings.xml
deleted file mode 100644
index 41cd28e..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-ur/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"ٹیدرنگ میں انٹرنیٹ نہیں ہے"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"آلات منسلک نہیں ہو سکتے"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"ٹیدرنگ آف کریں"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"ہاٹ اسپاٹ یا ٹیدرنگ آن ہے"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"رومنگ کے دوران اضافی چارجز لاگو ہو سکتے ہیں"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-uz/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-uz/strings.xml
deleted file mode 100644
index c847bc9..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-uz/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"Modem internetga ulanmagan"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"Qurilmalar ulanmadi"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Modem rejimini faolsizlantirish"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Hotspot yoki modem rejimi yoniq"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Rouming vaqtida qoʻshimcha haq olinishi mumkin"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-vi/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-vi/strings.xml
deleted file mode 100644
index a74326f..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-vi/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"Không có Internet để chia sẻ kết Internet"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"Các thiết bị không thể kết nối"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Tắt tính năng chia sẻ Internet"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"Điểm phát sóng hoặc tính năng chia sẻ Internet đang bật"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Bạn có thể mất thêm phí dữ liệu khi chuyển vùng"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-zh-rCN/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-zh-rCN/strings.xml
deleted file mode 100644
index d737003..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-zh-rCN/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"共享网络未连接到互联网"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"设备无法连接"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"关闭网络共享"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"热点或网络共享已开启"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"漫游时可能会产生额外的费用"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-zh-rHK/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-zh-rHK/strings.xml
deleted file mode 100644
index f378a9d..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-zh-rHK/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"無法透過網絡共享連線至互聯網"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"裝置無法連接"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"關閉網絡共享"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"熱點或網絡共享已開啟"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"漫遊時可能需要支付額外費用"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-zh-rTW/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-zh-rTW/strings.xml
deleted file mode 100644
index cd653df..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-zh-rTW/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"無法透過網路共用連上網際網路"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"裝置無法連線"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"關閉網路共用"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"無線基地台或網路共用已開啟"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"使用漫遊服務可能須支付額外費用"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-zu/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-zu/strings.xml
deleted file mode 100644
index 32f6df5..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480-zu/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"Ukusebenzisa ifoni njengemodemu akunayo i-inthanethi"</string>
- <string name="no_upstream_notification_message" msgid="6508394877641864863">"Amadivayisi awakwazi ukuxhumeka"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"Vala ukusebenzisa ifoni njengemodemu"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"I-hotspot noma ukusebenzisa ifoni njengemodemu kuvuliwe"</string>
- <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"Kungaba nezinkokhelo ezengeziwe uma uzula"</string>
-</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480/config.xml b/packages/Tethering/res/values-mcc311-mnc480/config.xml
deleted file mode 100644
index 5c5be04..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480/config.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-<resources>
- <!-- Delay(millisecond) to show no upstream notification after there's no Backhaul. Set delay to
- "0" for disable this feature. -->
- <integer name="delay_to_show_no_upstream_after_no_backhaul">5000</integer>
-
- <!-- Config for showing upstream roaming notification. -->
- <bool name="config_upstream_roaming_notification">true</bool>
-</resources>
\ No newline at end of file
diff --git a/packages/Tethering/res/values-mcc311-mnc480/strings.xml b/packages/Tethering/res/values-mcc311-mnc480/strings.xml
deleted file mode 100644
index ce9ff60..0000000
--- a/packages/Tethering/res/values-mcc311-mnc480/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-<resources>
- <!-- String for no upstream notification title [CHAR LIMIT=200] -->
- <string name="no_upstream_notification_title">Tethering has no internet</string>
- <!-- String for no upstream notification title [CHAR LIMIT=200] -->
- <string name="no_upstream_notification_message">Devices can\u2019t connect</string>
- <!-- String for no upstream notification disable button [CHAR LIMIT=200] -->
- <string name="no_upstream_notification_disable_button">Turn off tethering</string>
-
- <!-- String for cellular roaming notification title [CHAR LIMIT=200] -->
- <string name="upstream_roaming_notification_title">Hotspot or tethering is on</string>
- <!-- String for cellular roaming notification message [CHAR LIMIT=500] -->
- <string name="upstream_roaming_notification_message">Additional charges may apply while roaming</string>
-</resources>
diff --git a/packages/Tethering/res/values-mk/strings.xml b/packages/Tethering/res/values-mk/strings.xml
deleted file mode 100644
index 9ad9b9a..0000000
--- a/packages/Tethering/res/values-mk/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"Активно е врзување или точка на пристап"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"Допрете за поставување."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"Врзувањето е оневозможено"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"Контактирајте со администраторот за детали"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Статус на точката на пристап и врзувањето"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-ml/strings.xml b/packages/Tethering/res/values-ml/strings.xml
deleted file mode 100644
index 9db79ce..0000000
--- a/packages/Tethering/res/values-ml/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"ടെതറിംഗ് അല്ലെങ്കിൽ ഹോട്ട്സ്പോട്ട് സജീവമാണ്"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"സജ്ജീകരിക്കാൻ ടാപ്പ് ചെയ്യുക."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"ടെതറിംഗ് പ്രവർത്തനരഹിതമാക്കിയിരിക്കുന്നു"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"വിശദാംശങ്ങൾക്ക് നിങ്ങളുടെ അഡ്മിനെ ബന്ധപ്പെടുക"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"ഹോട്ട്സ്പോട്ടിന്റെയും ടെതറിംഗിന്റെയും നില"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-mn/strings.xml b/packages/Tethering/res/values-mn/strings.xml
deleted file mode 100644
index 42d1edb..0000000
--- a/packages/Tethering/res/values-mn/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"Модем болгох эсвэл сүлжээний цэг идэвхтэй байна"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"Тохируулахын тулд товшино уу."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"Модем болгохыг идэвхгүй болгосон"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"Дэлгэрэнгүй мэдээлэл авахын тулд админтайгаа холбогдоно уу"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Сүлжээний цэг болон модем болгох төлөв"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-mr/strings.xml b/packages/Tethering/res/values-mr/strings.xml
deleted file mode 100644
index 13995b6..0000000
--- a/packages/Tethering/res/values-mr/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"टेदरिंग किंवा हॉटस्पॉट अॅक्टिव्ह आहे"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"सेट करण्यासाठी टॅप करा."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"टेदरिंग बंद केले आहे"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"तपशीलांसाठी तुमच्या ॲडमिनशी संपर्क साधा"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"हॉटस्पॉट आणि टेदरिंगची स्थिती"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-ms/strings.xml b/packages/Tethering/res/values-ms/strings.xml
deleted file mode 100644
index d6a67f3..0000000
--- a/packages/Tethering/res/values-ms/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"Penambatan atau tempat liputan aktif"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"Ketik untuk membuat persediaan."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"Penambatan dilumpuhkan"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"Hubungi pentadbir anda untuk mendapatkan maklumat lanjut"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Status tempat liputan & penambatan"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-my/strings.xml b/packages/Tethering/res/values-my/strings.xml
deleted file mode 100644
index 49f6b88..0000000
--- a/packages/Tethering/res/values-my/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"မိုဘိုင်းဖုန်းသုံး ချိတ်ဆက်မျှဝေခြင်း သို့မဟုတ် ဟော့စပေါ့ ဖွင့်ထားသည်"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"စနစ်ထည့်သွင်းရန် တို့ပါ။"</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"မိုဘိုင်းဖုန်းသုံး ချိတ်ဆက်မျှဝေခြင်းကို ပိတ်ထားသည်"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"အသေးစိတ်အတွက် သင့်စီမံခန့်ခွဲသူကို ဆက်သွယ်ပါ"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"ဟော့စပေါ့နှင့် မိုဘိုင်းဖုန်းသုံး ချိတ်ဆက်မျှဝေခြင်း အခြေအနေ"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-nb/strings.xml b/packages/Tethering/res/values-nb/strings.xml
deleted file mode 100644
index 9594e0a..0000000
--- a/packages/Tethering/res/values-nb/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"Internettdeling eller Wi-Fi-sone er aktiv"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"Trykk for å konfigurere."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"Internettdeling er slått av"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"Ta kontakt med administratoren din for å få mer informasjon"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Status for Wi-Fi-sone og internettdeling"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-ne/strings.xml b/packages/Tethering/res/values-ne/strings.xml
deleted file mode 100644
index 72ae3a8..0000000
--- a/packages/Tethering/res/values-ne/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"टेदरिङ वा हटस्पट सक्रिय छ"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"सेटअप गर्न ट्याप गर्नुहोस्।"</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"टेदरिङ सुविधा असक्षम पारिएको छ"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"विवरणहरूका लागि आफ्ना प्रशासकलाई सम्पर्क गर्नुहोस्"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"हटस्पट तथा टेदरिङको स्थिति"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-nl/strings.xml b/packages/Tethering/res/values-nl/strings.xml
deleted file mode 100644
index 18b2bbf..0000000
--- a/packages/Tethering/res/values-nl/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"Tethering of hotspot actief"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"Tik om in te stellen."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"Tethering is uitgeschakeld"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"Neem contact op met je beheerder voor meer informatie"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Status van hotspot en tethering"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-or/strings.xml b/packages/Tethering/res/values-or/strings.xml
deleted file mode 100644
index a15a6db..0000000
--- a/packages/Tethering/res/values-or/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"ଟିଥେରିଂ କିମ୍ୱା ହଟସ୍ପଟ୍ ସକ୍ରିୟ ଅଛି"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"ସେଟ୍ ଅପ୍ କରିବାକୁ ଟାପ୍ କରନ୍ତୁ।"</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"ଟିଥେରିଂ ଅକ୍ଷମ କରାଯାଇଛି"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"ବିବରଣୀଗୁଡ଼ିକ ପାଇଁ ଆପଣଙ୍କ ଆଡମିନଙ୍କ ସହ ଯୋଗାଯୋଗ କରନ୍ତୁ"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"ହଟସ୍ପଟ୍ ଓ ଟିଥେରିଂ ସ୍ଥିତି"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-pa/strings.xml b/packages/Tethering/res/values-pa/strings.xml
deleted file mode 100644
index a8235e4..0000000
--- a/packages/Tethering/res/values-pa/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"ਟੈਦਰਿੰਗ ਜਾਂ ਹੌਟਸਪੌਟ ਕਿਰਿਆਸ਼ੀਲ"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"ਸੈੱਟਅੱਪ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ।"</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"ਟੈਦਰਿੰਗ ਨੂੰ ਬੰਦ ਕੀਤਾ ਗਿਆ ਹੈ"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"ਵੇਰਵਿਆਂ ਲਈ ਆਪਣੇ ਪ੍ਰਸ਼ਾਸਕ ਨਾਲ ਸੰਪਰਕ ਕਰੋ"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"ਹੌਟਸਪੌਟ ਅਤੇ ਟੈਦਰਿੰਗ ਦੀ ਸਥਿਤੀ"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-pl/strings.xml b/packages/Tethering/res/values-pl/strings.xml
deleted file mode 100644
index ccb017d..0000000
--- a/packages/Tethering/res/values-pl/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"Aktywny tethering lub punkt dostępu"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"Kliknij, by skonfigurować"</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"Tethering został wyłączony"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"Aby uzyskać szczegółowe informacje, skontaktuj się z administratorem"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Hotspot i tethering – stan"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-pt-rBR/strings.xml b/packages/Tethering/res/values-pt-rBR/strings.xml
deleted file mode 100644
index a0a4745..0000000
--- a/packages/Tethering/res/values-pt-rBR/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"Ponto de acesso ou tethering ativo"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"Toque para configurar."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"Tethering desativado"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"Fale com seu administrador para saber detalhes"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Status de ponto de acesso e tethering"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-pt-rPT/strings.xml b/packages/Tethering/res/values-pt-rPT/strings.xml
deleted file mode 100644
index e3f03fc..0000000
--- a/packages/Tethering/res/values-pt-rPT/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"Ligação (à Internet) via telemóvel ou zona Wi-Fi ativas"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"Toque para configurar."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"A ligação (à Internet) via telemóvel está desativada."</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"Contacte o administrador para obter detalhes."</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Estado da zona Wi-Fi e da ligação (à Internet) via telemóvel"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-pt/strings.xml b/packages/Tethering/res/values-pt/strings.xml
deleted file mode 100644
index a0a4745..0000000
--- a/packages/Tethering/res/values-pt/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"Ponto de acesso ou tethering ativo"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"Toque para configurar."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"Tethering desativado"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"Fale com seu administrador para saber detalhes"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Status de ponto de acesso e tethering"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-ro/strings.xml b/packages/Tethering/res/values-ro/strings.xml
deleted file mode 100644
index 5706a4a..0000000
--- a/packages/Tethering/res/values-ro/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"Tethering sau hotspot activ"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"Atingeți ca să configurați."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"Tetheringul este dezactivat"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"Contactați administratorul pentru detalii"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Starea hotspotului și a tetheringului"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-ru/strings.xml b/packages/Tethering/res/values-ru/strings.xml
deleted file mode 100644
index 7cb6f7d..0000000
--- a/packages/Tethering/res/values-ru/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"Включен режим модема или точка доступа"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"Нажмите, чтобы настроить."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"Использование телефона в качестве модема запрещено"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"Чтобы узнать подробности, обратитесь к администратору."</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Статус хот-спота и режима модема"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-si/strings.xml b/packages/Tethering/res/values-si/strings.xml
deleted file mode 100644
index ec34c22..0000000
--- a/packages/Tethering/res/values-si/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"ටෙදරින් හෝ හොට්ස්පොට් සක්රීයයි"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"පිහිටුවීමට තට්ටු කරන්න."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"ටෙදරින් අබල කර ඇත"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"විස්තර සඳහා ඔබගේ පරිපාලක අමතන්න"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"හොට්ස්පොට් & ටෙදරින් තත්ත්වය"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-sk/strings.xml b/packages/Tethering/res/values-sk/strings.xml
deleted file mode 100644
index 43e787c..0000000
--- a/packages/Tethering/res/values-sk/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"Tethering alebo prístupový bod je aktívny"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"Klepnutím prejdete na nastavenie."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"Tethering je deaktivovaný"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"O podrobnosti požiadajte svojho správcu"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Stav hotspotu a tetheringu"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-sl/strings.xml b/packages/Tethering/res/values-sl/strings.xml
deleted file mode 100644
index 5943362..0000000
--- a/packages/Tethering/res/values-sl/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"Povezava z internetom prek mobilnega telefona ali dostopna točka je aktivna"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"Dotaknite se, če želite nastaviti."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"Povezava z internetom prek mobilnega telefona je onemogočena"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"Za podrobnosti se obrnite na skrbnika"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Stanje dostopne točke in povezave z internetom prek mobilnega telefona"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-sq/strings.xml b/packages/Tethering/res/values-sq/strings.xml
deleted file mode 100644
index 21e1155..0000000
--- a/packages/Tethering/res/values-sq/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"Ndarja e internetit ose zona e qasjes së internetit është aktive"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"Trokit për ta konfiguruar."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"Ndarja e internetit është çaktivizuar"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"Kontakto me administratorin për detaje"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Statusi i zonës së qasjes dhe ndarjes së internetit"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-sr/strings.xml b/packages/Tethering/res/values-sr/strings.xml
deleted file mode 100644
index e2e4dc6..0000000
--- a/packages/Tethering/res/values-sr/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"Привезивање или хотспот је активан"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"Додирните да бисте подесили."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"Привезивање је онемогућено"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"Потражите детаље од администратора"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Статус хотспота и привезивања"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-sv/strings.xml b/packages/Tethering/res/values-sv/strings.xml
deleted file mode 100644
index 72702c2..0000000
--- a/packages/Tethering/res/values-sv/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"Internetdelning eller surfzon har aktiverats"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"Tryck om du vill konfigurera."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"Internetdelning har inaktiverats"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"Kontakta administratören om du vill veta mer"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Trådlös surfzon och internetdelning har inaktiverats"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-sw/strings.xml b/packages/Tethering/res/values-sw/strings.xml
deleted file mode 100644
index 65e4aa8ce..0000000
--- a/packages/Tethering/res/values-sw/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"Kusambaza mtandao au mtandaopepe umewashwa"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"Gusa ili uweke mipangilio."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"Umezima kipengele cha kusambaza mtandao"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"Wasiliana na msimamizi wako ili upate maelezo zaidi"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Mtandaopepe na hali ya kusambaza mtandao"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-ta/strings.xml b/packages/Tethering/res/values-ta/strings.xml
deleted file mode 100644
index 4aba62d..0000000
--- a/packages/Tethering/res/values-ta/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"டெதெரிங் அல்லது ஹாட்ஸ்பாட் இயங்குகிறது"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"அமைக்க, தட்டவும்."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"டெதெரிங் முடக்கப்பட்டுள்ளது"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"விவரங்களுக்கு உங்கள் நிர்வாகியைத் தொடர்புகொள்ளவும்"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"ஹாட்ஸ்பாட் & டெதெரிங் நிலை"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-te/strings.xml b/packages/Tethering/res/values-te/strings.xml
deleted file mode 100644
index 1f91791..0000000
--- a/packages/Tethering/res/values-te/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"టెథరింగ్ లేదా హాట్స్పాట్ యాక్టివ్గా ఉంది"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"సెటప్ చేయడానికి ట్యాప్ చేయండి."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"టెథరింగ్ డిజేబుల్ చేయబడింది"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"వివరాల కోసం మీ అడ్మిన్ని సంప్రదించండి"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"హాట్స్పాట్ & టెథరింగ్ స్థితి"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-th/strings.xml b/packages/Tethering/res/values-th/strings.xml
deleted file mode 100644
index 44171c0..0000000
--- a/packages/Tethering/res/values-th/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"การเชื่อมต่ออินเทอร์เน็ตผ่านมือถือหรือฮอตสปอตทำงานอยู่"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"แตะเพื่อตั้งค่า"</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"ปิดใช้การเชื่อมต่ออินเทอร์เน็ตผ่านมือถือแล้ว"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"ติดต่อผู้ดูแลระบบเพื่อขอรายละเอียด"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"สถานะฮอตสปอตและการเชื่อมต่ออินเทอร์เน็ตผ่านมือถือ"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-tl/strings.xml b/packages/Tethering/res/values-tl/strings.xml
deleted file mode 100644
index 7347dd3..0000000
--- a/packages/Tethering/res/values-tl/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"Aktibo ang pag-tether o hotspot"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"I-tap para i-set up."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"Naka-disable ang pag-tether"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"Makipag-ugnayan sa iyong admin para sa mga detalye"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Status ng hotspot at pag-tether"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-tr/strings.xml b/packages/Tethering/res/values-tr/strings.xml
deleted file mode 100644
index 32030f1..0000000
--- a/packages/Tethering/res/values-tr/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"Tethering veya hotspot etkin"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"Ayarlamak için dokunun."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"Tethering devre dışı bırakıldı"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"Ayrıntılı bilgi için yöneticinize başvurun"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Hotspot ve tethering durumu"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-uk/strings.xml b/packages/Tethering/res/values-uk/strings.xml
deleted file mode 100644
index 1ca89b3..0000000
--- a/packages/Tethering/res/values-uk/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"Модем чи точка доступу активні"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"Натисніть, щоб налаштувати."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"Використання телефона як модема вимкнено"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"Щоб дізнатися більше, зв\'яжіться з адміністратором"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Статус точки доступу та модема"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-ur/strings.xml b/packages/Tethering/res/values-ur/strings.xml
deleted file mode 100644
index d72c7d4..0000000
--- a/packages/Tethering/res/values-ur/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"ٹیدرنگ یا ہاٹ اسپاٹ فعال"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"سیٹ اپ کرنے کیلئے تھپتھپائیں۔"</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"ٹیدرنگ غیر فعال ہے"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"تفصیلات کے لئے اپنے منتظم سے رابطہ کریں"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"ہاٹ اسپاٹ اور ٹیتھرنگ کا اسٹیٹس"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-uz/strings.xml b/packages/Tethering/res/values-uz/strings.xml
deleted file mode 100644
index af3b2eb..0000000
--- a/packages/Tethering/res/values-uz/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"Modem rejimi yoki hotspot yoniq"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"Sozlash uchun bosing."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"Modem rejimi faolsizlantirildi"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"Tafsilotlari uchun administratoringizga murojaat qiling"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Hotspot va modem rejimi holati"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-vi/strings.xml b/packages/Tethering/res/values-vi/strings.xml
deleted file mode 100644
index 21a0735..0000000
--- a/packages/Tethering/res/values-vi/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"Tính năng chia sẻ Internet hoặc điểm phát sóng đang hoạt động"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"Hãy nhấn để thiết lập."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"Đã tắt tính năng chia sẻ Internet"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"Hãy liên hệ với quản trị viên của bạn để biết chi tiết"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"Trạng thái điểm phát sóng và chia sẻ Internet"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-zh-rCN/strings.xml b/packages/Tethering/res/values-zh-rCN/strings.xml
deleted file mode 100644
index 98e3b4b..0000000
--- a/packages/Tethering/res/values-zh-rCN/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"网络共享或热点已启用"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"点按即可设置。"</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"网络共享已停用"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"如需了解详情,请与您的管理员联系"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"热点和网络共享状态"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-zh-rHK/strings.xml b/packages/Tethering/res/values-zh-rHK/strings.xml
deleted file mode 100644
index 9cafd42..0000000
--- a/packages/Tethering/res/values-zh-rHK/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"網絡共享或熱點已啟用"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"輕按即可設定。"</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"網絡共享已停用"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"請聯絡您的管理員以瞭解詳情"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"熱點和網絡共享狀態"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-zh-rTW/strings.xml b/packages/Tethering/res/values-zh-rTW/strings.xml
deleted file mode 100644
index 50a50bf..0000000
--- a/packages/Tethering/res/values-zh-rTW/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"網路共用或無線基地台已啟用"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"輕觸即可進行設定。"</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"網路共用已停用"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"詳情請洽你的管理員"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"無線基地台與網路共用狀態"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values-zu/strings.xml b/packages/Tethering/res/values-zu/strings.xml
deleted file mode 100644
index f210f87..0000000
--- a/packages/Tethering/res/values-zu/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"Ukusebenzisa njengemodemu noma i-hotspot ephathekayo kuvuliwe"</string>
- <string name="tethered_notification_message" msgid="64800879503420696">"Thepha ukuze usethe."</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"Ukusebenzisa ifoni njengemodemu kukhutshaziwe"</string>
- <string name="disable_tether_notification_message" msgid="6717523799293901476">"Xhumana nomphathi wakho ukuze uthole imininingwane"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"I-Hotspot nesimo sokusebenzisa ifoni njengemodemu"</string>
- <string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
- <string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
- <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
- <string name="upstream_roaming_notification_title" msgid="4772373823198997030"></string>
- <string name="upstream_roaming_notification_message" msgid="3985577843181551650"></string>
-</resources>
diff --git a/packages/Tethering/res/values/config.xml b/packages/Tethering/res/values/config.xml
deleted file mode 100644
index 5f8d299..0000000
--- a/packages/Tethering/res/values/config.xml
+++ /dev/null
@@ -1,194 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-<resources>
- <!--
- OEMs that wish to change the below settings must do so via a runtime resource overlay package
- and *NOT* by changing this file. This file is part of the tethering mainline module.
- TODO: define two resources for each config item: a default_* resource and a config_* resource,
- config_* is empty by default but may be overridden by RROs.
- -->
- <!-- List of regexpressions describing the interface (if any) that represent tetherable
- USB interfaces. If the device doesn't want to support tethering over USB this should
- be empty. An example would be "usb.*" -->
- <string-array translatable="false" name="config_tether_usb_regexs">
- <item>"usb\\d"</item>
- <item>"rndis\\d"</item>
- </string-array>
-
- <!-- List of regexpressions describing the interface (if any) that represent tetherable
- NCM interfaces. If the device doesn't want to support tethering over NCM this should
- be empty. -->
- <string-array translatable="false" name="config_tether_ncm_regexs">
- </string-array>
-
- <!-- List of regexpressions describing the interface (if any) that represent tetherable
- Wifi interfaces. If the device doesn't want to support tethering over Wifi this
- should be empty. An example would be "softap.*" -->
- <string-array translatable="false" name="config_tether_wifi_regexs">
- <item>"wlan\\d"</item>
- <item>"softap\\d"</item>
- </string-array>
-
- <!-- List of regexpressions describing the interface (if any) that represent tetherable
- WiGig interfaces. If the device doesn't want to support tethering over WiGig this
- should be empty. An example would be "wigig\\d" -->
- <string-array translatable="false" name="config_tether_wigig_regexs">
- <item>"wigig\\d"</item>
- </string-array>
-
- <!-- List of regexpressions describing the interface (if any) that represent tetherable
- Wifi P2P interfaces. If the device doesn't want to support tethering over Wifi P2p this
- should be empty. An example would be "p2p-p2p\\d-.*" -->
- <string-array translatable="false" name="config_tether_wifi_p2p_regexs">
- <item>"p2p-p2p\\d-.*"</item>
- <item>"p2p\\d"</item>
- </string-array>
-
- <!-- List of regexpressions describing the interface (if any) that represent tetherable
- bluetooth interfaces. If the device doesn't want to support tethering over bluetooth this
- should be empty. -->
- <string-array translatable="false" name="config_tether_bluetooth_regexs">
- <item>"bt-pan"</item>
- </string-array>
-
- <!-- Use the BPF offload for tethering when the kernel has support. True by default.
- If the device doesn't want to support tether BPF offload, this should be false.
- Note that this setting could be overridden by device config.
- -->
- <bool translatable="false" name="config_tether_enable_bpf_offload">true</bool>
-
- <!-- Use the old dnsmasq DHCP server for tethering instead of the framework implementation. -->
- <bool translatable="false" name="config_tether_enable_legacy_dhcp_server">false</bool>
-
- <!-- Use legacy wifi p2p dedicated address instead of randomize address. -->
- <bool translatable="false" name="config_tether_enable_legacy_wifi_p2p_dedicated_ip">false</bool>
-
- <!-- Dhcp range (min, max) to use for tethering purposes -->
- <string-array translatable="false" name="config_tether_dhcp_range">
- </string-array>
-
- <!-- Used to config periodic polls tether offload stats from tethering offload HAL to make the
- data warnings work. 5000(ms) by default. If the device doesn't want to poll tether
- offload stats, this should be -1. Note that this setting could be override by
- runtime resource overlays.
- -->
- <integer translatable="false" name="config_tether_offload_poll_interval">5000</integer>
-
- <!-- Array of ConnectivityManager.TYPE_{BLUETOOTH, ETHERNET, MOBILE, MOBILE_DUN, MOBILE_HIPRI,
- WIFI} values allowable for tethering.
-
- Common options are [1, 4] for TYPE_WIFI and TYPE_MOBILE_DUN or
- [1,7,0] for TYPE_WIFI, TYPE_BLUETOOTH, and TYPE_MOBILE.
-
- This list is also modified by code within the framework, including:
-
- - TYPE_ETHERNET (9) is prepended to this list, and
-
- - the return value of TelephonyManager.isTetheringApnRequired()
- determines how the array is further modified:
-
- * TRUE (DUN REQUIRED).
- TYPE_MOBILE is removed (if present).
- TYPE_MOBILE_HIPRI is removed (if present).
- TYPE_MOBILE_DUN is appended (if not already present).
-
- * FALSE (DUN NOT REQUIRED).
- TYPE_MOBILE_DUN is removed (if present).
- If both of TYPE_MOBILE{,_HIPRI} are not present:
- TYPE_MOBILE is appended.
- TYPE_MOBILE_HIPRI is appended.
-
- For other changes applied to this list, now and in the future, see
- com.android.networkstack.tethering.TetheringConfiguration.
-
- Note also: the order of this is important. The first upstream type
- for which a satisfying network exists is used.
- -->
- <integer-array translatable="false" name="config_tether_upstream_types">
- </integer-array>
-
- <!-- When true, the tethering upstream network follows the current default
- Internet network (except when the current default network is mobile,
- in which case a DUN network will be used if required).
-
- When true, overrides the config_tether_upstream_types setting above.
- -->
- <bool translatable="false" name="config_tether_upstream_automatic">true</bool>
-
-
- <!-- If the mobile hotspot feature requires provisioning, a package name and class name
- can be provided to launch a supported application that provisions the devices.
- EntitlementManager will send an intent to Settings with the specified package name and
- class name in extras to launch provision app.
- TODO: note what extras here.
-
- See EntitlementManager#runUiTetherProvisioning and
- packages/apps/Settings/src/com/android/settings/network/TetherProvisioningActivity.java
- for more details.
-
- For ui-less/periodic recheck support see config_mobile_hotspot_provision_app_no_ui
- -->
- <!-- The first element is the package name and the second element is the class name
- of the provisioning app -->
- <string-array translatable="false" name="config_mobile_hotspot_provision_app">
- <!--
- <item>com.example.provisioning</item>
- <item>com.example.provisioning.Activity</item>
- -->
- </string-array>
-
- <!-- If the mobile hotspot feature requires provisioning, an action can be provided
- that will be broadcast in non-ui cases for checking the provisioning status.
- EntitlementManager will pass the specified name to Settings and Settings would
- launch provisioning app by sending an intent with the package name.
-
- A second broadcast, action defined by config_mobile_hotspot_provision_response,
- will be sent back to notify if provisioning succeeded or not. The response will
- match that of the activity in config_mobile_hotspot_provision_app, but instead
- contained within the int extra "EntitlementResult".
- TODO: provide the system api for "EntitlementResult" extra and note it here.
-
- See EntitlementManager#runSilentTetherProvisioning and
- packages/apps/Settings/src/com/android/settings/wifi/tether/TetherService.java for more
- details.
- -->
- <string translatable="false" name="config_mobile_hotspot_provision_app_no_ui"></string>
-
- <!-- Sent in response to a provisioning check. The caller must hold the
- permission android.permission.TETHER_PRIVILEGED for Settings to
- receive this response.
-
- See config_mobile_hotspot_provision_response
- -->
- <string translatable="false" name="config_mobile_hotspot_provision_response"></string>
-
- <!-- Number of hours between each background provisioning call -->
- <integer translatable="false" name="config_mobile_hotspot_provision_check_period">24</integer>
-
- <!-- ComponentName of the service used to run no ui tether provisioning. -->
- <string translatable="false" name="config_wifi_tether_enable">com.android.settings/.wifi.tether.TetherService</string>
-
- <!-- No upstream notification is shown when there is a downstream but no upstream that is able
- to do the tethering. -->
- <!-- Delay(millisecond) to show no upstream notification after there's no Backhaul. Set delay to
- "-1" for disable this feature. -->
- <integer name="delay_to_show_no_upstream_after_no_backhaul">-1</integer>
-
- <!-- Cellular roaming notification is shown when upstream is cellular network and in roaming
- state. -->
- <!-- Config for showing upstream roaming notification. -->
- <bool name="config_upstream_roaming_notification">false</bool>
-</resources>
diff --git a/packages/Tethering/res/values/overlayable.xml b/packages/Tethering/res/values/overlayable.xml
deleted file mode 100644
index 0ee7a99..0000000
--- a/packages/Tethering/res/values/overlayable.xml
+++ /dev/null
@@ -1,46 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-<resources xmlns:android="http://schemas.android.com/apk/res/android">
- <overlayable name="TetheringConfig">
- <policy type="product|system|vendor">
- <!-- Params from config.xml that can be overlaid -->
- <item type="array" name="config_tether_usb_regexs"/>
- <item type="array" name="config_tether_ncm_regexs" />
- <item type="array" name="config_tether_wifi_regexs"/>
- <item type="array" name="config_tether_wigig_regexs"/>
- <item type="array" name="config_tether_wifi_p2p_regexs"/>
- <item type="array" name="config_tether_bluetooth_regexs"/>
- <item type="array" name="config_tether_dhcp_range"/>
- <!-- Use the BPF offload for tethering when the kernel has support. True by default.
- If the device doesn't want to support tether BPF offload, this should be false.
- Note that this setting could be overridden by device config.
- -->
- <item type="bool" name="config_tether_enable_bpf_offload"/>
- <item type="bool" name="config_tether_enable_legacy_dhcp_server"/>
- <item type="bool" name="config_tether_enable_legacy_wifi_p2p_dedicated_ip"/>
- <item type="integer" name="config_tether_offload_poll_interval"/>
- <item type="array" name="config_tether_upstream_types"/>
- <item type="bool" name="config_tether_upstream_automatic"/>
- <!-- Configuration values for tethering entitlement check -->
- <item type="array" name="config_mobile_hotspot_provision_app"/>
- <item type="string" name="config_mobile_hotspot_provision_app_no_ui"/>
- <item type="string" name="config_mobile_hotspot_provision_response"/>
- <item type="integer" name="config_mobile_hotspot_provision_check_period"/>
- <item type="string" name="config_wifi_tether_enable"/>
- <!-- Params from config.xml that can be overlaid -->
- </policy>
- </overlayable>
-</resources>
diff --git a/packages/Tethering/res/values/strings.xml b/packages/Tethering/res/values/strings.xml
deleted file mode 100644
index d63c7c5..0000000
--- a/packages/Tethering/res/values/strings.xml
+++ /dev/null
@@ -1,47 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- Shown when the device is tethered -->
- <!-- String for tethered notification title [CHAR LIMIT=200] -->
- <string name="tethered_notification_title">Tethering or hotspot active</string>
- <!-- String for tethered notification message [CHAR LIMIT=200] -->
- <string name="tethered_notification_message">Tap to set up.</string>
-
- <!-- This notification is shown when tethering has been disabled on a user's device.
- The device is managed by the user's employer. Tethering can't be turned on unless the
- IT administrator allows it. The noun "admin" is another reference for "IT administrator." -->
- <!-- String for tether disabling notification title [CHAR LIMIT=200] -->
- <string name="disable_tether_notification_title">Tethering is disabled</string>
- <!-- String for tether disabling notification message [CHAR LIMIT=200] -->
- <string name="disable_tether_notification_message">Contact your admin for details</string>
-
- <!-- This string should be consistent with the "Hotspot & tethering" text in the "Network and
- Internet" settings page. That is currently the tether_settings_title_all string. -->
- <!-- String for tether notification channel name [CHAR LIMIT=200] -->
- <string name="notification_channel_tethering_status">Hotspot & tethering status</string>
-
- <!-- String for no upstream notification title [CHAR LIMIT=200] -->
- <string name="no_upstream_notification_title"></string>
- <!-- String for no upstream notification message [CHAR LIMIT=200] -->
- <string name="no_upstream_notification_message"></string>
- <!-- String for no upstream notification disable button [CHAR LIMIT=200] -->
- <string name="no_upstream_notification_disable_button"></string>
-
- <!-- String for cellular roaming notification title [CHAR LIMIT=200] -->
- <string name="upstream_roaming_notification_title"></string>
- <!-- String for cellular roaming notification message [CHAR LIMIT=500] -->
- <string name="upstream_roaming_notification_message"></string>
-</resources>
diff --git a/packages/Tethering/src/android/net/dhcp/DhcpServerCallbacks.java b/packages/Tethering/src/android/net/dhcp/DhcpServerCallbacks.java
deleted file mode 100644
index 9fda125..0000000
--- a/packages/Tethering/src/android/net/dhcp/DhcpServerCallbacks.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2018 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 android.net.dhcp;
-
-/**
- * Convenience wrapper around IDhcpServerCallbacks.Stub that implements getInterfaceVersion().
- * @hide
- */
-public abstract class DhcpServerCallbacks extends IDhcpServerCallbacks.Stub {
- /**
- * Get the version of the aidl interface implemented by the callbacks.
- */
- @Override
- public int getInterfaceVersion() {
- return IDhcpServerCallbacks.VERSION;
- }
-
- @Override
- public String getInterfaceHash() {
- return IDhcpServerCallbacks.HASH;
- }
-}
diff --git a/packages/Tethering/src/android/net/dhcp/DhcpServingParamsParcelExt.java b/packages/Tethering/src/android/net/dhcp/DhcpServingParamsParcelExt.java
deleted file mode 100644
index aaaec17..0000000
--- a/packages/Tethering/src/android/net/dhcp/DhcpServingParamsParcelExt.java
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * Copyright (C) 2018 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 android.net.dhcp;
-
-import static com.android.net.module.util.Inet4AddressUtils.inet4AddressToIntHTH;
-
-import android.net.LinkAddress;
-import android.util.ArraySet;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import java.net.Inet4Address;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Set;
-
-/**
- * Subclass of {@link DhcpServingParamsParcel} with additional utility methods for building.
- *
- * <p>This utility class does not check for validity of the parameters: invalid parameters are
- * reported by the receiving module when unparceling the parcel.
- *
- * @see DhcpServingParams
- * @hide
- */
-public class DhcpServingParamsParcelExt extends DhcpServingParamsParcel {
- public static final int MTU_UNSET = 0;
-
- /**
- * Set the server address and served prefix for the DHCP server.
- *
- * <p>This parameter is required.
- */
- public DhcpServingParamsParcelExt setServerAddr(@NonNull LinkAddress serverAddr) {
- this.serverAddr = inet4AddressToIntHTH((Inet4Address) serverAddr.getAddress());
- this.serverAddrPrefixLength = serverAddr.getPrefixLength();
- return this;
- }
-
- /**
- * Set the default routers to be advertised to DHCP clients.
- *
- * <p>Each router must be inside the served prefix. This may be an empty set, but it must
- * always be set explicitly.
- */
- public DhcpServingParamsParcelExt setDefaultRouters(@NonNull Set<Inet4Address> defaultRouters) {
- this.defaultRouters = toIntArray(defaultRouters);
- return this;
- }
-
- /**
- * Set the default routers to be advertised to DHCP clients.
- *
- * <p>Each router must be inside the served prefix. This may be an empty list of routers,
- * but it must always be set explicitly.
- */
- public DhcpServingParamsParcelExt setDefaultRouters(@NonNull Inet4Address... defaultRouters) {
- return setDefaultRouters(newArraySet(defaultRouters));
- }
-
- /**
- * Convenience method to build the parameters with no default router.
- *
- * <p>Equivalent to calling {@link #setDefaultRouters(Inet4Address...)} with no address.
- */
- public DhcpServingParamsParcelExt setNoDefaultRouter() {
- return setDefaultRouters();
- }
-
- /**
- * Set the DNS servers to be advertised to DHCP clients.
- *
- * <p>This may be an empty set, but it must always be set explicitly.
- */
- public DhcpServingParamsParcelExt setDnsServers(@NonNull Set<Inet4Address> dnsServers) {
- this.dnsServers = toIntArray(dnsServers);
- return this;
- }
-
- /**
- * Set the DNS servers to be advertised to DHCP clients.
- *
- * <p>This may be an empty list of servers, but it must always be set explicitly.
- */
- public DhcpServingParamsParcelExt setDnsServers(@NonNull Inet4Address... dnsServers) {
- return setDnsServers(newArraySet(dnsServers));
- }
-
- /**
- * Convenience method to build the parameters with no DNS server.
- *
- * <p>Equivalent to calling {@link #setDnsServers(Inet4Address...)} with no address.
- */
- public DhcpServingParamsParcelExt setNoDnsServer() {
- return setDnsServers();
- }
-
- /**
- * Set excluded addresses that the DHCP server is not allowed to assign to clients.
- *
- * <p>This parameter is optional. DNS servers and default routers are always excluded
- * and do not need to be set here.
- */
- public DhcpServingParamsParcelExt setExcludedAddrs(@NonNull Set<Inet4Address> excludedAddrs) {
- this.excludedAddrs = toIntArray(excludedAddrs);
- return this;
- }
-
- /**
- * Set excluded addresses that the DHCP server is not allowed to assign to clients.
- *
- * <p>This parameter is optional. DNS servers and default routers are always excluded
- * and do not need to be set here.
- */
- public DhcpServingParamsParcelExt setExcludedAddrs(@NonNull Inet4Address... excludedAddrs) {
- return setExcludedAddrs(newArraySet(excludedAddrs));
- }
-
- /**
- * Set the lease time for leases assigned by the DHCP server.
- *
- * <p>This parameter is required.
- */
- public DhcpServingParamsParcelExt setDhcpLeaseTimeSecs(long dhcpLeaseTimeSecs) {
- this.dhcpLeaseTimeSecs = dhcpLeaseTimeSecs;
- return this;
- }
-
- /**
- * Set the link MTU to be advertised to DHCP clients.
- *
- * <p>If set to {@link #MTU_UNSET}, no MTU will be advertised to clients. This parameter
- * is optional and defaults to {@link #MTU_UNSET}.
- */
- public DhcpServingParamsParcelExt setLinkMtu(int linkMtu) {
- this.linkMtu = linkMtu;
- return this;
- }
-
- /**
- * Set whether the DHCP server should send the ANDROID_METERED vendor-specific option.
- *
- * <p>If not set, the default value is false.
- */
- public DhcpServingParamsParcelExt setMetered(boolean metered) {
- this.metered = metered;
- return this;
- }
-
- /**
- * Set the client address to tell DHCP server only offer this address.
- * The client's prefix length is the same as server's.
- *
- * <p>If not set, the default value is null.
- */
- public DhcpServingParamsParcelExt setSingleClientAddr(@Nullable Inet4Address clientAddr) {
- this.singleClientAddr = clientAddr == null ? 0 : inet4AddressToIntHTH(clientAddr);
- return this;
- }
-
- /**
- * Set whether the DHCP server should request a new prefix from IpServer when receiving
- * DHCPDECLINE message in certain particular link (e.g. there is only one downstream USB
- * tethering client). If it's false, process DHCPDECLINE message as RFC2131#4.3.3 suggests.
- *
- * <p>If not set, the default value is false.
- */
- public DhcpServingParamsParcelExt setChangePrefixOnDecline(boolean changePrefixOnDecline) {
- this.changePrefixOnDecline = changePrefixOnDecline;
- return this;
- }
-
- private static int[] toIntArray(@NonNull Collection<Inet4Address> addrs) {
- int[] res = new int[addrs.size()];
- int i = 0;
- for (Inet4Address addr : addrs) {
- res[i] = inet4AddressToIntHTH(addr);
- i++;
- }
- return res;
- }
-
- private static ArraySet<Inet4Address> newArraySet(Inet4Address... addrs) {
- ArraySet<Inet4Address> addrSet = new ArraySet<>(addrs.length);
- Collections.addAll(addrSet, addrs);
- return addrSet;
- }
-}
diff --git a/packages/Tethering/src/android/net/ip/DadProxy.java b/packages/Tethering/src/android/net/ip/DadProxy.java
deleted file mode 100644
index e2976b7..0000000
--- a/packages/Tethering/src/android/net/ip/DadProxy.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * 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 android.net.ip;
-
-import android.net.util.InterfaceParams;
-import android.os.Handler;
-
-import androidx.annotation.VisibleForTesting;
-
-/**
- * Basic Duplicate address detection proxy.
- *
- * @hide
- */
-public class DadProxy {
- private static final String TAG = DadProxy.class.getSimpleName();
-
- @VisibleForTesting
- public static NeighborPacketForwarder naForwarder;
- public static NeighborPacketForwarder nsForwarder;
-
- public DadProxy(Handler h, InterfaceParams tetheredIface) {
- naForwarder = new NeighborPacketForwarder(h, tetheredIface,
- NeighborPacketForwarder.ICMPV6_NEIGHBOR_ADVERTISEMENT);
- nsForwarder = new NeighborPacketForwarder(h, tetheredIface,
- NeighborPacketForwarder.ICMPV6_NEIGHBOR_SOLICITATION);
- }
-
- /** Stop NS/NA Forwarders. */
- public void stop() {
- naForwarder.stop();
- nsForwarder.stop();
- }
-
- /** Set upstream iface on both forwarders. */
- public void setUpstreamIface(InterfaceParams upstreamIface) {
- naForwarder.setUpstreamIface(upstreamIface);
- nsForwarder.setUpstreamIface(upstreamIface);
- }
-}
diff --git a/packages/Tethering/src/android/net/ip/IpServer.java b/packages/Tethering/src/android/net/ip/IpServer.java
deleted file mode 100644
index 52d59fc..0000000
--- a/packages/Tethering/src/android/net/ip/IpServer.java
+++ /dev/null
@@ -1,1422 +0,0 @@
-/*
- * Copyright (C) 2016 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 android.net.ip;
-
-import static android.net.RouteInfo.RTN_UNICAST;
-import static android.net.TetheringManager.TetheringRequest.checkStaticAddressConfiguration;
-import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS;
-import static android.net.util.NetworkConstants.RFC7421_PREFIX_LENGTH;
-import static android.net.util.NetworkConstants.asByte;
-import static android.net.util.PrefixUtils.asIpPrefix;
-import static android.net.util.TetheringMessageBase.BASE_IPSERVER;
-import static android.system.OsConstants.RT_SCOPE_UNIVERSE;
-
-import static com.android.net.module.util.Inet4AddressUtils.intToInet4AddressHTH;
-
-import android.net.INetd;
-import android.net.INetworkStackStatusCallback;
-import android.net.IpPrefix;
-import android.net.LinkAddress;
-import android.net.LinkProperties;
-import android.net.MacAddress;
-import android.net.RouteInfo;
-import android.net.TetheredClient;
-import android.net.TetheringManager;
-import android.net.TetheringRequestParcel;
-import android.net.dhcp.DhcpLeaseParcelable;
-import android.net.dhcp.DhcpServerCallbacks;
-import android.net.dhcp.DhcpServingParamsParcel;
-import android.net.dhcp.DhcpServingParamsParcelExt;
-import android.net.dhcp.IDhcpEventCallbacks;
-import android.net.dhcp.IDhcpServer;
-import android.net.ip.IpNeighborMonitor.NeighborEvent;
-import android.net.ip.RouterAdvertisementDaemon.RaParams;
-import android.net.shared.NetdUtils;
-import android.net.shared.RouteUtils;
-import android.net.util.InterfaceParams;
-import android.net.util.InterfaceSet;
-import android.net.util.PrefixUtils;
-import android.net.util.SharedLog;
-import android.os.Build;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.os.RemoteException;
-import android.os.ServiceSpecificException;
-import android.util.Log;
-import android.util.SparseArray;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.android.internal.util.MessageUtils;
-import com.android.internal.util.State;
-import com.android.internal.util.StateMachine;
-import com.android.networkstack.tethering.BpfCoordinator;
-import com.android.networkstack.tethering.BpfCoordinator.Ipv6ForwardingRule;
-import com.android.networkstack.tethering.PrivateAddressCoordinator;
-
-import java.io.IOException;
-import java.net.Inet4Address;
-import java.net.Inet6Address;
-import java.net.NetworkInterface;
-import java.net.UnknownHostException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Objects;
-import java.util.Random;
-import java.util.Set;
-
-/**
- * Provides the interface to IP-layer serving functionality for a given network
- * interface, e.g. for tethering or "local-only hotspot" mode.
- *
- * @hide
- */
-public class IpServer extends StateMachine {
- public static final int STATE_UNAVAILABLE = 0;
- public static final int STATE_AVAILABLE = 1;
- public static final int STATE_TETHERED = 2;
- public static final int STATE_LOCAL_ONLY = 3;
-
- /** Get string name of |state|.*/
- public static String getStateString(int state) {
- switch (state) {
- case STATE_UNAVAILABLE: return "UNAVAILABLE";
- case STATE_AVAILABLE: return "AVAILABLE";
- case STATE_TETHERED: return "TETHERED";
- case STATE_LOCAL_ONLY: return "LOCAL_ONLY";
- }
- return "UNKNOWN: " + state;
- }
-
- private static final byte DOUG_ADAMS = (byte) 42;
-
- // TODO: have PanService use some visible version of this constant
- private static final String BLUETOOTH_IFACE_ADDR = "192.168.44.1/24";
-
- // TODO: have this configurable
- private static final int DHCP_LEASE_TIME_SECS = 3600;
-
- private static final MacAddress NULL_MAC_ADDRESS = MacAddress.fromString("00:00:00:00:00:00");
-
- private static final String TAG = "IpServer";
- private static final boolean DBG = false;
- private static final boolean VDBG = false;
- private static final Class[] sMessageClasses = {
- IpServer.class
- };
- private static final SparseArray<String> sMagicDecoderRing =
- MessageUtils.findMessageNames(sMessageClasses);
-
- /** IpServer callback. */
- public static class Callback {
- /**
- * Notify that |who| has changed its tethering state.
- *
- * @param who the calling instance of IpServer
- * @param state one of STATE_*
- * @param lastError one of TetheringManager.TETHER_ERROR_*
- */
- public void updateInterfaceState(IpServer who, int state, int lastError) { }
-
- /**
- * Notify that |who| has new LinkProperties.
- *
- * @param who the calling instance of IpServer
- * @param newLp the new LinkProperties to report
- */
- public void updateLinkProperties(IpServer who, LinkProperties newLp) { }
-
- /**
- * Notify that the DHCP leases changed in one of the IpServers.
- */
- public void dhcpLeasesChanged() { }
-
- /**
- * Request Tethering change.
- *
- * @param tetheringType the downstream type of this IpServer.
- * @param enabled enable or disable tethering.
- */
- public void requestEnableTethering(int tetheringType, boolean enabled) { }
- }
-
- /** Capture IpServer dependencies, for injection. */
- public abstract static class Dependencies {
- /**
- * Create a DadProxy instance to be used by IpServer.
- * To support multiple tethered interfaces concurrently DAD Proxy
- * needs to be supported per IpServer instead of per upstream.
- */
- public DadProxy getDadProxy(Handler handler, InterfaceParams ifParams) {
- return new DadProxy(handler, ifParams);
- }
-
- /** Create an IpNeighborMonitor to be used by this IpServer */
- public IpNeighborMonitor getIpNeighborMonitor(Handler handler, SharedLog log,
- IpNeighborMonitor.NeighborEventConsumer consumer) {
- return new IpNeighborMonitor(handler, log, consumer);
- }
-
- /** Create a RouterAdvertisementDaemon instance to be used by IpServer.*/
- public RouterAdvertisementDaemon getRouterAdvertisementDaemon(InterfaceParams ifParams) {
- return new RouterAdvertisementDaemon(ifParams);
- }
-
- /** Get |ifName|'s interface information.*/
- public InterfaceParams getInterfaceParams(String ifName) {
- return InterfaceParams.getByName(ifName);
- }
-
- /** Get |ifName|'s interface index. */
- public int getIfindex(String ifName) {
- try {
- return NetworkInterface.getByName(ifName).getIndex();
- } catch (IOException | NullPointerException e) {
- Log.e(TAG, "Can't determine interface index for interface " + ifName);
- return 0;
- }
- }
-
- /** Create a DhcpServer instance to be used by IpServer. */
- public abstract void makeDhcpServer(String ifName, DhcpServingParamsParcel params,
- DhcpServerCallbacks cb);
- }
-
- // request from the user that it wants to tether
- public static final int CMD_TETHER_REQUESTED = BASE_IPSERVER + 1;
- // request from the user that it wants to untether
- public static final int CMD_TETHER_UNREQUESTED = BASE_IPSERVER + 2;
- // notification that this interface is down
- public static final int CMD_INTERFACE_DOWN = BASE_IPSERVER + 3;
- // notification from the {@link Tethering.TetherMainSM} that it had trouble enabling IP
- // Forwarding
- public static final int CMD_IP_FORWARDING_ENABLE_ERROR = BASE_IPSERVER + 4;
- // notification from the {@link Tethering.TetherMainSM} SM that it had trouble disabling IP
- // Forwarding
- public static final int CMD_IP_FORWARDING_DISABLE_ERROR = BASE_IPSERVER + 5;
- // notification from the {@link Tethering.TetherMainSM} SM that it had trouble starting
- // tethering
- public static final int CMD_START_TETHERING_ERROR = BASE_IPSERVER + 6;
- // notification from the {@link Tethering.TetherMainSM} that it had trouble stopping tethering
- public static final int CMD_STOP_TETHERING_ERROR = BASE_IPSERVER + 7;
- // notification from the {@link Tethering.TetherMainSM} that it had trouble setting the DNS
- // forwarders
- public static final int CMD_SET_DNS_FORWARDERS_ERROR = BASE_IPSERVER + 8;
- // the upstream connection has changed
- public static final int CMD_TETHER_CONNECTION_CHANGED = BASE_IPSERVER + 9;
- // new IPv6 tethering parameters need to be processed
- public static final int CMD_IPV6_TETHER_UPDATE = BASE_IPSERVER + 10;
- // new neighbor cache entry on our interface
- public static final int CMD_NEIGHBOR_EVENT = BASE_IPSERVER + 11;
- // request from DHCP server that it wants to have a new prefix
- public static final int CMD_NEW_PREFIX_REQUEST = BASE_IPSERVER + 12;
- // request from PrivateAddressCoordinator to restart tethering.
- public static final int CMD_NOTIFY_PREFIX_CONFLICT = BASE_IPSERVER + 13;
-
- private final State mInitialState;
- private final State mLocalHotspotState;
- private final State mTetheredState;
- private final State mUnavailableState;
- private final State mWaitingForRestartState;
-
- private final SharedLog mLog;
- private final INetd mNetd;
- @NonNull
- private final BpfCoordinator mBpfCoordinator;
- private final Callback mCallback;
- private final InterfaceController mInterfaceCtrl;
- private final PrivateAddressCoordinator mPrivateAddressCoordinator;
-
- private final String mIfaceName;
- private final int mInterfaceType;
- private final LinkProperties mLinkProperties;
- private final boolean mUsingLegacyDhcp;
- private final boolean mUsingBpfOffload;
-
- private final Dependencies mDeps;
-
- private int mLastError;
- private int mServingMode;
- private InterfaceSet mUpstreamIfaceSet; // may change over time
- private InterfaceParams mInterfaceParams;
- // TODO: De-duplicate this with mLinkProperties above. Currently, these link
- // properties are those selected by the IPv6TetheringCoordinator and relayed
- // to us. By comparison, mLinkProperties contains the addresses and directly
- // connected routes that have been formed from these properties iff. we have
- // succeeded in configuring them and are able to announce them within Router
- // Advertisements (otherwise, we do not add them to mLinkProperties at all).
- private LinkProperties mLastIPv6LinkProperties;
- private RouterAdvertisementDaemon mRaDaemon;
- private DadProxy mDadProxy;
-
- // To be accessed only on the handler thread
- private int mDhcpServerStartIndex = 0;
- private IDhcpServer mDhcpServer;
- private RaParams mLastRaParams;
-
- private LinkAddress mStaticIpv4ServerAddr;
- private LinkAddress mStaticIpv4ClientAddr;
-
- @NonNull
- private List<TetheredClient> mDhcpLeases = Collections.emptyList();
-
- private int mLastIPv6UpstreamIfindex = 0;
-
- private class MyNeighborEventConsumer implements IpNeighborMonitor.NeighborEventConsumer {
- public void accept(NeighborEvent e) {
- sendMessage(CMD_NEIGHBOR_EVENT, e);
- }
- }
-
- private final IpNeighborMonitor mIpNeighborMonitor;
-
- private LinkAddress mIpv4Address;
-
- // TODO: Add a dependency object to pass the data members or variables from the tethering
- // object. It helps to reduce the arguments of the constructor.
- public IpServer(
- String ifaceName, Looper looper, int interfaceType, SharedLog log,
- INetd netd, @NonNull BpfCoordinator coordinator, Callback callback,
- boolean usingLegacyDhcp, boolean usingBpfOffload,
- PrivateAddressCoordinator addressCoordinator, Dependencies deps) {
- super(ifaceName, looper);
- mLog = log.forSubComponent(ifaceName);
- mNetd = netd;
- mBpfCoordinator = coordinator;
- mCallback = callback;
- mInterfaceCtrl = new InterfaceController(ifaceName, mNetd, mLog);
- mIfaceName = ifaceName;
- mInterfaceType = interfaceType;
- mLinkProperties = new LinkProperties();
- mUsingLegacyDhcp = usingLegacyDhcp;
- mUsingBpfOffload = usingBpfOffload;
- mPrivateAddressCoordinator = addressCoordinator;
- mDeps = deps;
- resetLinkProperties();
- mLastError = TetheringManager.TETHER_ERROR_NO_ERROR;
- mServingMode = STATE_AVAILABLE;
-
- mIpNeighborMonitor = mDeps.getIpNeighborMonitor(getHandler(), mLog,
- new MyNeighborEventConsumer());
-
- // IP neighbor monitor monitors the neighbor events for adding/removing offload
- // forwarding rules per client. If BPF offload is not supported, don't start listening
- // for neighbor events. See updateIpv6ForwardingRules, addIpv6ForwardingRule,
- // removeIpv6ForwardingRule.
- if (mUsingBpfOffload && !mIpNeighborMonitor.start()) {
- mLog.e("Failed to create IpNeighborMonitor on " + mIfaceName);
- }
-
- mInitialState = new InitialState();
- mLocalHotspotState = new LocalHotspotState();
- mTetheredState = new TetheredState();
- mUnavailableState = new UnavailableState();
- mWaitingForRestartState = new WaitingForRestartState();
- addState(mInitialState);
- addState(mLocalHotspotState);
- addState(mTetheredState);
- addState(mWaitingForRestartState, mTetheredState);
- addState(mUnavailableState);
-
- setInitialState(mInitialState);
- }
-
- /** Interface name which IpServer served.*/
- public String interfaceName() {
- return mIfaceName;
- }
-
- /**
- * Tethering downstream type. It would be one of TetheringManager#TETHERING_*.
- */
- public int interfaceType() {
- return mInterfaceType;
- }
-
- /** Last error from this IpServer. */
- public int lastError() {
- return mLastError;
- }
-
- /** Serving mode is the current state of IpServer state machine. */
- public int servingMode() {
- return mServingMode;
- }
-
- /** The properties of the network link which IpServer is serving. */
- public LinkProperties linkProperties() {
- return new LinkProperties(mLinkProperties);
- }
-
- /** The address which IpServer is using. */
- public LinkAddress getAddress() {
- return mIpv4Address;
- }
-
- /**
- * Get the latest list of DHCP leases that was reported. Must be called on the IpServer looper
- * thread.
- */
- public List<TetheredClient> getAllLeases() {
- return Collections.unmodifiableList(mDhcpLeases);
- }
-
- /** Stop this IpServer. After this is called this IpServer should not be used any more. */
- public void stop() {
- sendMessage(CMD_INTERFACE_DOWN);
- }
-
- /**
- * Tethering is canceled. IpServer state machine will be available and wait for
- * next tethering request.
- */
- public void unwanted() {
- sendMessage(CMD_TETHER_UNREQUESTED);
- }
-
- /** Internals. */
-
- private boolean startIPv4() {
- return configureIPv4(true);
- }
-
- /**
- * Convenience wrapper around INetworkStackStatusCallback to run callbacks on the IpServer
- * handler.
- *
- * <p>Different instances of this class can be created for each call to IDhcpServer methods,
- * with different implementations of the callback, to differentiate handling of success/error in
- * each call.
- */
- private abstract class OnHandlerStatusCallback extends INetworkStackStatusCallback.Stub {
- @Override
- public void onStatusAvailable(int statusCode) {
- getHandler().post(() -> callback(statusCode));
- }
-
- public abstract void callback(int statusCode);
-
- @Override
- public int getInterfaceVersion() {
- return this.VERSION;
- }
-
- @Override
- public String getInterfaceHash() {
- return this.HASH;
- }
- }
-
- private class DhcpServerCallbacksImpl extends DhcpServerCallbacks {
- private final int mStartIndex;
-
- private DhcpServerCallbacksImpl(int startIndex) {
- mStartIndex = startIndex;
- }
-
- @Override
- public void onDhcpServerCreated(int statusCode, IDhcpServer server) throws RemoteException {
- getHandler().post(() -> {
- // We are on the handler thread: mDhcpServerStartIndex can be read safely.
- if (mStartIndex != mDhcpServerStartIndex) {
- // This start request is obsolete. Explicitly stop the DHCP server to shut
- // down its thread. When the |server| binder token goes out of scope, the
- // garbage collector will finalize it, which causes the network stack process
- // garbage collector to collect the server itself.
- try {
- server.stop(null);
- } catch (RemoteException e) { }
- return;
- }
-
- if (statusCode != STATUS_SUCCESS) {
- mLog.e("Error obtaining DHCP server: " + statusCode);
- handleError();
- return;
- }
-
- mDhcpServer = server;
- try {
- mDhcpServer.startWithCallbacks(new OnHandlerStatusCallback() {
- @Override
- public void callback(int startStatusCode) {
- if (startStatusCode != STATUS_SUCCESS) {
- mLog.e("Error starting DHCP server: " + startStatusCode);
- handleError();
- }
- }
- }, new DhcpEventCallback());
- } catch (RemoteException e) {
- throw new IllegalStateException(e);
- }
- });
- }
-
- private void handleError() {
- mLastError = TetheringManager.TETHER_ERROR_DHCPSERVER_ERROR;
- transitionTo(mInitialState);
- }
- }
-
- private class DhcpEventCallback extends IDhcpEventCallbacks.Stub {
- @Override
- public void onLeasesChanged(List<DhcpLeaseParcelable> leaseParcelables) {
- final ArrayList<TetheredClient> leases = new ArrayList<>();
- for (DhcpLeaseParcelable lease : leaseParcelables) {
- final LinkAddress address = new LinkAddress(
- intToInet4AddressHTH(lease.netAddr), lease.prefixLength,
- 0 /* flags */, RT_SCOPE_UNIVERSE /* as per RFC6724#3.2 */,
- lease.expTime /* deprecationTime */, lease.expTime /* expirationTime */);
-
- final MacAddress macAddress;
- try {
- macAddress = MacAddress.fromBytes(lease.hwAddr);
- } catch (IllegalArgumentException e) {
- Log.wtf(TAG, "Invalid address received from DhcpServer: "
- + Arrays.toString(lease.hwAddr));
- return;
- }
-
- final TetheredClient.AddressInfo addressInfo = new TetheredClient.AddressInfo(
- address, lease.hostname);
- leases.add(new TetheredClient(
- macAddress,
- Collections.singletonList(addressInfo),
- mInterfaceType));
- }
-
- getHandler().post(() -> {
- mDhcpLeases = leases;
- mCallback.dhcpLeasesChanged();
- });
- }
-
- @Override
- public void onNewPrefixRequest(@NonNull final IpPrefix currentPrefix) {
- Objects.requireNonNull(currentPrefix);
- sendMessage(CMD_NEW_PREFIX_REQUEST, currentPrefix);
- }
-
- @Override
- public int getInterfaceVersion() {
- return this.VERSION;
- }
-
- @Override
- public String getInterfaceHash() throws RemoteException {
- return this.HASH;
- }
- }
-
- private RouteInfo getDirectConnectedRoute(@NonNull final LinkAddress ipv4Address) {
- Objects.requireNonNull(ipv4Address);
- return new RouteInfo(PrefixUtils.asIpPrefix(ipv4Address), null, mIfaceName, RTN_UNICAST);
- }
-
- private DhcpServingParamsParcel makeServingParams(@NonNull final Inet4Address defaultRouter,
- @NonNull final Inet4Address dnsServer, @NonNull LinkAddress serverAddr,
- @Nullable Inet4Address clientAddr) {
- final boolean changePrefixOnDecline =
- (mInterfaceType == TetheringManager.TETHERING_NCM && clientAddr == null);
- return new DhcpServingParamsParcelExt()
- .setDefaultRouters(defaultRouter)
- .setDhcpLeaseTimeSecs(DHCP_LEASE_TIME_SECS)
- .setDnsServers(dnsServer)
- .setServerAddr(serverAddr)
- .setMetered(true)
- .setSingleClientAddr(clientAddr)
- .setChangePrefixOnDecline(changePrefixOnDecline);
- // TODO: also advertise link MTU
- }
-
- private boolean startDhcp(final LinkAddress serverLinkAddr, final LinkAddress clientLinkAddr) {
- if (mUsingLegacyDhcp) {
- return true;
- }
-
- final Inet4Address addr = (Inet4Address) serverLinkAddr.getAddress();
- final Inet4Address clientAddr = clientLinkAddr == null ? null :
- (Inet4Address) clientLinkAddr.getAddress();
-
- final DhcpServingParamsParcel params = makeServingParams(addr /* defaultRouter */,
- addr /* dnsServer */, serverLinkAddr, clientAddr);
- mDhcpServerStartIndex++;
- mDeps.makeDhcpServer(
- mIfaceName, params, new DhcpServerCallbacksImpl(mDhcpServerStartIndex));
- return true;
- }
-
- private void stopDhcp() {
- // Make all previous start requests obsolete so servers are not started later
- mDhcpServerStartIndex++;
-
- if (mDhcpServer != null) {
- try {
- mDhcpServer.stop(new OnHandlerStatusCallback() {
- @Override
- public void callback(int statusCode) {
- if (statusCode != STATUS_SUCCESS) {
- mLog.e("Error stopping DHCP server: " + statusCode);
- mLastError = TetheringManager.TETHER_ERROR_DHCPSERVER_ERROR;
- // Not much more we can do here
- }
- mDhcpLeases.clear();
- getHandler().post(mCallback::dhcpLeasesChanged);
- }
- });
- mDhcpServer = null;
- } catch (RemoteException e) {
- mLog.e("Error stopping DHCP server", e);
- // Not much more we can do here
- }
- }
- }
-
- private boolean configureDhcp(boolean enable, final LinkAddress serverAddr,
- final LinkAddress clientAddr) {
- if (enable) {
- return startDhcp(serverAddr, clientAddr);
- } else {
- stopDhcp();
- return true;
- }
- }
-
- private void stopIPv4() {
- configureIPv4(false);
- // NOTE: All of configureIPv4() will be refactored out of existence
- // into calls to InterfaceController, shared with startIPv4().
- mInterfaceCtrl.clearIPv4Address();
- mPrivateAddressCoordinator.releaseDownstream(this);
- mIpv4Address = null;
- mStaticIpv4ServerAddr = null;
- mStaticIpv4ClientAddr = null;
- }
-
- private boolean configureIPv4(boolean enabled) {
- if (VDBG) Log.d(TAG, "configureIPv4(" + enabled + ")");
-
- if (enabled) {
- mIpv4Address = requestIpv4Address(true /* useLastAddress */);
- }
-
- if (mIpv4Address == null) {
- mLog.e("No available ipv4 address");
- return false;
- }
-
- if (mInterfaceType == TetheringManager.TETHERING_BLUETOOTH) {
- // BT configures the interface elsewhere: only start DHCP.
- // TODO: make all tethering types behave the same way, and delete the bluetooth
- // code that calls into NetworkManagementService directly.
- return configureDhcp(enabled, mIpv4Address, null /* clientAddress */);
- }
-
- final IpPrefix ipv4Prefix = asIpPrefix(mIpv4Address);
-
- final Boolean setIfaceUp;
- if (mInterfaceType == TetheringManager.TETHERING_WIFI
- || mInterfaceType == TetheringManager.TETHERING_WIFI_P2P
- || mInterfaceType == TetheringManager.TETHERING_ETHERNET
- || mInterfaceType == TetheringManager.TETHERING_WIGIG) {
- // The WiFi and Ethernet stack has ownership of the interface up/down state.
- // It is unclear whether the Bluetooth or USB stacks will manage their own
- // state.
- setIfaceUp = null;
- } else {
- setIfaceUp = enabled;
- }
- if (!mInterfaceCtrl.setInterfaceConfiguration(mIpv4Address, setIfaceUp)) {
- mLog.e("Error configuring interface");
- if (!enabled) stopDhcp();
- return false;
- }
-
- if (enabled) {
- mLinkProperties.addLinkAddress(mIpv4Address);
- mLinkProperties.addRoute(getDirectConnectedRoute(mIpv4Address));
- } else {
- mLinkProperties.removeLinkAddress(mIpv4Address);
- mLinkProperties.removeRoute(getDirectConnectedRoute(mIpv4Address));
- }
- return configureDhcp(enabled, mIpv4Address, mStaticIpv4ClientAddr);
- }
-
- private LinkAddress requestIpv4Address(final boolean useLastAddress) {
- if (mStaticIpv4ServerAddr != null) return mStaticIpv4ServerAddr;
-
- if (mInterfaceType == TetheringManager.TETHERING_BLUETOOTH) {
- return new LinkAddress(BLUETOOTH_IFACE_ADDR);
- }
-
- return mPrivateAddressCoordinator.requestDownstreamAddress(this, useLastAddress);
- }
-
- private boolean startIPv6() {
- mInterfaceParams = mDeps.getInterfaceParams(mIfaceName);
- if (mInterfaceParams == null) {
- mLog.e("Failed to find InterfaceParams");
- stopIPv6();
- return false;
- }
-
- mRaDaemon = mDeps.getRouterAdvertisementDaemon(mInterfaceParams);
- if (!mRaDaemon.start()) {
- stopIPv6();
- return false;
- }
-
- // TODO: use ShimUtils instead of explicitly checking the version here.
- if (Build.VERSION.SDK_INT > Build.VERSION_CODES.R || "S".equals(Build.VERSION.CODENAME)
- || "T".equals(Build.VERSION.CODENAME)) {
- // DAD Proxy starts forwarding packets after IPv6 upstream is present.
- mDadProxy = mDeps.getDadProxy(getHandler(), mInterfaceParams);
- }
-
- return true;
- }
-
- private void stopIPv6() {
- mInterfaceParams = null;
- setRaParams(null);
-
- if (mRaDaemon != null) {
- mRaDaemon.stop();
- mRaDaemon = null;
- }
-
- if (mDadProxy != null) {
- mDadProxy.stop();
- mDadProxy = null;
- }
- }
-
- // IPv6TetheringCoordinator sends updates with carefully curated IPv6-only
- // LinkProperties. These have extraneous data filtered out and only the
- // necessary prefixes included (per its prefix distribution policy).
- //
- // TODO: Evaluate using a data structure than is more directly suited to
- // communicating only the relevant information.
- private void updateUpstreamIPv6LinkProperties(LinkProperties v6only, int ttlAdjustment) {
- if (mRaDaemon == null) return;
-
- // Avoid unnecessary work on spurious updates.
- if (Objects.equals(mLastIPv6LinkProperties, v6only)) {
- return;
- }
-
- RaParams params = null;
- String upstreamIface = null;
- InterfaceParams upstreamIfaceParams = null;
- int upstreamIfIndex = 0;
-
- if (v6only != null) {
- upstreamIface = v6only.getInterfaceName();
- upstreamIfaceParams = mDeps.getInterfaceParams(upstreamIface);
- if (upstreamIfaceParams != null) {
- upstreamIfIndex = upstreamIfaceParams.index;
- }
- params = new RaParams();
- params.mtu = v6only.getMtu();
- params.hasDefaultRoute = v6only.hasIpv6DefaultRoute();
-
- if (params.hasDefaultRoute) params.hopLimit = getHopLimit(upstreamIface, ttlAdjustment);
-
- for (LinkAddress linkAddr : v6only.getLinkAddresses()) {
- if (linkAddr.getPrefixLength() != RFC7421_PREFIX_LENGTH) continue;
-
- final IpPrefix prefix = new IpPrefix(
- linkAddr.getAddress(), linkAddr.getPrefixLength());
- params.prefixes.add(prefix);
-
- final Inet6Address dnsServer = getLocalDnsIpFor(prefix);
- if (dnsServer != null) {
- params.dnses.add(dnsServer);
- }
- }
-
- // Add upstream index to name mapping for the tether stats usage in the coordinator.
- // Although this mapping could be added by both class Tethering and IpServer, adding
- // mapping from IpServer guarantees that the mapping is added before the adding
- // forwarding rules. That is because there are different state machines in both
- // classes. It is hard to guarantee the link property update order between multiple
- // state machines.
- mBpfCoordinator.addUpstreamNameToLookupTable(upstreamIfIndex, upstreamIface);
- }
-
- // If v6only is null, we pass in null to setRaParams(), which handles
- // deprecation of any existing RA data.
-
- setRaParams(params);
- mLastIPv6LinkProperties = v6only;
-
- updateIpv6ForwardingRules(mLastIPv6UpstreamIfindex, upstreamIfIndex, null);
- mLastIPv6UpstreamIfindex = upstreamIfIndex;
- if (mDadProxy != null) {
- mDadProxy.setUpstreamIface(upstreamIfaceParams);
- }
- }
-
- private void removeRoutesFromLocalNetwork(@NonNull final List<RouteInfo> toBeRemoved) {
- final int removalFailures = RouteUtils.removeRoutesFromLocalNetwork(
- mNetd, toBeRemoved);
- if (removalFailures > 0) {
- mLog.e(String.format("Failed to remove %d IPv6 routes from local table.",
- removalFailures));
- }
-
- for (RouteInfo route : toBeRemoved) mLinkProperties.removeRoute(route);
- }
-
- private void addRoutesToLocalNetwork(@NonNull final List<RouteInfo> toBeAdded) {
- try {
- // It's safe to call networkAddInterface() even if
- // the interface is already in the local_network.
- mNetd.networkAddInterface(INetd.LOCAL_NET_ID, mIfaceName);
- try {
- // Add routes from local network. Note that adding routes that
- // already exist does not cause an error (EEXIST is silently ignored).
- RouteUtils.addRoutesToLocalNetwork(mNetd, mIfaceName, toBeAdded);
- } catch (IllegalStateException e) {
- mLog.e("Failed to add IPv4/v6 routes to local table: " + e);
- return;
- }
- } catch (ServiceSpecificException | RemoteException e) {
- mLog.e("Failed to add " + mIfaceName + " to local table: ", e);
- return;
- }
-
- for (RouteInfo route : toBeAdded) mLinkProperties.addRoute(route);
- }
-
- private void configureLocalIPv6Routes(
- HashSet<IpPrefix> deprecatedPrefixes, HashSet<IpPrefix> newPrefixes) {
- // [1] Remove the routes that are deprecated.
- if (!deprecatedPrefixes.isEmpty()) {
- removeRoutesFromLocalNetwork(getLocalRoutesFor(mIfaceName, deprecatedPrefixes));
- }
-
- // [2] Add only the routes that have not previously been added.
- if (newPrefixes != null && !newPrefixes.isEmpty()) {
- HashSet<IpPrefix> addedPrefixes = (HashSet) newPrefixes.clone();
- if (mLastRaParams != null) {
- addedPrefixes.removeAll(mLastRaParams.prefixes);
- }
-
- if (!addedPrefixes.isEmpty()) {
- addRoutesToLocalNetwork(getLocalRoutesFor(mIfaceName, addedPrefixes));
- }
- }
- }
-
- private void configureLocalIPv6Dns(
- HashSet<Inet6Address> deprecatedDnses, HashSet<Inet6Address> newDnses) {
- // TODO: Is this really necessary? Can we not fail earlier if INetd cannot be located?
- if (mNetd == null) {
- if (newDnses != null) newDnses.clear();
- mLog.e("No netd service instance available; not setting local IPv6 addresses");
- return;
- }
-
- // [1] Remove deprecated local DNS IP addresses.
- if (!deprecatedDnses.isEmpty()) {
- for (Inet6Address dns : deprecatedDnses) {
- if (!mInterfaceCtrl.removeAddress(dns, RFC7421_PREFIX_LENGTH)) {
- mLog.e("Failed to remove local dns IP " + dns);
- }
-
- mLinkProperties.removeLinkAddress(new LinkAddress(dns, RFC7421_PREFIX_LENGTH));
- }
- }
-
- // [2] Add only the local DNS IP addresses that have not previously been added.
- if (newDnses != null && !newDnses.isEmpty()) {
- final HashSet<Inet6Address> addedDnses = (HashSet) newDnses.clone();
- if (mLastRaParams != null) {
- addedDnses.removeAll(mLastRaParams.dnses);
- }
-
- for (Inet6Address dns : addedDnses) {
- if (!mInterfaceCtrl.addAddress(dns, RFC7421_PREFIX_LENGTH)) {
- mLog.e("Failed to add local dns IP " + dns);
- newDnses.remove(dns);
- }
-
- mLinkProperties.addLinkAddress(new LinkAddress(dns, RFC7421_PREFIX_LENGTH));
- }
- }
-
- try {
- mNetd.tetherApplyDnsInterfaces();
- } catch (ServiceSpecificException | RemoteException e) {
- mLog.e("Failed to update local DNS caching server");
- if (newDnses != null) newDnses.clear();
- }
- }
-
- private void addIpv6ForwardingRule(Ipv6ForwardingRule rule) {
- // Theoretically, we don't need this check because IP neighbor monitor doesn't start if BPF
- // offload is disabled. Add this check just in case.
- // TODO: Perhaps remove this protection check.
- if (!mUsingBpfOffload) return;
-
- mBpfCoordinator.tetherOffloadRuleAdd(this, rule);
- }
-
- private void removeIpv6ForwardingRule(Ipv6ForwardingRule rule) {
- // TODO: Perhaps remove this protection check.
- // See the related comment in #addIpv6ForwardingRule.
- if (!mUsingBpfOffload) return;
-
- mBpfCoordinator.tetherOffloadRuleRemove(this, rule);
- }
-
- private void clearIpv6ForwardingRules() {
- if (!mUsingBpfOffload) return;
-
- mBpfCoordinator.tetherOffloadRuleClear(this);
- }
-
- private void updateIpv6ForwardingRule(int newIfindex) {
- // TODO: Perhaps remove this protection check.
- // See the related comment in #addIpv6ForwardingRule.
- if (!mUsingBpfOffload) return;
-
- mBpfCoordinator.tetherOffloadRuleUpdate(this, newIfindex);
- }
-
- // Handles all updates to IPv6 forwarding rules. These can currently change only if the upstream
- // changes or if a neighbor event is received.
- private void updateIpv6ForwardingRules(int prevUpstreamIfindex, int upstreamIfindex,
- NeighborEvent e) {
- // If we no longer have an upstream, clear forwarding rules and do nothing else.
- if (upstreamIfindex == 0) {
- clearIpv6ForwardingRules();
- return;
- }
-
- // If the upstream interface has changed, remove all rules and re-add them with the new
- // upstream interface.
- if (prevUpstreamIfindex != upstreamIfindex) {
- updateIpv6ForwardingRule(upstreamIfindex);
- }
-
- // If we're here to process a NeighborEvent, do so now.
- // mInterfaceParams must be non-null or the event would not have arrived.
- if (e == null) return;
- if (!(e.ip instanceof Inet6Address) || e.ip.isMulticastAddress()
- || e.ip.isLoopbackAddress() || e.ip.isLinkLocalAddress()) {
- return;
- }
-
- // When deleting rules, we still need to pass a non-null MAC, even though it's ignored.
- // Do this here instead of in the Ipv6ForwardingRule constructor to ensure that we never
- // add rules with a null MAC, only delete them.
- MacAddress dstMac = e.isValid() ? e.macAddr : NULL_MAC_ADDRESS;
- Ipv6ForwardingRule rule = new Ipv6ForwardingRule(upstreamIfindex,
- mInterfaceParams.index, (Inet6Address) e.ip, mInterfaceParams.macAddr, dstMac);
- if (e.isValid()) {
- addIpv6ForwardingRule(rule);
- } else {
- removeIpv6ForwardingRule(rule);
- }
- }
-
- private void handleNeighborEvent(NeighborEvent e) {
- if (mInterfaceParams != null
- && mInterfaceParams.index == e.ifindex
- && mInterfaceParams.hasMacAddress) {
- updateIpv6ForwardingRules(mLastIPv6UpstreamIfindex, mLastIPv6UpstreamIfindex, e);
- }
- }
-
- private void handleNewPrefixRequest(@NonNull final IpPrefix currentPrefix) {
- if (!currentPrefix.contains(mIpv4Address.getAddress())
- || currentPrefix.getPrefixLength() != mIpv4Address.getPrefixLength()) {
- Log.e(TAG, "Invalid prefix: " + currentPrefix);
- return;
- }
-
- final LinkAddress deprecatedLinkAddress = mIpv4Address;
- mIpv4Address = requestIpv4Address(false);
- if (mIpv4Address == null) {
- mLog.e("Fail to request a new downstream prefix");
- return;
- }
- final Inet4Address srvAddr = (Inet4Address) mIpv4Address.getAddress();
-
- // Add new IPv4 address on the interface.
- if (!mInterfaceCtrl.addAddress(srvAddr, currentPrefix.getPrefixLength())) {
- mLog.e("Failed to add new IP " + srvAddr);
- return;
- }
-
- // Remove deprecated routes from local network.
- removeRoutesFromLocalNetwork(
- Collections.singletonList(getDirectConnectedRoute(deprecatedLinkAddress)));
- mLinkProperties.removeLinkAddress(deprecatedLinkAddress);
-
- // Add new routes to local network.
- addRoutesToLocalNetwork(
- Collections.singletonList(getDirectConnectedRoute(mIpv4Address)));
- mLinkProperties.addLinkAddress(mIpv4Address);
-
- // Update local DNS caching server with new IPv4 address, otherwise, dnsmasq doesn't
- // listen on the interface configured with new IPv4 address, that results DNS validation
- // failure of downstream client even if appropriate routes have been configured.
- try {
- mNetd.tetherApplyDnsInterfaces();
- } catch (ServiceSpecificException | RemoteException e) {
- mLog.e("Failed to update local DNS caching server");
- return;
- }
- sendLinkProperties();
-
- // Notify DHCP server that new prefix/route has been applied on IpServer.
- final Inet4Address clientAddr = mStaticIpv4ClientAddr == null ? null :
- (Inet4Address) mStaticIpv4ClientAddr.getAddress();
- final DhcpServingParamsParcel params = makeServingParams(srvAddr /* defaultRouter */,
- srvAddr /* dnsServer */, mIpv4Address /* serverLinkAddress */, clientAddr);
- try {
- mDhcpServer.updateParams(params, new OnHandlerStatusCallback() {
- @Override
- public void callback(int statusCode) {
- if (statusCode != STATUS_SUCCESS) {
- mLog.e("Error updating DHCP serving params: " + statusCode);
- }
- }
- });
- } catch (RemoteException e) {
- mLog.e("Error updating DHCP serving params", e);
- }
- }
-
- private byte getHopLimit(String upstreamIface, int adjustTTL) {
- try {
- int upstreamHopLimit = Integer.parseUnsignedInt(
- mNetd.getProcSysNet(INetd.IPV6, INetd.CONF, upstreamIface, "hop_limit"));
- upstreamHopLimit = upstreamHopLimit + adjustTTL;
- // Cap the hop limit to 255.
- return (byte) Integer.min(upstreamHopLimit, 255);
- } catch (Exception e) {
- mLog.e("Failed to find upstream interface hop limit", e);
- }
- return RaParams.DEFAULT_HOPLIMIT;
- }
-
- private void setRaParams(RaParams newParams) {
- if (mRaDaemon != null) {
- final RaParams deprecatedParams =
- RaParams.getDeprecatedRaParams(mLastRaParams, newParams);
-
- configureLocalIPv6Routes(deprecatedParams.prefixes,
- (newParams != null) ? newParams.prefixes : null);
-
- configureLocalIPv6Dns(deprecatedParams.dnses,
- (newParams != null) ? newParams.dnses : null);
-
- mRaDaemon.buildNewRa(deprecatedParams, newParams);
- }
-
- mLastRaParams = newParams;
- }
-
- private void logMessage(State state, int what) {
- mLog.log(state.getName() + " got " + sMagicDecoderRing.get(what, Integer.toString(what)));
- }
-
- private void sendInterfaceState(int newInterfaceState) {
- mServingMode = newInterfaceState;
- mCallback.updateInterfaceState(this, newInterfaceState, mLastError);
- sendLinkProperties();
- }
-
- private void sendLinkProperties() {
- mCallback.updateLinkProperties(this, new LinkProperties(mLinkProperties));
- }
-
- private void resetLinkProperties() {
- mLinkProperties.clear();
- mLinkProperties.setInterfaceName(mIfaceName);
- }
-
- private void maybeConfigureStaticIp(final TetheringRequestParcel request) {
- // Ignore static address configuration if they are invalid or null. In theory, static
- // addresses should not be invalid here because TetheringManager do not allow caller to
- // specify invalid static address configuration.
- if (request == null || request.localIPv4Address == null
- || request.staticClientAddress == null || !checkStaticAddressConfiguration(
- request.localIPv4Address, request.staticClientAddress)) {
- return;
- }
-
- mStaticIpv4ServerAddr = request.localIPv4Address;
- mStaticIpv4ClientAddr = request.staticClientAddress;
- }
-
- class InitialState extends State {
- @Override
- public void enter() {
- sendInterfaceState(STATE_AVAILABLE);
- }
-
- @Override
- public boolean processMessage(Message message) {
- logMessage(this, message.what);
- switch (message.what) {
- case CMD_TETHER_REQUESTED:
- mLastError = TetheringManager.TETHER_ERROR_NO_ERROR;
- switch (message.arg1) {
- case STATE_LOCAL_ONLY:
- maybeConfigureStaticIp((TetheringRequestParcel) message.obj);
- transitionTo(mLocalHotspotState);
- break;
- case STATE_TETHERED:
- maybeConfigureStaticIp((TetheringRequestParcel) message.obj);
- transitionTo(mTetheredState);
- break;
- default:
- mLog.e("Invalid tethering interface serving state specified.");
- }
- break;
- case CMD_INTERFACE_DOWN:
- transitionTo(mUnavailableState);
- break;
- case CMD_IPV6_TETHER_UPDATE:
- updateUpstreamIPv6LinkProperties((LinkProperties) message.obj, message.arg1);
- break;
- default:
- return NOT_HANDLED;
- }
- return HANDLED;
- }
- }
-
- class BaseServingState extends State {
- @Override
- public void enter() {
- if (!startIPv4()) {
- mLastError = TetheringManager.TETHER_ERROR_IFACE_CFG_ERROR;
- return;
- }
-
- try {
- NetdUtils.tetherInterface(mNetd, mIfaceName, asIpPrefix(mIpv4Address));
- } catch (RemoteException | ServiceSpecificException | IllegalStateException e) {
- mLog.e("Error Tethering", e);
- mLastError = TetheringManager.TETHER_ERROR_TETHER_IFACE_ERROR;
- return;
- }
-
- if (!startIPv6()) {
- mLog.e("Failed to startIPv6");
- // TODO: Make this a fatal error once Bluetooth IPv6 is sorted.
- return;
- }
- }
-
- @Override
- public void exit() {
- // Note that at this point, we're leaving the tethered state. We can fail any
- // of these operations, but it doesn't really change that we have to try them
- // all in sequence.
- stopIPv6();
-
- try {
- NetdUtils.untetherInterface(mNetd, mIfaceName);
- } catch (RemoteException | ServiceSpecificException e) {
- mLastError = TetheringManager.TETHER_ERROR_UNTETHER_IFACE_ERROR;
- mLog.e("Failed to untether interface: " + e);
- }
-
- stopIPv4();
-
- resetLinkProperties();
- }
-
- @Override
- public boolean processMessage(Message message) {
- logMessage(this, message.what);
- switch (message.what) {
- case CMD_TETHER_UNREQUESTED:
- transitionTo(mInitialState);
- if (DBG) Log.d(TAG, "Untethered (unrequested)" + mIfaceName);
- break;
- case CMD_INTERFACE_DOWN:
- transitionTo(mUnavailableState);
- if (DBG) Log.d(TAG, "Untethered (ifdown)" + mIfaceName);
- break;
- case CMD_IPV6_TETHER_UPDATE:
- updateUpstreamIPv6LinkProperties((LinkProperties) message.obj, message.arg1);
- sendLinkProperties();
- break;
- case CMD_IP_FORWARDING_ENABLE_ERROR:
- case CMD_IP_FORWARDING_DISABLE_ERROR:
- case CMD_START_TETHERING_ERROR:
- case CMD_STOP_TETHERING_ERROR:
- case CMD_SET_DNS_FORWARDERS_ERROR:
- mLastError = TetheringManager.TETHER_ERROR_INTERNAL_ERROR;
- transitionTo(mInitialState);
- break;
- case CMD_NEW_PREFIX_REQUEST:
- handleNewPrefixRequest((IpPrefix) message.obj);
- break;
- case CMD_NOTIFY_PREFIX_CONFLICT:
- mLog.i("restart tethering: " + mInterfaceType);
- mCallback.requestEnableTethering(mInterfaceType, false /* enabled */);
- transitionTo(mWaitingForRestartState);
- break;
- default:
- return false;
- }
- return true;
- }
- }
-
- // Handling errors in BaseServingState.enter() by transitioning is
- // problematic because transitioning during a multi-state jump yields
- // a Log.wtf(). Ultimately, there should be only one ServingState,
- // and forwarding and NAT rules should be handled by a coordinating
- // functional element outside of IpServer.
- class LocalHotspotState extends BaseServingState {
- @Override
- public void enter() {
- super.enter();
- if (mLastError != TetheringManager.TETHER_ERROR_NO_ERROR) {
- transitionTo(mInitialState);
- }
-
- if (DBG) Log.d(TAG, "Local hotspot " + mIfaceName);
- sendInterfaceState(STATE_LOCAL_ONLY);
- }
-
- @Override
- public boolean processMessage(Message message) {
- if (super.processMessage(message)) return true;
-
- logMessage(this, message.what);
- switch (message.what) {
- case CMD_TETHER_REQUESTED:
- mLog.e("CMD_TETHER_REQUESTED while in local-only hotspot mode.");
- break;
- case CMD_TETHER_CONNECTION_CHANGED:
- // Ignored in local hotspot state.
- break;
- default:
- return false;
- }
- return true;
- }
- }
-
- // Handling errors in BaseServingState.enter() by transitioning is
- // problematic because transitioning during a multi-state jump yields
- // a Log.wtf(). Ultimately, there should be only one ServingState,
- // and forwarding and NAT rules should be handled by a coordinating
- // functional element outside of IpServer.
- class TetheredState extends BaseServingState {
- @Override
- public void enter() {
- super.enter();
- if (mLastError != TetheringManager.TETHER_ERROR_NO_ERROR) {
- transitionTo(mInitialState);
- }
-
- if (DBG) Log.d(TAG, "Tethered " + mIfaceName);
- sendInterfaceState(STATE_TETHERED);
- }
-
- @Override
- public void exit() {
- cleanupUpstream();
- super.exit();
- }
-
- private void cleanupUpstream() {
- if (mUpstreamIfaceSet == null) return;
-
- for (String ifname : mUpstreamIfaceSet.ifnames) cleanupUpstreamInterface(ifname);
- mUpstreamIfaceSet = null;
- clearIpv6ForwardingRules();
- }
-
- private void cleanupUpstreamInterface(String upstreamIface) {
- // Note that we don't care about errors here.
- // Sometimes interfaces are gone before we get
- // to remove their rules, which generates errors.
- // Just do the best we can.
- try {
- mNetd.ipfwdRemoveInterfaceForward(mIfaceName, upstreamIface);
- } catch (RemoteException | ServiceSpecificException e) {
- mLog.e("Exception in ipfwdRemoveInterfaceForward: " + e.toString());
- }
- try {
- mNetd.tetherRemoveForward(mIfaceName, upstreamIface);
- } catch (RemoteException | ServiceSpecificException e) {
- mLog.e("Exception in disableNat: " + e.toString());
- }
- }
-
- @Override
- public boolean processMessage(Message message) {
- if (super.processMessage(message)) return true;
-
- logMessage(this, message.what);
- switch (message.what) {
- case CMD_TETHER_REQUESTED:
- mLog.e("CMD_TETHER_REQUESTED while already tethering.");
- break;
- case CMD_TETHER_CONNECTION_CHANGED:
- final InterfaceSet newUpstreamIfaceSet = (InterfaceSet) message.obj;
- if (noChangeInUpstreamIfaceSet(newUpstreamIfaceSet)) {
- if (VDBG) Log.d(TAG, "Connection changed noop - dropping");
- break;
- }
-
- if (newUpstreamIfaceSet == null) {
- cleanupUpstream();
- break;
- }
-
- for (String removed : upstreamInterfacesRemoved(newUpstreamIfaceSet)) {
- cleanupUpstreamInterface(removed);
- }
-
- final Set<String> added = upstreamInterfacesAdd(newUpstreamIfaceSet);
- // This makes the call to cleanupUpstream() in the error
- // path for any interface neatly cleanup all the interfaces.
- mUpstreamIfaceSet = newUpstreamIfaceSet;
-
- for (String ifname : added) {
- try {
- mNetd.tetherAddForward(mIfaceName, ifname);
- mNetd.ipfwdAddInterfaceForward(mIfaceName, ifname);
- } catch (RemoteException | ServiceSpecificException e) {
- mLog.e("Exception enabling NAT: " + e.toString());
- cleanupUpstream();
- mLastError = TetheringManager.TETHER_ERROR_ENABLE_FORWARDING_ERROR;
- transitionTo(mInitialState);
- return true;
- }
- }
- break;
- case CMD_NEIGHBOR_EVENT:
- handleNeighborEvent((NeighborEvent) message.obj);
- break;
- default:
- return false;
- }
- return true;
- }
-
- private boolean noChangeInUpstreamIfaceSet(InterfaceSet newIfaces) {
- if (mUpstreamIfaceSet == null && newIfaces == null) return true;
- if (mUpstreamIfaceSet != null && newIfaces != null) {
- return mUpstreamIfaceSet.equals(newIfaces);
- }
- return false;
- }
-
- private Set<String> upstreamInterfacesRemoved(InterfaceSet newIfaces) {
- if (mUpstreamIfaceSet == null) return new HashSet<>();
-
- final HashSet<String> removed = new HashSet<>(mUpstreamIfaceSet.ifnames);
- removed.removeAll(newIfaces.ifnames);
- return removed;
- }
-
- private Set<String> upstreamInterfacesAdd(InterfaceSet newIfaces) {
- final HashSet<String> added = new HashSet<>(newIfaces.ifnames);
- if (mUpstreamIfaceSet != null) added.removeAll(mUpstreamIfaceSet.ifnames);
- return added;
- }
- }
-
- /**
- * This state is terminal for the per interface state machine. At this
- * point, the tethering main state machine should have removed this interface
- * specific state machine from its list of possible recipients of
- * tethering requests. The state machine itself will hang around until
- * the garbage collector finds it.
- */
- class UnavailableState extends State {
- @Override
- public void enter() {
- mIpNeighborMonitor.stop();
- mLastError = TetheringManager.TETHER_ERROR_NO_ERROR;
- sendInterfaceState(STATE_UNAVAILABLE);
- }
- }
-
- class WaitingForRestartState extends State {
- @Override
- public boolean processMessage(Message message) {
- logMessage(this, message.what);
- switch (message.what) {
- case CMD_TETHER_UNREQUESTED:
- transitionTo(mInitialState);
- mLog.i("Untethered (unrequested) and restarting " + mIfaceName);
- mCallback.requestEnableTethering(mInterfaceType, true /* enabled */);
- break;
- case CMD_INTERFACE_DOWN:
- transitionTo(mUnavailableState);
- mLog.i("Untethered (interface down) and restarting" + mIfaceName);
- mCallback.requestEnableTethering(mInterfaceType, true /* enabled */);
- break;
- default:
- return false;
- }
- return true;
- }
- }
-
- // Accumulate routes representing "prefixes to be assigned to the local
- // interface", for subsequent modification of local_network routing.
- private static ArrayList<RouteInfo> getLocalRoutesFor(
- String ifname, HashSet<IpPrefix> prefixes) {
- final ArrayList<RouteInfo> localRoutes = new ArrayList<RouteInfo>();
- for (IpPrefix ipp : prefixes) {
- localRoutes.add(new RouteInfo(ipp, null, ifname, RTN_UNICAST));
- }
- return localRoutes;
- }
-
- // Given a prefix like 2001:db8::/64 return an address like 2001:db8::1.
- private static Inet6Address getLocalDnsIpFor(IpPrefix localPrefix) {
- final byte[] dnsBytes = localPrefix.getRawAddress();
- dnsBytes[dnsBytes.length - 1] = getRandomSanitizedByte(DOUG_ADAMS, asByte(0), asByte(1));
- try {
- return Inet6Address.getByAddress(null, dnsBytes, 0);
- } catch (UnknownHostException e) {
- Log.wtf(TAG, "Failed to construct Inet6Address from: " + localPrefix);
- return null;
- }
- }
-
- private static byte getRandomSanitizedByte(byte dflt, byte... excluded) {
- final byte random = (byte) (new Random()).nextInt();
- for (int value : excluded) {
- if (random == value) return dflt;
- }
- return random;
- }
-}
diff --git a/packages/Tethering/src/android/net/ip/NeighborPacketForwarder.java b/packages/Tethering/src/android/net/ip/NeighborPacketForwarder.java
deleted file mode 100644
index 73fc833..0000000
--- a/packages/Tethering/src/android/net/ip/NeighborPacketForwarder.java
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * 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 android.net.ip;
-
-import static android.system.OsConstants.AF_INET6;
-import static android.system.OsConstants.AF_PACKET;
-import static android.system.OsConstants.ETH_P_IPV6;
-import static android.system.OsConstants.IPPROTO_RAW;
-import static android.system.OsConstants.SOCK_DGRAM;
-import static android.system.OsConstants.SOCK_NONBLOCK;
-import static android.system.OsConstants.SOCK_RAW;
-
-import android.net.util.InterfaceParams;
-import android.net.util.PacketReader;
-import android.net.util.SocketUtils;
-import android.net.util.TetheringUtils;
-import android.os.Handler;
-import android.system.ErrnoException;
-import android.system.Os;
-import android.util.Log;
-
-import java.io.FileDescriptor;
-import java.io.IOException;
-import java.net.Inet6Address;
-import java.net.InetSocketAddress;
-import java.net.SocketAddress;
-import java.net.SocketException;
-import java.net.UnknownHostException;
-import java.util.Arrays;
-
-/**
- * Basic IPv6 Neighbor Advertisement Forwarder.
- *
- * Forward NA packets from upstream iface to tethered iface
- * and NS packets from tethered iface to upstream iface.
- *
- * @hide
- */
-public class NeighborPacketForwarder extends PacketReader {
- private final String mTag;
-
- private FileDescriptor mFd;
-
- // TODO: get these from NetworkStackConstants.
- private static final int IPV6_ADDR_LEN = 16;
- private static final int IPV6_DST_ADDR_OFFSET = 24;
- private static final int IPV6_HEADER_LEN = 40;
- private static final int ETH_HEADER_LEN = 14;
-
- private InterfaceParams mListenIfaceParams, mSendIfaceParams;
-
- private final int mType;
- public static final int ICMPV6_NEIGHBOR_ADVERTISEMENT = 136;
- public static final int ICMPV6_NEIGHBOR_SOLICITATION = 135;
-
- public NeighborPacketForwarder(Handler h, InterfaceParams tetheredInterface, int type) {
- super(h);
- mTag = NeighborPacketForwarder.class.getSimpleName() + "-"
- + tetheredInterface.name + "-" + type;
- mType = type;
-
- if (mType == ICMPV6_NEIGHBOR_ADVERTISEMENT) {
- mSendIfaceParams = tetheredInterface;
- } else {
- mListenIfaceParams = tetheredInterface;
- }
- }
-
- /** Set new upstream iface and start/stop based on new params. */
- public void setUpstreamIface(InterfaceParams upstreamParams) {
- final InterfaceParams oldUpstreamParams;
-
- if (mType == ICMPV6_NEIGHBOR_ADVERTISEMENT) {
- oldUpstreamParams = mListenIfaceParams;
- mListenIfaceParams = upstreamParams;
- } else {
- oldUpstreamParams = mSendIfaceParams;
- mSendIfaceParams = upstreamParams;
- }
-
- if (oldUpstreamParams == null && upstreamParams != null) {
- start();
- } else if (oldUpstreamParams != null && upstreamParams == null) {
- stop();
- } else if (oldUpstreamParams != null && upstreamParams != null
- && oldUpstreamParams.index != upstreamParams.index) {
- stop();
- start();
- }
- }
-
- // TODO: move NetworkStackUtils.closeSocketQuietly to
- // frameworks/libs/net/common/device/com/android/net/module/util/[someclass].
- private void closeSocketQuietly(FileDescriptor fd) {
- try {
- SocketUtils.closeSocket(fd);
- } catch (IOException ignored) {
- }
- }
-
- @Override
- protected FileDescriptor createFd() {
- try {
- // ICMPv6 packets from modem do not have eth header, so RAW socket cannot be used.
- // To keep uniformity in both directions PACKET socket can be used.
- mFd = Os.socket(AF_PACKET, SOCK_DGRAM | SOCK_NONBLOCK, 0);
-
- // TODO: convert setup*Socket to setupICMPv6BpfFilter with filter type?
- if (mType == ICMPV6_NEIGHBOR_ADVERTISEMENT) {
- TetheringUtils.setupNaSocket(mFd);
- } else if (mType == ICMPV6_NEIGHBOR_SOLICITATION) {
- TetheringUtils.setupNsSocket(mFd);
- }
-
- SocketAddress bindAddress = SocketUtils.makePacketSocketAddress(
- ETH_P_IPV6, mListenIfaceParams.index);
- Os.bind(mFd, bindAddress);
- } catch (ErrnoException | SocketException e) {
- Log.wtf(mTag, "Failed to create socket", e);
- closeSocketQuietly(mFd);
- return null;
- }
-
- return mFd;
- }
-
- private Inet6Address getIpv6DestinationAddress(byte[] recvbuf) {
- Inet6Address dstAddr;
- try {
- dstAddr = (Inet6Address) Inet6Address.getByAddress(Arrays.copyOfRange(recvbuf,
- IPV6_DST_ADDR_OFFSET, IPV6_DST_ADDR_OFFSET + IPV6_ADDR_LEN));
- } catch (UnknownHostException | ClassCastException impossible) {
- throw new AssertionError("16-byte array not valid IPv6 address?");
- }
- return dstAddr;
- }
-
- @Override
- protected void handlePacket(byte[] recvbuf, int length) {
- if (mSendIfaceParams == null) {
- return;
- }
-
- // The BPF filter should already have checked the length of the packet, but...
- if (length < IPV6_HEADER_LEN) {
- return;
- }
- Inet6Address destv6 = getIpv6DestinationAddress(recvbuf);
- if (!destv6.isMulticastAddress()) {
- return;
- }
- InetSocketAddress dest = new InetSocketAddress(destv6, 0);
-
- FileDescriptor fd = null;
- try {
- fd = Os.socket(AF_INET6, SOCK_RAW | SOCK_NONBLOCK, IPPROTO_RAW);
- SocketUtils.bindSocketToInterface(fd, mSendIfaceParams.name);
-
- int ret = Os.sendto(fd, recvbuf, 0, length, 0, dest);
- } catch (ErrnoException | SocketException e) {
- Log.e(mTag, "handlePacket error: " + e);
- } finally {
- closeSocketQuietly(fd);
- }
- }
-}
diff --git a/packages/Tethering/src/android/net/ip/RouterAdvertisementDaemon.java b/packages/Tethering/src/android/net/ip/RouterAdvertisementDaemon.java
deleted file mode 100644
index 7c0b7cc7..0000000
--- a/packages/Tethering/src/android/net/ip/RouterAdvertisementDaemon.java
+++ /dev/null
@@ -1,744 +0,0 @@
-/*
- * Copyright (C) 2016 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 android.net.ip;
-
-import static android.net.util.NetworkConstants.IPV6_MIN_MTU;
-import static android.net.util.NetworkConstants.RFC7421_PREFIX_LENGTH;
-import static android.net.util.TetheringUtils.getAllNodesForScopeId;
-import static android.system.OsConstants.AF_INET6;
-import static android.system.OsConstants.IPPROTO_ICMPV6;
-import static android.system.OsConstants.SOCK_RAW;
-import static android.system.OsConstants.SOL_SOCKET;
-import static android.system.OsConstants.SO_SNDTIMEO;
-
-import android.net.IpPrefix;
-import android.net.LinkAddress;
-import android.net.TrafficStats;
-import android.net.util.InterfaceParams;
-import android.net.util.SocketUtils;
-import android.net.util.TetheringUtils;
-import android.system.ErrnoException;
-import android.system.Os;
-import android.system.StructTimeval;
-import android.util.Log;
-
-import com.android.internal.annotations.GuardedBy;
-import com.android.internal.util.TrafficStatsConstants;
-
-import java.io.FileDescriptor;
-import java.io.IOException;
-import java.net.Inet6Address;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.net.SocketException;
-import java.nio.BufferOverflowException;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Random;
-import java.util.Set;
-import java.util.concurrent.atomic.AtomicInteger;
-
-
-/**
- * Basic IPv6 Router Advertisement Daemon.
- *
- * TODO:
- *
- * - Rewrite using Handler (and friends) so that AlarmManager can deliver
- * "kick" messages when it's time to send a multicast RA.
- *
- * @hide
- */
-public class RouterAdvertisementDaemon {
- private static final String TAG = RouterAdvertisementDaemon.class.getSimpleName();
- private static final byte ICMPV6_ND_ROUTER_SOLICIT = asByte(133);
- private static final byte ICMPV6_ND_ROUTER_ADVERT = asByte(134);
- private static final int MIN_RA_HEADER_SIZE = 16;
-
- // Summary of various timers and lifetimes.
- private static final int MIN_RTR_ADV_INTERVAL_SEC = 300;
- private static final int MAX_RTR_ADV_INTERVAL_SEC = 600;
- // In general, router, prefix, and DNS lifetimes are all advised to be
- // greater than or equal to 3 * MAX_RTR_ADV_INTERVAL. Here, we double
- // that to allow for multicast packet loss.
- //
- // This MAX_RTR_ADV_INTERVAL_SEC and DEFAULT_LIFETIME are also consistent
- // with the https://tools.ietf.org/html/rfc7772#section-4 discussion of
- // "approximately 7 RAs per hour".
- private static final int DEFAULT_LIFETIME = 6 * MAX_RTR_ADV_INTERVAL_SEC;
- // From https://tools.ietf.org/html/rfc4861#section-10 .
- private static final int MIN_DELAY_BETWEEN_RAS_SEC = 3;
- // Both initial and final RAs, but also for changes in RA contents.
- // From https://tools.ietf.org/html/rfc4861#section-10 .
- private static final int MAX_URGENT_RTR_ADVERTISEMENTS = 5;
-
- private static final int DAY_IN_SECONDS = 86_400;
-
- private final InterfaceParams mInterface;
- private final InetSocketAddress mAllNodes;
-
- // This lock is to protect the RA from being updated while being
- // transmitted on another thread (multicast or unicast).
- //
- // TODO: This should be handled with a more RCU-like approach.
- private final Object mLock = new Object();
- @GuardedBy("mLock")
- private final byte[] mRA = new byte[IPV6_MIN_MTU];
- @GuardedBy("mLock")
- private int mRaLength;
- @GuardedBy("mLock")
- private final DeprecatedInfoTracker mDeprecatedInfoTracker;
- @GuardedBy("mLock")
- private RaParams mRaParams;
-
- private volatile FileDescriptor mSocket;
- private volatile MulticastTransmitter mMulticastTransmitter;
- private volatile UnicastResponder mUnicastResponder;
-
- /** Encapsulate the RA parameters for RouterAdvertisementDaemon.*/
- public static class RaParams {
- // Tethered traffic will have the hop limit properly decremented.
- // Consequently, set the hoplimit greater by one than the upstream
- // unicast hop limit.
- //
- // TODO: Dynamically pass down the IPV6_UNICAST_HOPS value from the
- // upstream interface for more correct behaviour.
- static final byte DEFAULT_HOPLIMIT = 65;
-
- public boolean hasDefaultRoute;
- public byte hopLimit;
- public int mtu;
- public HashSet<IpPrefix> prefixes;
- public HashSet<Inet6Address> dnses;
-
- public RaParams() {
- hasDefaultRoute = false;
- hopLimit = DEFAULT_HOPLIMIT;
- mtu = IPV6_MIN_MTU;
- prefixes = new HashSet<IpPrefix>();
- dnses = new HashSet<Inet6Address>();
- }
-
- public RaParams(RaParams other) {
- hasDefaultRoute = other.hasDefaultRoute;
- hopLimit = other.hopLimit;
- mtu = other.mtu;
- prefixes = (HashSet) other.prefixes.clone();
- dnses = (HashSet) other.dnses.clone();
- }
-
- /**
- * Returns the subset of RA parameters that become deprecated when
- * moving from announcing oldRa to announcing newRa.
- *
- * Currently only tracks differences in |prefixes| and |dnses|.
- */
- public static RaParams getDeprecatedRaParams(RaParams oldRa, RaParams newRa) {
- RaParams newlyDeprecated = new RaParams();
-
- if (oldRa != null) {
- for (IpPrefix ipp : oldRa.prefixes) {
- if (newRa == null || !newRa.prefixes.contains(ipp)) {
- newlyDeprecated.prefixes.add(ipp);
- }
- }
-
- for (Inet6Address dns : oldRa.dnses) {
- if (newRa == null || !newRa.dnses.contains(dns)) {
- newlyDeprecated.dnses.add(dns);
- }
- }
- }
-
- return newlyDeprecated;
- }
- }
-
- private static class DeprecatedInfoTracker {
- private final HashMap<IpPrefix, Integer> mPrefixes = new HashMap<>();
- private final HashMap<Inet6Address, Integer> mDnses = new HashMap<>();
-
- Set<IpPrefix> getPrefixes() {
- return mPrefixes.keySet();
- }
-
- void putPrefixes(Set<IpPrefix> prefixes) {
- for (IpPrefix ipp : prefixes) {
- mPrefixes.put(ipp, MAX_URGENT_RTR_ADVERTISEMENTS);
- }
- }
-
- void removePrefixes(Set<IpPrefix> prefixes) {
- for (IpPrefix ipp : prefixes) {
- mPrefixes.remove(ipp);
- }
- }
-
- Set<Inet6Address> getDnses() {
- return mDnses.keySet();
- }
-
- void putDnses(Set<Inet6Address> dnses) {
- for (Inet6Address dns : dnses) {
- mDnses.put(dns, MAX_URGENT_RTR_ADVERTISEMENTS);
- }
- }
-
- void removeDnses(Set<Inet6Address> dnses) {
- for (Inet6Address dns : dnses) {
- mDnses.remove(dns);
- }
- }
-
- boolean isEmpty() {
- return mPrefixes.isEmpty() && mDnses.isEmpty();
- }
-
- private boolean decrementCounters() {
- boolean removed = decrementCounter(mPrefixes);
- removed |= decrementCounter(mDnses);
- return removed;
- }
-
- private <T> boolean decrementCounter(HashMap<T, Integer> map) {
- boolean removed = false;
-
- for (Iterator<Map.Entry<T, Integer>> it = map.entrySet().iterator();
- it.hasNext();) {
- Map.Entry<T, Integer> kv = it.next();
- if (kv.getValue() == 0) {
- it.remove();
- removed = true;
- } else {
- kv.setValue(kv.getValue() - 1);
- }
- }
-
- return removed;
- }
- }
-
- public RouterAdvertisementDaemon(InterfaceParams ifParams) {
- mInterface = ifParams;
- mAllNodes = new InetSocketAddress(getAllNodesForScopeId(mInterface.index), 0);
- mDeprecatedInfoTracker = new DeprecatedInfoTracker();
- }
-
- /** Build new RA.*/
- public void buildNewRa(RaParams deprecatedParams, RaParams newParams) {
- synchronized (mLock) {
- if (deprecatedParams != null) {
- mDeprecatedInfoTracker.putPrefixes(deprecatedParams.prefixes);
- mDeprecatedInfoTracker.putDnses(deprecatedParams.dnses);
- }
-
- if (newParams != null) {
- // Process information that is no longer deprecated.
- mDeprecatedInfoTracker.removePrefixes(newParams.prefixes);
- mDeprecatedInfoTracker.removeDnses(newParams.dnses);
- }
-
- mRaParams = newParams;
- assembleRaLocked();
- }
-
- maybeNotifyMulticastTransmitter();
- }
-
- /** Start router advertisement daemon. */
- public boolean start() {
- if (!createSocket()) {
- return false;
- }
-
- mMulticastTransmitter = new MulticastTransmitter();
- mMulticastTransmitter.start();
-
- mUnicastResponder = new UnicastResponder();
- mUnicastResponder.start();
-
- return true;
- }
-
- /** Stop router advertisement daemon. */
- public void stop() {
- closeSocket();
- // Wake up mMulticastTransmitter thread to interrupt a potential 1 day sleep before
- // the thread's termination.
- maybeNotifyMulticastTransmitter();
- mMulticastTransmitter = null;
- mUnicastResponder = null;
- }
-
- @GuardedBy("mLock")
- private void assembleRaLocked() {
- final ByteBuffer ra = ByteBuffer.wrap(mRA);
- ra.order(ByteOrder.BIG_ENDIAN);
-
- final boolean haveRaParams = (mRaParams != null);
- boolean shouldSendRA = false;
-
- try {
- putHeader(ra, haveRaParams && mRaParams.hasDefaultRoute,
- haveRaParams ? mRaParams.hopLimit : RaParams.DEFAULT_HOPLIMIT);
- putSlla(ra, mInterface.macAddr.toByteArray());
- mRaLength = ra.position();
-
- // https://tools.ietf.org/html/rfc5175#section-4 says:
- //
- // "MUST NOT be added to a Router Advertisement message
- // if no flags in the option are set."
- //
- // putExpandedFlagsOption(ra);
-
- if (haveRaParams) {
- putMtu(ra, mRaParams.mtu);
- mRaLength = ra.position();
-
- for (IpPrefix ipp : mRaParams.prefixes) {
- putPio(ra, ipp, DEFAULT_LIFETIME, DEFAULT_LIFETIME);
- mRaLength = ra.position();
- shouldSendRA = true;
- }
-
- if (mRaParams.dnses.size() > 0) {
- putRdnss(ra, mRaParams.dnses, DEFAULT_LIFETIME);
- mRaLength = ra.position();
- shouldSendRA = true;
- }
- }
-
- for (IpPrefix ipp : mDeprecatedInfoTracker.getPrefixes()) {
- putPio(ra, ipp, 0, 0);
- mRaLength = ra.position();
- shouldSendRA = true;
- }
-
- final Set<Inet6Address> deprecatedDnses = mDeprecatedInfoTracker.getDnses();
- if (!deprecatedDnses.isEmpty()) {
- putRdnss(ra, deprecatedDnses, 0);
- mRaLength = ra.position();
- shouldSendRA = true;
- }
- } catch (BufferOverflowException e) {
- // The packet up to mRaLength is valid, since it has been updated
- // progressively as the RA was built. Log an error, and continue
- // on as best as possible.
- Log.e(TAG, "Could not construct new RA: " + e);
- }
-
- // We have nothing worth announcing; indicate as much to maybeSendRA().
- if (!shouldSendRA) {
- mRaLength = 0;
- }
- }
-
- private void maybeNotifyMulticastTransmitter() {
- final MulticastTransmitter m = mMulticastTransmitter;
- if (m != null) {
- m.hup();
- }
- }
-
- private static byte asByte(int value) {
- return (byte) value;
- }
- private static short asShort(int value) {
- return (short) value;
- }
-
- private static void putHeader(ByteBuffer ra, boolean hasDefaultRoute, byte hopLimit) {
- /**
- Router Advertisement Message Format
-
- 0 1 2 3
- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Type | Code | Checksum |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Cur Hop Limit |M|O|H|Prf|P|R|R| Router Lifetime |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Reachable Time |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Retrans Timer |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Options ...
- +-+-+-+-+-+-+-+-+-+-+-+-
- */
- ra.put(ICMPV6_ND_ROUTER_ADVERT)
- .put(asByte(0))
- .putShort(asShort(0))
- .put(hopLimit)
- // RFC 4191 "high" preference, iff. advertising a default route.
- .put(hasDefaultRoute ? asByte(0x08) : asByte(0))
- .putShort(hasDefaultRoute ? asShort(DEFAULT_LIFETIME) : asShort(0))
- .putInt(0)
- .putInt(0);
- }
-
- private static void putSlla(ByteBuffer ra, byte[] slla) {
- /**
- Source/Target Link-layer Address
-
- 0 1 2 3
- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Type | Length | Link-Layer Address ...
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
- if (slla == null || slla.length != 6) {
- // Only IEEE 802.3 6-byte addresses are supported.
- return;
- }
-
- final byte nd_option_slla = 1;
- final byte slla_num_8octets = 1;
- ra.put(nd_option_slla)
- .put(slla_num_8octets)
- .put(slla);
- }
-
- private static void putExpandedFlagsOption(ByteBuffer ra) {
- /**
- Router Advertisement Expanded Flags Option
-
- 0 1 2 3
- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Type | Length | Bit fields available ..
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- ... for assignment |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
-
- final byte nd_option__efo = 26;
- final byte efo_num_8octets = 1;
-
- ra.put(nd_option__efo)
- .put(efo_num_8octets)
- .putShort(asShort(0))
- .putInt(0);
- }
-
- private static void putMtu(ByteBuffer ra, int mtu) {
- /**
- MTU
-
- 0 1 2 3
- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Type | Length | Reserved |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | MTU |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
- final byte nd_option_mtu = 5;
- final byte mtu_num_8octs = 1;
- ra.put(nd_option_mtu)
- .put(mtu_num_8octs)
- .putShort(asShort(0))
- .putInt((mtu < IPV6_MIN_MTU) ? IPV6_MIN_MTU : mtu);
- }
-
- private static void putPio(ByteBuffer ra, IpPrefix ipp,
- int validTime, int preferredTime) {
- /**
- Prefix Information
-
- 0 1 2 3
- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Type | Length | Prefix Length |L|A| Reserved1 |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Valid Lifetime |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Preferred Lifetime |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Reserved2 |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | |
- + +
- | |
- + Prefix +
- | |
- + +
- | |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
- final int prefixLength = ipp.getPrefixLength();
- if (prefixLength != 64) {
- return;
- }
- final byte nd_option_pio = 3;
- final byte pio_num_8octets = 4;
-
- if (validTime < 0) validTime = 0;
- if (preferredTime < 0) preferredTime = 0;
- if (preferredTime > validTime) preferredTime = validTime;
-
- final byte[] addr = ipp.getAddress().getAddress();
- ra.put(nd_option_pio)
- .put(pio_num_8octets)
- .put(asByte(prefixLength))
- .put(asByte(0xc0)) /* L & A set */
- .putInt(validTime)
- .putInt(preferredTime)
- .putInt(0)
- .put(addr);
- }
-
- private static void putRio(ByteBuffer ra, IpPrefix ipp) {
- /**
- Route Information Option
-
- 0 1 2 3
- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Type | Length | Prefix Length |Resvd|Prf|Resvd|
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Route Lifetime |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Prefix (Variable Length) |
- . .
- . .
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
- final int prefixLength = ipp.getPrefixLength();
- if (prefixLength > 64) {
- return;
- }
- final byte nd_option_rio = 24;
- final byte rio_num_8octets = asByte(
- (prefixLength == 0) ? 1 : (prefixLength <= 8) ? 2 : 3);
-
- final byte[] addr = ipp.getAddress().getAddress();
- ra.put(nd_option_rio)
- .put(rio_num_8octets)
- .put(asByte(prefixLength))
- .put(asByte(0x18))
- .putInt(DEFAULT_LIFETIME);
-
- // Rely upon an IpPrefix's address being properly zeroed.
- if (prefixLength > 0) {
- ra.put(addr, 0, (prefixLength <= 64) ? 8 : 16);
- }
- }
-
- private static void putRdnss(ByteBuffer ra, Set<Inet6Address> dnses, int lifetime) {
- /**
- Recursive DNS Server (RDNSS) Option
-
- 0 1 2 3
- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Type | Length | Reserved |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Lifetime |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | |
- : Addresses of IPv6 Recursive DNS Servers :
- | |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
-
- final HashSet<Inet6Address> filteredDnses = new HashSet<>();
- for (Inet6Address dns : dnses) {
- if ((new LinkAddress(dns, RFC7421_PREFIX_LENGTH)).isGlobalPreferred()) {
- filteredDnses.add(dns);
- }
- }
- if (filteredDnses.isEmpty()) return;
-
- final byte nd_option_rdnss = 25;
- final byte rdnss_num_8octets = asByte(dnses.size() * 2 + 1);
- ra.put(nd_option_rdnss)
- .put(rdnss_num_8octets)
- .putShort(asShort(0))
- .putInt(lifetime);
-
- for (Inet6Address dns : filteredDnses) {
- // NOTE: If the full of list DNS servers doesn't fit in the packet,
- // this code will cause a buffer overflow and the RA won't include
- // this instance of the option at all.
- //
- // TODO: Consider looking at ra.remaining() to determine how many
- // DNS servers will fit, and adding only those.
- ra.put(dns.getAddress());
- }
- }
-
- private boolean createSocket() {
- final int send_timout_ms = 300;
-
- final int oldTag = TrafficStats.getAndSetThreadStatsTag(
- TrafficStatsConstants.TAG_SYSTEM_NEIGHBOR);
- try {
- mSocket = Os.socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
- // Setting SNDTIMEO is purely for defensive purposes.
- Os.setsockoptTimeval(
- mSocket, SOL_SOCKET, SO_SNDTIMEO, StructTimeval.fromMillis(send_timout_ms));
- SocketUtils.bindSocketToInterface(mSocket, mInterface.name);
- TetheringUtils.setupRaSocket(mSocket, mInterface.index);
- } catch (ErrnoException | IOException e) {
- Log.e(TAG, "Failed to create RA daemon socket: " + e);
- return false;
- } finally {
- TrafficStats.setThreadStatsTag(oldTag);
- }
-
- return true;
- }
-
- private void closeSocket() {
- if (mSocket != null) {
- try {
- SocketUtils.closeSocket(mSocket);
- } catch (IOException ignored) { }
- }
- mSocket = null;
- }
-
- private boolean isSocketValid() {
- final FileDescriptor s = mSocket;
- return (s != null) && s.valid();
- }
-
- private boolean isSuitableDestination(InetSocketAddress dest) {
- if (mAllNodes.equals(dest)) {
- return true;
- }
-
- final InetAddress destip = dest.getAddress();
- return (destip instanceof Inet6Address)
- && destip.isLinkLocalAddress()
- && (((Inet6Address) destip).getScopeId() == mInterface.index);
- }
-
- private void maybeSendRA(InetSocketAddress dest) {
- if (dest == null || !isSuitableDestination(dest)) {
- dest = mAllNodes;
- }
-
- try {
- synchronized (mLock) {
- if (mRaLength < MIN_RA_HEADER_SIZE) {
- // No actual RA to send.
- return;
- }
- Os.sendto(mSocket, mRA, 0, mRaLength, 0, dest);
- }
- Log.d(TAG, "RA sendto " + dest.getAddress().getHostAddress());
- } catch (ErrnoException | SocketException e) {
- if (isSocketValid()) {
- Log.e(TAG, "sendto error: " + e);
- }
- }
- }
-
- private final class UnicastResponder extends Thread {
- private final InetSocketAddress mSolicitor = new InetSocketAddress(0);
- // The recycled buffer for receiving Router Solicitations from clients.
- // If the RS is larger than IPV6_MIN_MTU the packets are truncated.
- // This is fine since currently only byte 0 is examined anyway.
- private final byte[] mSolicitation = new byte[IPV6_MIN_MTU];
-
- @Override
- public void run() {
- while (isSocketValid()) {
- try {
- // Blocking receive.
- final int rval = Os.recvfrom(
- mSocket, mSolicitation, 0, mSolicitation.length, 0, mSolicitor);
- // Do the least possible amount of validation.
- if (rval < 1 || mSolicitation[0] != ICMPV6_ND_ROUTER_SOLICIT) {
- continue;
- }
- } catch (ErrnoException | SocketException e) {
- if (isSocketValid()) {
- Log.e(TAG, "recvfrom error: " + e);
- }
- continue;
- }
-
- maybeSendRA(mSolicitor);
- }
- }
- }
-
- // TODO: Consider moving this to run on a provided Looper as a Handler,
- // with WakeupMessage-style messages providing the timer driven input.
- private final class MulticastTransmitter extends Thread {
- private final Random mRandom = new Random();
- private final AtomicInteger mUrgentAnnouncements = new AtomicInteger(0);
-
- @Override
- public void run() {
- while (isSocketValid()) {
- try {
- Thread.sleep(getNextMulticastTransmitDelayMs());
- } catch (InterruptedException ignored) {
- // Stop sleeping, immediately send an RA, and continue.
- }
-
- maybeSendRA(mAllNodes);
- synchronized (mLock) {
- if (mDeprecatedInfoTracker.decrementCounters()) {
- // At least one deprecated PIO has been removed;
- // reassemble the RA.
- assembleRaLocked();
- }
- }
- }
- }
-
- public void hup() {
- // Set to one fewer that the desired number, because as soon as
- // the thread interrupt is processed we immediately send an RA
- // and mUrgentAnnouncements is not examined until the subsequent
- // sleep interval computation (i.e. this way we send 3 and not 4).
- mUrgentAnnouncements.set(MAX_URGENT_RTR_ADVERTISEMENTS - 1);
- interrupt();
- }
-
- private int getNextMulticastTransmitDelaySec() {
- boolean deprecationInProgress = false;
- synchronized (mLock) {
- if (mRaLength < MIN_RA_HEADER_SIZE) {
- // No actual RA to send; just sleep for 1 day.
- return DAY_IN_SECONDS;
- }
- deprecationInProgress = !mDeprecatedInfoTracker.isEmpty();
- }
-
- final int urgentPending = mUrgentAnnouncements.getAndDecrement();
- if ((urgentPending > 0) || deprecationInProgress) {
- return MIN_DELAY_BETWEEN_RAS_SEC;
- }
-
- return MIN_RTR_ADV_INTERVAL_SEC + mRandom.nextInt(
- MAX_RTR_ADV_INTERVAL_SEC - MIN_RTR_ADV_INTERVAL_SEC);
- }
-
- private long getNextMulticastTransmitDelayMs() {
- return 1000 * (long) getNextMulticastTransmitDelaySec();
- }
- }
-}
diff --git a/packages/Tethering/src/android/net/util/BaseNetdUnsolicitedEventListener.java b/packages/Tethering/src/android/net/util/BaseNetdUnsolicitedEventListener.java
deleted file mode 100644
index b1ffdb0..0000000
--- a/packages/Tethering/src/android/net/util/BaseNetdUnsolicitedEventListener.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2019 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 android.net.util;
-
-import android.net.INetdUnsolicitedEventListener;
-
-import androidx.annotation.NonNull;
-
-/**
- * Base {@link INetdUnsolicitedEventListener} that provides no-op implementations which can be
- * overridden.
- */
-public class BaseNetdUnsolicitedEventListener extends INetdUnsolicitedEventListener.Stub {
-
- @Override
- public void onInterfaceClassActivityChanged(boolean isActive, int timerLabel, long timestampNs,
- int uid) { }
-
- @Override
- public void onQuotaLimitReached(@NonNull String alertName, @NonNull String ifName) { }
-
- @Override
- public void onInterfaceDnsServerInfo(@NonNull String ifName, long lifetimeS,
- @NonNull String[] servers) { }
-
- @Override
- public void onInterfaceAddressUpdated(@NonNull String addr, String ifName, int flags,
- int scope) { }
-
- @Override
- public void onInterfaceAddressRemoved(@NonNull String addr, @NonNull String ifName, int flags,
- int scope) { }
-
- @Override
- public void onInterfaceAdded(@NonNull String ifName) { }
-
- @Override
- public void onInterfaceRemoved(@NonNull String ifName) { }
-
- @Override
- public void onInterfaceChanged(@NonNull String ifName, boolean up) { }
-
- @Override
- public void onInterfaceLinkStateChanged(@NonNull String ifName, boolean up) { }
-
- @Override
- public void onRouteChanged(boolean updated, @NonNull String route, @NonNull String gateway,
- @NonNull String ifName) { }
-
- @Override
- public void onStrictCleartextDetected(int uid, @NonNull String hex) { }
-
- @Override
- public int getInterfaceVersion() {
- return INetdUnsolicitedEventListener.VERSION;
- }
-
- @Override
- public String getInterfaceHash() {
- return INetdUnsolicitedEventListener.HASH;
- }
-}
diff --git a/packages/Tethering/src/android/net/util/InterfaceSet.java b/packages/Tethering/src/android/net/util/InterfaceSet.java
deleted file mode 100644
index 7589787..0000000
--- a/packages/Tethering/src/android/net/util/InterfaceSet.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2018 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 android.net.util;
-
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.StringJoiner;
-
-
-/**
- * @hide
- */
-public class InterfaceSet {
- public final Set<String> ifnames;
-
- public InterfaceSet(String... names) {
- final Set<String> nameSet = new HashSet<>();
- for (String name : names) {
- if (name != null) nameSet.add(name);
- }
- ifnames = Collections.unmodifiableSet(nameSet);
- }
-
- @Override
- public String toString() {
- final StringJoiner sj = new StringJoiner(",", "[", "]");
- for (String ifname : ifnames) sj.add(ifname);
- return sj.toString();
- }
-
- @Override
- public boolean equals(Object obj) {
- return obj != null
- && obj instanceof InterfaceSet
- && ifnames.equals(((InterfaceSet) obj).ifnames);
- }
-}
diff --git a/packages/Tethering/src/android/net/util/PrefixUtils.java b/packages/Tethering/src/android/net/util/PrefixUtils.java
deleted file mode 100644
index f203e999..0000000
--- a/packages/Tethering/src/android/net/util/PrefixUtils.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2017 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 android.net.util;
-
-import android.net.IpPrefix;
-import android.net.LinkAddress;
-import android.net.LinkProperties;
-
-import java.net.Inet4Address;
-import java.net.InetAddress;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-
-
-/**
- * @hide
- */
-public class PrefixUtils {
- private static final IpPrefix[] MIN_NON_FORWARDABLE_PREFIXES = {
- pfx("127.0.0.0/8"), // IPv4 loopback
- pfx("169.254.0.0/16"), // IPv4 link-local, RFC3927#section-8
- pfx("::/3"),
- pfx("fe80::/64"), // IPv6 link-local
- pfx("fc00::/7"), // IPv6 ULA
- pfx("ff02::/8"), // IPv6 link-local multicast
- };
-
- public static final IpPrefix DEFAULT_WIFI_P2P_PREFIX = pfx("192.168.49.0/24");
-
- /** Get non forwardable prefixes. */
- public static Set<IpPrefix> getNonForwardablePrefixes() {
- final HashSet<IpPrefix> prefixes = new HashSet<>();
- addNonForwardablePrefixes(prefixes);
- return prefixes;
- }
-
- /** Add non forwardable prefixes. */
- public static void addNonForwardablePrefixes(Set<IpPrefix> prefixes) {
- Collections.addAll(prefixes, MIN_NON_FORWARDABLE_PREFIXES);
- }
-
- /** Get local prefixes from |lp|. */
- public static Set<IpPrefix> localPrefixesFrom(LinkProperties lp) {
- final HashSet<IpPrefix> localPrefixes = new HashSet<>();
- if (lp == null) return localPrefixes;
-
- for (LinkAddress addr : lp.getAllLinkAddresses()) {
- if (addr.getAddress().isLinkLocalAddress()) continue;
- localPrefixes.add(asIpPrefix(addr));
- }
- // TODO: Add directly-connected routes as well (ones from which we did
- // not also form a LinkAddress)?
-
- return localPrefixes;
- }
-
- /** Convert LinkAddress |addr| to IpPrefix. */
- public static IpPrefix asIpPrefix(LinkAddress addr) {
- return new IpPrefix(addr.getAddress(), addr.getPrefixLength());
- }
-
- /** Convert InetAddress |ip| to IpPrefix. */
- public static IpPrefix ipAddressAsPrefix(InetAddress ip) {
- final int bitLength = (ip instanceof Inet4Address)
- ? NetworkConstants.IPV4_ADDR_BITS
- : NetworkConstants.IPV6_ADDR_BITS;
- return new IpPrefix(ip, bitLength);
- }
-
- private static IpPrefix pfx(String prefixStr) {
- return new IpPrefix(prefixStr);
- }
-}
diff --git a/packages/Tethering/src/android/net/util/TetheringMessageBase.java b/packages/Tethering/src/android/net/util/TetheringMessageBase.java
deleted file mode 100644
index 29c0a81..0000000
--- a/packages/Tethering/src/android/net/util/TetheringMessageBase.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * 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 android.net.util;
-
-/**
- * This class defines Message.what base addresses for various state machine.
- */
-public class TetheringMessageBase {
- public static final int BASE_MAIN_SM = 0;
- public static final int BASE_IPSERVER = 100;
-
-}
diff --git a/packages/Tethering/src/android/net/util/TetheringUtils.java b/packages/Tethering/src/android/net/util/TetheringUtils.java
deleted file mode 100644
index 53b54f7..0000000
--- a/packages/Tethering/src/android/net/util/TetheringUtils.java
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright (C) 2019 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 android.net.util;
-
-import android.net.TetherStatsParcel;
-import android.net.TetheringRequestParcel;
-import android.util.Log;
-
-import androidx.annotation.NonNull;
-
-import java.io.FileDescriptor;
-import java.net.Inet6Address;
-import java.net.SocketException;
-import java.net.UnknownHostException;
-import java.util.Arrays;
-import java.util.Objects;
-
-/**
- * The classes and the methods for tethering utilization.
- *
- * {@hide}
- */
-public class TetheringUtils {
- public static final byte[] ALL_NODES = new byte[] {
- (byte) 0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
- };
-
- /**
- * Configures a socket for receiving and sending ICMPv6 neighbor advertisments.
- * @param fd the socket's {@link FileDescriptor}.
- */
- public static native void setupNaSocket(FileDescriptor fd)
- throws SocketException;
-
- /**
- * Configures a socket for receiving and sending ICMPv6 neighbor solicitations.
- * @param fd the socket's {@link FileDescriptor}.
- */
- public static native void setupNsSocket(FileDescriptor fd)
- throws SocketException;
-
- /**
- * The object which records offload Tx/Rx forwarded bytes/packets.
- * TODO: Replace the inner class ForwardedStats of class OffloadHardwareInterface with
- * this class as well.
- */
- public static class ForwardedStats {
- public final long rxBytes;
- public final long rxPackets;
- public final long txBytes;
- public final long txPackets;
-
- public ForwardedStats() {
- rxBytes = 0;
- rxPackets = 0;
- txBytes = 0;
- txPackets = 0;
- }
-
- public ForwardedStats(long rxBytes, long txBytes) {
- this.rxBytes = rxBytes;
- this.rxPackets = 0;
- this.txBytes = txBytes;
- this.txPackets = 0;
- }
-
- public ForwardedStats(long rxBytes, long rxPackets, long txBytes, long txPackets) {
- this.rxBytes = rxBytes;
- this.rxPackets = rxPackets;
- this.txBytes = txBytes;
- this.txPackets = txPackets;
- }
-
- public ForwardedStats(@NonNull TetherStatsParcel tetherStats) {
- rxBytes = tetherStats.rxBytes;
- rxPackets = tetherStats.rxPackets;
- txBytes = tetherStats.txBytes;
- txPackets = tetherStats.txPackets;
- }
-
- public ForwardedStats(@NonNull ForwardedStats other) {
- rxBytes = other.rxBytes;
- rxPackets = other.rxPackets;
- txBytes = other.txBytes;
- txPackets = other.txPackets;
- }
-
- /** Add Tx/Rx bytes/packets and return the result as a new object. */
- @NonNull
- public ForwardedStats add(@NonNull ForwardedStats other) {
- return new ForwardedStats(rxBytes + other.rxBytes, rxPackets + other.rxPackets,
- txBytes + other.txBytes, txPackets + other.txPackets);
- }
-
- /** Subtract Tx/Rx bytes/packets and return the result as a new object. */
- @NonNull
- public ForwardedStats subtract(@NonNull ForwardedStats other) {
- // TODO: Perhaps throw an exception if any negative difference value just in case.
- final long rxBytesDiff = Math.max(rxBytes - other.rxBytes, 0);
- final long rxPacketsDiff = Math.max(rxPackets - other.rxPackets, 0);
- final long txBytesDiff = Math.max(txBytes - other.txBytes, 0);
- final long txPacketsDiff = Math.max(txPackets - other.txPackets, 0);
- return new ForwardedStats(rxBytesDiff, rxPacketsDiff, txBytesDiff, txPacketsDiff);
- }
-
- /** Returns the string representation of this object. */
- @NonNull
- public String toString() {
- return String.format("ForwardedStats(rxb: %d, rxp: %d, txb: %d, txp: %d)", rxBytes,
- rxPackets, txBytes, txPackets);
- }
- }
-
- /**
- * Configures a socket for receiving ICMPv6 router solicitations and sending advertisements.
- * @param fd the socket's {@link FileDescriptor}.
- * @param ifIndex the interface index.
- */
- public static native void setupRaSocket(FileDescriptor fd, int ifIndex)
- throws SocketException;
-
- /**
- * Read s as an unsigned 16-bit integer.
- */
- public static int uint16(short s) {
- return s & 0xffff;
- }
-
- /** Check whether two TetheringRequestParcels are the same. */
- public static boolean isTetheringRequestEquals(final TetheringRequestParcel request,
- final TetheringRequestParcel otherRequest) {
- if (request == otherRequest) return true;
-
- return request != null && otherRequest != null
- && request.tetheringType == otherRequest.tetheringType
- && Objects.equals(request.localIPv4Address, otherRequest.localIPv4Address)
- && Objects.equals(request.staticClientAddress, otherRequest.staticClientAddress)
- && request.exemptFromEntitlementCheck == otherRequest.exemptFromEntitlementCheck
- && request.showProvisioningUi == otherRequest.showProvisioningUi;
- }
-
- /** Get inet6 address for all nodes given scope ID. */
- public static Inet6Address getAllNodesForScopeId(int scopeId) {
- try {
- return Inet6Address.getByAddress("ff02::1", ALL_NODES, scopeId);
- } catch (UnknownHostException uhe) {
- Log.wtf("TetheringUtils", "Failed to construct Inet6Address from "
- + Arrays.toString(ALL_NODES) + " and scopedId " + scopeId);
- return null;
- }
- }
-}
diff --git a/packages/Tethering/src/android/net/util/VersionedBroadcastListener.java b/packages/Tethering/src/android/net/util/VersionedBroadcastListener.java
deleted file mode 100644
index e2804ab..0000000
--- a/packages/Tethering/src/android/net/util/VersionedBroadcastListener.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (C) 2017 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 android.net.util;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.Handler;
-import android.util.Log;
-
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.function.Consumer;
-
-
-/**
- * A utility class that runs the provided callback on the provided handler when
- * intents matching the provided filter arrive. Intents received by a stale
- * receiver are safely ignored.
- *
- * Calls to startListening() and stopListening() must happen on the same thread.
- *
- * @hide
- */
-public class VersionedBroadcastListener {
- private static final boolean DBG = false;
-
- private final String mTag;
- private final Context mContext;
- private final Handler mHandler;
- private final IntentFilter mFilter;
- private final Consumer<Intent> mCallback;
- private final AtomicInteger mGenerationNumber;
- private BroadcastReceiver mReceiver;
-
- public VersionedBroadcastListener(String tag, Context ctx, Handler handler,
- IntentFilter filter, Consumer<Intent> callback) {
- mTag = tag;
- mContext = ctx;
- mHandler = handler;
- mFilter = filter;
- mCallback = callback;
- mGenerationNumber = new AtomicInteger(0);
- }
-
- /** Start listening to intent broadcast. */
- public void startListening() {
- if (DBG) Log.d(mTag, "startListening");
- if (mReceiver != null) return;
-
- mReceiver = new Receiver(mTag, mGenerationNumber, mCallback);
- mContext.registerReceiver(mReceiver, mFilter, null, mHandler);
- }
-
- /** Stop listening to intent broadcast. */
- public void stopListening() {
- if (DBG) Log.d(mTag, "stopListening");
- if (mReceiver == null) return;
-
- mGenerationNumber.incrementAndGet();
- mContext.unregisterReceiver(mReceiver);
- mReceiver = null;
- }
-
- private static class Receiver extends BroadcastReceiver {
- public final String tag;
- public final AtomicInteger atomicGenerationNumber;
- public final Consumer<Intent> callback;
- // Used to verify this receiver is still current.
- public final int generationNumber;
-
- Receiver(String tag, AtomicInteger atomicGenerationNumber, Consumer<Intent> callback) {
- this.tag = tag;
- this.atomicGenerationNumber = atomicGenerationNumber;
- this.callback = callback;
- generationNumber = atomicGenerationNumber.incrementAndGet();
- }
-
- @Override
- public void onReceive(Context context, Intent intent) {
- final int currentGenerationNumber = atomicGenerationNumber.get();
-
- if (DBG) {
- Log.d(tag, "receiver generationNumber=" + generationNumber
- + ", current generationNumber=" + currentGenerationNumber);
- }
- if (generationNumber != currentGenerationNumber) return;
-
- callback.accept(intent);
- }
- }
-}
diff --git a/packages/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java b/packages/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java
deleted file mode 100644
index 20f30ea..0000000
--- a/packages/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java
+++ /dev/null
@@ -1,778 +0,0 @@
-/*
- * 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;
-
-import static android.net.NetworkStats.DEFAULT_NETWORK_NO;
-import static android.net.NetworkStats.METERED_NO;
-import static android.net.NetworkStats.ROAMING_NO;
-import static android.net.NetworkStats.SET_DEFAULT;
-import static android.net.NetworkStats.TAG_NONE;
-import static android.net.NetworkStats.UID_ALL;
-import static android.net.NetworkStats.UID_TETHERING;
-import static android.net.netstats.provider.NetworkStatsProvider.QUOTA_UNLIMITED;
-
-import static com.android.networkstack.tethering.TetheringConfiguration.DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS;
-
-import android.app.usage.NetworkStatsManager;
-import android.net.INetd;
-import android.net.MacAddress;
-import android.net.NetworkStats;
-import android.net.NetworkStats.Entry;
-import android.net.TetherOffloadRuleParcel;
-import android.net.TetherStatsParcel;
-import android.net.ip.IpServer;
-import android.net.netstats.provider.NetworkStatsProvider;
-import android.net.util.SharedLog;
-import android.net.util.TetheringUtils.ForwardedStats;
-import android.os.ConditionVariable;
-import android.os.Handler;
-import android.os.RemoteException;
-import android.os.ServiceSpecificException;
-import android.text.TextUtils;
-import android.util.Log;
-import android.util.SparseArray;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.IndentingPrintWriter;
-
-import java.net.Inet6Address;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.Objects;
-
-/**
- * This coordinator is responsible for providing BPF offload relevant functionality.
- * - Get tethering stats.
- * - Set data limit.
- * - Set global alert.
- * - Add/remove forwarding rules.
- *
- * @hide
- */
-public class BpfCoordinator {
- private static final String TAG = BpfCoordinator.class.getSimpleName();
- private static final int DUMP_TIMEOUT_MS = 10_000;
-
- @VisibleForTesting
- enum StatsType {
- STATS_PER_IFACE,
- STATS_PER_UID,
- }
-
- @NonNull
- private final Handler mHandler;
- @NonNull
- private final INetd mNetd;
- @NonNull
- private final SharedLog mLog;
- @NonNull
- private final Dependencies mDeps;
- @Nullable
- private final BpfTetherStatsProvider mStatsProvider;
-
- // True if BPF offload is supported, false otherwise. The BPF offload could be disabled by
- // a runtime resource overlay package or device configuration. This flag is only initialized
- // in the constructor because it is hard to unwind all existing change once device
- // configuration is changed. Especially the forwarding rules. Keep the same setting
- // to make it simpler. See also TetheringConfiguration.
- private final boolean mIsBpfEnabled;
-
- // Tracks whether BPF tethering is started or not. This is set by tethering before it
- // starts the first IpServer and is cleared by tethering shortly before the last IpServer
- // is stopped. Note that rule updates (especially deletions, but sometimes additions as
- // well) may arrive when this is false. If they do, they must be communicated to netd.
- // Changes in data limits may also arrive when this is false, and if they do, they must
- // also be communicated to netd.
- private boolean mPollingStarted = false;
-
- // Tracking remaining alert quota. Unlike limit quota is subject to interface, the alert
- // quota is interface independent and global for tether offload.
- private long mRemainingAlertQuota = QUOTA_UNLIMITED;
-
- // Maps upstream interface index to offloaded traffic statistics.
- // Always contains the latest total bytes/packets, since each upstream was started, received
- // from the BPF maps for each interface.
- private final SparseArray<ForwardedStats> mStats = new SparseArray<>();
-
- // Maps upstream interface names to interface quotas.
- // Always contains the latest value received from the framework for each interface, regardless
- // of whether offload is currently running (or is even supported) on that interface. Only
- // includes interfaces that have a quota set. Note that this map is used for storing the quota
- // which is set from the service. Because the service uses the interface name to present the
- // interface, this map uses the interface name to be the mapping index.
- private final HashMap<String, Long> mInterfaceQuotas = new HashMap<>();
-
- // Maps upstream interface index to interface names.
- // Store all interface name since boot. Used for lookup what interface name it is from the
- // tether stats got from netd because netd reports interface index to present an interface.
- // TODO: Remove the unused interface name.
- private final SparseArray<String> mInterfaceNames = new SparseArray<>();
-
- // Map of downstream rule maps. Each of these maps represents the IPv6 forwarding rules for a
- // given downstream. Each map:
- // - Is owned by the IpServer that is responsible for that downstream.
- // - Must only be modified by that IpServer.
- // - Is created when the IpServer adds its first rule, and deleted when the IpServer deletes
- // its last rule (or clears its rules).
- // TODO: Perhaps seal the map and rule operations which communicates with netd into a class.
- // TODO: Does this need to be a LinkedHashMap or can it just be a HashMap? Also, could it be
- // a ConcurrentHashMap, in order to avoid the copies in tetherOffloadRuleClear
- // and tetherOffloadRuleUpdate?
- // TODO: Perhaps use one-dimensional map and access specific downstream rules via downstream
- // index. For doing that, IpServer must guarantee that it always has a valid IPv6 downstream
- // interface index while calling function to clear all rules. IpServer may be calling clear
- // rules function without a valid IPv6 downstream interface index even if it may have one
- // before. IpServer would need to call getInterfaceParams() in the constructor instead of when
- // startIpv6() is called, and make mInterfaceParams final.
- private final HashMap<IpServer, LinkedHashMap<Inet6Address, Ipv6ForwardingRule>>
- mIpv6ForwardingRules = new LinkedHashMap<>();
-
- // Runnable that used by scheduling next polling of stats.
- private final Runnable mScheduledPollingTask = () -> {
- updateForwardedStatsFromNetd();
- maybeSchedulePollingStats();
- };
-
- @VisibleForTesting
- public abstract static class Dependencies {
- /** Get handler. */
- @NonNull public abstract Handler getHandler();
-
- /** Get netd. */
- @NonNull public abstract INetd getNetd();
-
- /** Get network stats manager. */
- @NonNull public abstract NetworkStatsManager getNetworkStatsManager();
-
- /** Get shared log. */
- @NonNull public abstract SharedLog getSharedLog();
-
- /** Get tethering configuration. */
- @Nullable public abstract TetheringConfiguration getTetherConfig();
- }
-
- @VisibleForTesting
- public BpfCoordinator(@NonNull Dependencies deps) {
- mDeps = deps;
- mHandler = mDeps.getHandler();
- mNetd = mDeps.getNetd();
- mLog = mDeps.getSharedLog().forSubComponent(TAG);
- mIsBpfEnabled = isBpfEnabled();
- BpfTetherStatsProvider provider = new BpfTetherStatsProvider();
- try {
- mDeps.getNetworkStatsManager().registerNetworkStatsProvider(
- getClass().getSimpleName(), provider);
- } catch (RuntimeException e) {
- // TODO: Perhaps not allow to use BPF offload because the reregistration failure
- // implied that no data limit could be applies on a metered upstream if any.
- Log.wtf(TAG, "Cannot register offload stats provider: " + e);
- provider = null;
- }
- mStatsProvider = provider;
- }
-
- /**
- * Start BPF tethering offload stats polling when the first upstream is started.
- * Note that this can be only called on handler thread.
- * TODO: Perhaps check BPF support before starting.
- * TODO: Start the stats polling only if there is any client on the downstream.
- */
- public void startPolling() {
- if (mPollingStarted) return;
-
- if (!mIsBpfEnabled) {
- mLog.i("Offload disabled");
- return;
- }
-
- mPollingStarted = true;
- maybeSchedulePollingStats();
-
- mLog.i("Polling started");
- }
-
- /**
- * Stop BPF tethering offload stats polling.
- * The data limit cleanup and the tether stats maps cleanup are not implemented here.
- * These cleanups rely on all IpServers calling #tetherOffloadRuleRemove. After the
- * last rule is removed from the upstream, #tetherOffloadRuleRemove does the cleanup
- * functionality.
- * Note that this can be only called on handler thread.
- */
- public void stopPolling() {
- if (!mPollingStarted) return;
-
- // Stop scheduled polling tasks and poll the latest stats from BPF maps.
- if (mHandler.hasCallbacks(mScheduledPollingTask)) {
- mHandler.removeCallbacks(mScheduledPollingTask);
- }
- updateForwardedStatsFromNetd();
- mPollingStarted = false;
-
- mLog.i("Polling stopped");
- }
-
- /**
- * Add forwarding rule. After adding the first rule on a given upstream, must add the data
- * limit on the given upstream.
- * Note that this can be only called on handler thread.
- */
- public void tetherOffloadRuleAdd(
- @NonNull final IpServer ipServer, @NonNull final Ipv6ForwardingRule rule) {
- if (!mIsBpfEnabled) return;
-
- try {
- // TODO: Perhaps avoid to add a duplicate rule.
- mNetd.tetherOffloadRuleAdd(rule.toTetherOffloadRuleParcel());
- } catch (RemoteException | ServiceSpecificException e) {
- mLog.e("Could not add IPv6 forwarding rule: ", e);
- return;
- }
-
- if (!mIpv6ForwardingRules.containsKey(ipServer)) {
- mIpv6ForwardingRules.put(ipServer, new LinkedHashMap<Inet6Address,
- Ipv6ForwardingRule>());
- }
- LinkedHashMap<Inet6Address, Ipv6ForwardingRule> rules = mIpv6ForwardingRules.get(ipServer);
-
- // Setup the data limit on the given upstream if the first rule is added.
- final int upstreamIfindex = rule.upstreamIfindex;
- if (!isAnyRuleOnUpstream(upstreamIfindex)) {
- // If failed to set a data limit, probably should not use this upstream, because
- // the upstream may not want to blow through the data limit that was told to apply.
- // TODO: Perhaps stop the coordinator.
- boolean success = updateDataLimit(upstreamIfindex);
- if (!success) {
- final String iface = mInterfaceNames.get(upstreamIfindex);
- mLog.e("Setting data limit for " + iface + " failed.");
- }
- }
-
- // Must update the adding rule after calling #isAnyRuleOnUpstream because it needs to
- // check if it is about adding a first rule for a given upstream.
- rules.put(rule.address, rule);
- }
-
- /**
- * Remove forwarding rule. After removing the last rule on a given upstream, must clear
- * data limit, update the last tether stats and remove the tether stats in the BPF maps.
- * Note that this can be only called on handler thread.
- */
- public void tetherOffloadRuleRemove(
- @NonNull final IpServer ipServer, @NonNull final Ipv6ForwardingRule rule) {
- if (!mIsBpfEnabled) return;
-
- try {
- // TODO: Perhaps avoid to remove a non-existent rule.
- mNetd.tetherOffloadRuleRemove(rule.toTetherOffloadRuleParcel());
- } catch (RemoteException | ServiceSpecificException e) {
- mLog.e("Could not remove IPv6 forwarding rule: ", e);
- return;
- }
-
- LinkedHashMap<Inet6Address, Ipv6ForwardingRule> rules = mIpv6ForwardingRules.get(ipServer);
- if (rules == null) return;
-
- // Must remove rules before calling #isAnyRuleOnUpstream because it needs to check if
- // the last rule is removed for a given upstream. If no rule is removed, return early.
- // Avoid unnecessary work on a non-existent rule which may have never been added or
- // removed already.
- if (rules.remove(rule.address) == null) return;
-
- // Remove the downstream entry if it has no more rule.
- if (rules.isEmpty()) {
- mIpv6ForwardingRules.remove(ipServer);
- }
-
- // Do cleanup functionality if there is no more rule on the given upstream.
- final int upstreamIfindex = rule.upstreamIfindex;
- if (!isAnyRuleOnUpstream(upstreamIfindex)) {
- try {
- final TetherStatsParcel stats =
- mNetd.tetherOffloadGetAndClearStats(upstreamIfindex);
- // Update the last stats delta and delete the local cache for a given upstream.
- updateQuotaAndStatsFromSnapshot(new TetherStatsParcel[] {stats});
- mStats.remove(upstreamIfindex);
- } catch (RemoteException | ServiceSpecificException e) {
- Log.wtf(TAG, "Exception when cleanup tether stats for upstream index "
- + upstreamIfindex + ": ", e);
- }
- }
- }
-
- /**
- * Clear all forwarding rules for a given downstream.
- * Note that this can be only called on handler thread.
- */
- public void tetherOffloadRuleClear(@NonNull final IpServer ipServer) {
- if (!mIsBpfEnabled) return;
-
- final LinkedHashMap<Inet6Address, Ipv6ForwardingRule> rules = mIpv6ForwardingRules.get(
- ipServer);
- if (rules == null) return;
-
- // Need to build a rule list because the rule map may be changed in the iteration.
- for (final Ipv6ForwardingRule rule : new ArrayList<Ipv6ForwardingRule>(rules.values())) {
- tetherOffloadRuleRemove(ipServer, rule);
- }
- }
-
- /**
- * Update existing forwarding rules to new upstream for a given downstream.
- * Note that this can be only called on handler thread.
- */
- public void tetherOffloadRuleUpdate(@NonNull final IpServer ipServer, int newUpstreamIfindex) {
- if (!mIsBpfEnabled) return;
-
- final LinkedHashMap<Inet6Address, Ipv6ForwardingRule> rules = mIpv6ForwardingRules.get(
- ipServer);
- if (rules == null) return;
-
- // Need to build a rule list because the rule map may be changed in the iteration.
- for (final Ipv6ForwardingRule rule : new ArrayList<Ipv6ForwardingRule>(rules.values())) {
- // Remove the old rule before adding the new one because the map uses the same key for
- // both rules. Reversing the processing order causes that the new rule is removed as
- // unexpected.
- // TODO: Add new rule first to reduce the latency which has no rule.
- tetherOffloadRuleRemove(ipServer, rule);
- tetherOffloadRuleAdd(ipServer, rule.onNewUpstream(newUpstreamIfindex));
- }
- }
-
- /**
- * Add upstream name to lookup table. The lookup table is used for tether stats interface name
- * lookup because the netd only reports interface index in BPF tether stats but the service
- * expects the interface name in NetworkStats object.
- * Note that this can be only called on handler thread.
- */
- public void addUpstreamNameToLookupTable(int upstreamIfindex, @NonNull String upstreamIface) {
- if (!mIsBpfEnabled) return;
-
- if (upstreamIfindex == 0 || TextUtils.isEmpty(upstreamIface)) return;
-
- // The same interface index to name mapping may be added by different IpServer objects or
- // re-added by reconnection on the same upstream interface. Ignore the duplicate one.
- final String iface = mInterfaceNames.get(upstreamIfindex);
- if (iface == null) {
- mInterfaceNames.put(upstreamIfindex, upstreamIface);
- } else if (!TextUtils.equals(iface, upstreamIface)) {
- Log.wtf(TAG, "The upstream interface name " + upstreamIface
- + " is different from the existing interface name "
- + iface + " for index " + upstreamIfindex);
- }
- }
-
- /**
- * Dump information.
- * Block the function until all the data are dumped on the handler thread or timed-out. The
- * reason is that dumpsys invokes this function on the thread of caller and the data may only
- * be allowed to be accessed on the handler thread.
- */
- public void dump(@NonNull IndentingPrintWriter pw) {
- final ConditionVariable dumpDone = new ConditionVariable();
- mHandler.post(() -> {
- pw.println("mIsBpfEnabled: " + mIsBpfEnabled);
- pw.println("Polling " + (mPollingStarted ? "started" : "not started"));
- pw.println("Stats provider " + (mStatsProvider != null
- ? "registered" : "not registered"));
- pw.println("Upstream quota: " + mInterfaceQuotas.toString());
- pw.println("Polling interval: " + getPollingInterval() + " ms");
-
- pw.println("Forwarding stats:");
- pw.increaseIndent();
- if (mStats.size() == 0) {
- pw.println("<empty>");
- } else {
- dumpStats(pw);
- }
- pw.decreaseIndent();
-
- pw.println("Forwarding rules:");
- pw.increaseIndent();
- if (mIpv6ForwardingRules.size() == 0) {
- pw.println("<empty>");
- } else {
- dumpIpv6ForwardingRules(pw);
- }
- pw.decreaseIndent();
-
- dumpDone.open();
- });
- if (!dumpDone.block(DUMP_TIMEOUT_MS)) {
- pw.println("... dump timed-out after " + DUMP_TIMEOUT_MS + "ms");
- }
- }
-
- private void dumpStats(@NonNull IndentingPrintWriter pw) {
- for (int i = 0; i < mStats.size(); i++) {
- final int upstreamIfindex = mStats.keyAt(i);
- final ForwardedStats stats = mStats.get(upstreamIfindex);
- pw.println(String.format("%d(%s) - %s", upstreamIfindex, mInterfaceNames.get(
- upstreamIfindex), stats.toString()));
- }
- }
-
- private void dumpIpv6ForwardingRules(@NonNull IndentingPrintWriter pw) {
- for (Map.Entry<IpServer, LinkedHashMap<Inet6Address, Ipv6ForwardingRule>> entry :
- mIpv6ForwardingRules.entrySet()) {
- IpServer ipServer = entry.getKey();
- // The rule downstream interface index is paired with the interface name from
- // IpServer#interfaceName. See #startIPv6, #updateIpv6ForwardingRules in IpServer.
- final String downstreamIface = ipServer.interfaceName();
- pw.println("[" + downstreamIface + "]: iif(iface) oif(iface) v6addr srcmac dstmac");
-
- pw.increaseIndent();
- LinkedHashMap<Inet6Address, Ipv6ForwardingRule> rules = entry.getValue();
- for (Ipv6ForwardingRule rule : rules.values()) {
- final int upstreamIfindex = rule.upstreamIfindex;
- pw.println(String.format("%d(%s) %d(%s) %s %s %s", upstreamIfindex,
- mInterfaceNames.get(upstreamIfindex), rule.downstreamIfindex,
- downstreamIface, rule.address, rule.srcMac, rule.dstMac));
- }
- pw.decreaseIndent();
- }
- }
-
- /** IPv6 forwarding rule class. */
- public static class Ipv6ForwardingRule {
- public final int upstreamIfindex;
- public final int downstreamIfindex;
-
- @NonNull
- public final Inet6Address address;
- @NonNull
- public final MacAddress srcMac;
- @NonNull
- public final MacAddress dstMac;
-
- public Ipv6ForwardingRule(int upstreamIfindex, int downstreamIfIndex,
- @NonNull Inet6Address address, @NonNull MacAddress srcMac,
- @NonNull MacAddress dstMac) {
- this.upstreamIfindex = upstreamIfindex;
- this.downstreamIfindex = downstreamIfIndex;
- this.address = address;
- this.srcMac = srcMac;
- this.dstMac = dstMac;
- }
-
- /** Return a new rule object which updates with new upstream index. */
- @NonNull
- public Ipv6ForwardingRule onNewUpstream(int newUpstreamIfindex) {
- return new Ipv6ForwardingRule(newUpstreamIfindex, downstreamIfindex, address, srcMac,
- dstMac);
- }
-
- /**
- * Don't manipulate TetherOffloadRuleParcel directly because implementing onNewUpstream()
- * would be error-prone due to generated stable AIDL classes not having a copy constructor.
- */
- @NonNull
- public TetherOffloadRuleParcel toTetherOffloadRuleParcel() {
- final TetherOffloadRuleParcel parcel = new TetherOffloadRuleParcel();
- parcel.inputInterfaceIndex = upstreamIfindex;
- parcel.outputInterfaceIndex = downstreamIfindex;
- parcel.destination = address.getAddress();
- parcel.prefixLength = 128;
- parcel.srcL2Address = srcMac.toByteArray();
- parcel.dstL2Address = dstMac.toByteArray();
- return parcel;
- }
-
- @Override
- public boolean equals(Object o) {
- if (!(o instanceof Ipv6ForwardingRule)) return false;
- Ipv6ForwardingRule that = (Ipv6ForwardingRule) o;
- return this.upstreamIfindex == that.upstreamIfindex
- && this.downstreamIfindex == that.downstreamIfindex
- && Objects.equals(this.address, that.address)
- && Objects.equals(this.srcMac, that.srcMac)
- && Objects.equals(this.dstMac, that.dstMac);
- }
-
- @Override
- public int hashCode() {
- // TODO: if this is ever used in production code, don't pass ifindices
- // to Objects.hash() to avoid autoboxing overhead.
- return Objects.hash(upstreamIfindex, downstreamIfindex, address, srcMac, dstMac);
- }
- }
-
- /**
- * A BPF tethering stats provider to provide network statistics to the system.
- * Note that this class' data may only be accessed on the handler thread.
- */
- @VisibleForTesting
- class BpfTetherStatsProvider extends NetworkStatsProvider {
- // The offloaded traffic statistics per interface that has not been reported since the
- // last call to pushTetherStats. Only the interfaces that were ever tethering upstreams
- // and has pending tether stats delta are included in this NetworkStats object.
- private NetworkStats mIfaceStats = new NetworkStats(0L, 0);
-
- // The same stats as above, but counts network stats per uid.
- private NetworkStats mUidStats = new NetworkStats(0L, 0);
-
- @Override
- public void onRequestStatsUpdate(int token) {
- mHandler.post(() -> pushTetherStats());
- }
-
- @Override
- public void onSetAlert(long quotaBytes) {
- mHandler.post(() -> updateAlertQuota(quotaBytes));
- }
-
- @Override
- public void onSetLimit(@NonNull String iface, long quotaBytes) {
- if (quotaBytes < QUOTA_UNLIMITED) {
- throw new IllegalArgumentException("invalid quota value " + quotaBytes);
- }
-
- mHandler.post(() -> {
- final Long curIfaceQuota = mInterfaceQuotas.get(iface);
-
- if (null == curIfaceQuota && QUOTA_UNLIMITED == quotaBytes) return;
-
- if (quotaBytes == QUOTA_UNLIMITED) {
- mInterfaceQuotas.remove(iface);
- } else {
- mInterfaceQuotas.put(iface, quotaBytes);
- }
- maybeUpdateDataLimit(iface);
- });
- }
-
- @VisibleForTesting
- void pushTetherStats() {
- try {
- // The token is not used for now. See b/153606961.
- notifyStatsUpdated(0 /* token */, mIfaceStats, mUidStats);
-
- // Clear the accumulated tether stats delta after reported. Note that create a new
- // empty object because NetworkStats#clear is @hide.
- mIfaceStats = new NetworkStats(0L, 0);
- mUidStats = new NetworkStats(0L, 0);
- } catch (RuntimeException e) {
- mLog.e("Cannot report network stats: ", e);
- }
- }
-
- private void accumulateDiff(@NonNull NetworkStats ifaceDiff,
- @NonNull NetworkStats uidDiff) {
- mIfaceStats = mIfaceStats.add(ifaceDiff);
- mUidStats = mUidStats.add(uidDiff);
- }
- }
-
- private boolean isBpfEnabled() {
- final TetheringConfiguration config = mDeps.getTetherConfig();
- return (config != null) ? config.isBpfOffloadEnabled() : true /* default value */;
- }
-
- private int getInterfaceIndexFromRules(@NonNull String ifName) {
- for (LinkedHashMap<Inet6Address, Ipv6ForwardingRule> rules : mIpv6ForwardingRules
- .values()) {
- for (Ipv6ForwardingRule rule : rules.values()) {
- final int upstreamIfindex = rule.upstreamIfindex;
- if (TextUtils.equals(ifName, mInterfaceNames.get(upstreamIfindex))) {
- return upstreamIfindex;
- }
- }
- }
- return 0;
- }
-
- private long getQuotaBytes(@NonNull String iface) {
- final Long limit = mInterfaceQuotas.get(iface);
- final long quotaBytes = (limit != null) ? limit : QUOTA_UNLIMITED;
-
- return quotaBytes;
- }
-
- private boolean sendDataLimitToNetd(int ifIndex, long quotaBytes) {
- if (ifIndex == 0) {
- Log.wtf(TAG, "Invalid interface index.");
- return false;
- }
-
- try {
- mNetd.tetherOffloadSetInterfaceQuota(ifIndex, quotaBytes);
- } catch (RemoteException | ServiceSpecificException e) {
- mLog.e("Exception when updating quota " + quotaBytes + ": ", e);
- return false;
- }
-
- return true;
- }
-
- // Handle the data limit update from the service which is the stats provider registered for.
- private void maybeUpdateDataLimit(@NonNull String iface) {
- // Set data limit only on a given upstream which has at least one rule. If we can't get
- // an interface index for a given interface name, it means either there is no rule for
- // a given upstream or the interface name is not an upstream which is monitored by the
- // coordinator.
- final int ifIndex = getInterfaceIndexFromRules(iface);
- if (ifIndex == 0) return;
-
- final long quotaBytes = getQuotaBytes(iface);
- sendDataLimitToNetd(ifIndex, quotaBytes);
- }
-
- // Handle the data limit update while adding forwarding rules.
- private boolean updateDataLimit(int ifIndex) {
- final String iface = mInterfaceNames.get(ifIndex);
- if (iface == null) {
- mLog.e("Fail to get the interface name for index " + ifIndex);
- return false;
- }
- final long quotaBytes = getQuotaBytes(iface);
- return sendDataLimitToNetd(ifIndex, quotaBytes);
- }
-
- private boolean isAnyRuleOnUpstream(int upstreamIfindex) {
- for (LinkedHashMap<Inet6Address, Ipv6ForwardingRule> rules : mIpv6ForwardingRules
- .values()) {
- for (Ipv6ForwardingRule rule : rules.values()) {
- if (upstreamIfindex == rule.upstreamIfindex) return true;
- }
- }
- return false;
- }
-
- @NonNull
- private NetworkStats buildNetworkStats(@NonNull StatsType type, int ifIndex,
- @NonNull final ForwardedStats diff) {
- NetworkStats stats = new NetworkStats(0L, 0);
- final String iface = mInterfaceNames.get(ifIndex);
- if (iface == null) {
- // TODO: Use Log.wtf once the coordinator owns full control of tether stats from netd.
- // For now, netd may add the empty stats for the upstream which is not monitored by
- // the coordinator. Silently ignore it.
- return stats;
- }
- final int uid = (type == StatsType.STATS_PER_UID) ? UID_TETHERING : UID_ALL;
- // Note that the argument 'metered', 'roaming' and 'defaultNetwork' are not recorded for
- // network stats snapshot. See NetworkStatsRecorder#recordSnapshotLocked.
- return stats.addEntry(new Entry(iface, uid, SET_DEFAULT, TAG_NONE, METERED_NO,
- ROAMING_NO, DEFAULT_NETWORK_NO, diff.rxBytes, diff.rxPackets,
- diff.txBytes, diff.txPackets, 0L /* operations */));
- }
-
- private void updateAlertQuota(long newQuota) {
- if (newQuota < QUOTA_UNLIMITED) {
- throw new IllegalArgumentException("invalid quota value " + newQuota);
- }
- if (mRemainingAlertQuota == newQuota) return;
-
- mRemainingAlertQuota = newQuota;
- if (mRemainingAlertQuota == 0) {
- mLog.i("onAlertReached");
- if (mStatsProvider != null) mStatsProvider.notifyAlertReached();
- }
- }
-
- private void updateQuotaAndStatsFromSnapshot(
- @NonNull final TetherStatsParcel[] tetherStatsList) {
- long usedAlertQuota = 0;
- for (TetherStatsParcel tetherStats : tetherStatsList) {
- final Integer ifIndex = tetherStats.ifIndex;
- final ForwardedStats curr = new ForwardedStats(tetherStats);
- final ForwardedStats base = mStats.get(ifIndex);
- final ForwardedStats diff = (base != null) ? curr.subtract(base) : curr;
- usedAlertQuota += diff.rxBytes + diff.txBytes;
-
- // Update the local cache for counting tether stats delta.
- mStats.put(ifIndex, curr);
-
- // Update the accumulated tether stats delta to the stats provider for the service
- // querying.
- if (mStatsProvider != null) {
- try {
- mStatsProvider.accumulateDiff(
- buildNetworkStats(StatsType.STATS_PER_IFACE, ifIndex, diff),
- buildNetworkStats(StatsType.STATS_PER_UID, ifIndex, diff));
- } catch (ArrayIndexOutOfBoundsException e) {
- Log.wtf(TAG, "Fail to update the accumulated stats delta for interface index "
- + ifIndex + " : ", e);
- }
- }
- }
-
- if (mRemainingAlertQuota > 0 && usedAlertQuota > 0) {
- // Trim to zero if overshoot.
- final long newQuota = Math.max(mRemainingAlertQuota - usedAlertQuota, 0);
- updateAlertQuota(newQuota);
- }
-
- // TODO: Count the used limit quota for notifying data limit reached.
- }
-
- private void updateForwardedStatsFromNetd() {
- final TetherStatsParcel[] tetherStatsList;
- try {
- // The reported tether stats are total data usage for all currently-active upstream
- // interfaces since tethering start.
- tetherStatsList = mNetd.tetherOffloadGetStats();
- } catch (RemoteException | ServiceSpecificException e) {
- mLog.e("Problem fetching tethering stats: ", e);
- return;
- }
- updateQuotaAndStatsFromSnapshot(tetherStatsList);
- }
-
- @VisibleForTesting
- int getPollingInterval() {
- // The valid range of interval is DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS..max_long.
- // Ignore the config value is less than the minimum polling interval. Note that the
- // minimum interval definition is invoked as OffloadController#isPollingStatsNeeded does.
- // TODO: Perhaps define a minimum polling interval constant.
- final TetheringConfiguration config = mDeps.getTetherConfig();
- final int configInterval = (config != null) ? config.getOffloadPollInterval() : 0;
- return Math.max(DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS, configInterval);
- }
-
- private void maybeSchedulePollingStats() {
- if (!mPollingStarted) return;
-
- if (mHandler.hasCallbacks(mScheduledPollingTask)) {
- mHandler.removeCallbacks(mScheduledPollingTask);
- }
-
- mHandler.postDelayed(mScheduledPollingTask, getPollingInterval());
- }
-
- // Return forwarding rule map. This is used for testing only.
- // Note that this can be only called on handler thread.
- @NonNull
- @VisibleForTesting
- final HashMap<IpServer, LinkedHashMap<Inet6Address, Ipv6ForwardingRule>>
- getForwardingRulesForTesting() {
- return mIpv6ForwardingRules;
- }
-
- // Return upstream interface name map. This is used for testing only.
- // Note that this can be only called on handler thread.
- @NonNull
- @VisibleForTesting
- final SparseArray<String> getInterfaceNamesForTesting() {
- return mInterfaceNames;
- }
-}
diff --git a/packages/Tethering/src/com/android/networkstack/tethering/ConnectedClientsTracker.java b/packages/Tethering/src/com/android/networkstack/tethering/ConnectedClientsTracker.java
deleted file mode 100644
index 8a96988..0000000
--- a/packages/Tethering/src/com/android/networkstack/tethering/ConnectedClientsTracker.java
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * 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;
-
-import static android.net.TetheringManager.TETHERING_WIFI;
-
-import android.net.MacAddress;
-import android.net.TetheredClient;
-import android.net.TetheredClient.AddressInfo;
-import android.net.ip.IpServer;
-import android.net.wifi.WifiClient;
-import android.os.SystemClock;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.VisibleForTesting;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * Tracker for clients connected to downstreams.
- *
- * <p>This class is not thread safe, it is intended to be used only from the tethering handler
- * thread.
- */
-public class ConnectedClientsTracker {
- private final Clock mClock;
-
- @NonNull
- private List<WifiClient> mLastWifiClients = Collections.emptyList();
- @NonNull
- private List<TetheredClient> mLastTetheredClients = Collections.emptyList();
-
- @VisibleForTesting
- static class Clock {
- public long elapsedRealtime() {
- return SystemClock.elapsedRealtime();
- }
- }
-
- public ConnectedClientsTracker() {
- this(new Clock());
- }
-
- @VisibleForTesting
- ConnectedClientsTracker(Clock clock) {
- mClock = clock;
- }
-
- /**
- * Update the tracker with new connected clients.
- *
- * <p>The new list can be obtained through {@link #getLastTetheredClients()}.
- * @param ipServers The IpServers used to assign addresses to clients.
- * @param wifiClients The list of L2-connected WiFi clients. Null for no change since last
- * update.
- * @return True if the list of clients changed since the last calculation.
- */
- public boolean updateConnectedClients(
- Iterable<IpServer> ipServers, @Nullable List<WifiClient> wifiClients) {
- final long now = mClock.elapsedRealtime();
-
- if (wifiClients != null) {
- mLastWifiClients = wifiClients;
- }
- final Set<MacAddress> wifiClientMacs = getClientMacs(mLastWifiClients);
-
- // Build the list of non-expired leases from all IpServers, grouped by mac address
- final Map<MacAddress, TetheredClient> clientsMap = new HashMap<>();
- for (IpServer server : ipServers) {
- for (TetheredClient client : server.getAllLeases()) {
- if (client.getTetheringType() == TETHERING_WIFI
- && !wifiClientMacs.contains(client.getMacAddress())) {
- // Skip leases of WiFi clients that are not (or no longer) L2-connected
- continue;
- }
- final TetheredClient prunedClient = pruneExpired(client, now);
- if (prunedClient == null) continue; // All addresses expired
-
- addLease(clientsMap, prunedClient);
- }
- }
-
- // TODO: add IPv6 addresses from netlink
-
- // Add connected WiFi clients that do not have any known address
- for (MacAddress client : wifiClientMacs) {
- if (clientsMap.containsKey(client)) continue;
- clientsMap.put(client, new TetheredClient(
- client, Collections.emptyList() /* addresses */, TETHERING_WIFI));
- }
-
- final HashSet<TetheredClient> clients = new HashSet<>(clientsMap.values());
- final boolean clientsChanged = clients.size() != mLastTetheredClients.size()
- || !clients.containsAll(mLastTetheredClients);
- mLastTetheredClients = Collections.unmodifiableList(new ArrayList<>(clients));
- return clientsChanged;
- }
-
- private static void addLease(Map<MacAddress, TetheredClient> clientsMap, TetheredClient lease) {
- final TetheredClient aggregateClient = clientsMap.getOrDefault(
- lease.getMacAddress(), lease);
- if (aggregateClient == lease) {
- // This is the first lease with this mac address
- clientsMap.put(lease.getMacAddress(), lease);
- return;
- }
-
- // Only add the address info; this assumes that the tethering type is the same when the mac
- // address is the same. If a client is connected through different tethering types with the
- // same mac address, connected clients callbacks will report all of its addresses under only
- // one of these tethering types. This keeps the API simple considering that such a scenario
- // would really be a rare edge case.
- clientsMap.put(lease.getMacAddress(), aggregateClient.addAddresses(lease));
- }
-
- /**
- * Get the last list of tethered clients, as calculated in {@link #updateConnectedClients}.
- *
- * <p>The returned list is immutable.
- */
- @NonNull
- public List<TetheredClient> getLastTetheredClients() {
- return mLastTetheredClients;
- }
-
- private static boolean hasExpiredAddress(List<AddressInfo> addresses, long now) {
- for (AddressInfo info : addresses) {
- if (info.getExpirationTime() <= now) {
- return true;
- }
- }
- return false;
- }
-
- @Nullable
- private static TetheredClient pruneExpired(TetheredClient client, long now) {
- final List<AddressInfo> addresses = client.getAddresses();
- if (addresses.size() == 0) return null;
- if (!hasExpiredAddress(addresses, now)) return client;
-
- final ArrayList<AddressInfo> newAddrs = new ArrayList<>(addresses.size() - 1);
- for (AddressInfo info : addresses) {
- if (info.getExpirationTime() > now) {
- newAddrs.add(info);
- }
- }
-
- if (newAddrs.size() == 0) {
- return null;
- }
- return new TetheredClient(client.getMacAddress(), newAddrs, client.getTetheringType());
- }
-
- @NonNull
- private static Set<MacAddress> getClientMacs(@NonNull List<WifiClient> clients) {
- final Set<MacAddress> macs = new HashSet<>(clients.size());
- for (WifiClient c : clients) {
- macs.add(c.getMacAddress());
- }
- return macs;
- }
-}
diff --git a/packages/Tethering/src/com/android/networkstack/tethering/EntitlementManager.java b/packages/Tethering/src/com/android/networkstack/tethering/EntitlementManager.java
deleted file mode 100644
index bb7322f..0000000
--- a/packages/Tethering/src/com/android/networkstack/tethering/EntitlementManager.java
+++ /dev/null
@@ -1,646 +0,0 @@
-/*
- * Copyright (C) 2018 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;
-
-import static android.net.TetheringConstants.EXTRA_ADD_TETHER_TYPE;
-import static android.net.TetheringConstants.EXTRA_PROVISION_CALLBACK;
-import static android.net.TetheringConstants.EXTRA_RUN_PROVISION;
-import static android.net.TetheringConstants.EXTRA_TETHER_PROVISIONING_RESPONSE;
-import static android.net.TetheringConstants.EXTRA_TETHER_SILENT_PROVISIONING_ACTION;
-import static android.net.TetheringConstants.EXTRA_TETHER_SUBID;
-import static android.net.TetheringConstants.EXTRA_TETHER_UI_PROVISIONING_APP_NAME;
-import static android.net.TetheringManager.TETHERING_BLUETOOTH;
-import static android.net.TetheringManager.TETHERING_ETHERNET;
-import static android.net.TetheringManager.TETHERING_INVALID;
-import static android.net.TetheringManager.TETHERING_USB;
-import static android.net.TetheringManager.TETHERING_WIFI;
-import static android.net.TetheringManager.TETHER_ERROR_ENTITLEMENT_UNKNOWN;
-import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
-import static android.net.TetheringManager.TETHER_ERROR_PROVISIONING_FAILED;
-
-import android.app.AlarmManager;
-import android.app.PendingIntent;
-import android.content.BroadcastReceiver;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.net.util.SharedLog;
-import android.os.Bundle;
-import android.os.ConditionVariable;
-import android.os.Handler;
-import android.os.Parcel;
-import android.os.PersistableBundle;
-import android.os.ResultReceiver;
-import android.os.SystemClock;
-import android.os.SystemProperties;
-import android.provider.Settings;
-import android.telephony.CarrierConfigManager;
-import android.util.SparseIntArray;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.io.PrintWriter;
-import java.util.BitSet;
-
-/**
- * Re-check tethering provisioning for enabled downstream tether types.
- * Reference TetheringManager.TETHERING_{@code *} for each tether type.
- *
- * All methods of this class must be accessed from the thread of tethering
- * state machine.
- * @hide
- */
-public class EntitlementManager {
- private static final String TAG = EntitlementManager.class.getSimpleName();
- private static final boolean DBG = false;
-
- @VisibleForTesting
- protected static final String DISABLE_PROVISIONING_SYSPROP_KEY = "net.tethering.noprovisioning";
- private static final String ACTION_PROVISIONING_ALARM =
- "com.android.networkstack.tethering.PROVISIONING_RECHECK_ALARM";
-
- private final ComponentName mSilentProvisioningService;
- private static final int MS_PER_HOUR = 60 * 60 * 1000;
- private static final int DUMP_TIMEOUT = 10_000;
-
- // The BitSet is the bit map of each enabled downstream types, ex:
- // {@link TetheringManager.TETHERING_WIFI}
- // {@link TetheringManager.TETHERING_USB}
- // {@link TetheringManager.TETHERING_BLUETOOTH}
- private final BitSet mCurrentDownstreams;
- private final BitSet mExemptedDownstreams;
- private final Context mContext;
- private final SharedLog mLog;
- private final SparseIntArray mEntitlementCacheValue;
- private final Handler mHandler;
- // Key: TetheringManager.TETHERING_*(downstream).
- // Value: TetheringManager.TETHER_ERROR_{NO_ERROR or PROVISION_FAILED}(provisioning result).
- private final SparseIntArray mCurrentEntitlementResults;
- private final Runnable mPermissionChangeCallback;
- private PendingIntent mProvisioningRecheckAlarm;
- private boolean mLastCellularUpstreamPermitted = true;
- private boolean mUsingCellularAsUpstream = false;
- private boolean mNeedReRunProvisioningUi = false;
- private OnUiEntitlementFailedListener mListener;
- private TetheringConfigurationFetcher mFetcher;
-
- public EntitlementManager(Context ctx, Handler h, SharedLog log,
- Runnable callback) {
- mContext = ctx;
- mLog = log.forSubComponent(TAG);
- mCurrentDownstreams = new BitSet();
- mExemptedDownstreams = new BitSet();
- mCurrentEntitlementResults = new SparseIntArray();
- mEntitlementCacheValue = new SparseIntArray();
- mPermissionChangeCallback = callback;
- mHandler = h;
- mContext.registerReceiver(mReceiver, new IntentFilter(ACTION_PROVISIONING_ALARM),
- null, mHandler);
- mSilentProvisioningService = ComponentName.unflattenFromString(
- mContext.getResources().getString(R.string.config_wifi_tether_enable));
- }
-
- public void setOnUiEntitlementFailedListener(final OnUiEntitlementFailedListener listener) {
- mListener = listener;
- }
-
- /** Callback fired when UI entitlement failed. */
- public interface OnUiEntitlementFailedListener {
- /**
- * Ui entitlement check fails in |downstream|.
- *
- * @param downstream tethering type from TetheringManager.TETHERING_{@code *}.
- */
- void onUiEntitlementFailed(int downstream);
- }
-
- public void setTetheringConfigurationFetcher(final TetheringConfigurationFetcher fetcher) {
- mFetcher = fetcher;
- }
-
- /** Interface to fetch TetheringConfiguration. */
- public interface TetheringConfigurationFetcher {
- /**
- * Fetch current tethering configuration. This will be called to ensure whether entitlement
- * check is needed.
- * @return TetheringConfiguration instance.
- */
- TetheringConfiguration fetchTetheringConfiguration();
- }
-
- /**
- * Check if cellular upstream is permitted.
- */
- public boolean isCellularUpstreamPermitted() {
- final TetheringConfiguration config = mFetcher.fetchTetheringConfiguration();
-
- return isCellularUpstreamPermitted(config);
- }
-
- private boolean isCellularUpstreamPermitted(final TetheringConfiguration config) {
- if (!isTetherProvisioningRequired(config)) return true;
-
- // If provisioning is required and EntitlementManager doesn't know any downstreams, cellular
- // upstream should not be enabled. Enable cellular upstream for exempted downstreams only
- // when there is no non-exempted downstream.
- if (mCurrentDownstreams.isEmpty()) return !mExemptedDownstreams.isEmpty();
-
- return mCurrentEntitlementResults.indexOfValue(TETHER_ERROR_NO_ERROR) > -1;
- }
-
- /**
- * Set exempted downstream type. If there is only exempted downstream type active,
- * corresponding entitlement check will not be run and cellular upstream will be permitted
- * by default. If a privileged app enables tethering without a provisioning check, and then
- * another app enables tethering of the same type but does not disable the provisioning check,
- * then the downstream immediately loses exempt status and a provisioning check is run.
- * If any non-exempted downstream type is active, the cellular upstream will be gated by the
- * result of entitlement check from non-exempted downstreams. If entitlement check is still
- * in progress on non-exempt downstreams, ceullar upstream would default be disabled. When any
- * non-exempted downstream gets positive entitlement result, ceullar upstream will be enabled.
- */
- public void setExemptedDownstreamType(final int type) {
- mExemptedDownstreams.set(type, true);
- }
-
- /**
- * This is called when tethering starts.
- * Launch provisioning app if upstream is cellular.
- *
- * @param downstreamType tethering type from TetheringManager.TETHERING_{@code *}
- * @param showProvisioningUi a boolean indicating whether to show the
- * provisioning app UI if there is one.
- */
- public void startProvisioningIfNeeded(int downstreamType, boolean showProvisioningUi) {
- if (!isValidDownstreamType(downstreamType)) return;
-
- mCurrentDownstreams.set(downstreamType, true);
-
- mExemptedDownstreams.set(downstreamType, false);
-
- final TetheringConfiguration config = mFetcher.fetchTetheringConfiguration();
- if (!isTetherProvisioningRequired(config)) return;
-
- // If upstream is not cellular, provisioning app would not be launched
- // till upstream change to cellular.
- if (mUsingCellularAsUpstream) {
- if (showProvisioningUi) {
- runUiTetherProvisioning(downstreamType, config);
- } else {
- runSilentTetherProvisioning(downstreamType, config);
- }
- mNeedReRunProvisioningUi = false;
- } else {
- mNeedReRunProvisioningUi |= showProvisioningUi;
- }
- }
-
- /**
- * Tell EntitlementManager that a given type of tethering has been disabled
- *
- * @param type tethering type from TetheringManager.TETHERING_{@code *}
- */
- public void stopProvisioningIfNeeded(int downstreamType) {
- if (!isValidDownstreamType(downstreamType)) return;
-
- mCurrentDownstreams.set(downstreamType, false);
- // There are lurking bugs where the notion of "provisioning required" or
- // "tethering supported" may change without without tethering being notified properly.
- // Remove the mapping all the time no matter provisioning is required or not.
- removeDownstreamMapping(downstreamType);
- mExemptedDownstreams.set(downstreamType, false);
- }
-
- /**
- * Notify EntitlementManager if upstream is cellular or not.
- *
- * @param isCellular whether tethering upstream is cellular.
- */
- public void notifyUpstream(boolean isCellular) {
- if (DBG) {
- mLog.i("notifyUpstream: " + isCellular
- + ", mLastCellularUpstreamPermitted: " + mLastCellularUpstreamPermitted
- + ", mNeedReRunProvisioningUi: " + mNeedReRunProvisioningUi);
- }
- mUsingCellularAsUpstream = isCellular;
-
- if (mUsingCellularAsUpstream) {
- final TetheringConfiguration config = mFetcher.fetchTetheringConfiguration();
- maybeRunProvisioning(config);
- }
- }
-
- /** Run provisioning if needed */
- public void maybeRunProvisioning() {
- final TetheringConfiguration config = mFetcher.fetchTetheringConfiguration();
- maybeRunProvisioning(config);
- }
-
- private void maybeRunProvisioning(final TetheringConfiguration config) {
- if (mCurrentDownstreams.isEmpty() || !isTetherProvisioningRequired(config)) {
- return;
- }
-
- // Whenever any entitlement value changes, all downstreams will re-evaluate whether they
- // are allowed. Therefore even if the silent check here ends in a failure and the UI later
- // yields success, then the downstream that got a failure will re-evaluate as a result of
- // the change and get the new correct value.
- for (int downstream = mCurrentDownstreams.nextSetBit(0); downstream >= 0;
- downstream = mCurrentDownstreams.nextSetBit(downstream + 1)) {
- if (mCurrentEntitlementResults.indexOfKey(downstream) < 0) {
- if (mNeedReRunProvisioningUi) {
- mNeedReRunProvisioningUi = false;
- runUiTetherProvisioning(downstream, config);
- } else {
- runSilentTetherProvisioning(downstream, config);
- }
- }
- }
- }
-
- /**
- * Check if the device requires a provisioning check in order to enable tethering.
- *
- * @param config an object that encapsulates the various tethering configuration elements.
- * @return a boolean - {@code true} indicating tether provisioning is required by the carrier.
- */
- @VisibleForTesting
- protected boolean isTetherProvisioningRequired(final TetheringConfiguration config) {
- if (SystemProperties.getBoolean(DISABLE_PROVISIONING_SYSPROP_KEY, false)
- || config.provisioningApp.length == 0) {
- return false;
- }
- if (carrierConfigAffirmsEntitlementCheckNotRequired(config)) {
- return false;
- }
- return (config.provisioningApp.length == 2);
- }
-
- /**
- * Re-check tethering provisioning for all enabled tether types.
- * Reference TetheringManager.TETHERING_{@code *} for each tether type.
- *
- * @param config an object that encapsulates the various tethering configuration elements.
- * Note: this method is only called from @{link Tethering.TetherMainSM} on the handler thread.
- * If there are new callers from different threads, the logic should move to
- * @{link Tethering.TetherMainSM} handler to avoid race conditions.
- */
- public void reevaluateSimCardProvisioning(final TetheringConfiguration config) {
- if (DBG) mLog.i("reevaluateSimCardProvisioning");
-
- if (!mHandler.getLooper().isCurrentThread()) {
- // Except for test, this log should not appear in normal flow.
- mLog.log("reevaluateSimCardProvisioning() don't run in TetherMainSM thread");
- }
- mEntitlementCacheValue.clear();
- mCurrentEntitlementResults.clear();
-
- // TODO: refine provisioning check to isTetherProvisioningRequired() ??
- if (!config.hasMobileHotspotProvisionApp()
- || carrierConfigAffirmsEntitlementCheckNotRequired(config)) {
- evaluateCellularPermission(config);
- return;
- }
-
- if (mUsingCellularAsUpstream) {
- maybeRunProvisioning(config);
- }
- }
-
- /**
- * Get carrier configuration bundle.
- * @param config an object that encapsulates the various tethering configuration elements.
- * */
- public PersistableBundle getCarrierConfig(final TetheringConfiguration config) {
- final CarrierConfigManager configManager = (CarrierConfigManager) mContext
- .getSystemService(Context.CARRIER_CONFIG_SERVICE);
- if (configManager == null) return null;
-
- final PersistableBundle carrierConfig = configManager.getConfigForSubId(
- config.activeDataSubId);
-
- if (CarrierConfigManager.isConfigForIdentifiedCarrier(carrierConfig)) {
- return carrierConfig;
- }
-
- return null;
- }
-
- // The logic here is aimed solely at confirming that a CarrierConfig exists
- // and affirms that entitlement checks are not required.
- //
- // TODO: find a better way to express this, or alter the checking process
- // entirely so that this is more intuitive.
- private boolean carrierConfigAffirmsEntitlementCheckNotRequired(
- final TetheringConfiguration config) {
- // Check carrier config for entitlement checks
- final PersistableBundle carrierConfig = getCarrierConfig(config);
- if (carrierConfig == null) return false;
-
- // A CarrierConfigManager was found and it has a config.
- final boolean isEntitlementCheckRequired = carrierConfig.getBoolean(
- CarrierConfigManager.KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL);
- return !isEntitlementCheckRequired;
- }
-
- /**
- * Run no UI tethering provisioning check.
- * @param type tethering type from TetheringManager.TETHERING_{@code *}
- * @param subId default data subscription ID.
- */
- @VisibleForTesting
- protected Intent runSilentTetherProvisioning(int type, final TetheringConfiguration config) {
- if (DBG) mLog.i("runSilentTetherProvisioning: " + type);
- // For silent provisioning, settings would stop tethering when entitlement fail.
- ResultReceiver receiver = buildProxyReceiver(type, false/* notifyFail */, null);
-
- Intent intent = new Intent();
- intent.putExtra(EXTRA_ADD_TETHER_TYPE, type);
- intent.putExtra(EXTRA_RUN_PROVISION, true);
- intent.putExtra(EXTRA_TETHER_SILENT_PROVISIONING_ACTION, config.provisioningAppNoUi);
- intent.putExtra(EXTRA_TETHER_PROVISIONING_RESPONSE, config.provisioningResponse);
- intent.putExtra(EXTRA_PROVISION_CALLBACK, receiver);
- intent.putExtra(EXTRA_TETHER_SUBID, config.activeDataSubId);
- intent.setComponent(mSilentProvisioningService);
- // Only admin user can change tethering and SilentTetherProvisioning don't need to
- // show UI, it is fine to always start setting's background service as system user.
- mContext.startService(intent);
- return intent;
- }
-
- private void runUiTetherProvisioning(int type, final TetheringConfiguration config) {
- ResultReceiver receiver = buildProxyReceiver(type, true/* notifyFail */, null);
- runUiTetherProvisioning(type, config, receiver);
- }
-
- /**
- * Run the UI-enabled tethering provisioning check.
- * @param type tethering type from TetheringManager.TETHERING_{@code *}
- * @param subId default data subscription ID.
- * @param receiver to receive entitlement check result.
- */
- @VisibleForTesting
- protected Intent runUiTetherProvisioning(int type, final TetheringConfiguration config,
- ResultReceiver receiver) {
- if (DBG) mLog.i("runUiTetherProvisioning: " + type);
-
- Intent intent = new Intent(Settings.ACTION_TETHER_PROVISIONING_UI);
- intent.putExtra(EXTRA_ADD_TETHER_TYPE, type);
- intent.putExtra(EXTRA_TETHER_UI_PROVISIONING_APP_NAME, config.provisioningApp);
- intent.putExtra(EXTRA_PROVISION_CALLBACK, receiver);
- intent.putExtra(EXTRA_TETHER_SUBID, config.activeDataSubId);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- // Only launch entitlement UI for system user. Entitlement UI should not appear for other
- // user because only admin user is allowed to change tethering.
- mContext.startActivity(intent);
- return intent;
- }
-
- // Not needed to check if this don't run on the handler thread because it's private.
- private void scheduleProvisioningRechecks(final TetheringConfiguration config) {
- if (mProvisioningRecheckAlarm == null) {
- final int period = config.provisioningCheckPeriod;
- if (period <= 0) return;
-
- Intent intent = new Intent(ACTION_PROVISIONING_ALARM);
- mProvisioningRecheckAlarm = PendingIntent.getBroadcast(mContext, 0, intent, 0);
- AlarmManager alarmManager = (AlarmManager) mContext.getSystemService(
- Context.ALARM_SERVICE);
- long periodMs = period * MS_PER_HOUR;
- long firstAlarmTime = SystemClock.elapsedRealtime() + periodMs;
- alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME, firstAlarmTime, periodMs,
- mProvisioningRecheckAlarm);
- }
- }
-
- private void cancelTetherProvisioningRechecks() {
- if (mProvisioningRecheckAlarm != null) {
- AlarmManager alarmManager = (AlarmManager) mContext.getSystemService(
- Context.ALARM_SERVICE);
- alarmManager.cancel(mProvisioningRecheckAlarm);
- mProvisioningRecheckAlarm = null;
- }
- }
-
- private void evaluateCellularPermission(final TetheringConfiguration config) {
- final boolean permitted = isCellularUpstreamPermitted(config);
-
- if (DBG) {
- mLog.i("Cellular permission change from " + mLastCellularUpstreamPermitted
- + " to " + permitted);
- }
-
- if (mLastCellularUpstreamPermitted != permitted) {
- mLog.log("Cellular permission change: " + permitted);
- mPermissionChangeCallback.run();
- }
- // Only schedule periodic re-check when tether is provisioned
- // and the result is ok.
- if (permitted && mCurrentEntitlementResults.size() > 0) {
- scheduleProvisioningRechecks(config);
- } else {
- cancelTetherProvisioningRechecks();
- }
- mLastCellularUpstreamPermitted = permitted;
- }
-
- /**
- * Add the mapping between provisioning result and tethering type.
- * Notify UpstreamNetworkMonitor if Cellular permission changes.
- *
- * @param type tethering type from TetheringManager.TETHERING_{@code *}
- * @param resultCode Provisioning result
- */
- protected void addDownstreamMapping(int type, int resultCode) {
- mLog.i("addDownstreamMapping: " + type + ", result: " + resultCode
- + " ,TetherTypeRequested: " + mCurrentDownstreams.get(type));
- if (!mCurrentDownstreams.get(type)) return;
-
- mCurrentEntitlementResults.put(type, resultCode);
- final TetheringConfiguration config = mFetcher.fetchTetheringConfiguration();
- evaluateCellularPermission(config);
- }
-
- /**
- * Remove the mapping for input tethering type.
- * @param type tethering type from TetheringManager.TETHERING_{@code *}
- */
- protected void removeDownstreamMapping(int type) {
- mLog.i("removeDownstreamMapping: " + type);
- mCurrentEntitlementResults.delete(type);
- final TetheringConfiguration config = mFetcher.fetchTetheringConfiguration();
- evaluateCellularPermission(config);
- }
-
- private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (ACTION_PROVISIONING_ALARM.equals(intent.getAction())) {
- mLog.log("Received provisioning alarm");
- final TetheringConfiguration config = mFetcher.fetchTetheringConfiguration();
- reevaluateSimCardProvisioning(config);
- }
- }
- };
-
- private static boolean isValidDownstreamType(int type) {
- switch (type) {
- case TETHERING_BLUETOOTH:
- case TETHERING_ETHERNET:
- case TETHERING_USB:
- case TETHERING_WIFI:
- return true;
- default:
- return false;
- }
- }
-
- /**
- * Dump the infromation of EntitlementManager.
- * @param pw {@link PrintWriter} is used to print formatted
- */
- public void dump(PrintWriter pw) {
- final ConditionVariable mWaiting = new ConditionVariable();
- mHandler.post(() -> {
- pw.print("isCellularUpstreamPermitted: ");
- pw.println(isCellularUpstreamPermitted());
- for (int type = mCurrentDownstreams.nextSetBit(0); type >= 0;
- type = mCurrentDownstreams.nextSetBit(type + 1)) {
- pw.print("Type: ");
- pw.print(typeString(type));
- if (mCurrentEntitlementResults.indexOfKey(type) > -1) {
- pw.print(", Value: ");
- pw.println(errorString(mCurrentEntitlementResults.get(type)));
- } else {
- pw.println(", Value: empty");
- }
- }
- mWaiting.open();
- });
- if (!mWaiting.block(DUMP_TIMEOUT)) {
- pw.println("... dump timed out after " + DUMP_TIMEOUT + "ms");
- }
- pw.print("Exempted: [");
- for (int type = mExemptedDownstreams.nextSetBit(0); type >= 0;
- type = mExemptedDownstreams.nextSetBit(type + 1)) {
- pw.print(typeString(type));
- pw.print(", ");
- }
- pw.println("]");
- }
-
- private static String typeString(int type) {
- switch (type) {
- case TETHERING_BLUETOOTH: return "TETHERING_BLUETOOTH";
- case TETHERING_INVALID: return "TETHERING_INVALID";
- case TETHERING_USB: return "TETHERING_USB";
- case TETHERING_WIFI: return "TETHERING_WIFI";
- default:
- return String.format("TETHERING UNKNOWN TYPE (%d)", type);
- }
- }
-
- private static String errorString(int value) {
- switch (value) {
- case TETHER_ERROR_ENTITLEMENT_UNKNOWN: return "TETHER_ERROR_ENTITLEMENT_UNKONWN";
- case TETHER_ERROR_NO_ERROR: return "TETHER_ERROR_NO_ERROR";
- case TETHER_ERROR_PROVISIONING_FAILED: return "TETHER_ERROR_PROVISIONING_FAILED";
- default:
- return String.format("UNKNOWN ERROR (%d)", value);
- }
- }
-
- private ResultReceiver buildProxyReceiver(int type, boolean notifyFail,
- final ResultReceiver receiver) {
- ResultReceiver rr = new ResultReceiver(mHandler) {
- @Override
- protected void onReceiveResult(int resultCode, Bundle resultData) {
- int updatedCacheValue = updateEntitlementCacheValue(type, resultCode);
- addDownstreamMapping(type, updatedCacheValue);
- if (updatedCacheValue == TETHER_ERROR_PROVISIONING_FAILED && notifyFail) {
- mListener.onUiEntitlementFailed(type);
- }
- if (receiver != null) receiver.send(updatedCacheValue, null);
- }
- };
-
- return writeToParcel(rr);
- }
-
- // Instances of ResultReceiver need to be public classes for remote processes to be able
- // to load them (otherwise, ClassNotFoundException). For private classes, this method
- // performs a trick : round-trip parceling any instance of ResultReceiver will return a
- // vanilla instance of ResultReceiver sharing the binder token with the original receiver.
- // The binder token has a reference to the original instance of the private class and will
- // still call its methods, and can be sent over. However it cannot be used for anything
- // else than sending over a Binder call.
- // While round-trip parceling is not great, there is currently no other way of generating
- // a vanilla instance of ResultReceiver because all its fields are private.
- private ResultReceiver writeToParcel(final ResultReceiver receiver) {
- Parcel parcel = Parcel.obtain();
- receiver.writeToParcel(parcel, 0);
- parcel.setDataPosition(0);
- ResultReceiver receiverForSending = ResultReceiver.CREATOR.createFromParcel(parcel);
- parcel.recycle();
- return receiverForSending;
- }
-
- /**
- * Update the last entitlement value to internal cache
- *
- * @param type tethering type from TetheringManager.TETHERING_{@code *}
- * @param resultCode last entitlement value
- * @return the last updated entitlement value
- */
- private int updateEntitlementCacheValue(int type, int resultCode) {
- if (DBG) {
- mLog.i("updateEntitlementCacheValue: " + type + ", result: " + resultCode);
- }
- if (resultCode == TETHER_ERROR_NO_ERROR) {
- mEntitlementCacheValue.put(type, resultCode);
- return resultCode;
- } else {
- mEntitlementCacheValue.put(type, TETHER_ERROR_PROVISIONING_FAILED);
- return TETHER_ERROR_PROVISIONING_FAILED;
- }
- }
-
- /** Get the last value of the tethering entitlement check. */
- public void requestLatestTetheringEntitlementResult(int downstream, ResultReceiver receiver,
- boolean showEntitlementUi) {
- if (!isValidDownstreamType(downstream)) {
- receiver.send(TETHER_ERROR_ENTITLEMENT_UNKNOWN, null);
- return;
- }
-
- final TetheringConfiguration config = mFetcher.fetchTetheringConfiguration();
- if (!isTetherProvisioningRequired(config)) {
- receiver.send(TETHER_ERROR_NO_ERROR, null);
- return;
- }
-
- final int cacheValue = mEntitlementCacheValue.get(
- downstream, TETHER_ERROR_ENTITLEMENT_UNKNOWN);
- if (cacheValue == TETHER_ERROR_NO_ERROR || !showEntitlementUi) {
- receiver.send(cacheValue, null);
- } else {
- ResultReceiver proxy = buildProxyReceiver(downstream, false/* notifyFail */, receiver);
- runUiTetherProvisioning(downstream, config, proxy);
- }
- }
-}
diff --git a/packages/Tethering/src/com/android/networkstack/tethering/IPv6TetheringCoordinator.java b/packages/Tethering/src/com/android/networkstack/tethering/IPv6TetheringCoordinator.java
deleted file mode 100644
index f3dcaa2..0000000
--- a/packages/Tethering/src/com/android/networkstack/tethering/IPv6TetheringCoordinator.java
+++ /dev/null
@@ -1,328 +0,0 @@
-/*
- * Copyright (C) 2016 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;
-
-import android.net.IpPrefix;
-import android.net.LinkAddress;
-import android.net.LinkProperties;
-import android.net.Network;
-import android.net.NetworkCapabilities;
-import android.net.RouteInfo;
-import android.net.ip.IpServer;
-import android.net.util.NetworkConstants;
-import android.net.util.SharedLog;
-import android.util.Log;
-
-import java.net.Inet6Address;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.LinkedList;
-import java.util.Random;
-
-
-/**
- * IPv6 tethering is rather different from IPv4 owing to the absence of NAT.
- * This coordinator is responsible for evaluating the dedicated prefixes
- * assigned to the device and deciding how to divvy them up among downstream
- * interfaces.
- *
- * @hide
- */
-public class IPv6TetheringCoordinator {
- private static final String TAG = IPv6TetheringCoordinator.class.getSimpleName();
- private static final boolean DBG = false;
- private static final boolean VDBG = false;
-
- private static class Downstream {
- public final IpServer ipServer;
- public final int mode; // IpServer.STATE_*
- // Used to append to a ULA /48, constructing a ULA /64 for local use.
- public final short subnetId;
-
- Downstream(IpServer ipServer, int mode, short subnetId) {
- this.ipServer = ipServer;
- this.mode = mode;
- this.subnetId = subnetId;
- }
- }
-
- private final ArrayList<IpServer> mNotifyList;
- private final SharedLog mLog;
- // NOTE: mActiveDownstreams is a list and not a hash data structure because
- // we keep active downstreams in arrival order. This is done so /64s can
- // be parceled out on a "first come, first served" basis and a /64 used by
- // a downstream that is no longer active can be redistributed to any next
- // waiting active downstream (again, in arrival order).
- private final LinkedList<Downstream> mActiveDownstreams;
- private final byte[] mUniqueLocalPrefix;
- private short mNextSubnetId;
- private UpstreamNetworkState mUpstreamNetworkState;
-
- public IPv6TetheringCoordinator(ArrayList<IpServer> notifyList, SharedLog log) {
- mNotifyList = notifyList;
- mLog = log.forSubComponent(TAG);
- mActiveDownstreams = new LinkedList<>();
- mUniqueLocalPrefix = generateUniqueLocalPrefix();
- mNextSubnetId = 0;
- }
-
- /** Add active downstream to ipv6 tethering candidate list. */
- public void addActiveDownstream(IpServer downstream, int mode) {
- if (findDownstream(downstream) == null) {
- // Adding a new downstream appends it to the list. Adding a
- // downstream a second time without first removing it has no effect.
- // We never change the mode of a downstream except by first removing
- // it and then re-adding it (with its new mode specified);
- if (mActiveDownstreams.offer(new Downstream(downstream, mode, mNextSubnetId))) {
- // Make sure subnet IDs are always positive. They are appended
- // to a ULA /48 to make a ULA /64 for local use.
- mNextSubnetId = (short) Math.max(0, mNextSubnetId + 1);
- }
- updateIPv6TetheringInterfaces();
- }
- }
-
- /** Remove downstream from ipv6 tethering candidate list. */
- public void removeActiveDownstream(IpServer downstream) {
- stopIPv6TetheringOn(downstream);
- if (mActiveDownstreams.remove(findDownstream(downstream))) {
- updateIPv6TetheringInterfaces();
- }
-
- // When tethering is stopping we can reset the subnet counter.
- if (mNotifyList.isEmpty()) {
- if (!mActiveDownstreams.isEmpty()) {
- Log.wtf(TAG, "Tethering notify list empty, IPv6 downstreams non-empty.");
- }
- mNextSubnetId = 0;
- }
- }
-
- /**
- * Call when UpstreamNetworkState may be changed.
- * If upstream has ipv6 for tethering, update this new UpstreamNetworkState
- * to IpServer. Otherwise stop ipv6 tethering on downstream interfaces.
- */
- public void updateUpstreamNetworkState(UpstreamNetworkState ns) {
- if (VDBG) {
- Log.d(TAG, "updateUpstreamNetworkState: " + toDebugString(ns));
- }
- if (TetheringInterfaceUtils.getIPv6Interface(ns) == null) {
- stopIPv6TetheringOnAllInterfaces();
- setUpstreamNetworkState(null);
- return;
- }
-
- if (mUpstreamNetworkState != null
- && !ns.network.equals(mUpstreamNetworkState.network)) {
- stopIPv6TetheringOnAllInterfaces();
- }
-
- setUpstreamNetworkState(ns);
- updateIPv6TetheringInterfaces();
- }
-
- private void stopIPv6TetheringOnAllInterfaces() {
- for (IpServer ipServer : mNotifyList) {
- stopIPv6TetheringOn(ipServer);
- }
- }
-
- private void setUpstreamNetworkState(UpstreamNetworkState ns) {
- if (ns == null) {
- mUpstreamNetworkState = null;
- } else {
- // Make a deep copy of the parts we need.
- mUpstreamNetworkState = new UpstreamNetworkState(
- new LinkProperties(ns.linkProperties),
- new NetworkCapabilities(ns.networkCapabilities),
- new Network(ns.network));
- }
-
- mLog.log("setUpstreamNetworkState: " + toDebugString(mUpstreamNetworkState));
- }
-
- private void updateIPv6TetheringInterfaces() {
- for (IpServer ipServer : mNotifyList) {
- final LinkProperties lp = getInterfaceIPv6LinkProperties(ipServer);
- ipServer.sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, getTtlAdjustment(), 0, lp);
- break;
- }
- }
-
- private int getTtlAdjustment() {
- if (mUpstreamNetworkState == null || mUpstreamNetworkState.networkCapabilities == null) {
- return 0;
- }
-
- // If upstream is cellular, set the TTL in Router Advertisements to "network-set TTL" - 1
- // for carrier requirement.
- if (mUpstreamNetworkState.networkCapabilities.hasTransport(
- NetworkCapabilities.TRANSPORT_CELLULAR)) {
- return -1;
- }
-
- // For other non-cellular upstream, set TTL as "network-set TTL" + 1 to preventing arbitrary
- // distinction between tethered and untethered traffic.
- return 1;
- }
-
- private LinkProperties getInterfaceIPv6LinkProperties(IpServer ipServer) {
- final Downstream ds = findDownstream(ipServer);
- if (ds == null) return null;
-
- if (ds.mode == IpServer.STATE_LOCAL_ONLY) {
- // Build a Unique Locally-assigned Prefix configuration.
- return getUniqueLocalConfig(mUniqueLocalPrefix, ds.subnetId);
- }
-
- // This downstream is in IpServer.STATE_TETHERED mode.
- if (mUpstreamNetworkState == null || mUpstreamNetworkState.linkProperties == null) {
- return null;
- }
-
- // NOTE: Here, in future, we would have policies to decide how to divvy
- // up the available dedicated prefixes among downstream interfaces.
- // At this time we have no such mechanism--we only support tethering
- // IPv6 toward the oldest (first requested) active downstream.
-
- final Downstream currentActive = mActiveDownstreams.peek();
- if (currentActive != null && currentActive.ipServer == ipServer) {
- final LinkProperties lp = getIPv6OnlyLinkProperties(
- mUpstreamNetworkState.linkProperties);
- if (lp.hasIpv6DefaultRoute() && lp.hasGlobalIpv6Address()) {
- return lp;
- }
- }
-
- return null;
- }
-
- Downstream findDownstream(IpServer ipServer) {
- for (Downstream ds : mActiveDownstreams) {
- if (ds.ipServer == ipServer) return ds;
- }
- return null;
- }
-
- private static LinkProperties getIPv6OnlyLinkProperties(LinkProperties lp) {
- final LinkProperties v6only = new LinkProperties();
- if (lp == null) {
- return v6only;
- }
-
- // NOTE: At this time we don't copy over any information about any
- // stacked links. No current stacked link configuration has IPv6.
-
- v6only.setInterfaceName(lp.getInterfaceName());
-
- v6only.setMtu(lp.getMtu());
-
- for (LinkAddress linkAddr : lp.getLinkAddresses()) {
- if (linkAddr.isGlobalPreferred() && linkAddr.getPrefixLength() == 64) {
- v6only.addLinkAddress(linkAddr);
- }
- }
-
- for (RouteInfo routeInfo : lp.getRoutes()) {
- final IpPrefix destination = routeInfo.getDestination();
- if ((destination.getAddress() instanceof Inet6Address)
- && (destination.getPrefixLength() <= 64)) {
- v6only.addRoute(routeInfo);
- }
- }
-
- for (InetAddress dnsServer : lp.getDnsServers()) {
- if (isIPv6GlobalAddress(dnsServer)) {
- // For now we include ULAs.
- v6only.addDnsServer(dnsServer);
- }
- }
-
- v6only.setDomains(lp.getDomains());
-
- return v6only;
- }
-
- // TODO: Delete this and switch to LinkAddress#isGlobalPreferred once we
- // announce our own IPv6 address as DNS server.
- private static boolean isIPv6GlobalAddress(InetAddress ip) {
- return (ip instanceof Inet6Address)
- && !ip.isAnyLocalAddress()
- && !ip.isLoopbackAddress()
- && !ip.isLinkLocalAddress()
- && !ip.isSiteLocalAddress()
- && !ip.isMulticastAddress();
- }
-
- private static LinkProperties getUniqueLocalConfig(byte[] ulp, short subnetId) {
- final LinkProperties lp = new LinkProperties();
-
- final IpPrefix local48 = makeUniqueLocalPrefix(ulp, (short) 0, 48);
- lp.addRoute(new RouteInfo(local48, null, null, RouteInfo.RTN_UNICAST));
-
- final IpPrefix local64 = makeUniqueLocalPrefix(ulp, subnetId, 64);
- // Because this is a locally-generated ULA, we don't have an upstream
- // address. But because the downstream IP address management code gets
- // its prefix from the upstream's IP address, we create a fake one here.
- lp.addLinkAddress(new LinkAddress(local64.getAddress(), 64));
-
- lp.setMtu(NetworkConstants.ETHER_MTU);
- return lp;
- }
-
- private static IpPrefix makeUniqueLocalPrefix(byte[] in6addr, short subnetId, int prefixlen) {
- final byte[] bytes = Arrays.copyOf(in6addr, in6addr.length);
- bytes[7] = (byte) (subnetId >> 8);
- bytes[8] = (byte) subnetId;
- final InetAddress addr;
- try {
- addr = InetAddress.getByAddress(bytes);
- } catch (UnknownHostException e) {
- throw new IllegalStateException("Invalid address length: " + bytes.length, e);
- }
- return new IpPrefix(addr, prefixlen);
- }
-
- // Generates a Unique Locally-assigned Prefix:
- //
- // https://tools.ietf.org/html/rfc4193#section-3.1
- //
- // The result is a /48 that can be used for local-only communications.
- private static byte[] generateUniqueLocalPrefix() {
- final byte[] ulp = new byte[6]; // 6 = 48bits / 8bits/byte
- (new Random()).nextBytes(ulp);
-
- final byte[] in6addr = Arrays.copyOf(ulp, NetworkConstants.IPV6_ADDR_LEN);
- in6addr[0] = (byte) 0xfd; // fc00::/7 and L=1
-
- return in6addr;
- }
-
- private static String toDebugString(UpstreamNetworkState ns) {
- if (ns == null) {
- return "UpstreamNetworkState{null}";
- }
- return ns.toString();
- }
-
- private static void stopIPv6TetheringOn(IpServer ipServer) {
- ipServer.sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, 0, 0, null);
- }
-}
diff --git a/packages/Tethering/src/com/android/networkstack/tethering/OffloadController.java b/packages/Tethering/src/com/android/networkstack/tethering/OffloadController.java
deleted file mode 100644
index 88c77b0..0000000
--- a/packages/Tethering/src/com/android/networkstack/tethering/OffloadController.java
+++ /dev/null
@@ -1,811 +0,0 @@
-/*
- * Copyright (C) 2017 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;
-
-import static android.net.NetworkStats.DEFAULT_NETWORK_NO;
-import static android.net.NetworkStats.METERED_NO;
-import static android.net.NetworkStats.ROAMING_NO;
-import static android.net.NetworkStats.SET_DEFAULT;
-import static android.net.NetworkStats.TAG_NONE;
-import static android.net.NetworkStats.UID_ALL;
-import static android.net.NetworkStats.UID_TETHERING;
-import static android.net.netstats.provider.NetworkStatsProvider.QUOTA_UNLIMITED;
-import static android.provider.Settings.Global.TETHER_OFFLOAD_DISABLED;
-
-import static com.android.networkstack.tethering.TetheringConfiguration.DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.app.usage.NetworkStatsManager;
-import android.content.ContentResolver;
-import android.net.InetAddresses;
-import android.net.IpPrefix;
-import android.net.LinkAddress;
-import android.net.LinkProperties;
-import android.net.NetworkStats;
-import android.net.NetworkStats.Entry;
-import android.net.RouteInfo;
-import android.net.netlink.ConntrackMessage;
-import android.net.netlink.NetlinkConstants;
-import android.net.netlink.NetlinkSocket;
-import android.net.netstats.provider.NetworkStatsProvider;
-import android.net.util.SharedLog;
-import android.os.Handler;
-import android.provider.Settings;
-import android.system.ErrnoException;
-import android.system.OsConstants;
-import android.text.TextUtils;
-import android.util.Log;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.IndentingPrintWriter;
-import com.android.networkstack.tethering.OffloadHardwareInterface.ForwardedStats;
-
-import java.net.Inet4Address;
-import java.net.Inet6Address;
-import java.net.InetAddress;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- * A class to encapsulate the business logic of programming the tethering
- * hardware offload interface.
- *
- * @hide
- */
-public class OffloadController {
- private static final String TAG = OffloadController.class.getSimpleName();
- private static final boolean DBG = false;
- private static final String ANYIP = "0.0.0.0";
- private static final ForwardedStats EMPTY_STATS = new ForwardedStats();
-
- @VisibleForTesting
- enum StatsType {
- STATS_PER_IFACE,
- STATS_PER_UID,
- }
-
- private enum UpdateType { IF_NEEDED, FORCE };
-
- private final Handler mHandler;
- private final OffloadHardwareInterface mHwInterface;
- private final ContentResolver mContentResolver;
- @Nullable
- private final OffloadTetheringStatsProvider mStatsProvider;
- private final SharedLog mLog;
- private final HashMap<String, LinkProperties> mDownstreams;
- private boolean mConfigInitialized;
- private boolean mControlInitialized;
- private LinkProperties mUpstreamLinkProperties;
- // The complete set of offload-exempt prefixes passed in via Tethering from
- // all upstream and downstream sources.
- private Set<IpPrefix> mExemptPrefixes;
- // A strictly "smaller" set of prefixes, wherein offload-approved prefixes
- // (e.g. downstream on-link prefixes) have been removed and replaced with
- // prefixes representing only the locally-assigned IP addresses.
- private Set<String> mLastLocalPrefixStrs;
-
- // Maps upstream interface names to offloaded traffic statistics.
- // Always contains the latest value received from the hardware for each interface, regardless of
- // whether offload is currently running on that interface.
- private ConcurrentHashMap<String, ForwardedStats> mForwardedStats =
- new ConcurrentHashMap<>(16, 0.75F, 1);
-
- // Maps upstream interface names to interface quotas.
- // Always contains the latest value received from the framework for each interface, regardless
- // of whether offload is currently running (or is even supported) on that interface. Only
- // includes upstream interfaces that have a quota set.
- private HashMap<String, Long> mInterfaceQuotas = new HashMap<>();
-
- // Tracking remaining alert quota. Unlike limit quota is subject to interface, the alert
- // quota is interface independent and global for tether offload. Note that this is only
- // accessed on the handler thread and in the constructor.
- private long mRemainingAlertQuota = QUOTA_UNLIMITED;
- // Runnable that used to schedule the next stats poll.
- private final Runnable mScheduledPollingTask = () -> {
- updateStatsForCurrentUpstream();
- maybeSchedulePollingStats();
- };
-
- private int mNatUpdateCallbacksReceived;
- private int mNatUpdateNetlinkErrors;
-
- @NonNull
- private final Dependencies mDeps;
-
- // TODO: Put more parameters in constructor into dependency object.
- interface Dependencies {
- @NonNull
- TetheringConfiguration getTetherConfig();
- }
-
- public OffloadController(Handler h, OffloadHardwareInterface hwi,
- ContentResolver contentResolver, NetworkStatsManager nsm, SharedLog log,
- @NonNull Dependencies deps) {
- mHandler = h;
- mHwInterface = hwi;
- mContentResolver = contentResolver;
- mLog = log.forSubComponent(TAG);
- mDownstreams = new HashMap<>();
- mExemptPrefixes = new HashSet<>();
- mLastLocalPrefixStrs = new HashSet<>();
- OffloadTetheringStatsProvider provider = new OffloadTetheringStatsProvider();
- try {
- nsm.registerNetworkStatsProvider(getClass().getSimpleName(), provider);
- } catch (RuntimeException e) {
- Log.wtf(TAG, "Cannot register offload stats provider: " + e);
- provider = null;
- }
- mStatsProvider = provider;
- mDeps = deps;
- }
-
- /** Start hardware offload. */
- public boolean start() {
- if (started()) return true;
-
- if (isOffloadDisabled()) {
- mLog.i("tethering offload disabled");
- return false;
- }
-
- if (!mConfigInitialized) {
- mConfigInitialized = mHwInterface.initOffloadConfig();
- if (!mConfigInitialized) {
- mLog.i("tethering offload config not supported");
- stop();
- return false;
- }
- }
-
- mControlInitialized = mHwInterface.initOffloadControl(
- // OffloadHardwareInterface guarantees that these callback
- // methods are called on the handler passed to it, which is the
- // same as mHandler, as coordinated by the setup in Tethering.
- new OffloadHardwareInterface.ControlCallback() {
- @Override
- public void onStarted() {
- if (!started()) return;
- mLog.log("onStarted");
- }
-
- @Override
- public void onStoppedError() {
- if (!started()) return;
- mLog.log("onStoppedError");
- }
-
- @Override
- public void onStoppedUnsupported() {
- if (!started()) return;
- mLog.log("onStoppedUnsupported");
- // Poll for statistics and trigger a sweep of tethering
- // stats by observers. This might not succeed, but it's
- // worth trying anyway. We need to do this because from
- // this point on we continue with software forwarding,
- // and we need to synchronize stats and limits between
- // software and hardware forwarding.
- updateStatsForAllUpstreams();
- if (mStatsProvider != null) mStatsProvider.pushTetherStats();
- }
-
- @Override
- public void onSupportAvailable() {
- if (!started()) return;
- mLog.log("onSupportAvailable");
-
- // [1] Poll for statistics and trigger a sweep of stats
- // by observers. We need to do this to ensure that any
- // limits set take into account any software tethering
- // traffic that has been happening in the meantime.
- updateStatsForAllUpstreams();
- if (mStatsProvider != null) mStatsProvider.pushTetherStats();
- // [2] (Re)Push all state.
- computeAndPushLocalPrefixes(UpdateType.FORCE);
- pushAllDownstreamState();
- pushUpstreamParameters(null);
- }
-
- @Override
- public void onStoppedLimitReached() {
- if (!started()) return;
- mLog.log("onStoppedLimitReached");
-
- // We cannot reliably determine on which interface the limit was reached,
- // because the HAL interface does not specify it. We cannot just use the
- // current upstream, because that might have changed since the time that
- // the HAL queued the callback.
- // TODO: rev the HAL so that it provides an interface name.
-
- updateStatsForCurrentUpstream();
- if (mStatsProvider != null) {
- mStatsProvider.pushTetherStats();
- // Push stats to service does not cause the service react to it
- // immediately. Inform the service about limit reached.
- mStatsProvider.notifyLimitReached();
- }
- }
-
- @Override
- public void onNatTimeoutUpdate(int proto,
- String srcAddr, int srcPort,
- String dstAddr, int dstPort) {
- if (!started()) return;
- updateNatTimeout(proto, srcAddr, srcPort, dstAddr, dstPort);
- }
- });
-
- final boolean isStarted = started();
- if (!isStarted) {
- mLog.i("tethering offload control not supported");
- stop();
- } else {
- mLog.log("tethering offload started");
- mNatUpdateCallbacksReceived = 0;
- mNatUpdateNetlinkErrors = 0;
- maybeSchedulePollingStats();
- }
- return isStarted;
- }
-
- /** Stop hardware offload. */
- public void stop() {
- // Completely stops tethering offload. After this method is called, it is no longer safe to
- // call any HAL method, no callbacks from the hardware will be delivered, and any in-flight
- // callbacks must be ignored. Offload may be started again by calling start().
- final boolean wasStarted = started();
- updateStatsForCurrentUpstream();
- mUpstreamLinkProperties = null;
- mHwInterface.stopOffloadControl();
- mControlInitialized = false;
- mConfigInitialized = false;
- if (mHandler.hasCallbacks(mScheduledPollingTask)) {
- mHandler.removeCallbacks(mScheduledPollingTask);
- }
- if (wasStarted) mLog.log("tethering offload stopped");
- }
-
- private boolean started() {
- return mConfigInitialized && mControlInitialized;
- }
-
- @VisibleForTesting
- class OffloadTetheringStatsProvider extends NetworkStatsProvider {
- // These stats must only ever be touched on the handler thread.
- @NonNull
- private NetworkStats mIfaceStats = new NetworkStats(0L, 0);
- @NonNull
- private NetworkStats mUidStats = new NetworkStats(0L, 0);
-
- /**
- * A helper function that collect tether stats from local hashmap. Note that this does not
- * invoke binder call.
- */
- @VisibleForTesting
- @NonNull
- NetworkStats getTetherStats(@NonNull StatsType how) {
- NetworkStats stats = new NetworkStats(0L, 0);
- final int uid = (how == StatsType.STATS_PER_UID) ? UID_TETHERING : UID_ALL;
-
- for (final Map.Entry<String, ForwardedStats> kv : mForwardedStats.entrySet()) {
- final ForwardedStats value = kv.getValue();
- final Entry entry = new Entry(kv.getKey(), uid, SET_DEFAULT, TAG_NONE, METERED_NO,
- ROAMING_NO, DEFAULT_NETWORK_NO, value.rxBytes, 0L, value.txBytes, 0L, 0L);
- stats = stats.addEntry(entry);
- }
-
- return stats;
- }
-
- @Override
- public void onSetLimit(String iface, long quotaBytes) {
- // Listen for all iface is necessary since upstream might be changed after limit
- // is set.
- mHandler.post(() -> {
- final Long curIfaceQuota = mInterfaceQuotas.get(iface);
-
- // If the quota is set to unlimited, the value set to HAL is Long.MAX_VALUE,
- // which is ~8.4 x 10^6 TiB, no one can actually reach it. Thus, it is not
- // useful to set it multiple times.
- // Otherwise, the quota needs to be updated to tell HAL to re-count from now even
- // if the quota is the same as the existing one.
- if (null == curIfaceQuota && QUOTA_UNLIMITED == quotaBytes) return;
-
- if (quotaBytes == QUOTA_UNLIMITED) {
- mInterfaceQuotas.remove(iface);
- } else {
- mInterfaceQuotas.put(iface, quotaBytes);
- }
- maybeUpdateDataLimit(iface);
- });
- }
-
- /**
- * Push stats to service, but does not cause a force polling. Note that this can only be
- * called on the handler thread.
- */
- public void pushTetherStats() {
- // TODO: remove the accumulated stats and report the diff from HAL directly.
- final NetworkStats ifaceDiff =
- getTetherStats(StatsType.STATS_PER_IFACE).subtract(mIfaceStats);
- final NetworkStats uidDiff =
- getTetherStats(StatsType.STATS_PER_UID).subtract(mUidStats);
- try {
- notifyStatsUpdated(0 /* token */, ifaceDiff, uidDiff);
- mIfaceStats = mIfaceStats.add(ifaceDiff);
- mUidStats = mUidStats.add(uidDiff);
- } catch (RuntimeException e) {
- mLog.e("Cannot report network stats: ", e);
- }
- }
-
- @Override
- public void onRequestStatsUpdate(int token) {
- // Do not attempt to update stats by querying the offload HAL
- // synchronously from a different thread than the Handler thread. http://b/64771555.
- mHandler.post(() -> {
- updateStatsForCurrentUpstream();
- pushTetherStats();
- });
- }
-
- @Override
- public void onSetAlert(long quotaBytes) {
- // TODO: Ask offload HAL to notify alert without stopping traffic.
- // Post it to handler thread since it access remaining quota bytes.
- mHandler.post(() -> {
- updateAlertQuota(quotaBytes);
- maybeSchedulePollingStats();
- });
- }
- }
-
- private String currentUpstreamInterface() {
- return (mUpstreamLinkProperties != null)
- ? mUpstreamLinkProperties.getInterfaceName() : null;
- }
-
- private void maybeUpdateStats(String iface) {
- if (TextUtils.isEmpty(iface)) {
- return;
- }
-
- // Always called on the handler thread.
- //
- // Use get()/put() instead of updating ForwardedStats in place because we can be called
- // concurrently with getTetherStats. In combination with the guarantees provided by
- // ConcurrentHashMap, this ensures that getTetherStats always gets the most recent copy of
- // the stats for each interface, and does not observe partial writes where rxBytes is
- // updated and txBytes is not.
- ForwardedStats diff = mHwInterface.getForwardedStats(iface);
- final long usedAlertQuota = diff.rxBytes + diff.txBytes;
- ForwardedStats base = mForwardedStats.get(iface);
- if (base != null) {
- diff.add(base);
- }
-
- // Update remaining alert quota if it is still positive.
- if (mRemainingAlertQuota > 0 && usedAlertQuota > 0) {
- // Trim to zero if overshoot.
- final long newQuota = Math.max(mRemainingAlertQuota - usedAlertQuota, 0);
- updateAlertQuota(newQuota);
- }
-
- mForwardedStats.put(iface, diff);
- // diff is a new object, just created by getForwardedStats(). Therefore, anyone reading from
- // mForwardedStats (i.e., any caller of getTetherStats) will see the new stats immediately.
- }
-
- /**
- * Update remaining alert quota, fire the {@link NetworkStatsProvider#notifyAlertReached()}
- * callback when it reaches zero. This can be invoked either from service setting the alert, or
- * {@code maybeUpdateStats} when updating stats. Note that this can be only called on
- * handler thread.
- *
- * @param newQuota non-negative value to indicate the new quota, or
- * {@link NetworkStatsProvider#QUOTA_UNLIMITED} to indicate there is no
- * quota.
- */
- private void updateAlertQuota(long newQuota) {
- if (newQuota < QUOTA_UNLIMITED) {
- throw new IllegalArgumentException("invalid quota value " + newQuota);
- }
- if (mRemainingAlertQuota == newQuota) return;
-
- mRemainingAlertQuota = newQuota;
- if (mRemainingAlertQuota == 0) {
- mLog.i("notifyAlertReached");
- if (mStatsProvider != null) mStatsProvider.notifyAlertReached();
- }
- }
-
- /**
- * Schedule polling if needed, this will be stopped if offload has been
- * stopped or remaining quota reaches zero or upstream is empty.
- * Note that this can be only called on handler thread.
- */
- private void maybeSchedulePollingStats() {
- if (!isPollingStatsNeeded()) return;
-
- if (mHandler.hasCallbacks(mScheduledPollingTask)) {
- mHandler.removeCallbacks(mScheduledPollingTask);
- }
- mHandler.postDelayed(mScheduledPollingTask,
- mDeps.getTetherConfig().getOffloadPollInterval());
- }
-
- private boolean isPollingStatsNeeded() {
- return started() && mRemainingAlertQuota > 0
- && !TextUtils.isEmpty(currentUpstreamInterface())
- && mDeps.getTetherConfig() != null
- && mDeps.getTetherConfig().getOffloadPollInterval()
- >= DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS;
- }
-
- private boolean maybeUpdateDataLimit(String iface) {
- // setDataLimit may only be called while offload is occurring on this upstream.
- if (!started() || !TextUtils.equals(iface, currentUpstreamInterface())) {
- return true;
- }
-
- Long limit = mInterfaceQuotas.get(iface);
- if (limit == null) {
- limit = Long.MAX_VALUE;
- }
-
- return mHwInterface.setDataLimit(iface, limit);
- }
-
- private void updateStatsForCurrentUpstream() {
- maybeUpdateStats(currentUpstreamInterface());
- }
-
- private void updateStatsForAllUpstreams() {
- // In practice, there should only ever be a single digit number of
- // upstream interfaces over the lifetime of an active tethering session.
- // Roughly speaking, imagine a very ambitious one or two of each of the
- // following interface types: [ "rmnet_data", "wlan", "eth", "rndis" ].
- for (Map.Entry<String, ForwardedStats> kv : mForwardedStats.entrySet()) {
- maybeUpdateStats(kv.getKey());
- }
- }
-
- /** Set current tethering upstream LinkProperties. */
- public void setUpstreamLinkProperties(LinkProperties lp) {
- if (!started() || Objects.equals(mUpstreamLinkProperties, lp)) return;
-
- final String prevUpstream = currentUpstreamInterface();
-
- mUpstreamLinkProperties = (lp != null) ? new LinkProperties(lp) : null;
- // Make sure we record this interface in the ForwardedStats map.
- final String iface = currentUpstreamInterface();
- if (!TextUtils.isEmpty(iface)) mForwardedStats.putIfAbsent(iface, EMPTY_STATS);
-
- maybeSchedulePollingStats();
-
- // TODO: examine return code and decide what to do if programming
- // upstream parameters fails (probably just wait for a subsequent
- // onOffloadEvent() callback to tell us offload is available again and
- // then reapply all state).
- computeAndPushLocalPrefixes(UpdateType.IF_NEEDED);
- pushUpstreamParameters(prevUpstream);
- }
-
- /** Set local prefixes. */
- public void setLocalPrefixes(Set<IpPrefix> localPrefixes) {
- mExemptPrefixes = localPrefixes;
-
- if (!started()) return;
- computeAndPushLocalPrefixes(UpdateType.IF_NEEDED);
- }
-
- /** Update current downstream LinkProperties. */
- public void notifyDownstreamLinkProperties(LinkProperties lp) {
- final String ifname = lp.getInterfaceName();
- final LinkProperties oldLp = mDownstreams.put(ifname, new LinkProperties(lp));
- if (Objects.equals(oldLp, lp)) return;
-
- if (!started()) return;
- pushDownstreamState(oldLp, lp);
- }
-
- private void pushDownstreamState(LinkProperties oldLp, LinkProperties newLp) {
- final String ifname = newLp.getInterfaceName();
- final List<RouteInfo> oldRoutes =
- (oldLp != null) ? oldLp.getRoutes() : Collections.EMPTY_LIST;
- final List<RouteInfo> newRoutes = newLp.getRoutes();
-
- // For each old route, if not in new routes: remove.
- for (RouteInfo ri : oldRoutes) {
- if (shouldIgnoreDownstreamRoute(ri)) continue;
- if (!newRoutes.contains(ri)) {
- mHwInterface.removeDownstreamPrefix(ifname, ri.getDestination().toString());
- }
- }
-
- // For each new route, if not in old routes: add.
- for (RouteInfo ri : newRoutes) {
- if (shouldIgnoreDownstreamRoute(ri)) continue;
- if (!oldRoutes.contains(ri)) {
- mHwInterface.addDownstreamPrefix(ifname, ri.getDestination().toString());
- }
- }
- }
-
- private void pushAllDownstreamState() {
- for (LinkProperties lp : mDownstreams.values()) {
- pushDownstreamState(null, lp);
- }
- }
-
- /** Remove downstream interface from offload hardware. */
- public void removeDownstreamInterface(String ifname) {
- final LinkProperties lp = mDownstreams.remove(ifname);
- if (lp == null) return;
-
- if (!started()) return;
-
- for (RouteInfo route : lp.getRoutes()) {
- if (shouldIgnoreDownstreamRoute(route)) continue;
- mHwInterface.removeDownstreamPrefix(ifname, route.getDestination().toString());
- }
- }
-
- private boolean isOffloadDisabled() {
- final int defaultDisposition = mHwInterface.getDefaultTetherOffloadDisabled();
- return (Settings.Global.getInt(
- mContentResolver, TETHER_OFFLOAD_DISABLED, defaultDisposition) != 0);
- }
-
- private boolean pushUpstreamParameters(String prevUpstream) {
- final String iface = currentUpstreamInterface();
-
- if (TextUtils.isEmpty(iface)) {
- final boolean rval = mHwInterface.setUpstreamParameters("", ANYIP, ANYIP, null);
- // Update stats after we've told the hardware to stop forwarding so
- // we don't miss packets.
- maybeUpdateStats(prevUpstream);
- return rval;
- }
-
- // A stacked interface cannot be an upstream for hardware offload.
- // Consequently, we examine only the primary interface name, look at
- // getAddresses() rather than getAllAddresses(), and check getRoutes()
- // rather than getAllRoutes().
- final ArrayList<String> v6gateways = new ArrayList<>();
- String v4addr = null;
- String v4gateway = null;
-
- for (InetAddress ip : mUpstreamLinkProperties.getAddresses()) {
- if (ip instanceof Inet4Address) {
- v4addr = ip.getHostAddress();
- break;
- }
- }
-
- // Find the gateway addresses of all default routes of either address family.
- for (RouteInfo ri : mUpstreamLinkProperties.getRoutes()) {
- if (!ri.hasGateway()) continue;
-
- final String gateway = ri.getGateway().getHostAddress();
- final InetAddress address = ri.getDestination().getAddress();
- if (ri.isDefaultRoute() && address instanceof Inet4Address) {
- v4gateway = gateway;
- } else if (ri.isDefaultRoute() && address instanceof Inet6Address) {
- v6gateways.add(gateway);
- }
- }
-
- boolean success = mHwInterface.setUpstreamParameters(
- iface, v4addr, v4gateway, (v6gateways.isEmpty() ? null : v6gateways));
-
- if (!success) {
- return success;
- }
-
- // Update stats after we've told the hardware to change routing so we don't miss packets.
- maybeUpdateStats(prevUpstream);
-
- // Data limits can only be set once offload is running on the upstream.
- success = maybeUpdateDataLimit(iface);
- if (!success) {
- // If we failed to set a data limit, don't use this upstream, because we don't want to
- // blow through the data limit that we were told to apply.
- mLog.log("Setting data limit for " + iface + " failed, disabling offload.");
- stop();
- }
-
- return success;
- }
-
- private boolean computeAndPushLocalPrefixes(UpdateType how) {
- final boolean force = (how == UpdateType.FORCE);
- final Set<String> localPrefixStrs = computeLocalPrefixStrings(
- mExemptPrefixes, mUpstreamLinkProperties);
- if (!force && mLastLocalPrefixStrs.equals(localPrefixStrs)) return true;
-
- mLastLocalPrefixStrs = localPrefixStrs;
- return mHwInterface.setLocalPrefixes(new ArrayList<>(localPrefixStrs));
- }
-
- // TODO: Factor in downstream LinkProperties once that information is available.
- private static Set<String> computeLocalPrefixStrings(
- Set<IpPrefix> localPrefixes, LinkProperties upstreamLinkProperties) {
- // Create an editable copy.
- final Set<IpPrefix> prefixSet = new HashSet<>(localPrefixes);
-
- // TODO: If a downstream interface (not currently passed in) is reusing
- // the /64 of the upstream (64share) then:
- //
- // [a] remove that /64 from the local prefixes
- // [b] add in /128s for IP addresses on the downstream interface
- // [c] add in /128s for IP addresses on the upstream interface
- //
- // Until downstream information is available here, simply add /128s from
- // the upstream network; they'll just be redundant with their /64.
- if (upstreamLinkProperties != null) {
- for (LinkAddress linkAddr : upstreamLinkProperties.getLinkAddresses()) {
- if (!linkAddr.isGlobalPreferred()) continue;
- final InetAddress ip = linkAddr.getAddress();
- if (!(ip instanceof Inet6Address)) continue;
- prefixSet.add(new IpPrefix(ip, 128));
- }
- }
-
- final HashSet<String> localPrefixStrs = new HashSet<>();
- for (IpPrefix pfx : prefixSet) localPrefixStrs.add(pfx.toString());
- return localPrefixStrs;
- }
-
- private static boolean shouldIgnoreDownstreamRoute(RouteInfo route) {
- // Ignore any link-local routes.
- final IpPrefix destination = route.getDestination();
- final LinkAddress linkAddr = new LinkAddress(destination.getAddress(),
- destination.getPrefixLength());
- if (!linkAddr.isGlobalPreferred()) return true;
-
- return false;
- }
-
- /** Dump information. */
- public void dump(IndentingPrintWriter pw) {
- if (isOffloadDisabled()) {
- pw.println("Offload disabled");
- return;
- }
- final boolean isStarted = started();
- pw.println("Offload HALs " + (isStarted ? "started" : "not started"));
- LinkProperties lp = mUpstreamLinkProperties;
- String upstream = (lp != null) ? lp.getInterfaceName() : null;
- pw.println("Current upstream: " + upstream);
- pw.println("Exempt prefixes: " + mLastLocalPrefixStrs);
- pw.println("NAT timeout update callbacks received during the "
- + (isStarted ? "current" : "last")
- + " offload session: "
- + mNatUpdateCallbacksReceived);
- pw.println("NAT timeout update netlink errors during the "
- + (isStarted ? "current" : "last")
- + " offload session: "
- + mNatUpdateNetlinkErrors);
- }
-
- private void updateNatTimeout(
- int proto, String srcAddr, int srcPort, String dstAddr, int dstPort) {
- final String protoName = protoNameFor(proto);
- if (protoName == null) {
- mLog.e("Unknown NAT update callback protocol: " + proto);
- return;
- }
-
- final Inet4Address src = parseIPv4Address(srcAddr);
- if (src == null) {
- mLog.e("Failed to parse IPv4 address: " + srcAddr);
- return;
- }
-
- if (!isValidUdpOrTcpPort(srcPort)) {
- mLog.e("Invalid src port: " + srcPort);
- return;
- }
-
- final Inet4Address dst = parseIPv4Address(dstAddr);
- if (dst == null) {
- mLog.e("Failed to parse IPv4 address: " + dstAddr);
- return;
- }
-
- if (!isValidUdpOrTcpPort(dstPort)) {
- mLog.e("Invalid dst port: " + dstPort);
- return;
- }
-
- mNatUpdateCallbacksReceived++;
- final String natDescription = String.format("%s (%s, %s) -> (%s, %s)",
- protoName, srcAddr, srcPort, dstAddr, dstPort);
- if (DBG) {
- mLog.log("NAT timeout update: " + natDescription);
- }
-
- final int timeoutSec = connectionTimeoutUpdateSecondsFor(proto);
- final byte[] msg = ConntrackMessage.newIPv4TimeoutUpdateRequest(
- proto, src, srcPort, dst, dstPort, timeoutSec);
-
- try {
- NetlinkSocket.sendOneShotKernelMessage(OsConstants.NETLINK_NETFILTER, msg);
- } catch (ErrnoException e) {
- mNatUpdateNetlinkErrors++;
- mLog.e("Error updating NAT conntrack entry >" + natDescription + "<: " + e
- + ", msg: " + NetlinkConstants.hexify(msg));
- mLog.log("NAT timeout update callbacks received: " + mNatUpdateCallbacksReceived);
- mLog.log("NAT timeout update netlink errors: " + mNatUpdateNetlinkErrors);
- }
- }
-
- private static Inet4Address parseIPv4Address(String addrString) {
- try {
- final InetAddress ip = InetAddresses.parseNumericAddress(addrString);
- // TODO: Consider other sanitization steps here, including perhaps:
- // not eql to 0.0.0.0
- // not within 169.254.0.0/16
- // not within ::ffff:0.0.0.0/96
- // not within ::/96
- // et cetera.
- if (ip instanceof Inet4Address) {
- return (Inet4Address) ip;
- }
- } catch (IllegalArgumentException iae) { }
- return null;
- }
-
- private static String protoNameFor(int proto) {
- // OsConstants values are not constant expressions; no switch statement.
- if (proto == OsConstants.IPPROTO_UDP) {
- return "UDP";
- } else if (proto == OsConstants.IPPROTO_TCP) {
- return "TCP";
- }
- return null;
- }
-
- private static int connectionTimeoutUpdateSecondsFor(int proto) {
- // TODO: Replace this with more thoughtful work, perhaps reading from
- // and maybe writing to any required
- //
- // /proc/sys/net/netfilter/nf_conntrack_tcp_timeout_*
- // /proc/sys/net/netfilter/nf_conntrack_udp_timeout{,_stream}
- //
- // entries. TBD.
- if (proto == OsConstants.IPPROTO_TCP) {
- // Cf. /proc/sys/net/netfilter/nf_conntrack_tcp_timeout_established
- return 432000;
- } else {
- // Cf. /proc/sys/net/netfilter/nf_conntrack_udp_timeout_stream
- return 180;
- }
- }
-
- private static boolean isValidUdpOrTcpPort(int port) {
- return port > 0 && port < 65536;
- }
-}
diff --git a/packages/Tethering/src/com/android/networkstack/tethering/OffloadHardwareInterface.java b/packages/Tethering/src/com/android/networkstack/tethering/OffloadHardwareInterface.java
deleted file mode 100644
index da5f25b..0000000
--- a/packages/Tethering/src/com/android/networkstack/tethering/OffloadHardwareInterface.java
+++ /dev/null
@@ -1,574 +0,0 @@
-/*
- * Copyright (C) 2017 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;
-
-import static android.net.netlink.StructNlMsgHdr.NLM_F_DUMP;
-import static android.net.netlink.StructNlMsgHdr.NLM_F_REQUEST;
-import static android.net.util.TetheringUtils.uint16;
-
-import android.annotation.NonNull;
-import android.hardware.tetheroffload.config.V1_0.IOffloadConfig;
-import android.hardware.tetheroffload.control.V1_0.IOffloadControl;
-import android.hardware.tetheroffload.control.V1_0.ITetheringOffloadCallback;
-import android.hardware.tetheroffload.control.V1_0.NatTimeoutUpdate;
-import android.hardware.tetheroffload.control.V1_0.NetworkProtocol;
-import android.hardware.tetheroffload.control.V1_0.OffloadCallbackEvent;
-import android.net.netlink.NetlinkSocket;
-import android.net.netlink.StructNfGenMsg;
-import android.net.netlink.StructNlMsgHdr;
-import android.net.util.SharedLog;
-import android.net.util.SocketUtils;
-import android.os.Handler;
-import android.os.NativeHandle;
-import android.os.RemoteException;
-import android.system.ErrnoException;
-import android.system.Os;
-import android.system.OsConstants;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.io.FileDescriptor;
-import java.io.IOException;
-import java.io.InterruptedIOException;
-import java.net.SocketAddress;
-import java.net.SocketException;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.util.ArrayList;
-import java.util.NoSuchElementException;
-
-
-/**
- * Capture tethering dependencies, for injection.
- *
- * @hide
- */
-public class OffloadHardwareInterface {
- private static final String TAG = OffloadHardwareInterface.class.getSimpleName();
- private static final String YIELDS = " -> ";
- // Change this value to control whether tether offload is enabled or
- // disabled by default in the absence of an explicit Settings value.
- // See accompanying unittest to distinguish 0 from non-0 values.
- private static final int DEFAULT_TETHER_OFFLOAD_DISABLED = 0;
- private static final String NO_INTERFACE_NAME = "";
- private static final String NO_IPV4_ADDRESS = "";
- private static final String NO_IPV4_GATEWAY = "";
- // Reference kernel/uapi/linux/netfilter/nfnetlink_compat.h
- public static final int NF_NETLINK_CONNTRACK_NEW = 1;
- public static final int NF_NETLINK_CONNTRACK_UPDATE = 2;
- public static final int NF_NETLINK_CONNTRACK_DESTROY = 4;
- // Reference libnetfilter_conntrack/linux_nfnetlink_conntrack.h
- public static final short NFNL_SUBSYS_CTNETLINK = 1;
- public static final short IPCTNL_MSG_CT_NEW = 0;
- public static final short IPCTNL_MSG_CT_GET = 1;
-
- private final long NETLINK_MESSAGE_TIMEOUT_MS = 500;
-
- private final Handler mHandler;
- private final SharedLog mLog;
- private final Dependencies mDeps;
- private IOffloadControl mOffloadControl;
- private TetheringOffloadCallback mTetheringOffloadCallback;
- private ControlCallback mControlCallback;
-
- /** The callback to notify status of offload management process. */
- public static class ControlCallback {
- /** Offload started. */
- public void onStarted() {}
- /**
- * Offload stopped because an error has occurred in lower layer.
- */
- public void onStoppedError() {}
- /**
- * Offload stopped because the device has moved to a bearer on which hardware offload is
- * not supported. Subsequent calls to setUpstreamParameters and add/removeDownstream will
- * likely fail and cannot be presumed to be saved inside of the hardware management process.
- * Upon receiving #onSupportAvailable(), the caller should reprogram the hardware to begin
- * offload again.
- */
- public void onStoppedUnsupported() {}
- /** Indicate that offload is able to proivde support for this time. */
- public void onSupportAvailable() {}
- /** Offload stopped because of usage limit reached. */
- public void onStoppedLimitReached() {}
-
- /** Indicate to update NAT timeout. */
- public void onNatTimeoutUpdate(int proto,
- String srcAddr, int srcPort,
- String dstAddr, int dstPort) {}
- }
-
- /** The object which records Tx/Rx forwarded bytes. */
- public static class ForwardedStats {
- public long rxBytes;
- public long txBytes;
-
- public ForwardedStats() {
- rxBytes = 0;
- txBytes = 0;
- }
-
- @VisibleForTesting
- public ForwardedStats(long rxBytes, long txBytes) {
- this.rxBytes = rxBytes;
- this.txBytes = txBytes;
- }
-
- /** Add Tx/Rx bytes. */
- public void add(ForwardedStats other) {
- rxBytes += other.rxBytes;
- txBytes += other.txBytes;
- }
-
- /** Returns the string representation of this object. */
- public String toString() {
- return String.format("rx:%s tx:%s", rxBytes, txBytes);
- }
- }
-
- public OffloadHardwareInterface(Handler h, SharedLog log) {
- this(h, log, new Dependencies(log));
- }
-
- OffloadHardwareInterface(Handler h, SharedLog log, Dependencies deps) {
- mHandler = h;
- mLog = log.forSubComponent(TAG);
- mDeps = deps;
- }
-
- /** Capture OffloadHardwareInterface dependencies, for injection. */
- static class Dependencies {
- private final SharedLog mLog;
-
- Dependencies(SharedLog log) {
- mLog = log;
- }
-
- public IOffloadConfig getOffloadConfig() {
- try {
- return IOffloadConfig.getService(true /*retry*/);
- } catch (RemoteException | NoSuchElementException e) {
- mLog.e("getIOffloadConfig error " + e);
- return null;
- }
- }
-
- public IOffloadControl getOffloadControl() {
- try {
- return IOffloadControl.getService(true /*retry*/);
- } catch (RemoteException | NoSuchElementException e) {
- mLog.e("tethering offload control not supported: " + e);
- return null;
- }
- }
-
- public NativeHandle createConntrackSocket(final int groups) {
- final FileDescriptor fd;
- try {
- fd = NetlinkSocket.forProto(OsConstants.NETLINK_NETFILTER);
- } catch (ErrnoException e) {
- mLog.e("Unable to create conntrack socket " + e);
- return null;
- }
-
- final SocketAddress sockAddr = SocketUtils.makeNetlinkSocketAddress(0, groups);
- try {
- Os.bind(fd, sockAddr);
- } catch (ErrnoException | SocketException e) {
- mLog.e("Unable to bind conntrack socket for groups " + groups + " error: " + e);
- try {
- SocketUtils.closeSocket(fd);
- } catch (IOException ie) {
- // Nothing we can do here
- }
- return null;
- }
- try {
- Os.connect(fd, sockAddr);
- } catch (ErrnoException | SocketException e) {
- mLog.e("connect to kernel fail for groups " + groups + " error: " + e);
- try {
- SocketUtils.closeSocket(fd);
- } catch (IOException ie) {
- // Nothing we can do here
- }
- return null;
- }
-
- return new NativeHandle(fd, true);
- }
- }
-
- /** Get default value indicating whether offload is supported. */
- public int getDefaultTetherOffloadDisabled() {
- return DEFAULT_TETHER_OFFLOAD_DISABLED;
- }
-
- /**
- * Offload management process need to know conntrack rules to support NAT, but it may not have
- * permission to create netlink netfilter sockets. Create two netlink netfilter sockets and
- * share them with offload management process.
- */
- public boolean initOffloadConfig() {
- final IOffloadConfig offloadConfig = mDeps.getOffloadConfig();
- if (offloadConfig == null) {
- mLog.e("Could not find IOffloadConfig service");
- return false;
- }
- // Per the IConfigOffload definition:
- //
- // h1 provides a file descriptor bound to the following netlink groups
- // (NF_NETLINK_CONNTRACK_NEW | NF_NETLINK_CONNTRACK_DESTROY).
- //
- // h2 provides a file descriptor bound to the following netlink groups
- // (NF_NETLINK_CONNTRACK_UPDATE | NF_NETLINK_CONNTRACK_DESTROY).
- final NativeHandle h1 = mDeps.createConntrackSocket(
- NF_NETLINK_CONNTRACK_NEW | NF_NETLINK_CONNTRACK_DESTROY);
- if (h1 == null) return false;
-
- sendIpv4NfGenMsg(h1, (short) ((NFNL_SUBSYS_CTNETLINK << 8) | IPCTNL_MSG_CT_GET),
- (short) (NLM_F_REQUEST | NLM_F_DUMP));
-
- final NativeHandle h2 = mDeps.createConntrackSocket(
- NF_NETLINK_CONNTRACK_UPDATE | NF_NETLINK_CONNTRACK_DESTROY);
- if (h2 == null) {
- closeFdInNativeHandle(h1);
- return false;
- }
-
- final CbResults results = new CbResults();
- try {
- offloadConfig.setHandles(h1, h2,
- (boolean success, String errMsg) -> {
- results.mSuccess = success;
- results.mErrMsg = errMsg;
- });
- } catch (RemoteException e) {
- record("initOffloadConfig, setHandles fail", e);
- return false;
- }
- // Explicitly close FDs.
- closeFdInNativeHandle(h1);
- closeFdInNativeHandle(h2);
-
- record("initOffloadConfig, setHandles results:", results);
- return results.mSuccess;
- }
-
- @VisibleForTesting
- public void sendIpv4NfGenMsg(@NonNull NativeHandle handle, short type, short flags) {
- final int length = StructNlMsgHdr.STRUCT_SIZE + StructNfGenMsg.STRUCT_SIZE;
- final byte[] msg = new byte[length];
- final ByteBuffer byteBuffer = ByteBuffer.wrap(msg);
- byteBuffer.order(ByteOrder.nativeOrder());
-
- final StructNlMsgHdr nlh = new StructNlMsgHdr();
- nlh.nlmsg_len = length;
- nlh.nlmsg_type = type;
- nlh.nlmsg_flags = flags;
- nlh.nlmsg_seq = 0;
- nlh.pack(byteBuffer);
-
- // Header needs to be added to buffer since a generic netlink request is being sent.
- final StructNfGenMsg nfh = new StructNfGenMsg((byte) OsConstants.AF_INET);
- nfh.pack(byteBuffer);
-
- try {
- NetlinkSocket.sendMessage(handle.getFileDescriptor(), msg, 0 /* offset */, length,
- NETLINK_MESSAGE_TIMEOUT_MS);
- } catch (ErrnoException | InterruptedIOException e) {
- mLog.e("Unable to send netfilter message, error: " + e);
- }
- }
-
- private void closeFdInNativeHandle(final NativeHandle h) {
- try {
- h.close();
- } catch (IOException | IllegalStateException e) {
- // IllegalStateException means fd is already closed, do nothing here.
- // Also nothing we can do if IOException.
- }
- }
-
- /** Initialize the tethering offload HAL. */
- public boolean initOffloadControl(ControlCallback controlCb) {
- mControlCallback = controlCb;
-
- if (mOffloadControl == null) {
- mOffloadControl = mDeps.getOffloadControl();
- if (mOffloadControl == null) {
- mLog.e("tethering IOffloadControl.getService() returned null");
- return false;
- }
- }
-
- final String logmsg = String.format("initOffloadControl(%s)",
- (controlCb == null) ? "null"
- : "0x" + Integer.toHexString(System.identityHashCode(controlCb)));
-
- mTetheringOffloadCallback = new TetheringOffloadCallback(mHandler, mControlCallback, mLog);
- final CbResults results = new CbResults();
- try {
- mOffloadControl.initOffload(
- mTetheringOffloadCallback,
- (boolean success, String errMsg) -> {
- results.mSuccess = success;
- results.mErrMsg = errMsg;
- });
- } catch (RemoteException e) {
- record(logmsg, e);
- return false;
- }
-
- record(logmsg, results);
- return results.mSuccess;
- }
-
- /** Stop IOffloadControl. */
- public void stopOffloadControl() {
- if (mOffloadControl != null) {
- try {
- mOffloadControl.stopOffload(
- (boolean success, String errMsg) -> {
- if (!success) mLog.e("stopOffload failed: " + errMsg);
- });
- } catch (RemoteException e) {
- mLog.e("failed to stopOffload: " + e);
- }
- }
- mOffloadControl = null;
- mTetheringOffloadCallback = null;
- mControlCallback = null;
- mLog.log("stopOffloadControl()");
- }
-
- /** Get Tx/Rx usage from last query. */
- public ForwardedStats getForwardedStats(String upstream) {
- final String logmsg = String.format("getForwardedStats(%s)", upstream);
-
- final ForwardedStats stats = new ForwardedStats();
- try {
- mOffloadControl.getForwardedStats(
- upstream,
- (long rxBytes, long txBytes) -> {
- stats.rxBytes = (rxBytes > 0) ? rxBytes : 0;
- stats.txBytes = (txBytes > 0) ? txBytes : 0;
- });
- } catch (RemoteException e) {
- record(logmsg, e);
- return stats;
- }
-
- return stats;
- }
-
- /** Set local prefixes to offload management process. */
- public boolean setLocalPrefixes(ArrayList<String> localPrefixes) {
- final String logmsg = String.format("setLocalPrefixes([%s])",
- String.join(",", localPrefixes));
-
- final CbResults results = new CbResults();
- try {
- mOffloadControl.setLocalPrefixes(localPrefixes,
- (boolean success, String errMsg) -> {
- results.mSuccess = success;
- results.mErrMsg = errMsg;
- });
- } catch (RemoteException e) {
- record(logmsg, e);
- return false;
- }
-
- record(logmsg, results);
- return results.mSuccess;
- }
-
- /** Set data limit value to offload management process. */
- public boolean setDataLimit(String iface, long limit) {
-
- final String logmsg = String.format("setDataLimit(%s, %d)", iface, limit);
-
- final CbResults results = new CbResults();
- try {
- mOffloadControl.setDataLimit(
- iface, limit,
- (boolean success, String errMsg) -> {
- results.mSuccess = success;
- results.mErrMsg = errMsg;
- });
- } catch (RemoteException e) {
- record(logmsg, e);
- return false;
- }
-
- record(logmsg, results);
- return results.mSuccess;
- }
-
- /** Set upstream parameters to offload management process. */
- public boolean setUpstreamParameters(
- String iface, String v4addr, String v4gateway, ArrayList<String> v6gws) {
- iface = (iface != null) ? iface : NO_INTERFACE_NAME;
- v4addr = (v4addr != null) ? v4addr : NO_IPV4_ADDRESS;
- v4gateway = (v4gateway != null) ? v4gateway : NO_IPV4_GATEWAY;
- v6gws = (v6gws != null) ? v6gws : new ArrayList<>();
-
- final String logmsg = String.format("setUpstreamParameters(%s, %s, %s, [%s])",
- iface, v4addr, v4gateway, String.join(",", v6gws));
-
- final CbResults results = new CbResults();
- try {
- mOffloadControl.setUpstreamParameters(
- iface, v4addr, v4gateway, v6gws,
- (boolean success, String errMsg) -> {
- results.mSuccess = success;
- results.mErrMsg = errMsg;
- });
- } catch (RemoteException e) {
- record(logmsg, e);
- return false;
- }
-
- record(logmsg, results);
- return results.mSuccess;
- }
-
- /** Add downstream prefix to offload management process. */
- public boolean addDownstreamPrefix(String ifname, String prefix) {
- final String logmsg = String.format("addDownstreamPrefix(%s, %s)", ifname, prefix);
-
- final CbResults results = new CbResults();
- try {
- mOffloadControl.addDownstream(ifname, prefix,
- (boolean success, String errMsg) -> {
- results.mSuccess = success;
- results.mErrMsg = errMsg;
- });
- } catch (RemoteException e) {
- record(logmsg, e);
- return false;
- }
-
- record(logmsg, results);
- return results.mSuccess;
- }
-
- /** Remove downstream prefix from offload management process. */
- public boolean removeDownstreamPrefix(String ifname, String prefix) {
- final String logmsg = String.format("removeDownstreamPrefix(%s, %s)", ifname, prefix);
-
- final CbResults results = new CbResults();
- try {
- mOffloadControl.removeDownstream(ifname, prefix,
- (boolean success, String errMsg) -> {
- results.mSuccess = success;
- results.mErrMsg = errMsg;
- });
- } catch (RemoteException e) {
- record(logmsg, e);
- return false;
- }
-
- record(logmsg, results);
- return results.mSuccess;
- }
-
- private void record(String msg, Throwable t) {
- mLog.e(msg + YIELDS + "exception: " + t);
- }
-
- private void record(String msg, CbResults results) {
- final String logmsg = msg + YIELDS + results;
- if (!results.mSuccess) {
- mLog.e(logmsg);
- } else {
- mLog.log(logmsg);
- }
- }
-
- private static class TetheringOffloadCallback extends ITetheringOffloadCallback.Stub {
- public final Handler handler;
- public final ControlCallback controlCb;
- public final SharedLog log;
-
- TetheringOffloadCallback(Handler h, ControlCallback cb, SharedLog sharedLog) {
- handler = h;
- controlCb = cb;
- log = sharedLog;
- }
-
- @Override
- public void onEvent(int event) {
- handler.post(() -> {
- switch (event) {
- case OffloadCallbackEvent.OFFLOAD_STARTED:
- controlCb.onStarted();
- break;
- case OffloadCallbackEvent.OFFLOAD_STOPPED_ERROR:
- controlCb.onStoppedError();
- break;
- case OffloadCallbackEvent.OFFLOAD_STOPPED_UNSUPPORTED:
- controlCb.onStoppedUnsupported();
- break;
- case OffloadCallbackEvent.OFFLOAD_SUPPORT_AVAILABLE:
- controlCb.onSupportAvailable();
- break;
- case OffloadCallbackEvent.OFFLOAD_STOPPED_LIMIT_REACHED:
- controlCb.onStoppedLimitReached();
- break;
- default:
- log.e("Unsupported OffloadCallbackEvent: " + event);
- }
- });
- }
-
- @Override
- public void updateTimeout(NatTimeoutUpdate params) {
- handler.post(() -> {
- controlCb.onNatTimeoutUpdate(
- networkProtocolToOsConstant(params.proto),
- params.src.addr, uint16(params.src.port),
- params.dst.addr, uint16(params.dst.port));
- });
- }
- }
-
- private static int networkProtocolToOsConstant(int proto) {
- switch (proto) {
- case NetworkProtocol.TCP: return OsConstants.IPPROTO_TCP;
- case NetworkProtocol.UDP: return OsConstants.IPPROTO_UDP;
- default:
- // The caller checks this value and will log an error. Just make
- // sure it won't collide with valid OsContants.IPPROTO_* values.
- return -Math.abs(proto);
- }
- }
-
- private static class CbResults {
- boolean mSuccess;
- String mErrMsg;
-
- @Override
- public String toString() {
- if (mSuccess) {
- return "ok";
- } else {
- return "fail: " + mErrMsg;
- }
- }
- }
-}
diff --git a/packages/Tethering/src/com/android/networkstack/tethering/PrivateAddressCoordinator.java b/packages/Tethering/src/com/android/networkstack/tethering/PrivateAddressCoordinator.java
deleted file mode 100644
index 4f616cd..0000000
--- a/packages/Tethering/src/com/android/networkstack/tethering/PrivateAddressCoordinator.java
+++ /dev/null
@@ -1,416 +0,0 @@
-/*
- * 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;
-
-import static android.net.NetworkCapabilities.TRANSPORT_VPN;
-import static android.net.TetheringManager.TETHERING_BLUETOOTH;
-import static android.net.TetheringManager.TETHERING_WIFI_P2P;
-import static android.net.util.PrefixUtils.asIpPrefix;
-
-import static com.android.net.module.util.Inet4AddressUtils.inet4AddressToIntHTH;
-import static com.android.net.module.util.Inet4AddressUtils.intToInet4AddressHTH;
-import static com.android.net.module.util.Inet4AddressUtils.prefixLengthToV4NetmaskIntHTH;
-
-import static java.util.Arrays.asList;
-
-import android.content.Context;
-import android.net.ConnectivityManager;
-import android.net.IpPrefix;
-import android.net.LinkAddress;
-import android.net.Network;
-import android.net.ip.IpServer;
-import android.util.ArrayMap;
-import android.util.ArraySet;
-import android.util.SparseArray;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.IndentingPrintWriter;
-
-import java.net.Inet4Address;
-import java.net.InetAddress;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Random;
-import java.util.Set;
-
-/**
- * This class coordinate IP addresses conflict problem.
- *
- * Tethering downstream IP addresses may conflict with network assigned addresses. This
- * coordinator is responsible for recording all of network assigned addresses and dispatched
- * free address to downstream interfaces.
- *
- * This class is not thread-safe and should be accessed on the same tethering internal thread.
- * @hide
- */
-public class PrivateAddressCoordinator {
- public static final int PREFIX_LENGTH = 24;
-
- // Upstream monitor would be stopped when tethering is down. When tethering restart, downstream
- // address may be requested before coordinator get current upstream notification. To ensure
- // coordinator do not select conflict downstream prefix, mUpstreamPrefixMap would not be cleared
- // when tethering is down. Instead tethering would remove all deprecated upstreams from
- // mUpstreamPrefixMap when tethering is starting. See #maybeRemoveDeprecatedUpstreams().
- private final ArrayMap<Network, List<IpPrefix>> mUpstreamPrefixMap;
- private final ArraySet<IpServer> mDownstreams;
- private static final String LEGACY_WIFI_P2P_IFACE_ADDRESS = "192.168.49.1/24";
- private static final String LEGACY_BLUETOOTH_IFACE_ADDRESS = "192.168.44.1/24";
- private final List<IpPrefix> mTetheringPrefixes;
- private final ConnectivityManager mConnectivityMgr;
- private final TetheringConfiguration mConfig;
- // keyed by downstream type(TetheringManager.TETHERING_*).
- private final SparseArray<LinkAddress> mCachedAddresses;
-
- public PrivateAddressCoordinator(Context context, TetheringConfiguration config) {
- mDownstreams = new ArraySet<>();
- mUpstreamPrefixMap = new ArrayMap<>();
- mConnectivityMgr = (ConnectivityManager) context.getSystemService(
- Context.CONNECTIVITY_SERVICE);
- mConfig = config;
- mCachedAddresses = new SparseArray<>();
- // Reserved static addresses for bluetooth and wifi p2p.
- mCachedAddresses.put(TETHERING_BLUETOOTH, new LinkAddress(LEGACY_BLUETOOTH_IFACE_ADDRESS));
- mCachedAddresses.put(TETHERING_WIFI_P2P, new LinkAddress(LEGACY_WIFI_P2P_IFACE_ADDRESS));
-
- mTetheringPrefixes = new ArrayList<>(Arrays.asList(new IpPrefix("192.168.0.0/16")));
- if (config.isSelectAllPrefixRangeEnabled()) {
- mTetheringPrefixes.add(new IpPrefix("172.16.0.0/12"));
- mTetheringPrefixes.add(new IpPrefix("10.0.0.0/8"));
- }
- }
-
- /**
- * Record a new upstream IpPrefix which may conflict with tethering downstreams.
- * The downstreams will be notified if a conflict is found. When updateUpstreamPrefix is called,
- * UpstreamNetworkState must have an already populated LinkProperties.
- */
- public void updateUpstreamPrefix(final UpstreamNetworkState ns) {
- // Do not support VPN as upstream. Normally, networkCapabilities is not expected to be null,
- // but just checking to be sure.
- if (ns.networkCapabilities != null && ns.networkCapabilities.hasTransport(TRANSPORT_VPN)) {
- removeUpstreamPrefix(ns.network);
- return;
- }
-
- final ArrayList<IpPrefix> ipv4Prefixes = getIpv4Prefixes(
- ns.linkProperties.getAllLinkAddresses());
- if (ipv4Prefixes.isEmpty()) {
- removeUpstreamPrefix(ns.network);
- return;
- }
-
- mUpstreamPrefixMap.put(ns.network, ipv4Prefixes);
- handleMaybePrefixConflict(ipv4Prefixes);
- }
-
- private ArrayList<IpPrefix> getIpv4Prefixes(final List<LinkAddress> linkAddresses) {
- final ArrayList<IpPrefix> list = new ArrayList<>();
- for (LinkAddress address : linkAddresses) {
- if (!address.isIpv4()) continue;
-
- list.add(asIpPrefix(address));
- }
-
- return list;
- }
-
- private void handleMaybePrefixConflict(final List<IpPrefix> prefixes) {
- for (IpServer downstream : mDownstreams) {
- final IpPrefix target = getDownstreamPrefix(downstream);
-
- for (IpPrefix source : prefixes) {
- if (isConflictPrefix(source, target)) {
- downstream.sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
- break;
- }
- }
- }
- }
-
- /** Remove IpPrefix records corresponding to input network. */
- public void removeUpstreamPrefix(final Network network) {
- mUpstreamPrefixMap.remove(network);
- }
-
- /**
- * Maybe remove deprecated upstream records, this would be called once tethering started without
- * any exiting tethered downstream.
- */
- public void maybeRemoveDeprecatedUpstreams() {
- if (mUpstreamPrefixMap.isEmpty()) return;
-
- // Remove all upstreams that are no longer valid networks
- final Set<Network> toBeRemoved = new HashSet<>(mUpstreamPrefixMap.keySet());
- toBeRemoved.removeAll(asList(mConnectivityMgr.getAllNetworks()));
-
- mUpstreamPrefixMap.removeAll(toBeRemoved);
- }
-
- /**
- * Pick a random available address and mark its prefix as in use for the provided IpServer,
- * returns null if there is no available address.
- */
- @Nullable
- public LinkAddress requestDownstreamAddress(final IpServer ipServer, boolean useLastAddress) {
- if (mConfig.shouldEnableWifiP2pDedicatedIp()
- && ipServer.interfaceType() == TETHERING_WIFI_P2P) {
- return new LinkAddress(LEGACY_WIFI_P2P_IFACE_ADDRESS);
- }
-
- final LinkAddress cachedAddress = mCachedAddresses.get(ipServer.interfaceType());
- if (useLastAddress && cachedAddress != null
- && !isConflictWithUpstream(asIpPrefix(cachedAddress))) {
- mDownstreams.add(ipServer);
- return cachedAddress;
- }
-
- for (IpPrefix prefixRange : mTetheringPrefixes) {
- final LinkAddress newAddress = chooseDownstreamAddress(prefixRange);
- if (newAddress != null) {
- mDownstreams.add(ipServer);
- mCachedAddresses.put(ipServer.interfaceType(), newAddress);
- return newAddress;
- }
- }
-
- // No available address.
- return null;
- }
-
- private int getPrefixBaseAddress(final IpPrefix prefix) {
- return inet4AddressToIntHTH((Inet4Address) prefix.getAddress());
- }
-
- /**
- * Check whether input prefix conflict with upstream prefixes or in-use downstream prefixes.
- * If yes, return one of them.
- */
- private IpPrefix getConflictPrefix(final IpPrefix prefix) {
- final IpPrefix upstream = getConflictWithUpstream(prefix);
- if (upstream != null) return upstream;
-
- return getInUseDownstreamPrefix(prefix);
- }
-
- // Get the next non-conflict sub prefix. E.g: To get next sub prefix from 10.0.0.0/8, if the
- // previously selected prefix is 10.20.42.0/24(subPrefix: 0.20.42.0) and the conflicting prefix
- // is 10.16.0.0/20 (10.16.0.0 ~ 10.16.15.255), then the max address under subPrefix is
- // 0.16.15.255 and the next subPrefix is 0.16.16.255/24 (0.16.15.255 + 0.0.1.0).
- // Note: the sub address 0.0.0.255 here is fine to be any value that it will be replaced as
- // selected random sub address later.
- private int getNextSubPrefix(final IpPrefix conflictPrefix, final int prefixRangeMask) {
- final int suffixMask = ~prefixLengthToV4NetmaskIntHTH(conflictPrefix.getPrefixLength());
- // The largest offset within the prefix assignment block that still conflicts with
- // conflictPrefix.
- final int maxConflict =
- (getPrefixBaseAddress(conflictPrefix) | suffixMask) & ~prefixRangeMask;
-
- final int prefixMask = prefixLengthToV4NetmaskIntHTH(PREFIX_LENGTH);
- // Pick a sub prefix a full prefix (1 << (32 - PREFIX_LENGTH) addresses) greater than
- // maxConflict. This ensures that the selected prefix never overlaps with conflictPrefix.
- // There is no need to mask the result with PREFIX_LENGTH bits because this is done by
- // findAvailablePrefixFromRange when it constructs the prefix.
- return maxConflict + (1 << (32 - PREFIX_LENGTH));
- }
-
- private LinkAddress chooseDownstreamAddress(final IpPrefix prefixRange) {
- // The netmask of the prefix assignment block (e.g., 0xfff00000 for 172.16.0.0/12).
- final int prefixRangeMask = prefixLengthToV4NetmaskIntHTH(prefixRange.getPrefixLength());
-
- // The zero address in the block (e.g., 0xac100000 for 172.16.0.0/12).
- final int baseAddress = getPrefixBaseAddress(prefixRange);
-
- // The subnet mask corresponding to PREFIX_LENGTH.
- final int prefixMask = prefixLengthToV4NetmaskIntHTH(PREFIX_LENGTH);
-
- // The offset within prefixRange of a randomly-selected prefix of length PREFIX_LENGTH.
- // This may not be the prefix of the address returned by this method:
- // - If it is already in use, the method will return an address in another prefix.
- // - If all prefixes within prefixRange are in use, the method will return null. For
- // example, for a /24 prefix within 172.26.0.0/12, this will be a multiple of 256 in
- // [0, 1048576). In other words, a random 32-bit number with mask 0x000fff00.
- //
- // prefixRangeMask is required to ensure no wrapping. For example, consider:
- // - prefixRange 127.0.0.0/8
- // - randomPrefixStart 127.255.255.0
- // - A conflicting prefix of 127.255.254.0/23
- // In this case without prefixRangeMask, getNextSubPrefix would return 128.0.0.0, which
- // means the "start < end" check in findAvailablePrefixFromRange would not reject the prefix
- // because Java doesn't have unsigned integers, so 128.0.0.0 = 0x80000000 = -2147483648
- // is less than 127.0.0.0 = 0x7f000000 = 2130706432.
- //
- // Additionally, it makes debug output easier to read by making the numbers smaller.
- final int randomPrefixStart = getRandomInt() & ~prefixRangeMask & prefixMask;
-
- // A random offset within the prefix. Used to determine the local address once the prefix
- // is selected. It does not result in an IPv4 address ending in .0, .1, or .255
- // For a PREFIX_LENGTH of 255, this is a number between 2 and 254.
- final int subAddress = getSanitizedSubAddr(~prefixMask);
-
- // Find a prefix length PREFIX_LENGTH between randomPrefixStart and the end of the block,
- // such that the prefix does not conflict with any upstream.
- IpPrefix downstreamPrefix = findAvailablePrefixFromRange(
- randomPrefixStart, (~prefixRangeMask) + 1, baseAddress, prefixRangeMask);
- if (downstreamPrefix != null) return getLinkAddress(downstreamPrefix, subAddress);
-
- // If that failed, do the same, but between 0 and randomPrefixStart.
- downstreamPrefix = findAvailablePrefixFromRange(
- 0, randomPrefixStart, baseAddress, prefixRangeMask);
-
- return getLinkAddress(downstreamPrefix, subAddress);
- }
-
- private LinkAddress getLinkAddress(final IpPrefix prefix, final int subAddress) {
- if (prefix == null) return null;
-
- final InetAddress address = intToInet4AddressHTH(getPrefixBaseAddress(prefix) | subAddress);
- return new LinkAddress(address, PREFIX_LENGTH);
- }
-
- private IpPrefix findAvailablePrefixFromRange(final int start, final int end,
- final int baseAddress, final int prefixRangeMask) {
- int newSubPrefix = start;
- while (newSubPrefix < end) {
- final InetAddress address = intToInet4AddressHTH(baseAddress | newSubPrefix);
- final IpPrefix prefix = new IpPrefix(address, PREFIX_LENGTH);
-
- final IpPrefix conflictPrefix = getConflictPrefix(prefix);
-
- if (conflictPrefix == null) return prefix;
-
- newSubPrefix = getNextSubPrefix(conflictPrefix, prefixRangeMask);
- }
-
- return null;
- }
-
- /** Get random int which could be used to generate random address. */
- @VisibleForTesting
- public int getRandomInt() {
- return (new Random()).nextInt();
- }
-
- /** Get random subAddress and avoid selecting x.x.x.0, x.x.x.1 and x.x.x.255 address. */
- private int getSanitizedSubAddr(final int subAddrMask) {
- final int randomSubAddr = getRandomInt() & subAddrMask;
- // If prefix length > 30, the selecting speace would be less than 4 which may be hard to
- // avoid 3 consecutive address.
- if (PREFIX_LENGTH > 30) return randomSubAddr;
-
- // TODO: maybe it is not necessary to avoid .0, .1 and .255 address because tethering
- // address would not be conflicted. This code only works because PREFIX_LENGTH is not longer
- // than 24
- final int candidate = randomSubAddr & 0xff;
- if (candidate == 0 || candidate == 1 || candidate == 255) {
- return (randomSubAddr & 0xfffffffc) + 2;
- }
-
- return randomSubAddr;
- }
-
- /** Release downstream record for IpServer. */
- public void releaseDownstream(final IpServer ipServer) {
- mDownstreams.remove(ipServer);
- }
-
- /** Clear current upstream prefixes records. */
- public void clearUpstreamPrefixes() {
- mUpstreamPrefixMap.clear();
- }
-
- private IpPrefix getConflictWithUpstream(final IpPrefix prefix) {
- for (int i = 0; i < mUpstreamPrefixMap.size(); i++) {
- final List<IpPrefix> list = mUpstreamPrefixMap.valueAt(i);
- for (IpPrefix upstream : list) {
- if (isConflictPrefix(prefix, upstream)) return upstream;
- }
- }
- return null;
- }
-
- private boolean isConflictWithUpstream(final IpPrefix prefix) {
- return getConflictWithUpstream(prefix) != null;
- }
-
- private boolean isConflictPrefix(final IpPrefix prefix1, final IpPrefix prefix2) {
- if (prefix2.getPrefixLength() < prefix1.getPrefixLength()) {
- return prefix2.contains(prefix1.getAddress());
- }
-
- return prefix1.contains(prefix2.getAddress());
- }
-
- // InUse Prefixes are prefixes of mCachedAddresses which are active downstream addresses, last
- // downstream addresses(reserved for next time) and static addresses(e.g. bluetooth, wifi p2p).
- private IpPrefix getInUseDownstreamPrefix(final IpPrefix prefix) {
- for (int i = 0; i < mCachedAddresses.size(); i++) {
- final IpPrefix downstream = asIpPrefix(mCachedAddresses.valueAt(i));
- if (isConflictPrefix(prefix, downstream)) return downstream;
- }
-
- // IpServer may use manually-defined address (mStaticIpv4ServerAddr) which does not include
- // in mCachedAddresses.
- for (IpServer downstream : mDownstreams) {
- final IpPrefix target = getDownstreamPrefix(downstream);
-
- if (isConflictPrefix(prefix, target)) return target;
- }
-
- return null;
- }
-
- @NonNull
- private IpPrefix getDownstreamPrefix(final IpServer downstream) {
- final LinkAddress address = downstream.getAddress();
-
- return asIpPrefix(address);
- }
-
- void dump(final IndentingPrintWriter pw) {
- pw.println("mTetheringPrefixes:");
- pw.increaseIndent();
- for (IpPrefix prefix : mTetheringPrefixes) {
- pw.println(prefix);
- }
- pw.decreaseIndent();
-
- pw.println("mUpstreamPrefixMap:");
- pw.increaseIndent();
- for (int i = 0; i < mUpstreamPrefixMap.size(); i++) {
- pw.println(mUpstreamPrefixMap.keyAt(i) + " - " + mUpstreamPrefixMap.valueAt(i));
- }
- pw.decreaseIndent();
-
- pw.println("mDownstreams:");
- pw.increaseIndent();
- for (IpServer ipServer : mDownstreams) {
- pw.println(ipServer.interfaceType() + " - " + ipServer.getAddress());
- }
- pw.decreaseIndent();
-
- pw.println("mCachedAddresses:");
- pw.increaseIndent();
- for (int i = 0; i < mCachedAddresses.size(); i++) {
- pw.println(mCachedAddresses.keyAt(i) + " - " + mCachedAddresses.valueAt(i));
- }
- pw.decreaseIndent();
- }
-}
diff --git a/packages/Tethering/src/com/android/networkstack/tethering/Tethering.java b/packages/Tethering/src/com/android/networkstack/tethering/Tethering.java
deleted file mode 100644
index 5a0c5b0..0000000
--- a/packages/Tethering/src/com/android/networkstack/tethering/Tethering.java
+++ /dev/null
@@ -1,2427 +0,0 @@
-/*
- * Copyright (C) 2010 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;
-
-import static android.Manifest.permission.NETWORK_SETTINGS;
-import static android.Manifest.permission.NETWORK_STACK;
-import static android.content.pm.PackageManager.GET_ACTIVITIES;
-import static android.content.pm.PackageManager.PERMISSION_GRANTED;
-import static android.hardware.usb.UsbManager.USB_CONFIGURED;
-import static android.hardware.usb.UsbManager.USB_CONNECTED;
-import static android.hardware.usb.UsbManager.USB_FUNCTION_NCM;
-import static android.hardware.usb.UsbManager.USB_FUNCTION_RNDIS;
-import static android.net.ConnectivityManager.ACTION_RESTRICT_BACKGROUND_CHANGED;
-import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
-import static android.net.ConnectivityManager.EXTRA_NETWORK_INFO;
-import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK;
-import static android.net.TetheringManager.ACTION_TETHER_STATE_CHANGED;
-import static android.net.TetheringManager.EXTRA_ACTIVE_LOCAL_ONLY;
-import static android.net.TetheringManager.EXTRA_ACTIVE_TETHER;
-import static android.net.TetheringManager.EXTRA_AVAILABLE_TETHER;
-import static android.net.TetheringManager.EXTRA_ERRORED_TETHER;
-import static android.net.TetheringManager.TETHERING_BLUETOOTH;
-import static android.net.TetheringManager.TETHERING_ETHERNET;
-import static android.net.TetheringManager.TETHERING_INVALID;
-import static android.net.TetheringManager.TETHERING_NCM;
-import static android.net.TetheringManager.TETHERING_USB;
-import static android.net.TetheringManager.TETHERING_WIFI;
-import static android.net.TetheringManager.TETHERING_WIFI_P2P;
-import static android.net.TetheringManager.TETHERING_WIGIG;
-import static android.net.TetheringManager.TETHER_ERROR_INTERNAL_ERROR;
-import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
-import static android.net.TetheringManager.TETHER_ERROR_SERVICE_UNAVAIL;
-import static android.net.TetheringManager.TETHER_ERROR_UNAVAIL_IFACE;
-import static android.net.TetheringManager.TETHER_ERROR_UNKNOWN_IFACE;
-import static android.net.TetheringManager.TETHER_ERROR_UNKNOWN_TYPE;
-import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_FAILED;
-import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_STARTED;
-import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_STOPPED;
-import static android.net.util.TetheringMessageBase.BASE_MAIN_SM;
-import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME;
-import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_MODE;
-import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_STATE;
-import static android.net.wifi.WifiManager.IFACE_IP_MODE_CONFIGURATION_ERROR;
-import static android.net.wifi.WifiManager.IFACE_IP_MODE_LOCAL_ONLY;
-import static android.net.wifi.WifiManager.IFACE_IP_MODE_TETHERED;
-import static android.net.wifi.WifiManager.IFACE_IP_MODE_UNSPECIFIED;
-import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLED;
-import static android.telephony.CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED;
-import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
-
-import static com.android.networkstack.tethering.TetheringNotificationUpdater.DOWNSTREAM_NONE;
-
-import android.app.usage.NetworkStatsManager;
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothPan;
-import android.bluetooth.BluetoothProfile;
-import android.bluetooth.BluetoothProfile.ServiceListener;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.PackageManager;
-import android.hardware.usb.UsbManager;
-import android.net.ConnectivityManager;
-import android.net.EthernetManager;
-import android.net.IIntResultListener;
-import android.net.INetd;
-import android.net.ITetheringEventCallback;
-import android.net.IpPrefix;
-import android.net.LinkAddress;
-import android.net.LinkProperties;
-import android.net.Network;
-import android.net.NetworkCapabilities;
-import android.net.NetworkInfo;
-import android.net.TetherStatesParcel;
-import android.net.TetheredClient;
-import android.net.TetheringCallbackStartedParcel;
-import android.net.TetheringConfigurationParcel;
-import android.net.TetheringRequestParcel;
-import android.net.ip.IpServer;
-import android.net.shared.NetdUtils;
-import android.net.util.BaseNetdUnsolicitedEventListener;
-import android.net.util.InterfaceSet;
-import android.net.util.PrefixUtils;
-import android.net.util.SharedLog;
-import android.net.util.TetheringUtils;
-import android.net.util.VersionedBroadcastListener;
-import android.net.wifi.WifiClient;
-import android.net.wifi.WifiManager;
-import android.net.wifi.p2p.WifiP2pGroup;
-import android.net.wifi.p2p.WifiP2pInfo;
-import android.net.wifi.p2p.WifiP2pManager;
-import android.os.Binder;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.os.RemoteCallbackList;
-import android.os.RemoteException;
-import android.os.ResultReceiver;
-import android.os.ServiceSpecificException;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.provider.Settings;
-import android.telephony.PhoneStateListener;
-import android.telephony.TelephonyManager;
-import android.text.TextUtils;
-import android.util.ArrayMap;
-import android.util.Log;
-import android.util.SparseArray;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.android.internal.annotations.GuardedBy;
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.IndentingPrintWriter;
-import com.android.internal.util.MessageUtils;
-import com.android.internal.util.State;
-import com.android.internal.util.StateMachine;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.net.InetAddress;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.concurrent.Executor;
-import java.util.concurrent.RejectedExecutionException;
-
-/**
- *
- * This class holds much of the business logic to allow Android devices
- * to act as IP gateways via USB, BT, and WiFi interfaces.
- */
-public class Tethering {
-
- private static final String TAG = Tethering.class.getSimpleName();
- private static final boolean DBG = false;
- private static final boolean VDBG = false;
-
- private static final Class[] sMessageClasses = {
- Tethering.class, TetherMainSM.class, IpServer.class
- };
- private static final SparseArray<String> sMagicDecoderRing =
- MessageUtils.findMessageNames(sMessageClasses);
- // Keep in sync with NETID_UNSET in system/netd/include/netid_client.h
- private static final int NETID_UNSET = 0;
-
- private static class TetherState {
- public final IpServer ipServer;
- public int lastState;
- public int lastError;
-
- TetherState(IpServer ipServer) {
- this.ipServer = ipServer;
- // Assume all state machines start out available and with no errors.
- lastState = IpServer.STATE_AVAILABLE;
- lastError = TETHER_ERROR_NO_ERROR;
- }
-
- public boolean isCurrentlyServing() {
- switch (lastState) {
- case IpServer.STATE_TETHERED:
- case IpServer.STATE_LOCAL_ONLY:
- return true;
- default:
- return false;
- }
- }
- }
-
- /**
- * Cookie added when registering {@link android.net.TetheringManager.TetheringEventCallback}.
- */
- private static class CallbackCookie {
- public final boolean hasListClientsPermission;
-
- private CallbackCookie(boolean hasListClientsPermission) {
- this.hasListClientsPermission = hasListClientsPermission;
- }
- }
-
- private final SharedLog mLog = new SharedLog(TAG);
- private final RemoteCallbackList<ITetheringEventCallback> mTetheringEventCallbacks =
- new RemoteCallbackList<>();
- // Currently active tethering requests per tethering type. Only one of each type can be
- // requested at a time. After a tethering type is requested, the map keeps tethering parameters
- // to be used after the interface comes up asynchronously.
- private final SparseArray<TetheringRequestParcel> mActiveTetheringRequests =
- new SparseArray<>();
-
- // used to synchronize public access to members
- // TODO(b/153621704): remove mPublicSync to make Tethering lock free
- private final Object mPublicSync;
- private final Context mContext;
- private final ArrayMap<String, TetherState> mTetherStates;
- private final BroadcastReceiver mStateReceiver;
- private final Looper mLooper;
- private final StateMachine mTetherMainSM;
- private final OffloadController mOffloadController;
- private final UpstreamNetworkMonitor mUpstreamNetworkMonitor;
- // TODO: Figure out how to merge this and other downstream-tracking objects
- // into a single coherent structure.
- // Use LinkedHashSet for predictable ordering order for ConnectedClientsTracker.
- private final LinkedHashSet<IpServer> mForwardedDownstreams;
- private final VersionedBroadcastListener mCarrierConfigChange;
- private final TetheringDependencies mDeps;
- private final EntitlementManager mEntitlementMgr;
- private final Handler mHandler;
- private final INetd mNetd;
- private final NetdCallback mNetdCallback;
- private final UserRestrictionActionListener mTetheringRestriction;
- private final ActiveDataSubIdListener mActiveDataSubIdListener;
- private final ConnectedClientsTracker mConnectedClientsTracker;
- private final TetheringThreadExecutor mExecutor;
- private final TetheringNotificationUpdater mNotificationUpdater;
- private final UserManager mUserManager;
- private final BpfCoordinator mBpfCoordinator;
- private final PrivateAddressCoordinator mPrivateAddressCoordinator;
- private int mActiveDataSubId = INVALID_SUBSCRIPTION_ID;
- // All the usage of mTetheringEventCallback should run in the same thread.
- private ITetheringEventCallback mTetheringEventCallback = null;
-
- private volatile TetheringConfiguration mConfig;
- private InterfaceSet mCurrentUpstreamIfaceSet;
-
- private boolean mRndisEnabled; // track the RNDIS function enabled state
- // True iff. WiFi tethering should be started when soft AP is ready.
- private boolean mWifiTetherRequested;
- private Network mTetherUpstream;
- private TetherStatesParcel mTetherStatesParcel;
- private boolean mDataSaverEnabled = false;
- private String mWifiP2pTetherInterface = null;
- private int mOffloadStatus = TETHER_HARDWARE_OFFLOAD_STOPPED;
-
- @GuardedBy("mPublicSync")
- private EthernetManager.TetheredInterfaceRequest mEthernetIfaceRequest;
- @GuardedBy("mPublicSync")
- private String mConfiguredEthernetIface;
- @GuardedBy("mPublicSync")
- private EthernetCallback mEthernetCallback;
-
- public Tethering(TetheringDependencies deps) {
- mLog.mark("Tethering.constructed");
- mDeps = deps;
- mContext = mDeps.getContext();
- mNetd = mDeps.getINetd(mContext);
- mLooper = mDeps.getTetheringLooper();
- mNotificationUpdater = mDeps.getNotificationUpdater(mContext, mLooper);
-
- mPublicSync = new Object();
-
- mTetherStates = new ArrayMap<>();
- mConnectedClientsTracker = new ConnectedClientsTracker();
-
- mTetherMainSM = new TetherMainSM("TetherMain", mLooper, deps);
- mTetherMainSM.start();
-
- mHandler = mTetherMainSM.getHandler();
- mOffloadController = mDeps.getOffloadController(mHandler, mLog,
- new OffloadController.Dependencies() {
-
- @Override
- public TetheringConfiguration getTetherConfig() {
- return mConfig;
- }
- });
- mUpstreamNetworkMonitor = mDeps.getUpstreamNetworkMonitor(mContext, mTetherMainSM, mLog,
- TetherMainSM.EVENT_UPSTREAM_CALLBACK);
- mForwardedDownstreams = new LinkedHashSet<>();
-
- IntentFilter filter = new IntentFilter();
- filter.addAction(ACTION_CARRIER_CONFIG_CHANGED);
- // EntitlementManager will send EVENT_UPSTREAM_PERMISSION_CHANGED when cellular upstream
- // permission is changed according to entitlement check result.
- mEntitlementMgr = mDeps.getEntitlementManager(mContext, mHandler, mLog,
- () -> mTetherMainSM.sendMessage(
- TetherMainSM.EVENT_UPSTREAM_PERMISSION_CHANGED));
- mEntitlementMgr.setOnUiEntitlementFailedListener((int downstream) -> {
- mLog.log("OBSERVED UiEnitlementFailed");
- stopTethering(downstream);
- });
- mEntitlementMgr.setTetheringConfigurationFetcher(() -> {
- return mConfig;
- });
-
- mCarrierConfigChange = new VersionedBroadcastListener(
- "CarrierConfigChangeListener", mContext, mHandler, filter,
- (Intent ignored) -> {
- mLog.log("OBSERVED carrier config change");
- updateConfiguration();
- mEntitlementMgr.reevaluateSimCardProvisioning(mConfig);
- });
-
- mStateReceiver = new StateReceiver();
-
- mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
- mTetheringRestriction = new UserRestrictionActionListener(
- mUserManager, this, mNotificationUpdater);
- mExecutor = new TetheringThreadExecutor(mHandler);
- mActiveDataSubIdListener = new ActiveDataSubIdListener(mExecutor);
- mNetdCallback = new NetdCallback();
-
- // Load tethering configuration.
- updateConfiguration();
- // It is OK for the configuration to be passed to the PrivateAddressCoordinator at
- // construction time because the only part of the configuration it uses is
- // shouldEnableWifiP2pDedicatedIp(), and currently do not support changing that.
- mPrivateAddressCoordinator = mDeps.getPrivateAddressCoordinator(mContext, mConfig);
-
- // Must be initialized after tethering configuration is loaded because BpfCoordinator
- // constructor needs to use the configuration.
- mBpfCoordinator = mDeps.getBpfCoordinator(
- new BpfCoordinator.Dependencies() {
- @NonNull
- public Handler getHandler() {
- return mHandler;
- }
-
- @NonNull
- public INetd getNetd() {
- return mNetd;
- }
-
- @NonNull
- public NetworkStatsManager getNetworkStatsManager() {
- return mContext.getSystemService(NetworkStatsManager.class);
- }
-
- @NonNull
- public SharedLog getSharedLog() {
- return mLog;
- }
-
- @Nullable
- public TetheringConfiguration getTetherConfig() {
- return mConfig;
- }
- });
-
- startStateMachineUpdaters();
- }
-
- /**
- * Start to register callbacks.
- * Call this function when tethering is ready to handle callback events.
- */
- private void startStateMachineUpdaters() {
- try {
- mNetd.registerUnsolicitedEventListener(mNetdCallback);
- } catch (RemoteException e) {
- mLog.e("Unable to register netd UnsolicitedEventListener");
- }
- mCarrierConfigChange.startListening();
- mContext.getSystemService(TelephonyManager.class).listen(mActiveDataSubIdListener,
- PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE);
-
- IntentFilter filter = new IntentFilter();
- filter.addAction(UsbManager.ACTION_USB_STATE);
- filter.addAction(CONNECTIVITY_ACTION);
- filter.addAction(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
- filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
- filter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
- filter.addAction(UserManager.ACTION_USER_RESTRICTIONS_CHANGED);
- filter.addAction(ACTION_RESTRICT_BACKGROUND_CHANGED);
- mContext.registerReceiver(mStateReceiver, filter, null, mHandler);
-
- final IntentFilter noUpstreamFilter = new IntentFilter();
- noUpstreamFilter.addAction(TetheringNotificationUpdater.ACTION_DISABLE_TETHERING);
- mContext.registerReceiver(
- mStateReceiver, noUpstreamFilter, PERMISSION_MAINLINE_NETWORK_STACK, mHandler);
-
- final WifiManager wifiManager = getWifiManager();
- if (wifiManager != null) {
- wifiManager.registerSoftApCallback(mExecutor, new TetheringSoftApCallback());
- }
-
- startTrackDefaultNetwork();
- }
-
- private class TetheringThreadExecutor implements Executor {
- private final Handler mTetherHandler;
- TetheringThreadExecutor(Handler handler) {
- mTetherHandler = handler;
- }
- @Override
- public void execute(Runnable command) {
- if (!mTetherHandler.post(command)) {
- throw new RejectedExecutionException(mTetherHandler + " is shutting down");
- }
- }
- }
-
- private class ActiveDataSubIdListener extends PhoneStateListener {
- ActiveDataSubIdListener(Executor executor) {
- super(executor);
- }
-
- @Override
- public void onActiveDataSubscriptionIdChanged(int subId) {
- mLog.log("OBSERVED active data subscription change, from " + mActiveDataSubId
- + " to " + subId);
- if (subId == mActiveDataSubId) return;
-
- mActiveDataSubId = subId;
- updateConfiguration();
- mNotificationUpdater.onActiveDataSubscriptionIdChanged(subId);
- // To avoid launching unexpected provisioning checks, ignore re-provisioning
- // when no CarrierConfig loaded yet. Assume reevaluateSimCardProvisioning()
- // will be triggered again when CarrierConfig is loaded.
- if (mEntitlementMgr.getCarrierConfig(mConfig) != null) {
- mEntitlementMgr.reevaluateSimCardProvisioning(mConfig);
- } else {
- mLog.log("IGNORED reevaluate provisioning, no carrier config loaded");
- }
- }
- }
-
- private WifiManager getWifiManager() {
- return (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
- }
-
- // NOTE: This is always invoked on the mLooper thread.
- private void updateConfiguration() {
- mConfig = mDeps.generateTetheringConfiguration(mContext, mLog, mActiveDataSubId);
- mUpstreamNetworkMonitor.updateMobileRequiresDun(mConfig.isDunRequired);
- reportConfigurationChanged(mConfig.toStableParcelable());
- }
-
- private void maybeDunSettingChanged() {
- final boolean isDunRequired = TetheringConfiguration.checkDunRequired(mContext);
- if (isDunRequired == mConfig.isDunRequired) return;
- updateConfiguration();
- }
-
- private class NetdCallback extends BaseNetdUnsolicitedEventListener {
- @Override
- public void onInterfaceChanged(String ifName, boolean up) {
- mHandler.post(() -> interfaceStatusChanged(ifName, up));
- }
-
- @Override
- public void onInterfaceLinkStateChanged(String ifName, boolean up) {
- mHandler.post(() -> interfaceLinkStateChanged(ifName, up));
- }
-
- @Override
- public void onInterfaceAdded(String ifName) {
- mHandler.post(() -> interfaceAdded(ifName));
- }
-
- @Override
- public void onInterfaceRemoved(String ifName) {
- mHandler.post(() -> interfaceRemoved(ifName));
- }
- }
-
- private class TetheringSoftApCallback implements WifiManager.SoftApCallback {
- // TODO: Remove onStateChanged override when this method has default on
- // WifiManager#SoftApCallback interface.
- // Wifi listener for state change of the soft AP
- @Override
- public void onStateChanged(final int state, final int failureReason) {
- // Nothing
- }
-
- // Called by wifi when the number of soft AP clients changed.
- @Override
- public void onConnectedClientsChanged(final List<WifiClient> clients) {
- updateConnectedClients(clients);
- }
- }
-
- void interfaceStatusChanged(String iface, boolean up) {
- // Never called directly: only called from interfaceLinkStateChanged.
- // See NetlinkHandler.cpp: notifyInterfaceChanged.
- if (VDBG) Log.d(TAG, "interfaceStatusChanged " + iface + ", " + up);
- synchronized (mPublicSync) {
- if (up) {
- maybeTrackNewInterfaceLocked(iface);
- } else {
- if (ifaceNameToType(iface) == TETHERING_BLUETOOTH
- || ifaceNameToType(iface) == TETHERING_WIGIG) {
- stopTrackingInterfaceLocked(iface);
- } else {
- // Ignore usb0 down after enabling RNDIS.
- // We will handle disconnect in interfaceRemoved.
- // Similarly, ignore interface down for WiFi. We monitor WiFi AP status
- // through the WifiManager.WIFI_AP_STATE_CHANGED_ACTION intent.
- if (VDBG) Log.d(TAG, "ignore interface down for " + iface);
- }
- }
- }
- }
-
- void interfaceLinkStateChanged(String iface, boolean up) {
- interfaceStatusChanged(iface, up);
- }
-
- private int ifaceNameToType(String iface) {
- final TetheringConfiguration cfg = mConfig;
-
- if (cfg.isWifi(iface)) {
- return TETHERING_WIFI;
- } else if (cfg.isWigig(iface)) {
- return TETHERING_WIGIG;
- } else if (cfg.isWifiP2p(iface)) {
- return TETHERING_WIFI_P2P;
- } else if (cfg.isUsb(iface)) {
- return TETHERING_USB;
- } else if (cfg.isBluetooth(iface)) {
- return TETHERING_BLUETOOTH;
- } else if (cfg.isNcm(iface)) {
- return TETHERING_NCM;
- }
- return TETHERING_INVALID;
- }
-
- void interfaceAdded(String iface) {
- if (VDBG) Log.d(TAG, "interfaceAdded " + iface);
- synchronized (mPublicSync) {
- maybeTrackNewInterfaceLocked(iface);
- }
- }
-
- void interfaceRemoved(String iface) {
- if (VDBG) Log.d(TAG, "interfaceRemoved " + iface);
- synchronized (mPublicSync) {
- stopTrackingInterfaceLocked(iface);
- }
- }
-
- void startTethering(final TetheringRequestParcel request, final IIntResultListener listener) {
- mHandler.post(() -> {
- final TetheringRequestParcel unfinishedRequest = mActiveTetheringRequests.get(
- request.tetheringType);
- // If tethering is already enabled with a different request,
- // disable before re-enabling.
- if (unfinishedRequest != null
- && !TetheringUtils.isTetheringRequestEquals(unfinishedRequest, request)) {
- enableTetheringInternal(request.tetheringType, false /* disabled */, null);
- mEntitlementMgr.stopProvisioningIfNeeded(request.tetheringType);
- }
- mActiveTetheringRequests.put(request.tetheringType, request);
-
- if (request.exemptFromEntitlementCheck) {
- mEntitlementMgr.setExemptedDownstreamType(request.tetheringType);
- } else {
- mEntitlementMgr.startProvisioningIfNeeded(request.tetheringType,
- request.showProvisioningUi);
- }
- enableTetheringInternal(request.tetheringType, true /* enabled */, listener);
- });
- }
-
- void stopTethering(int type) {
- mHandler.post(() -> {
- mActiveTetheringRequests.remove(type);
-
- enableTetheringInternal(type, false /* disabled */, null);
- mEntitlementMgr.stopProvisioningIfNeeded(type);
- });
- }
-
- /**
- * Enables or disables tethering for the given type. If provisioning is required, it will
- * schedule provisioning rechecks for the specified interface.
- */
- private void enableTetheringInternal(int type, boolean enable,
- final IIntResultListener listener) {
- int result = TETHER_ERROR_NO_ERROR;
- switch (type) {
- case TETHERING_WIFI:
- result = setWifiTethering(enable);
- break;
- case TETHERING_USB:
- result = setUsbTethering(enable);
- break;
- case TETHERING_BLUETOOTH:
- setBluetoothTethering(enable, listener);
- break;
- case TETHERING_NCM:
- result = setNcmTethering(enable);
- break;
- case TETHERING_ETHERNET:
- result = setEthernetTethering(enable);
- break;
- default:
- Log.w(TAG, "Invalid tether type.");
- result = TETHER_ERROR_UNKNOWN_TYPE;
- }
-
- // The result of Bluetooth tethering will be sent by #setBluetoothTethering.
- if (type != TETHERING_BLUETOOTH) {
- sendTetherResult(listener, result, type);
- }
- }
-
- private void sendTetherResult(final IIntResultListener listener, final int result,
- final int type) {
- if (listener != null) {
- try {
- listener.onResult(result);
- } catch (RemoteException e) { }
- }
-
- // If changing tethering fail, remove corresponding request
- // no matter who trigger the start/stop.
- if (result != TETHER_ERROR_NO_ERROR) mActiveTetheringRequests.remove(type);
- }
-
- private int setWifiTethering(final boolean enable) {
- final long ident = Binder.clearCallingIdentity();
- try {
- synchronized (mPublicSync) {
- final WifiManager mgr = getWifiManager();
- if (mgr == null) {
- mLog.e("setWifiTethering: failed to get WifiManager!");
- return TETHER_ERROR_SERVICE_UNAVAIL;
- }
- if ((enable && mgr.startTetheredHotspot(null /* use existing softap config */))
- || (!enable && mgr.stopSoftAp())) {
- mWifiTetherRequested = enable;
- return TETHER_ERROR_NO_ERROR;
- }
- }
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
-
- return TETHER_ERROR_INTERNAL_ERROR;
- }
-
- private void setBluetoothTethering(final boolean enable, final IIntResultListener listener) {
- final BluetoothAdapter adapter = mDeps.getBluetoothAdapter();
- if (adapter == null || !adapter.isEnabled()) {
- Log.w(TAG, "Tried to enable bluetooth tethering with null or disabled adapter. null: "
- + (adapter == null));
- sendTetherResult(listener, TETHER_ERROR_SERVICE_UNAVAIL, TETHERING_BLUETOOTH);
- return;
- }
-
- adapter.getProfileProxy(mContext, new ServiceListener() {
- @Override
- public void onServiceDisconnected(int profile) { }
-
- @Override
- public void onServiceConnected(int profile, BluetoothProfile proxy) {
- // Clear identify is fine because caller already pass tethering permission at
- // ConnectivityService#startTethering()(or stopTethering) before the control comes
- // here. Bluetooth will check tethering permission again that there is
- // Context#getOpPackageName() under BluetoothPan#setBluetoothTethering() to get
- // caller's package name for permission check.
- // Calling BluetoothPan#setBluetoothTethering() here means the package name always
- // be system server. If calling identity is not cleared, that package's uid might
- // not match calling uid and end up in permission denied.
- final long identityToken = Binder.clearCallingIdentity();
- try {
- ((BluetoothPan) proxy).setBluetoothTethering(enable);
- } finally {
- Binder.restoreCallingIdentity(identityToken);
- }
- // TODO: Enabling bluetooth tethering can fail asynchronously here.
- // We should figure out a way to bubble up that failure instead of sending success.
- final int result = (((BluetoothPan) proxy).isTetheringOn() == enable)
- ? TETHER_ERROR_NO_ERROR
- : TETHER_ERROR_INTERNAL_ERROR;
- sendTetherResult(listener, result, TETHERING_BLUETOOTH);
- adapter.closeProfileProxy(BluetoothProfile.PAN, proxy);
- }
- }, BluetoothProfile.PAN);
- }
-
- private int setEthernetTethering(final boolean enable) {
- final EthernetManager em = (EthernetManager) mContext.getSystemService(
- Context.ETHERNET_SERVICE);
- synchronized (mPublicSync) {
- if (enable) {
- if (mEthernetCallback != null) {
- Log.d(TAG, "Ethernet tethering already started");
- return TETHER_ERROR_NO_ERROR;
- }
-
- mEthernetCallback = new EthernetCallback();
- mEthernetIfaceRequest = em.requestTetheredInterface(mExecutor, mEthernetCallback);
- } else {
- stopEthernetTetheringLocked();
- }
- }
- return TETHER_ERROR_NO_ERROR;
- }
-
- private void stopEthernetTetheringLocked() {
- if (mConfiguredEthernetIface != null) {
- stopTrackingInterfaceLocked(mConfiguredEthernetIface);
- mConfiguredEthernetIface = null;
- }
- if (mEthernetCallback != null) {
- mEthernetIfaceRequest.release();
- mEthernetCallback = null;
- mEthernetIfaceRequest = null;
- }
- }
-
- private class EthernetCallback implements EthernetManager.TetheredInterfaceCallback {
- @Override
- public void onAvailable(String iface) {
- synchronized (mPublicSync) {
- if (this != mEthernetCallback) {
- // Ethernet callback arrived after Ethernet tethering stopped. Ignore.
- return;
- }
- maybeTrackNewInterfaceLocked(iface, TETHERING_ETHERNET);
- changeInterfaceState(iface, IpServer.STATE_TETHERED);
- mConfiguredEthernetIface = iface;
- }
- }
-
- @Override
- public void onUnavailable() {
- synchronized (mPublicSync) {
- if (this != mEthernetCallback) {
- // onAvailable called after stopping Ethernet tethering.
- return;
- }
- stopEthernetTetheringLocked();
- }
- }
- }
-
- int tether(String iface) {
- return tether(iface, IpServer.STATE_TETHERED);
- }
-
- private int tether(String iface, int requestedState) {
- if (DBG) Log.d(TAG, "Tethering " + iface);
- synchronized (mPublicSync) {
- TetherState tetherState = mTetherStates.get(iface);
- if (tetherState == null) {
- Log.e(TAG, "Tried to Tether an unknown iface: " + iface + ", ignoring");
- return TETHER_ERROR_UNKNOWN_IFACE;
- }
- // Ignore the error status of the interface. If the interface is available,
- // the errors are referring to past tethering attempts anyway.
- if (tetherState.lastState != IpServer.STATE_AVAILABLE) {
- Log.e(TAG, "Tried to Tether an unavailable iface: " + iface + ", ignoring");
- return TETHER_ERROR_UNAVAIL_IFACE;
- }
- // NOTE: If a CMD_TETHER_REQUESTED message is already in the TISM's queue but not yet
- // processed, this will be a no-op and it will not return an error.
- //
- // This code cannot race with untether() because they both synchronize on mPublicSync.
- // TODO: reexamine the threading and messaging model to totally remove mPublicSync.
- final int type = tetherState.ipServer.interfaceType();
- final TetheringRequestParcel request = mActiveTetheringRequests.get(type, null);
- if (request != null) {
- mActiveTetheringRequests.delete(type);
- }
- tetherState.ipServer.sendMessage(IpServer.CMD_TETHER_REQUESTED, requestedState, 0,
- request);
- return TETHER_ERROR_NO_ERROR;
- }
- }
-
- int untether(String iface) {
- if (DBG) Log.d(TAG, "Untethering " + iface);
- synchronized (mPublicSync) {
- TetherState tetherState = mTetherStates.get(iface);
- if (tetherState == null) {
- Log.e(TAG, "Tried to Untether an unknown iface :" + iface + ", ignoring");
- return TETHER_ERROR_UNKNOWN_IFACE;
- }
- if (!tetherState.isCurrentlyServing()) {
- Log.e(TAG, "Tried to untether an inactive iface :" + iface + ", ignoring");
- return TETHER_ERROR_UNAVAIL_IFACE;
- }
- tetherState.ipServer.sendMessage(IpServer.CMD_TETHER_UNREQUESTED);
- return TETHER_ERROR_NO_ERROR;
- }
- }
-
- void untetherAll() {
- stopTethering(TETHERING_WIFI);
- stopTethering(TETHERING_WIFI_P2P);
- stopTethering(TETHERING_USB);
- stopTethering(TETHERING_BLUETOOTH);
- stopTethering(TETHERING_ETHERNET);
- }
-
- int getLastTetherError(String iface) {
- synchronized (mPublicSync) {
- TetherState tetherState = mTetherStates.get(iface);
- if (tetherState == null) {
- Log.e(TAG, "Tried to getLastTetherError on an unknown iface :" + iface
- + ", ignoring");
- return TETHER_ERROR_UNKNOWN_IFACE;
- }
- return tetherState.lastError;
- }
- }
-
- private boolean isProvisioningNeededButUnavailable() {
- return isTetherProvisioningRequired() && !doesEntitlementPackageExist();
- }
-
- boolean isTetherProvisioningRequired() {
- final TetheringConfiguration cfg = mConfig;
- return mEntitlementMgr.isTetherProvisioningRequired(cfg);
- }
-
- private boolean doesEntitlementPackageExist() {
- // provisioningApp must contain package and class name.
- if (mConfig.provisioningApp.length != 2) {
- return false;
- }
-
- final PackageManager pm = mContext.getPackageManager();
- try {
- pm.getPackageInfo(mConfig.provisioningApp[0], GET_ACTIVITIES);
- } catch (PackageManager.NameNotFoundException e) {
- return false;
- }
- return true;
- }
-
- // TODO: Figure out how to update for local hotspot mode interfaces.
- private void sendTetherStateChangedBroadcast() {
- if (!isTetheringSupported()) return;
-
- final ArrayList<String> availableList = new ArrayList<>();
- final ArrayList<String> tetherList = new ArrayList<>();
- final ArrayList<String> localOnlyList = new ArrayList<>();
- final ArrayList<String> erroredList = new ArrayList<>();
- final ArrayList<Integer> lastErrorList = new ArrayList<>();
-
- final TetheringConfiguration cfg = mConfig;
- mTetherStatesParcel = new TetherStatesParcel();
-
- int downstreamTypesMask = DOWNSTREAM_NONE;
- synchronized (mPublicSync) {
- for (int i = 0; i < mTetherStates.size(); i++) {
- TetherState tetherState = mTetherStates.valueAt(i);
- String iface = mTetherStates.keyAt(i);
- if (tetherState.lastError != TETHER_ERROR_NO_ERROR) {
- erroredList.add(iface);
- lastErrorList.add(tetherState.lastError);
- } else if (tetherState.lastState == IpServer.STATE_AVAILABLE) {
- availableList.add(iface);
- } else if (tetherState.lastState == IpServer.STATE_LOCAL_ONLY) {
- localOnlyList.add(iface);
- } else if (tetherState.lastState == IpServer.STATE_TETHERED) {
- if (cfg.isUsb(iface)) {
- downstreamTypesMask |= (1 << TETHERING_USB);
- } else if (cfg.isWifi(iface)) {
- downstreamTypesMask |= (1 << TETHERING_WIFI);
- } else if (cfg.isBluetooth(iface)) {
- downstreamTypesMask |= (1 << TETHERING_BLUETOOTH);
- }
- tetherList.add(iface);
- }
- }
- }
-
- mTetherStatesParcel.availableList = availableList.toArray(new String[0]);
- mTetherStatesParcel.tetheredList = tetherList.toArray(new String[0]);
- mTetherStatesParcel.localOnlyList = localOnlyList.toArray(new String[0]);
- mTetherStatesParcel.erroredIfaceList = erroredList.toArray(new String[0]);
- mTetherStatesParcel.lastErrorList = new int[lastErrorList.size()];
- Iterator<Integer> iterator = lastErrorList.iterator();
- for (int i = 0; i < lastErrorList.size(); i++) {
- mTetherStatesParcel.lastErrorList[i] = iterator.next().intValue();
- }
- reportTetherStateChanged(mTetherStatesParcel);
-
- final Intent bcast = new Intent(ACTION_TETHER_STATE_CHANGED);
- bcast.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
- bcast.putStringArrayListExtra(EXTRA_AVAILABLE_TETHER, availableList);
- bcast.putStringArrayListExtra(EXTRA_ACTIVE_LOCAL_ONLY, localOnlyList);
- bcast.putStringArrayListExtra(EXTRA_ACTIVE_TETHER, tetherList);
- bcast.putStringArrayListExtra(EXTRA_ERRORED_TETHER, erroredList);
- mContext.sendStickyBroadcastAsUser(bcast, UserHandle.ALL);
- if (DBG) {
- Log.d(TAG, String.format(
- "sendTetherStateChangedBroadcast %s=[%s] %s=[%s] %s=[%s] %s=[%s]",
- "avail", TextUtils.join(",", availableList),
- "local_only", TextUtils.join(",", localOnlyList),
- "tether", TextUtils.join(",", tetherList),
- "error", TextUtils.join(",", erroredList)));
- }
-
- mNotificationUpdater.onDownstreamChanged(downstreamTypesMask);
- }
-
- private class StateReceiver extends BroadcastReceiver {
- @Override
- public void onReceive(Context content, Intent intent) {
- final String action = intent.getAction();
- if (action == null) return;
-
- if (action.equals(UsbManager.ACTION_USB_STATE)) {
- handleUsbAction(intent);
- } else if (action.equals(CONNECTIVITY_ACTION)) {
- handleConnectivityAction(intent);
- } else if (action.equals(WifiManager.WIFI_AP_STATE_CHANGED_ACTION)) {
- handleWifiApAction(intent);
- } else if (action.equals(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION)) {
- handleWifiP2pAction(intent);
- } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) {
- mLog.log("OBSERVED configuration changed");
- updateConfiguration();
- } else if (action.equals(UserManager.ACTION_USER_RESTRICTIONS_CHANGED)) {
- mLog.log("OBSERVED user restrictions changed");
- handleUserRestrictionAction();
- } else if (action.equals(ACTION_RESTRICT_BACKGROUND_CHANGED)) {
- mLog.log("OBSERVED data saver changed");
- handleDataSaverChanged();
- } else if (action.equals(TetheringNotificationUpdater.ACTION_DISABLE_TETHERING)) {
- untetherAll();
- }
- }
-
- private void handleConnectivityAction(Intent intent) {
- final NetworkInfo networkInfo =
- (NetworkInfo) intent.getParcelableExtra(EXTRA_NETWORK_INFO);
- if (networkInfo == null
- || networkInfo.getDetailedState() == NetworkInfo.DetailedState.FAILED) {
- return;
- }
-
- if (VDBG) Log.d(TAG, "Tethering got CONNECTIVITY_ACTION: " + networkInfo.toString());
- mTetherMainSM.sendMessage(TetherMainSM.CMD_UPSTREAM_CHANGED);
- }
-
- private void handleUsbAction(Intent intent) {
- final boolean usbConnected = intent.getBooleanExtra(USB_CONNECTED, false);
- final boolean usbConfigured = intent.getBooleanExtra(USB_CONFIGURED, false);
- final boolean rndisEnabled = intent.getBooleanExtra(USB_FUNCTION_RNDIS, false);
- final boolean ncmEnabled = intent.getBooleanExtra(USB_FUNCTION_NCM, false);
-
- mLog.log(String.format("USB bcast connected:%s configured:%s rndis:%s",
- usbConnected, usbConfigured, rndisEnabled));
-
- // There are three types of ACTION_USB_STATE:
- //
- // - DISCONNECTED (USB_CONNECTED and USB_CONFIGURED are 0)
- // Meaning: USB connection has ended either because of
- // software reset or hard unplug.
- //
- // - CONNECTED (USB_CONNECTED is 1, USB_CONFIGURED is 0)
- // Meaning: the first stage of USB protocol handshake has
- // occurred but it is not complete.
- //
- // - CONFIGURED (USB_CONNECTED and USB_CONFIGURED are 1)
- // Meaning: the USB handshake is completely done and all the
- // functions are ready to use.
- //
- // For more explanation, see b/62552150 .
- synchronized (Tethering.this.mPublicSync) {
- if (!usbConnected && mRndisEnabled) {
- // Turn off tethering if it was enabled and there is a disconnect.
- tetherMatchingInterfaces(IpServer.STATE_AVAILABLE, TETHERING_USB);
- mEntitlementMgr.stopProvisioningIfNeeded(TETHERING_USB);
- } else if (usbConfigured && rndisEnabled) {
- // Tether if rndis is enabled and usb is configured.
- tetherMatchingInterfaces(IpServer.STATE_TETHERED, TETHERING_USB);
- } else if (usbConnected && ncmEnabled) {
- tetherMatchingInterfaces(IpServer.STATE_LOCAL_ONLY, TETHERING_NCM);
- }
- mRndisEnabled = usbConfigured && rndisEnabled;
- }
- }
-
- private void handleWifiApAction(Intent intent) {
- final int curState = intent.getIntExtra(EXTRA_WIFI_AP_STATE, WIFI_AP_STATE_DISABLED);
- final String ifname = intent.getStringExtra(EXTRA_WIFI_AP_INTERFACE_NAME);
- final int ipmode = intent.getIntExtra(EXTRA_WIFI_AP_MODE, IFACE_IP_MODE_UNSPECIFIED);
-
- synchronized (Tethering.this.mPublicSync) {
- switch (curState) {
- case WifiManager.WIFI_AP_STATE_ENABLING:
- // We can see this state on the way to both enabled and failure states.
- break;
- case WifiManager.WIFI_AP_STATE_ENABLED:
- enableWifiIpServingLocked(ifname, ipmode);
- break;
- case WifiManager.WIFI_AP_STATE_DISABLING:
- // We can see this state on the way to disabled.
- break;
- case WifiManager.WIFI_AP_STATE_DISABLED:
- case WifiManager.WIFI_AP_STATE_FAILED:
- default:
- disableWifiIpServingLocked(ifname, curState);
- break;
- }
- }
- }
-
- private boolean isGroupOwner(WifiP2pGroup group) {
- return group != null && group.isGroupOwner()
- && !TextUtils.isEmpty(group.getInterface());
- }
-
- private void handleWifiP2pAction(Intent intent) {
- if (mConfig.isWifiP2pLegacyTetheringMode()) return;
-
- final WifiP2pInfo p2pInfo =
- (WifiP2pInfo) intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_INFO);
- final WifiP2pGroup group =
- (WifiP2pGroup) intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_GROUP);
-
- if (VDBG) {
- Log.d(TAG, "WifiP2pAction: P2pInfo: " + p2pInfo + " Group: " + group);
- }
-
- synchronized (Tethering.this.mPublicSync) {
- // if no group is formed, bring it down if needed.
- if (p2pInfo == null || !p2pInfo.groupFormed) {
- disableWifiP2pIpServingLockedIfNeeded(mWifiP2pTetherInterface);
- mWifiP2pTetherInterface = null;
- return;
- }
-
- // If there is a group but the device is not the owner, bail out.
- if (!isGroupOwner(group)) return;
-
- // If already serving from the correct interface, nothing to do.
- if (group.getInterface().equals(mWifiP2pTetherInterface)) return;
-
- // If already serving from another interface, turn it down first.
- if (!TextUtils.isEmpty(mWifiP2pTetherInterface)) {
- mLog.w("P2P tethered interface " + mWifiP2pTetherInterface
- + "is different from current interface "
- + group.getInterface() + ", re-tether it");
- disableWifiP2pIpServingLockedIfNeeded(mWifiP2pTetherInterface);
- }
-
- // Finally bring up serving on the new interface
- mWifiP2pTetherInterface = group.getInterface();
- enableWifiIpServingLocked(mWifiP2pTetherInterface, IFACE_IP_MODE_LOCAL_ONLY);
- }
- }
-
- private void handleUserRestrictionAction() {
- mTetheringRestriction.onUserRestrictionsChanged();
- }
-
- private void handleDataSaverChanged() {
- final ConnectivityManager connMgr = (ConnectivityManager) mContext.getSystemService(
- Context.CONNECTIVITY_SERVICE);
- final boolean isDataSaverEnabled = connMgr.getRestrictBackgroundStatus()
- != ConnectivityManager.RESTRICT_BACKGROUND_STATUS_DISABLED;
-
- if (mDataSaverEnabled == isDataSaverEnabled) return;
-
- mDataSaverEnabled = isDataSaverEnabled;
- if (mDataSaverEnabled) {
- untetherAll();
- }
- }
- }
-
- @VisibleForTesting
- boolean isTetheringActive() {
- return mActiveTetheringRequests.size() > 0;
- }
-
- @VisibleForTesting
- protected static class UserRestrictionActionListener {
- private final UserManager mUserMgr;
- private final Tethering mWrapper;
- private final TetheringNotificationUpdater mNotificationUpdater;
- public boolean mDisallowTethering;
-
- public UserRestrictionActionListener(@NonNull UserManager um, @NonNull Tethering wrapper,
- @NonNull TetheringNotificationUpdater updater) {
- mUserMgr = um;
- mWrapper = wrapper;
- mNotificationUpdater = updater;
- mDisallowTethering = false;
- }
-
- public void onUserRestrictionsChanged() {
- // getUserRestrictions gets restriction for this process' user, which is the primary
- // user. This is fine because DISALLOW_CONFIG_TETHERING can only be set on the primary
- // user. See UserManager.DISALLOW_CONFIG_TETHERING.
- final Bundle restrictions = mUserMgr.getUserRestrictions();
- final boolean newlyDisallowed =
- restrictions.getBoolean(UserManager.DISALLOW_CONFIG_TETHERING);
- final boolean prevDisallowed = mDisallowTethering;
- mDisallowTethering = newlyDisallowed;
-
- final boolean tetheringDisallowedChanged = (newlyDisallowed != prevDisallowed);
- if (!tetheringDisallowedChanged) {
- return;
- }
-
- if (!newlyDisallowed) {
- // Clear the restricted notification when user is allowed to have tethering
- // function.
- mNotificationUpdater.tetheringRestrictionLifted();
- return;
- }
-
- if (mWrapper.isTetheringActive()) {
- // Restricted notification is shown when tethering function is disallowed on
- // user's device.
- mNotificationUpdater.notifyTetheringDisabledByRestriction();
-
- // Untether from all downstreams since tethering is disallowed.
- mWrapper.untetherAll();
- }
- // TODO(b/148139325): send tetheringSupported on restriction change
- }
- }
-
- private void disableWifiIpServingLockedCommon(int tetheringType, String ifname, int apState) {
- mLog.log("Canceling WiFi tethering request -"
- + " type=" + tetheringType
- + " interface=" + ifname
- + " state=" + apState);
-
- if (!TextUtils.isEmpty(ifname)) {
- final TetherState ts = mTetherStates.get(ifname);
- if (ts != null) {
- ts.ipServer.unwanted();
- return;
- }
- }
-
- for (int i = 0; i < mTetherStates.size(); i++) {
- final IpServer ipServer = mTetherStates.valueAt(i).ipServer;
- if (ipServer.interfaceType() == tetheringType) {
- ipServer.unwanted();
- return;
- }
- }
-
- mLog.log("Error disabling Wi-Fi IP serving; "
- + (TextUtils.isEmpty(ifname) ? "no interface name specified"
- : "specified interface: " + ifname));
- }
-
- private void disableWifiIpServingLocked(String ifname, int apState) {
- // Regardless of whether we requested this transition, the AP has gone
- // down. Don't try to tether again unless we're requested to do so.
- // TODO: Remove this altogether, once Wi-Fi reliably gives us an
- // interface name with every broadcast.
- mWifiTetherRequested = false;
-
- disableWifiIpServingLockedCommon(TETHERING_WIFI, ifname, apState);
- }
-
- private void disableWifiP2pIpServingLockedIfNeeded(String ifname) {
- if (TextUtils.isEmpty(ifname)) return;
-
- disableWifiIpServingLockedCommon(TETHERING_WIFI_P2P, ifname, /* fake */ 0);
- }
-
- private void enableWifiIpServingLocked(String ifname, int wifiIpMode) {
- // Map wifiIpMode values to IpServer.Callback serving states, inferring
- // from mWifiTetherRequested as a final "best guess".
- final int ipServingMode;
- switch (wifiIpMode) {
- case IFACE_IP_MODE_TETHERED:
- ipServingMode = IpServer.STATE_TETHERED;
- break;
- case IFACE_IP_MODE_LOCAL_ONLY:
- ipServingMode = IpServer.STATE_LOCAL_ONLY;
- break;
- default:
- mLog.e("Cannot enable IP serving in unknown WiFi mode: " + wifiIpMode);
- return;
- }
-
- if (!TextUtils.isEmpty(ifname)) {
- maybeTrackNewInterfaceLocked(ifname);
- changeInterfaceState(ifname, ipServingMode);
- } else {
- mLog.e(String.format(
- "Cannot enable IP serving in mode %s on missing interface name",
- ipServingMode));
- }
- }
-
- // TODO: Consider renaming to something more accurate in its description.
- // This method:
- // - allows requesting either tethering or local hotspot serving states
- // - handles both enabling and disabling serving states
- // - only tethers the first matching interface in listInterfaces()
- // order of a given type
- private void tetherMatchingInterfaces(int requestedState, int interfaceType) {
- if (VDBG) {
- Log.d(TAG, "tetherMatchingInterfaces(" + requestedState + ", " + interfaceType + ")");
- }
-
- String[] ifaces = null;
- try {
- ifaces = mNetd.interfaceGetList();
- } catch (RemoteException | ServiceSpecificException e) {
- Log.e(TAG, "Error listing Interfaces", e);
- return;
- }
- String chosenIface = null;
- if (ifaces != null) {
- for (String iface : ifaces) {
- if (ifaceNameToType(iface) == interfaceType) {
- chosenIface = iface;
- break;
- }
- }
- }
- if (chosenIface == null) {
- Log.e(TAG, "could not find iface of type " + interfaceType);
- return;
- }
-
- changeInterfaceState(chosenIface, requestedState);
- }
-
- private void changeInterfaceState(String ifname, int requestedState) {
- final int result;
- switch (requestedState) {
- case IpServer.STATE_UNAVAILABLE:
- case IpServer.STATE_AVAILABLE:
- result = untether(ifname);
- break;
- case IpServer.STATE_TETHERED:
- case IpServer.STATE_LOCAL_ONLY:
- result = tether(ifname, requestedState);
- break;
- default:
- Log.wtf(TAG, "Unknown interface state: " + requestedState);
- return;
- }
- if (result != TETHER_ERROR_NO_ERROR) {
- Log.e(TAG, "unable start or stop tethering on iface " + ifname);
- return;
- }
- }
-
- TetheringConfiguration getTetheringConfiguration() {
- return mConfig;
- }
-
- boolean hasTetherableConfiguration() {
- final TetheringConfiguration cfg = mConfig;
- final boolean hasDownstreamConfiguration =
- (cfg.tetherableUsbRegexs.length != 0)
- || (cfg.tetherableWifiRegexs.length != 0)
- || (cfg.tetherableBluetoothRegexs.length != 0);
- final boolean hasUpstreamConfiguration = !cfg.preferredUpstreamIfaceTypes.isEmpty()
- || cfg.chooseUpstreamAutomatically;
-
- return hasDownstreamConfiguration && hasUpstreamConfiguration;
- }
-
- // TODO - update callers to use getTetheringConfiguration(),
- // which has only final members.
- String[] getTetherableUsbRegexs() {
- return copy(mConfig.tetherableUsbRegexs);
- }
-
- String[] getTetherableWifiRegexs() {
- return copy(mConfig.tetherableWifiRegexs);
- }
-
- String[] getTetherableBluetoothRegexs() {
- return copy(mConfig.tetherableBluetoothRegexs);
- }
-
- int setUsbTethering(boolean enable) {
- if (VDBG) Log.d(TAG, "setUsbTethering(" + enable + ")");
- UsbManager usbManager = (UsbManager) mContext.getSystemService(Context.USB_SERVICE);
- if (usbManager == null) {
- mLog.e("setUsbTethering: failed to get UsbManager!");
- return TETHER_ERROR_SERVICE_UNAVAIL;
- }
-
- synchronized (mPublicSync) {
- usbManager.setCurrentFunctions(enable ? UsbManager.FUNCTION_RNDIS
- : UsbManager.FUNCTION_NONE);
- }
- return TETHER_ERROR_NO_ERROR;
- }
-
- private int setNcmTethering(boolean enable) {
- if (VDBG) Log.d(TAG, "setNcmTethering(" + enable + ")");
- UsbManager usbManager = (UsbManager) mContext.getSystemService(Context.USB_SERVICE);
- synchronized (mPublicSync) {
- usbManager.setCurrentFunctions(enable ? UsbManager.FUNCTION_NCM
- : UsbManager.FUNCTION_NONE);
- }
- return TETHER_ERROR_NO_ERROR;
- }
-
- // TODO review API - figure out how to delete these entirely.
- String[] getTetheredIfaces() {
- ArrayList<String> list = new ArrayList<String>();
- synchronized (mPublicSync) {
- for (int i = 0; i < mTetherStates.size(); i++) {
- TetherState tetherState = mTetherStates.valueAt(i);
- if (tetherState.lastState == IpServer.STATE_TETHERED) {
- list.add(mTetherStates.keyAt(i));
- }
- }
- }
- return list.toArray(new String[list.size()]);
- }
-
- String[] getTetherableIfaces() {
- ArrayList<String> list = new ArrayList<String>();
- synchronized (mPublicSync) {
- for (int i = 0; i < mTetherStates.size(); i++) {
- TetherState tetherState = mTetherStates.valueAt(i);
- if (tetherState.lastState == IpServer.STATE_AVAILABLE) {
- list.add(mTetherStates.keyAt(i));
- }
- }
- }
- return list.toArray(new String[list.size()]);
- }
-
- String[] getTetheredDhcpRanges() {
- // TODO: this is only valid for the old DHCP server. Latest search suggests it is only used
- // by WifiP2pServiceImpl to start dnsmasq: remove/deprecate after migrating callers.
- return mConfig.legacyDhcpRanges;
- }
-
- String[] getErroredIfaces() {
- ArrayList<String> list = new ArrayList<String>();
- synchronized (mPublicSync) {
- for (int i = 0; i < mTetherStates.size(); i++) {
- TetherState tetherState = mTetherStates.valueAt(i);
- if (tetherState.lastError != TETHER_ERROR_NO_ERROR) {
- list.add(mTetherStates.keyAt(i));
- }
- }
- }
- return list.toArray(new String[list.size()]);
- }
-
- private void logMessage(State state, int what) {
- mLog.log(state.getName() + " got " + sMagicDecoderRing.get(what, Integer.toString(what)));
- }
-
- private boolean upstreamWanted() {
- if (!mForwardedDownstreams.isEmpty()) return true;
-
- synchronized (mPublicSync) {
- return mWifiTetherRequested;
- }
- }
-
- // Needed because the canonical source of upstream truth is just the
- // upstream interface set, |mCurrentUpstreamIfaceSet|.
- private boolean pertainsToCurrentUpstream(UpstreamNetworkState ns) {
- if (ns != null && ns.linkProperties != null && mCurrentUpstreamIfaceSet != null) {
- for (String ifname : ns.linkProperties.getAllInterfaceNames()) {
- if (mCurrentUpstreamIfaceSet.ifnames.contains(ifname)) {
- return true;
- }
- }
- }
- return false;
- }
-
- class TetherMainSM extends StateMachine {
- // an interface SM has requested Tethering/Local Hotspot
- static final int EVENT_IFACE_SERVING_STATE_ACTIVE = BASE_MAIN_SM + 1;
- // an interface SM has unrequested Tethering/Local Hotspot
- static final int EVENT_IFACE_SERVING_STATE_INACTIVE = BASE_MAIN_SM + 2;
- // upstream connection change - do the right thing
- static final int CMD_UPSTREAM_CHANGED = BASE_MAIN_SM + 3;
- // we don't have a valid upstream conn, check again after a delay
- static final int CMD_RETRY_UPSTREAM = BASE_MAIN_SM + 4;
- // Events from NetworkCallbacks that we process on the main state
- // machine thread on behalf of the UpstreamNetworkMonitor.
- static final int EVENT_UPSTREAM_CALLBACK = BASE_MAIN_SM + 5;
- // we treated the error and want now to clear it
- static final int CMD_CLEAR_ERROR = BASE_MAIN_SM + 6;
- static final int EVENT_IFACE_UPDATE_LINKPROPERTIES = BASE_MAIN_SM + 7;
- // Events from EntitlementManager to choose upstream again.
- static final int EVENT_UPSTREAM_PERMISSION_CHANGED = BASE_MAIN_SM + 8;
- private final State mInitialState;
- private final State mTetherModeAliveState;
-
- private final State mSetIpForwardingEnabledErrorState;
- private final State mSetIpForwardingDisabledErrorState;
- private final State mStartTetheringErrorState;
- private final State mStopTetheringErrorState;
- private final State mSetDnsForwardersErrorState;
-
- // This list is a little subtle. It contains all the interfaces that currently are
- // requesting tethering, regardless of whether these interfaces are still members of
- // mTetherStates. This allows us to maintain the following predicates:
- //
- // 1) mTetherStates contains the set of all currently existing, tetherable, link state up
- // interfaces.
- // 2) mNotifyList contains all state machines that may have outstanding tethering state
- // that needs to be torn down.
- //
- // Because we excise interfaces immediately from mTetherStates, we must maintain mNotifyList
- // so that the garbage collector does not clean up the state machine before it has a chance
- // to tear itself down.
- private final ArrayList<IpServer> mNotifyList;
- private final IPv6TetheringCoordinator mIPv6TetheringCoordinator;
- private final OffloadWrapper mOffload;
-
- private static final int UPSTREAM_SETTLE_TIME_MS = 10000;
-
- TetherMainSM(String name, Looper looper, TetheringDependencies deps) {
- super(name, looper);
-
- mInitialState = new InitialState();
- mTetherModeAliveState = new TetherModeAliveState();
- mSetIpForwardingEnabledErrorState = new SetIpForwardingEnabledErrorState();
- mSetIpForwardingDisabledErrorState = new SetIpForwardingDisabledErrorState();
- mStartTetheringErrorState = new StartTetheringErrorState();
- mStopTetheringErrorState = new StopTetheringErrorState();
- mSetDnsForwardersErrorState = new SetDnsForwardersErrorState();
-
- addState(mInitialState);
- addState(mTetherModeAliveState);
- addState(mSetIpForwardingEnabledErrorState);
- addState(mSetIpForwardingDisabledErrorState);
- addState(mStartTetheringErrorState);
- addState(mStopTetheringErrorState);
- addState(mSetDnsForwardersErrorState);
-
- mNotifyList = new ArrayList<>();
- mIPv6TetheringCoordinator = deps.getIPv6TetheringCoordinator(mNotifyList, mLog);
- mOffload = new OffloadWrapper();
-
- setInitialState(mInitialState);
- }
-
- class InitialState extends State {
- @Override
- public boolean processMessage(Message message) {
- logMessage(this, message.what);
- switch (message.what) {
- case EVENT_IFACE_SERVING_STATE_ACTIVE: {
- final IpServer who = (IpServer) message.obj;
- if (VDBG) Log.d(TAG, "Tether Mode requested by " + who);
- handleInterfaceServingStateActive(message.arg1, who);
- transitionTo(mTetherModeAliveState);
- break;
- }
- case EVENT_IFACE_SERVING_STATE_INACTIVE: {
- final IpServer who = (IpServer) message.obj;
- if (VDBG) Log.d(TAG, "Tether Mode unrequested by " + who);
- handleInterfaceServingStateInactive(who);
- break;
- }
- case EVENT_IFACE_UPDATE_LINKPROPERTIES:
- // Silently ignore these for now.
- break;
- default:
- return NOT_HANDLED;
- }
- return HANDLED;
- }
- }
-
- protected boolean turnOnMainTetherSettings() {
- final TetheringConfiguration cfg = mConfig;
- try {
- mNetd.ipfwdEnableForwarding(TAG);
- } catch (RemoteException | ServiceSpecificException e) {
- mLog.e(e);
- transitionTo(mSetIpForwardingEnabledErrorState);
- return false;
- }
-
- // TODO: Randomize DHCPv4 ranges, especially in hotspot mode.
- // Legacy DHCP server is disabled if passed an empty ranges array
- final String[] dhcpRanges = cfg.enableLegacyDhcpServer
- ? cfg.legacyDhcpRanges : new String[0];
- try {
- NetdUtils.tetherStart(mNetd, true /** usingLegacyDnsProxy */, dhcpRanges);
- } catch (RemoteException | ServiceSpecificException e) {
- try {
- // Stop and retry.
- mNetd.tetherStop();
- NetdUtils.tetherStart(mNetd, true /** usingLegacyDnsProxy */, dhcpRanges);
- } catch (RemoteException | ServiceSpecificException ee) {
- mLog.e(ee);
- transitionTo(mStartTetheringErrorState);
- return false;
- }
- }
- mLog.log("SET main tether settings: ON");
- return true;
- }
-
- protected boolean turnOffMainTetherSettings() {
- try {
- mNetd.tetherStop();
- } catch (RemoteException | ServiceSpecificException e) {
- mLog.e(e);
- transitionTo(mStopTetheringErrorState);
- return false;
- }
- try {
- mNetd.ipfwdDisableForwarding(TAG);
- } catch (RemoteException | ServiceSpecificException e) {
- mLog.e(e);
- transitionTo(mSetIpForwardingDisabledErrorState);
- return false;
- }
- transitionTo(mInitialState);
- mLog.log("SET main tether settings: OFF");
- return true;
- }
-
- protected void chooseUpstreamType(boolean tryCell) {
- // We rebuild configuration on ACTION_CONFIGURATION_CHANGED, but we
- // do not currently know how to watch for changes in DUN settings.
- maybeDunSettingChanged();
-
- final TetheringConfiguration config = mConfig;
- final UpstreamNetworkState ns = (config.chooseUpstreamAutomatically)
- ? mUpstreamNetworkMonitor.getCurrentPreferredUpstream()
- : mUpstreamNetworkMonitor.selectPreferredUpstreamType(
- config.preferredUpstreamIfaceTypes);
- if (ns == null) {
- if (tryCell) {
- mUpstreamNetworkMonitor.registerMobileNetworkRequest();
- // We think mobile should be coming up; don't set a retry.
- } else {
- sendMessageDelayed(CMD_RETRY_UPSTREAM, UPSTREAM_SETTLE_TIME_MS);
- }
- }
- setUpstreamNetwork(ns);
- final Network newUpstream = (ns != null) ? ns.network : null;
- if (mTetherUpstream != newUpstream) {
- mTetherUpstream = newUpstream;
- mUpstreamNetworkMonitor.setCurrentUpstream(mTetherUpstream);
- reportUpstreamChanged(ns);
- }
- }
-
- protected void setUpstreamNetwork(UpstreamNetworkState ns) {
- InterfaceSet ifaces = null;
- if (ns != null) {
- // Find the interface with the default IPv4 route. It may be the
- // interface described by linkProperties, or one of the interfaces
- // stacked on top of it.
- mLog.i("Looking for default routes on: " + ns.linkProperties);
- ifaces = TetheringInterfaceUtils.getTetheringInterfaces(ns);
- mLog.i("Found upstream interface(s): " + ifaces);
- }
-
- if (ifaces != null) {
- setDnsForwarders(ns.network, ns.linkProperties);
- }
- notifyDownstreamsOfNewUpstreamIface(ifaces);
- if (ns != null && pertainsToCurrentUpstream(ns)) {
- // If we already have UpstreamNetworkState for this network update it immediately.
- handleNewUpstreamNetworkState(ns);
- } else if (mCurrentUpstreamIfaceSet == null) {
- // There are no available upstream networks.
- handleNewUpstreamNetworkState(null);
- }
- }
-
- protected void setDnsForwarders(final Network network, final LinkProperties lp) {
- // TODO: Set v4 and/or v6 DNS per available connectivity.
- final Collection<InetAddress> dnses = lp.getDnsServers();
- // TODO: Properly support the absence of DNS servers.
- final String[] dnsServers;
- if (dnses != null && !dnses.isEmpty()) {
- dnsServers = new String[dnses.size()];
- int i = 0;
- for (InetAddress dns : dnses) {
- dnsServers[i++] = dns.getHostAddress();
- }
- } else {
- dnsServers = mConfig.defaultIPv4DNS;
- }
- final int netId = (network != null) ? network.getNetId() : NETID_UNSET;
- try {
- mNetd.tetherDnsSet(netId, dnsServers);
- mLog.log(String.format(
- "SET DNS forwarders: network=%s dnsServers=%s",
- network, Arrays.toString(dnsServers)));
- } catch (RemoteException | ServiceSpecificException e) {
- // TODO: Investigate how this can fail and what exactly
- // happens if/when such failures occur.
- mLog.e("setting DNS forwarders failed, " + e);
- transitionTo(mSetDnsForwardersErrorState);
- }
- }
-
- protected void notifyDownstreamsOfNewUpstreamIface(InterfaceSet ifaces) {
- mCurrentUpstreamIfaceSet = ifaces;
- for (IpServer ipServer : mNotifyList) {
- ipServer.sendMessage(IpServer.CMD_TETHER_CONNECTION_CHANGED, ifaces);
- }
- }
-
- protected void handleNewUpstreamNetworkState(UpstreamNetworkState ns) {
- mIPv6TetheringCoordinator.updateUpstreamNetworkState(ns);
- mOffload.updateUpstreamNetworkState(ns);
- }
-
- private void handleInterfaceServingStateActive(int mode, IpServer who) {
- if (mNotifyList.indexOf(who) < 0) {
- mNotifyList.add(who);
- mIPv6TetheringCoordinator.addActiveDownstream(who, mode);
- }
-
- if (mode == IpServer.STATE_TETHERED) {
- // No need to notify OffloadController just yet as there are no
- // "offload-able" prefixes to pass along. This will handled
- // when the TISM informs Tethering of its LinkProperties.
- mForwardedDownstreams.add(who);
- } else {
- mOffload.excludeDownstreamInterface(who.interfaceName());
- mForwardedDownstreams.remove(who);
- }
-
- // If this is a Wi-Fi interface, notify WifiManager of the active serving state.
- if (who.interfaceType() == TETHERING_WIFI) {
- final WifiManager mgr = getWifiManager();
- final String iface = who.interfaceName();
- switch (mode) {
- case IpServer.STATE_TETHERED:
- mgr.updateInterfaceIpState(iface, IFACE_IP_MODE_TETHERED);
- break;
- case IpServer.STATE_LOCAL_ONLY:
- mgr.updateInterfaceIpState(iface, IFACE_IP_MODE_LOCAL_ONLY);
- break;
- default:
- Log.wtf(TAG, "Unknown active serving mode: " + mode);
- break;
- }
- }
- }
-
- private void handleInterfaceServingStateInactive(IpServer who) {
- mNotifyList.remove(who);
- mIPv6TetheringCoordinator.removeActiveDownstream(who);
- mOffload.excludeDownstreamInterface(who.interfaceName());
- mForwardedDownstreams.remove(who);
- updateConnectedClients(null /* wifiClients */);
-
- // If this is a Wi-Fi interface, tell WifiManager of any errors
- // or the inactive serving state.
- if (who.interfaceType() == TETHERING_WIFI) {
- if (who.lastError() != TETHER_ERROR_NO_ERROR) {
- getWifiManager().updateInterfaceIpState(
- who.interfaceName(), IFACE_IP_MODE_CONFIGURATION_ERROR);
- } else {
- getWifiManager().updateInterfaceIpState(
- who.interfaceName(), IFACE_IP_MODE_UNSPECIFIED);
- }
- }
- }
-
- @VisibleForTesting
- void handleUpstreamNetworkMonitorCallback(int arg1, Object o) {
- if (arg1 == UpstreamNetworkMonitor.NOTIFY_LOCAL_PREFIXES) {
- mOffload.sendOffloadExemptPrefixes((Set<IpPrefix>) o);
- return;
- }
-
- final UpstreamNetworkState ns = (UpstreamNetworkState) o;
- switch (arg1) {
- case UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES:
- mPrivateAddressCoordinator.updateUpstreamPrefix(ns);
- break;
- case UpstreamNetworkMonitor.EVENT_ON_LOST:
- mPrivateAddressCoordinator.removeUpstreamPrefix(ns.network);
- break;
- }
-
- if (ns == null || !pertainsToCurrentUpstream(ns)) {
- // TODO: In future, this is where upstream evaluation and selection
- // could be handled for notifications which include sufficient data.
- // For example, after CONNECTIVITY_ACTION listening is removed, here
- // is where we could observe a Wi-Fi network becoming available and
- // passing validation.
- if (mCurrentUpstreamIfaceSet == null) {
- // If we have no upstream interface, try to run through upstream
- // selection again. If, for example, IPv4 connectivity has shown up
- // after IPv6 (e.g., 464xlat became available) we want the chance to
- // notice and act accordingly.
- chooseUpstreamType(false);
- }
- return;
- }
-
- switch (arg1) {
- case UpstreamNetworkMonitor.EVENT_ON_CAPABILITIES:
- if (ns.network.equals(mTetherUpstream)) {
- mNotificationUpdater.onUpstreamCapabilitiesChanged(ns.networkCapabilities);
- }
- handleNewUpstreamNetworkState(ns);
- break;
- case UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES:
- chooseUpstreamType(false);
- break;
- case UpstreamNetworkMonitor.EVENT_ON_LOST:
- // TODO: Re-evaluate possible upstreams. Currently upstream
- // reevaluation is triggered via received CONNECTIVITY_ACTION
- // broadcasts that result in being passed a
- // TetherMainSM.CMD_UPSTREAM_CHANGED.
- handleNewUpstreamNetworkState(null);
- break;
- default:
- mLog.e("Unknown arg1 value: " + arg1);
- break;
- }
- }
-
- class TetherModeAliveState extends State {
- boolean mUpstreamWanted = false;
- boolean mTryCell = true;
-
- @Override
- public void enter() {
- // If turning on main tether settings fails, we have already
- // transitioned to an error state; exit early.
- if (!turnOnMainTetherSettings()) {
- return;
- }
-
- mPrivateAddressCoordinator.maybeRemoveDeprecatedUpstreams();
- mUpstreamNetworkMonitor.startObserveAllNetworks();
-
- // TODO: De-duplicate with updateUpstreamWanted() below.
- if (upstreamWanted()) {
- mUpstreamWanted = true;
- mOffload.start();
- chooseUpstreamType(true);
- mTryCell = false;
- }
-
- // TODO: Check the upstream interface if it is managed by BPF offload.
- mBpfCoordinator.startPolling();
- }
-
- @Override
- public void exit() {
- mOffload.stop();
- mUpstreamNetworkMonitor.stop();
- notifyDownstreamsOfNewUpstreamIface(null);
- handleNewUpstreamNetworkState(null);
- if (mTetherUpstream != null) {
- mTetherUpstream = null;
- reportUpstreamChanged(null);
- }
- mBpfCoordinator.stopPolling();
- }
-
- private boolean updateUpstreamWanted() {
- final boolean previousUpstreamWanted = mUpstreamWanted;
- mUpstreamWanted = upstreamWanted();
- if (mUpstreamWanted != previousUpstreamWanted) {
- if (mUpstreamWanted) {
- mOffload.start();
- } else {
- mOffload.stop();
- }
- }
- return previousUpstreamWanted;
- }
-
- @Override
- public boolean processMessage(Message message) {
- logMessage(this, message.what);
- boolean retValue = true;
- switch (message.what) {
- case EVENT_IFACE_SERVING_STATE_ACTIVE: {
- IpServer who = (IpServer) message.obj;
- if (VDBG) Log.d(TAG, "Tether Mode requested by " + who);
- handleInterfaceServingStateActive(message.arg1, who);
- who.sendMessage(IpServer.CMD_TETHER_CONNECTION_CHANGED,
- mCurrentUpstreamIfaceSet);
- // If there has been a change and an upstream is now
- // desired, kick off the selection process.
- final boolean previousUpstreamWanted = updateUpstreamWanted();
- if (!previousUpstreamWanted && mUpstreamWanted) {
- chooseUpstreamType(true);
- }
- break;
- }
- case EVENT_IFACE_SERVING_STATE_INACTIVE: {
- IpServer who = (IpServer) message.obj;
- if (VDBG) Log.d(TAG, "Tether Mode unrequested by " + who);
- handleInterfaceServingStateInactive(who);
-
- if (mNotifyList.isEmpty()) {
- // This transitions us out of TetherModeAliveState,
- // either to InitialState or an error state.
- turnOffMainTetherSettings();
- break;
- }
-
- if (DBG) {
- Log.d(TAG, "TetherModeAlive still has " + mNotifyList.size()
- + " live requests:");
- for (IpServer o : mNotifyList) {
- Log.d(TAG, " " + o);
- }
- }
- // If there has been a change and an upstream is no
- // longer desired, release any mobile requests.
- final boolean previousUpstreamWanted = updateUpstreamWanted();
- if (previousUpstreamWanted && !mUpstreamWanted) {
- mUpstreamNetworkMonitor.releaseMobileNetworkRequest();
- }
- break;
- }
- case EVENT_IFACE_UPDATE_LINKPROPERTIES: {
- final LinkProperties newLp = (LinkProperties) message.obj;
- if (message.arg1 == IpServer.STATE_TETHERED) {
- mOffload.updateDownstreamLinkProperties(newLp);
- } else {
- mOffload.excludeDownstreamInterface(newLp.getInterfaceName());
- }
- break;
- }
- case EVENT_UPSTREAM_PERMISSION_CHANGED:
- case CMD_UPSTREAM_CHANGED:
- updateUpstreamWanted();
- if (!mUpstreamWanted) break;
-
- // Need to try DUN immediately if Wi-Fi goes down.
- chooseUpstreamType(true);
- mTryCell = false;
- break;
- case CMD_RETRY_UPSTREAM:
- updateUpstreamWanted();
- if (!mUpstreamWanted) break;
-
- chooseUpstreamType(mTryCell);
- mTryCell = !mTryCell;
- break;
- case EVENT_UPSTREAM_CALLBACK: {
- updateUpstreamWanted();
- if (mUpstreamWanted) {
- handleUpstreamNetworkMonitorCallback(message.arg1, message.obj);
- }
- break;
- }
- default:
- retValue = false;
- break;
- }
- return retValue;
- }
- }
-
- class ErrorState extends State {
- private int mErrorNotification;
-
- @Override
- public boolean processMessage(Message message) {
- boolean retValue = true;
- switch (message.what) {
- case EVENT_IFACE_SERVING_STATE_ACTIVE:
- IpServer who = (IpServer) message.obj;
- who.sendMessage(mErrorNotification);
- break;
- case CMD_CLEAR_ERROR:
- mErrorNotification = TETHER_ERROR_NO_ERROR;
- transitionTo(mInitialState);
- break;
- default:
- retValue = false;
- }
- return retValue;
- }
-
- void notify(int msgType) {
- mErrorNotification = msgType;
- for (IpServer ipServer : mNotifyList) {
- ipServer.sendMessage(msgType);
- }
- }
-
- }
-
- class SetIpForwardingEnabledErrorState extends ErrorState {
- @Override
- public void enter() {
- Log.e(TAG, "Error in setIpForwardingEnabled");
- notify(IpServer.CMD_IP_FORWARDING_ENABLE_ERROR);
- }
- }
-
- class SetIpForwardingDisabledErrorState extends ErrorState {
- @Override
- public void enter() {
- Log.e(TAG, "Error in setIpForwardingDisabled");
- notify(IpServer.CMD_IP_FORWARDING_DISABLE_ERROR);
- }
- }
-
- class StartTetheringErrorState extends ErrorState {
- @Override
- public void enter() {
- Log.e(TAG, "Error in startTethering");
- notify(IpServer.CMD_START_TETHERING_ERROR);
- try {
- mNetd.ipfwdDisableForwarding(TAG);
- } catch (RemoteException | ServiceSpecificException e) { }
- }
- }
-
- class StopTetheringErrorState extends ErrorState {
- @Override
- public void enter() {
- Log.e(TAG, "Error in stopTethering");
- notify(IpServer.CMD_STOP_TETHERING_ERROR);
- try {
- mNetd.ipfwdDisableForwarding(TAG);
- } catch (RemoteException | ServiceSpecificException e) { }
- }
- }
-
- class SetDnsForwardersErrorState extends ErrorState {
- @Override
- public void enter() {
- Log.e(TAG, "Error in setDnsForwarders");
- notify(IpServer.CMD_SET_DNS_FORWARDERS_ERROR);
- try {
- mNetd.tetherStop();
- } catch (RemoteException | ServiceSpecificException e) { }
- try {
- mNetd.ipfwdDisableForwarding(TAG);
- } catch (RemoteException | ServiceSpecificException e) { }
- }
- }
-
- // A wrapper class to handle multiple situations where several calls to
- // the OffloadController need to happen together.
- //
- // TODO: This suggests that the interface between OffloadController and
- // Tethering is in need of improvement. Refactor these calls into the
- // OffloadController implementation.
- class OffloadWrapper {
- public void start() {
- final int status = mOffloadController.start() ? TETHER_HARDWARE_OFFLOAD_STARTED
- : TETHER_HARDWARE_OFFLOAD_FAILED;
- updateOffloadStatus(status);
- sendOffloadExemptPrefixes();
- }
-
- public void stop() {
- mOffloadController.stop();
- updateOffloadStatus(TETHER_HARDWARE_OFFLOAD_STOPPED);
- }
-
- public void updateUpstreamNetworkState(UpstreamNetworkState ns) {
- mOffloadController.setUpstreamLinkProperties(
- (ns != null) ? ns.linkProperties : null);
- }
-
- public void updateDownstreamLinkProperties(LinkProperties newLp) {
- // Update the list of offload-exempt prefixes before adding
- // new prefixes on downstream interfaces to the offload HAL.
- sendOffloadExemptPrefixes();
- mOffloadController.notifyDownstreamLinkProperties(newLp);
- }
-
- public void excludeDownstreamInterface(String ifname) {
- // This and other interfaces may be in local-only hotspot mode;
- // resend all local prefixes to the OffloadController.
- sendOffloadExemptPrefixes();
- mOffloadController.removeDownstreamInterface(ifname);
- }
-
- public void sendOffloadExemptPrefixes() {
- sendOffloadExemptPrefixes(mUpstreamNetworkMonitor.getLocalPrefixes());
- }
-
- public void sendOffloadExemptPrefixes(final Set<IpPrefix> localPrefixes) {
- // Add in well-known minimum set.
- PrefixUtils.addNonForwardablePrefixes(localPrefixes);
- // Add tragically hardcoded prefixes.
- localPrefixes.add(PrefixUtils.DEFAULT_WIFI_P2P_PREFIX);
-
- // Maybe add prefixes or addresses for downstreams, depending on
- // the IP serving mode of each.
- for (IpServer ipServer : mNotifyList) {
- final LinkProperties lp = ipServer.linkProperties();
-
- switch (ipServer.servingMode()) {
- case IpServer.STATE_UNAVAILABLE:
- case IpServer.STATE_AVAILABLE:
- // No usable LinkProperties in these states.
- continue;
- case IpServer.STATE_TETHERED:
- // Only add IPv4 /32 and IPv6 /128 prefixes. The
- // directly-connected prefixes will be sent as
- // downstream "offload-able" prefixes.
- for (LinkAddress addr : lp.getAllLinkAddresses()) {
- final InetAddress ip = addr.getAddress();
- if (ip.isLinkLocalAddress()) continue;
- localPrefixes.add(PrefixUtils.ipAddressAsPrefix(ip));
- }
- break;
- case IpServer.STATE_LOCAL_ONLY:
- // Add prefixes covering all local IPs.
- localPrefixes.addAll(PrefixUtils.localPrefixesFrom(lp));
- break;
- }
- }
-
- mOffloadController.setLocalPrefixes(localPrefixes);
- }
-
- private void updateOffloadStatus(final int newStatus) {
- if (newStatus == mOffloadStatus) return;
-
- mOffloadStatus = newStatus;
- reportOffloadStatusChanged(mOffloadStatus);
- }
- }
- }
-
- private void startTrackDefaultNetwork() {
- mUpstreamNetworkMonitor.startTrackDefaultNetwork(mDeps.getDefaultNetworkRequest(),
- mEntitlementMgr);
- }
-
- /** Get the latest value of the tethering entitlement check. */
- void requestLatestTetheringEntitlementResult(int type, ResultReceiver receiver,
- boolean showEntitlementUi) {
- if (receiver == null) return;
-
- mHandler.post(() -> {
- mEntitlementMgr.requestLatestTetheringEntitlementResult(type, receiver,
- showEntitlementUi);
- });
- }
-
- /** Register tethering event callback */
- void registerTetheringEventCallback(ITetheringEventCallback callback) {
- final boolean hasListPermission =
- hasCallingPermission(NETWORK_SETTINGS)
- || hasCallingPermission(PERMISSION_MAINLINE_NETWORK_STACK)
- || hasCallingPermission(NETWORK_STACK);
- mHandler.post(() -> {
- mTetheringEventCallbacks.register(callback, new CallbackCookie(hasListPermission));
- final TetheringCallbackStartedParcel parcel = new TetheringCallbackStartedParcel();
- parcel.tetheringSupported = isTetheringSupported();
- parcel.upstreamNetwork = mTetherUpstream;
- parcel.config = mConfig.toStableParcelable();
- parcel.states =
- mTetherStatesParcel != null ? mTetherStatesParcel : emptyTetherStatesParcel();
- parcel.tetheredClients = hasListPermission
- ? mConnectedClientsTracker.getLastTetheredClients()
- : Collections.emptyList();
- parcel.offloadStatus = mOffloadStatus;
- try {
- callback.onCallbackStarted(parcel);
- } catch (RemoteException e) {
- // Not really very much to do here.
- }
- });
- }
-
- private TetherStatesParcel emptyTetherStatesParcel() {
- final TetherStatesParcel parcel = new TetherStatesParcel();
- parcel.availableList = new String[0];
- parcel.tetheredList = new String[0];
- parcel.localOnlyList = new String[0];
- parcel.erroredIfaceList = new String[0];
- parcel.lastErrorList = new int[0];
-
- return parcel;
- }
-
- private boolean hasCallingPermission(@NonNull String permission) {
- return mContext.checkCallingOrSelfPermission(permission) == PERMISSION_GRANTED;
- }
-
- /** Unregister tethering event callback */
- void unregisterTetheringEventCallback(ITetheringEventCallback callback) {
- mHandler.post(() -> {
- mTetheringEventCallbacks.unregister(callback);
- });
- }
-
- private void reportUpstreamChanged(UpstreamNetworkState ns) {
- final int length = mTetheringEventCallbacks.beginBroadcast();
- final Network network = (ns != null) ? ns.network : null;
- final NetworkCapabilities capabilities = (ns != null) ? ns.networkCapabilities : null;
- try {
- for (int i = 0; i < length; i++) {
- try {
- mTetheringEventCallbacks.getBroadcastItem(i).onUpstreamChanged(network);
- } catch (RemoteException e) {
- // Not really very much to do here.
- }
- }
- } finally {
- mTetheringEventCallbacks.finishBroadcast();
- }
- // Need to notify capabilities change after upstream network changed because new network's
- // capabilities should be checked every time.
- mNotificationUpdater.onUpstreamCapabilitiesChanged(capabilities);
- }
-
- private void reportConfigurationChanged(TetheringConfigurationParcel config) {
- final int length = mTetheringEventCallbacks.beginBroadcast();
- try {
- for (int i = 0; i < length; i++) {
- try {
- mTetheringEventCallbacks.getBroadcastItem(i).onConfigurationChanged(config);
- // TODO(b/148139325): send tetheringSupported on configuration change
- } catch (RemoteException e) {
- // Not really very much to do here.
- }
- }
- } finally {
- mTetheringEventCallbacks.finishBroadcast();
- }
- }
-
- private void reportTetherStateChanged(TetherStatesParcel states) {
- final int length = mTetheringEventCallbacks.beginBroadcast();
- try {
- for (int i = 0; i < length; i++) {
- try {
- mTetheringEventCallbacks.getBroadcastItem(i).onTetherStatesChanged(states);
- } catch (RemoteException e) {
- // Not really very much to do here.
- }
- }
- } finally {
- mTetheringEventCallbacks.finishBroadcast();
- }
- }
-
- private void reportTetherClientsChanged(List<TetheredClient> clients) {
- final int length = mTetheringEventCallbacks.beginBroadcast();
- try {
- for (int i = 0; i < length; i++) {
- try {
- final CallbackCookie cookie =
- (CallbackCookie) mTetheringEventCallbacks.getBroadcastCookie(i);
- if (!cookie.hasListClientsPermission) continue;
- mTetheringEventCallbacks.getBroadcastItem(i).onTetherClientsChanged(clients);
- } catch (RemoteException e) {
- // Not really very much to do here.
- }
- }
- } finally {
- mTetheringEventCallbacks.finishBroadcast();
- }
- }
-
- private void reportOffloadStatusChanged(final int status) {
- final int length = mTetheringEventCallbacks.beginBroadcast();
- try {
- for (int i = 0; i < length; i++) {
- try {
- mTetheringEventCallbacks.getBroadcastItem(i).onOffloadStatusChanged(status);
- } catch (RemoteException e) {
- // Not really very much to do here.
- }
- }
- } finally {
- mTetheringEventCallbacks.finishBroadcast();
- }
- }
-
- // if ro.tether.denied = true we default to no tethering
- // gservices could set the secure setting to 1 though to enable it on a build where it
- // had previously been turned off.
- boolean isTetheringSupported() {
- final int defaultVal = mDeps.isTetheringDenied() ? 0 : 1;
- final boolean tetherSupported = Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.TETHER_SUPPORTED, defaultVal) != 0;
- final boolean tetherEnabledInSettings = tetherSupported
- && !mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING);
-
- return tetherEnabledInSettings && hasTetherableConfiguration()
- && !isProvisioningNeededButUnavailable();
- }
-
- void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter writer, @Nullable String[] args) {
- // Binder.java closes the resource for us.
- @SuppressWarnings("resource")
- final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
- if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
- != PERMISSION_GRANTED) {
- pw.println("Permission Denial: can't dump.");
- return;
- }
-
- pw.println("Tethering:");
- pw.increaseIndent();
-
- pw.println("Configuration:");
- pw.increaseIndent();
- final TetheringConfiguration cfg = mConfig;
- cfg.dump(pw);
- pw.decreaseIndent();
-
- pw.println("Entitlement:");
- pw.increaseIndent();
- mEntitlementMgr.dump(pw);
- pw.decreaseIndent();
-
- synchronized (mPublicSync) {
- pw.println("Tether state:");
- pw.increaseIndent();
- for (int i = 0; i < mTetherStates.size(); i++) {
- final String iface = mTetherStates.keyAt(i);
- final TetherState tetherState = mTetherStates.valueAt(i);
- pw.print(iface + " - ");
-
- switch (tetherState.lastState) {
- case IpServer.STATE_UNAVAILABLE:
- pw.print("UnavailableState");
- break;
- case IpServer.STATE_AVAILABLE:
- pw.print("AvailableState");
- break;
- case IpServer.STATE_TETHERED:
- pw.print("TetheredState");
- break;
- case IpServer.STATE_LOCAL_ONLY:
- pw.print("LocalHotspotState");
- break;
- default:
- pw.print("UnknownState");
- break;
- }
- pw.println(" - lastError = " + tetherState.lastError);
- }
- pw.println("Upstream wanted: " + upstreamWanted());
- pw.println("Current upstream interface(s): " + mCurrentUpstreamIfaceSet);
- pw.decreaseIndent();
- }
-
- pw.println("Hardware offload:");
- pw.increaseIndent();
- mOffloadController.dump(pw);
- pw.decreaseIndent();
-
- pw.println("BPF offload:");
- pw.increaseIndent();
- mBpfCoordinator.dump(pw);
- pw.decreaseIndent();
-
- pw.println("Private address coordinator:");
- pw.increaseIndent();
- mPrivateAddressCoordinator.dump(pw);
- pw.decreaseIndent();
-
- pw.println("Log:");
- pw.increaseIndent();
- if (argsContain(args, "--short")) {
- pw.println("<log removed for brevity>");
- } else {
- mLog.dump(fd, pw, args);
- }
- pw.decreaseIndent();
-
- pw.decreaseIndent();
- }
-
- private static boolean argsContain(String[] args, String target) {
- for (String arg : args) {
- if (target.equals(arg)) return true;
- }
- return false;
- }
-
- private void updateConnectedClients(final List<WifiClient> wifiClients) {
- if (mConnectedClientsTracker.updateConnectedClients(mForwardedDownstreams, wifiClients)) {
- reportTetherClientsChanged(mConnectedClientsTracker.getLastTetheredClients());
- }
- }
-
- private IpServer.Callback makeControlCallback() {
- return new IpServer.Callback() {
- @Override
- public void updateInterfaceState(IpServer who, int state, int lastError) {
- notifyInterfaceStateChange(who, state, lastError);
- }
-
- @Override
- public void updateLinkProperties(IpServer who, LinkProperties newLp) {
- notifyLinkPropertiesChanged(who, newLp);
- }
-
- @Override
- public void dhcpLeasesChanged() {
- updateConnectedClients(null /* wifiClients */);
- }
-
- @Override
- public void requestEnableTethering(int tetheringType, boolean enabled) {
- enableTetheringInternal(tetheringType, enabled, null);
- }
- };
- }
-
- // TODO: Move into TetherMainSM.
- private void notifyInterfaceStateChange(IpServer who, int state, int error) {
- final String iface = who.interfaceName();
- synchronized (mPublicSync) {
- final TetherState tetherState = mTetherStates.get(iface);
- if (tetherState != null && tetherState.ipServer.equals(who)) {
- tetherState.lastState = state;
- tetherState.lastError = error;
- } else {
- if (DBG) Log.d(TAG, "got notification from stale iface " + iface);
- }
- }
-
- mLog.log(String.format("OBSERVED iface=%s state=%s error=%s", iface, state, error));
-
- // If TetherMainSM is in ErrorState, TetherMainSM stays there.
- // Thus we give a chance for TetherMainSM to recover to InitialState
- // by sending CMD_CLEAR_ERROR
- if (error == TETHER_ERROR_INTERNAL_ERROR) {
- mTetherMainSM.sendMessage(TetherMainSM.CMD_CLEAR_ERROR, who);
- }
- int which;
- switch (state) {
- case IpServer.STATE_UNAVAILABLE:
- case IpServer.STATE_AVAILABLE:
- which = TetherMainSM.EVENT_IFACE_SERVING_STATE_INACTIVE;
- break;
- case IpServer.STATE_TETHERED:
- case IpServer.STATE_LOCAL_ONLY:
- which = TetherMainSM.EVENT_IFACE_SERVING_STATE_ACTIVE;
- break;
- default:
- Log.wtf(TAG, "Unknown interface state: " + state);
- return;
- }
- mTetherMainSM.sendMessage(which, state, 0, who);
- sendTetherStateChangedBroadcast();
- }
-
- private void notifyLinkPropertiesChanged(IpServer who, LinkProperties newLp) {
- final String iface = who.interfaceName();
- final int state;
- synchronized (mPublicSync) {
- final TetherState tetherState = mTetherStates.get(iface);
- if (tetherState != null && tetherState.ipServer.equals(who)) {
- state = tetherState.lastState;
- } else {
- mLog.log("got notification from stale iface " + iface);
- return;
- }
- }
-
- mLog.log(String.format(
- "OBSERVED LinkProperties update iface=%s state=%s lp=%s",
- iface, IpServer.getStateString(state), newLp));
- final int which = TetherMainSM.EVENT_IFACE_UPDATE_LINKPROPERTIES;
- mTetherMainSM.sendMessage(which, state, 0, newLp);
- }
-
- private void maybeTrackNewInterfaceLocked(final String iface) {
- // If we don't care about this type of interface, ignore.
- final int interfaceType = ifaceNameToType(iface);
- if (interfaceType == TETHERING_INVALID) {
- mLog.log(iface + " is not a tetherable iface, ignoring");
- return;
- }
- maybeTrackNewInterfaceLocked(iface, interfaceType);
- }
-
- private void maybeTrackNewInterfaceLocked(final String iface, int interfaceType) {
- // If we have already started a TISM for this interface, skip.
- if (mTetherStates.containsKey(iface)) {
- mLog.log("active iface (" + iface + ") reported as added, ignoring");
- return;
- }
-
- mLog.log("adding TetheringInterfaceStateMachine for: " + iface);
- final TetherState tetherState = new TetherState(
- new IpServer(iface, mLooper, interfaceType, mLog, mNetd, mBpfCoordinator,
- makeControlCallback(), mConfig.enableLegacyDhcpServer,
- mConfig.isBpfOffloadEnabled(), mPrivateAddressCoordinator,
- mDeps.getIpServerDependencies()));
- mTetherStates.put(iface, tetherState);
- tetherState.ipServer.start();
- }
-
- private void stopTrackingInterfaceLocked(final String iface) {
- final TetherState tetherState = mTetherStates.get(iface);
- if (tetherState == null) {
- mLog.log("attempting to remove unknown iface (" + iface + "), ignoring");
- return;
- }
- tetherState.ipServer.stop();
- mLog.log("removing TetheringInterfaceStateMachine for: " + iface);
- mTetherStates.remove(iface);
- }
-
- private static String[] copy(String[] strarray) {
- return Arrays.copyOf(strarray, strarray.length);
- }
-}
diff --git a/packages/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java b/packages/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java
deleted file mode 100644
index 799637c..0000000
--- a/packages/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java
+++ /dev/null
@@ -1,521 +0,0 @@
-/*
- * Copyright (C) 2017 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;
-
-import static android.content.Context.TELEPHONY_SERVICE;
-import static android.net.ConnectivityManager.TYPE_ETHERNET;
-import static android.net.ConnectivityManager.TYPE_MOBILE;
-import static android.net.ConnectivityManager.TYPE_MOBILE_DUN;
-import static android.net.ConnectivityManager.TYPE_MOBILE_HIPRI;
-import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.net.TetheringConfigurationParcel;
-import android.net.util.SharedLog;
-import android.provider.DeviceConfig;
-import android.telephony.SubscriptionManager;
-import android.telephony.TelephonyManager;
-import android.text.TextUtils;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.StringJoiner;
-
-/**
- * A utility class to encapsulate the various tethering configuration elements.
- *
- * This configuration data includes elements describing upstream properties
- * (preferred and required types of upstream connectivity as well as default
- * DNS servers to use if none are available) and downstream properties (such
- * as regular expressions use to match suitable downstream interfaces and the
- * DHCPv4 ranges to use).
- *
- * @hide
- */
-public class TetheringConfiguration {
- private static final String TAG = TetheringConfiguration.class.getSimpleName();
-
- private static final String[] EMPTY_STRING_ARRAY = new String[0];
-
- // Default ranges used for the legacy DHCP server.
- // USB is 192.168.42.1 and 255.255.255.0
- // Wifi is 192.168.43.1 and 255.255.255.0
- // BT is limited to max default of 5 connections. 192.168.44.1 to 192.168.48.1
- // with 255.255.255.0
- // P2P is 192.168.49.1 and 255.255.255.0
- private static final String[] LEGACY_DHCP_DEFAULT_RANGE = {
- "192.168.42.2", "192.168.42.254", "192.168.43.2", "192.168.43.254",
- "192.168.44.2", "192.168.44.254", "192.168.45.2", "192.168.45.254",
- "192.168.46.2", "192.168.46.254", "192.168.47.2", "192.168.47.254",
- "192.168.48.2", "192.168.48.254", "192.168.49.2", "192.168.49.254",
- };
-
- private static final String[] DEFAULT_IPV4_DNS = {"8.8.4.4", "8.8.8.8"};
-
- /**
- * Override enabling BPF offload configuration for tethering.
- */
- public static final String OVERRIDE_TETHER_ENABLE_BPF_OFFLOAD =
- "override_tether_enable_bpf_offload";
-
- /**
- * Use the old dnsmasq DHCP server for tethering instead of the framework implementation.
- */
- public static final String TETHER_ENABLE_LEGACY_DHCP_SERVER =
- "tether_enable_legacy_dhcp_server";
-
- public static final String USE_LEGACY_WIFI_P2P_DEDICATED_IP =
- "use_legacy_wifi_p2p_dedicated_ip";
-
- /**
- * Flag use to enable select all prefix ranges feature.
- * TODO: Remove this flag if there are no problems after M-2020-12 rolls out.
- */
- public static final String TETHER_ENABLE_SELECT_ALL_PREFIX_RANGES =
- "tether_enable_select_all_prefix_ranges";
-
- /**
- * Default value that used to periodic polls tether offload stats from tethering offload HAL
- * to make the data warnings work.
- */
- public static final int DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS = 5000;
-
- public final String[] tetherableUsbRegexs;
- public final String[] tetherableWifiRegexs;
- public final String[] tetherableWigigRegexs;
- public final String[] tetherableWifiP2pRegexs;
- public final String[] tetherableBluetoothRegexs;
- public final String[] tetherableNcmRegexs;
- public final boolean isDunRequired;
- public final boolean chooseUpstreamAutomatically;
- public final Collection<Integer> preferredUpstreamIfaceTypes;
- public final String[] legacyDhcpRanges;
- public final String[] defaultIPv4DNS;
- public final boolean enableLegacyDhcpServer;
-
- public final String[] provisioningApp;
- public final String provisioningAppNoUi;
- public final int provisioningCheckPeriod;
- public final String provisioningResponse;
-
- public final int activeDataSubId;
-
- private final int mOffloadPollInterval;
- // TODO: Add to TetheringConfigurationParcel if required.
- private final boolean mEnableBpfOffload;
- private final boolean mEnableWifiP2pDedicatedIp;
-
- private final boolean mEnableSelectAllPrefixRange;
-
- public TetheringConfiguration(Context ctx, SharedLog log, int id) {
- final SharedLog configLog = log.forSubComponent("config");
-
- activeDataSubId = id;
- Resources res = getResources(ctx, activeDataSubId);
-
- tetherableUsbRegexs = getResourceStringArray(res, R.array.config_tether_usb_regexs);
- tetherableNcmRegexs = getResourceStringArray(res, R.array.config_tether_ncm_regexs);
- // TODO: Evaluate deleting this altogether now that Wi-Fi always passes
- // us an interface name. Careful consideration needs to be given to
- // implications for Settings and for provisioning checks.
- tetherableWifiRegexs = getResourceStringArray(res, R.array.config_tether_wifi_regexs);
- tetherableWigigRegexs = getResourceStringArray(res, R.array.config_tether_wigig_regexs);
- tetherableWifiP2pRegexs = getResourceStringArray(
- res, R.array.config_tether_wifi_p2p_regexs);
- tetherableBluetoothRegexs = getResourceStringArray(
- res, R.array.config_tether_bluetooth_regexs);
-
- isDunRequired = checkDunRequired(ctx);
-
- chooseUpstreamAutomatically = getResourceBoolean(
- res, R.bool.config_tether_upstream_automatic, false /** defaultValue */);
- preferredUpstreamIfaceTypes = getUpstreamIfaceTypes(res, isDunRequired);
-
- legacyDhcpRanges = getLegacyDhcpRanges(res);
- defaultIPv4DNS = copy(DEFAULT_IPV4_DNS);
- mEnableBpfOffload = getEnableBpfOffload(res);
- enableLegacyDhcpServer = getEnableLegacyDhcpServer(res);
-
- provisioningApp = getResourceStringArray(res, R.array.config_mobile_hotspot_provision_app);
- provisioningAppNoUi = getResourceString(res,
- R.string.config_mobile_hotspot_provision_app_no_ui);
- provisioningCheckPeriod = getResourceInteger(res,
- R.integer.config_mobile_hotspot_provision_check_period,
- 0 /* No periodic re-check */);
- provisioningResponse = getResourceString(res,
- R.string.config_mobile_hotspot_provision_response);
-
- mOffloadPollInterval = getResourceInteger(res,
- R.integer.config_tether_offload_poll_interval,
- DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS);
-
- mEnableWifiP2pDedicatedIp = getResourceBoolean(res,
- R.bool.config_tether_enable_legacy_wifi_p2p_dedicated_ip,
- false /* defaultValue */);
-
- // Flags should normally not be booleans, but this is a kill-switch flag that is only used
- // to turn off the feature, so binary rollback problems do not apply.
- mEnableSelectAllPrefixRange = getDeviceConfigBoolean(
- TETHER_ENABLE_SELECT_ALL_PREFIX_RANGES, true /* defaultValue */);
-
- configLog.log(toString());
- }
-
- /** Check whether input interface belong to usb.*/
- public boolean isUsb(String iface) {
- return matchesDownstreamRegexs(iface, tetherableUsbRegexs);
- }
-
- /** Check whether input interface belong to wifi.*/
- public boolean isWifi(String iface) {
- return matchesDownstreamRegexs(iface, tetherableWifiRegexs);
- }
-
- /** Check whether input interface belong to wigig.*/
- public boolean isWigig(String iface) {
- return matchesDownstreamRegexs(iface, tetherableWigigRegexs);
- }
-
- /** Check whether this interface is Wifi P2P interface. */
- public boolean isWifiP2p(String iface) {
- return matchesDownstreamRegexs(iface, tetherableWifiP2pRegexs);
- }
-
- /** Check whether using legacy mode for wifi P2P. */
- public boolean isWifiP2pLegacyTetheringMode() {
- return (tetherableWifiP2pRegexs == null || tetherableWifiP2pRegexs.length == 0);
- }
-
- /** Check whether input interface belong to bluetooth.*/
- public boolean isBluetooth(String iface) {
- return matchesDownstreamRegexs(iface, tetherableBluetoothRegexs);
- }
-
- /** Check if interface is ncm */
- public boolean isNcm(String iface) {
- return matchesDownstreamRegexs(iface, tetherableNcmRegexs);
- }
-
- /** Check whether no ui entitlement application is available.*/
- public boolean hasMobileHotspotProvisionApp() {
- return !TextUtils.isEmpty(provisioningAppNoUi);
- }
-
- /** Check whether dedicated wifi p2p address is enabled. */
- public boolean shouldEnableWifiP2pDedicatedIp() {
- return mEnableWifiP2pDedicatedIp;
- }
-
- /** Does the dumping.*/
- public void dump(PrintWriter pw) {
- pw.print("activeDataSubId: ");
- pw.println(activeDataSubId);
-
- dumpStringArray(pw, "tetherableUsbRegexs", tetherableUsbRegexs);
- dumpStringArray(pw, "tetherableWifiRegexs", tetherableWifiRegexs);
- dumpStringArray(pw, "tetherableWifiP2pRegexs", tetherableWifiP2pRegexs);
- dumpStringArray(pw, "tetherableBluetoothRegexs", tetherableBluetoothRegexs);
- dumpStringArray(pw, "tetherableNcmRegexs", tetherableNcmRegexs);
-
- pw.print("isDunRequired: ");
- pw.println(isDunRequired);
-
- pw.print("chooseUpstreamAutomatically: ");
- pw.println(chooseUpstreamAutomatically);
- pw.print("legacyPreredUpstreamIfaceTypes: ");
- pw.println(Arrays.toString(toIntArray(preferredUpstreamIfaceTypes)));
-
- dumpStringArray(pw, "legacyDhcpRanges", legacyDhcpRanges);
- dumpStringArray(pw, "defaultIPv4DNS", defaultIPv4DNS);
-
- pw.print("offloadPollInterval: ");
- pw.println(mOffloadPollInterval);
-
- dumpStringArray(pw, "provisioningApp", provisioningApp);
- pw.print("provisioningAppNoUi: ");
- pw.println(provisioningAppNoUi);
-
- pw.print("enableBpfOffload: ");
- pw.println(mEnableBpfOffload);
-
- pw.print("enableLegacyDhcpServer: ");
- pw.println(enableLegacyDhcpServer);
-
- pw.print("enableWifiP2pDedicatedIp: ");
- pw.println(mEnableWifiP2pDedicatedIp);
-
- pw.print("mEnableSelectAllPrefixRange: ");
- pw.println(mEnableSelectAllPrefixRange);
- }
-
- /** Returns the string representation of this object.*/
- public String toString() {
- final StringJoiner sj = new StringJoiner(" ");
- sj.add(String.format("activeDataSubId:%d", activeDataSubId));
- sj.add(String.format("tetherableUsbRegexs:%s", makeString(tetherableUsbRegexs)));
- sj.add(String.format("tetherableWifiRegexs:%s", makeString(tetherableWifiRegexs)));
- sj.add(String.format("tetherableWifiP2pRegexs:%s", makeString(tetherableWifiP2pRegexs)));
- sj.add(String.format("tetherableBluetoothRegexs:%s",
- makeString(tetherableBluetoothRegexs)));
- sj.add(String.format("isDunRequired:%s", isDunRequired));
- sj.add(String.format("chooseUpstreamAutomatically:%s", chooseUpstreamAutomatically));
- sj.add(String.format("offloadPollInterval:%d", mOffloadPollInterval));
- sj.add(String.format("preferredUpstreamIfaceTypes:%s",
- toIntArray(preferredUpstreamIfaceTypes)));
- sj.add(String.format("provisioningApp:%s", makeString(provisioningApp)));
- sj.add(String.format("provisioningAppNoUi:%s", provisioningAppNoUi));
- sj.add(String.format("enableBpfOffload:%s", mEnableBpfOffload));
- sj.add(String.format("enableLegacyDhcpServer:%s", enableLegacyDhcpServer));
- return String.format("TetheringConfiguration{%s}", sj.toString());
- }
-
- private static void dumpStringArray(PrintWriter pw, String label, String[] values) {
- pw.print(label);
- pw.print(": ");
-
- if (values != null) {
- final StringJoiner sj = new StringJoiner(", ", "[", "]");
- for (String value : values) sj.add(value);
- pw.print(sj.toString());
- } else {
- pw.print("null");
- }
-
- pw.println();
- }
-
- private static String makeString(String[] strings) {
- if (strings == null) return "null";
- final StringJoiner sj = new StringJoiner(",", "[", "]");
- for (String s : strings) sj.add(s);
- return sj.toString();
- }
-
- /** Check whether dun is required. */
- public static boolean checkDunRequired(Context ctx) {
- final TelephonyManager tm = (TelephonyManager) ctx.getSystemService(TELEPHONY_SERVICE);
- // TelephonyManager would uses the active data subscription, which should be the one used
- // by tethering.
- return (tm != null) ? tm.isTetheringApnRequired() : false;
- }
-
- public int getOffloadPollInterval() {
- return mOffloadPollInterval;
- }
-
- public boolean isBpfOffloadEnabled() {
- return mEnableBpfOffload;
- }
-
- public boolean isSelectAllPrefixRangeEnabled() {
- return mEnableSelectAllPrefixRange;
- }
-
- private static Collection<Integer> getUpstreamIfaceTypes(Resources res, boolean dunRequired) {
- final int[] ifaceTypes = res.getIntArray(R.array.config_tether_upstream_types);
- final ArrayList<Integer> upstreamIfaceTypes = new ArrayList<>(ifaceTypes.length);
- for (int i : ifaceTypes) {
- switch (i) {
- case TYPE_MOBILE:
- case TYPE_MOBILE_HIPRI:
- if (dunRequired) continue;
- break;
- case TYPE_MOBILE_DUN:
- if (!dunRequired) continue;
- break;
- }
- upstreamIfaceTypes.add(i);
- }
-
- // Fix up upstream interface types for DUN or mobile. NOTE: independent
- // of the value of |dunRequired|, cell data of one form or another is
- // *always* an upstream, regardless of the upstream interface types
- // specified by configuration resources.
- if (dunRequired) {
- appendIfNotPresent(upstreamIfaceTypes, TYPE_MOBILE_DUN);
- } else {
- // Do not modify if a cellular interface type is already present in the
- // upstream interface types. Add TYPE_MOBILE and TYPE_MOBILE_HIPRI if no
- // cellular interface types are found in the upstream interface types.
- // This preserves backwards compatibility and prevents the DUN and default
- // mobile types incorrectly appearing together, which could happen on
- // previous releases in the common case where checkDunRequired returned
- // DUN_UNSPECIFIED.
- if (!containsOneOf(upstreamIfaceTypes, TYPE_MOBILE, TYPE_MOBILE_HIPRI)) {
- upstreamIfaceTypes.add(TYPE_MOBILE);
- upstreamIfaceTypes.add(TYPE_MOBILE_HIPRI);
- }
- }
-
- // Always make sure our good friend Ethernet is present.
- // TODO: consider unilaterally forcing this at the front.
- prependIfNotPresent(upstreamIfaceTypes, TYPE_ETHERNET);
-
- return upstreamIfaceTypes;
- }
-
- private static boolean matchesDownstreamRegexs(String iface, String[] regexs) {
- for (String regex : regexs) {
- if (iface.matches(regex)) return true;
- }
- return false;
- }
-
- private static String[] getLegacyDhcpRanges(Resources res) {
- final String[] fromResource = getResourceStringArray(res, R.array.config_tether_dhcp_range);
- if ((fromResource.length > 0) && (fromResource.length % 2 == 0)) {
- return fromResource;
- }
- return copy(LEGACY_DHCP_DEFAULT_RANGE);
- }
-
- private static String getResourceString(Resources res, final int resId) {
- try {
- return res.getString(resId);
- } catch (Resources.NotFoundException e) {
- return "";
- }
- }
-
- private static boolean getResourceBoolean(Resources res, int resId, boolean defaultValue) {
- try {
- return res.getBoolean(resId);
- } catch (Resources.NotFoundException e404) {
- return defaultValue;
- }
- }
-
- private static String[] getResourceStringArray(Resources res, int resId) {
- try {
- final String[] strArray = res.getStringArray(resId);
- return (strArray != null) ? strArray : EMPTY_STRING_ARRAY;
- } catch (Resources.NotFoundException e404) {
- return EMPTY_STRING_ARRAY;
- }
- }
-
- private static int getResourceInteger(Resources res, int resId, int defaultValue) {
- try {
- return res.getInteger(resId);
- } catch (Resources.NotFoundException e404) {
- return defaultValue;
- }
- }
-
- private boolean getEnableBpfOffload(final Resources res) {
- // Get BPF offload config
- // Priority 1: Device config
- // Priority 2: Resource config
- // Priority 3: Default value
- final boolean defaultValue = getResourceBoolean(
- res, R.bool.config_tether_enable_bpf_offload, true /** default value */);
-
- return getDeviceConfigBoolean(OVERRIDE_TETHER_ENABLE_BPF_OFFLOAD, defaultValue);
- }
-
- private boolean getEnableLegacyDhcpServer(final Resources res) {
- return getResourceBoolean(
- res, R.bool.config_tether_enable_legacy_dhcp_server, false /** defaultValue */)
- || getDeviceConfigBoolean(
- TETHER_ENABLE_LEGACY_DHCP_SERVER, false /** defaultValue */);
- }
-
- private boolean getDeviceConfigBoolean(final String name, final boolean defaultValue) {
- // Due to the limitation of static mock for testing, using #getDeviceConfigProperty instead
- // of DeviceConfig#getBoolean. If using #getBoolean here, the test can't know that the
- // returned boolean value comes from device config or default value (because of null
- // property string). See the test case testBpfOffload{*} in TetheringConfigurationTest.java.
- final String value = getDeviceConfigProperty(name);
- return value != null ? Boolean.parseBoolean(value) : defaultValue;
- }
-
- @VisibleForTesting
- protected String getDeviceConfigProperty(String name) {
- return DeviceConfig.getProperty(NAMESPACE_CONNECTIVITY, name);
- }
-
- private Resources getResources(Context ctx, int subId) {
- if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
- return getResourcesForSubIdWrapper(ctx, subId);
- } else {
- return ctx.getResources();
- }
- }
-
- @VisibleForTesting
- protected Resources getResourcesForSubIdWrapper(Context ctx, int subId) {
- return SubscriptionManager.getResourcesForSubId(ctx, subId);
- }
-
- private static String[] copy(String[] strarray) {
- return Arrays.copyOf(strarray, strarray.length);
- }
-
- private static void prependIfNotPresent(ArrayList<Integer> list, int value) {
- if (list.contains(value)) return;
- list.add(0, value);
- }
-
- private static void appendIfNotPresent(ArrayList<Integer> list, int value) {
- if (list.contains(value)) return;
- list.add(value);
- }
-
- private static boolean containsOneOf(ArrayList<Integer> list, Integer... values) {
- for (Integer value : values) {
- if (list.contains(value)) return true;
- }
- return false;
- }
-
- private static int[] toIntArray(Collection<Integer> values) {
- final int[] result = new int[values.size()];
- int index = 0;
- for (Integer value : values) {
- result[index++] = value;
- }
- return result;
- }
-
- /**
- * Convert this TetheringConfiguration to a TetheringConfigurationParcel.
- */
- public TetheringConfigurationParcel toStableParcelable() {
- final TetheringConfigurationParcel parcel = new TetheringConfigurationParcel();
- parcel.subId = activeDataSubId;
- parcel.tetherableUsbRegexs = tetherableUsbRegexs;
- parcel.tetherableWifiRegexs = tetherableWifiRegexs;
- parcel.tetherableBluetoothRegexs = tetherableBluetoothRegexs;
- parcel.isDunRequired = isDunRequired;
- parcel.chooseUpstreamAutomatically = chooseUpstreamAutomatically;
-
- parcel.preferredUpstreamIfaceTypes = toIntArray(preferredUpstreamIfaceTypes);
-
- parcel.legacyDhcpRanges = legacyDhcpRanges;
- parcel.defaultIPv4DNS = defaultIPv4DNS;
- parcel.enableLegacyDhcpServer = enableLegacyDhcpServer;
- parcel.provisioningApp = provisioningApp;
- parcel.provisioningAppNoUi = provisioningAppNoUi;
- parcel.provisioningCheckPeriod = provisioningCheckPeriod;
- return parcel;
- }
-}
diff --git a/packages/Tethering/src/com/android/networkstack/tethering/TetheringDependencies.java b/packages/Tethering/src/com/android/networkstack/tethering/TetheringDependencies.java
deleted file mode 100644
index 45b9141..0000000
--- a/packages/Tethering/src/com/android/networkstack/tethering/TetheringDependencies.java
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Copyright (C) 2017 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;
-
-import android.app.usage.NetworkStatsManager;
-import android.bluetooth.BluetoothAdapter;
-import android.content.Context;
-import android.net.INetd;
-import android.net.NetworkRequest;
-import android.net.ip.IpServer;
-import android.net.util.SharedLog;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.SystemProperties;
-import android.text.TextUtils;
-
-import androidx.annotation.NonNull;
-
-import com.android.internal.util.StateMachine;
-
-import java.util.ArrayList;
-
-
-/**
- * Capture tethering dependencies, for injection.
- *
- * @hide
- */
-public abstract class TetheringDependencies {
- /**
- * Get a reference to the BpfCoordinator to be used by tethering.
- */
- public @NonNull BpfCoordinator getBpfCoordinator(
- @NonNull BpfCoordinator.Dependencies deps) {
- return new BpfCoordinator(deps);
- }
-
- /**
- * Get a reference to the offload hardware interface to be used by tethering.
- */
- public OffloadHardwareInterface getOffloadHardwareInterface(Handler h, SharedLog log) {
- return new OffloadHardwareInterface(h, log);
- }
-
- /**
- * Get a reference to the offload controller to be used by tethering.
- */
- @NonNull
- public OffloadController getOffloadController(@NonNull Handler h,
- @NonNull SharedLog log, @NonNull OffloadController.Dependencies deps) {
- final NetworkStatsManager statsManager =
- (NetworkStatsManager) getContext().getSystemService(Context.NETWORK_STATS_SERVICE);
- return new OffloadController(h, getOffloadHardwareInterface(h, log),
- getContext().getContentResolver(), statsManager, log, deps);
- }
-
-
- /**
- * Get a reference to the UpstreamNetworkMonitor to be used by tethering.
- */
- public UpstreamNetworkMonitor getUpstreamNetworkMonitor(Context ctx, StateMachine target,
- SharedLog log, int what) {
- return new UpstreamNetworkMonitor(ctx, target, log, what);
- }
-
- /**
- * Get a reference to the IPv6TetheringCoordinator to be used by tethering.
- */
- public IPv6TetheringCoordinator getIPv6TetheringCoordinator(
- ArrayList<IpServer> notifyList, SharedLog log) {
- return new IPv6TetheringCoordinator(notifyList, log);
- }
-
- /**
- * Get dependencies to be used by IpServer.
- */
- public abstract IpServer.Dependencies getIpServerDependencies();
-
- /**
- * Indicates whether tethering is supported on the device.
- */
- public boolean isTetheringSupported() {
- return true;
- }
-
- /**
- * Get the NetworkRequest that should be fulfilled by the default network.
- */
- public abstract NetworkRequest getDefaultNetworkRequest();
-
- /**
- * Get a reference to the EntitlementManager to be used by tethering.
- */
- public EntitlementManager getEntitlementManager(Context ctx, Handler h, SharedLog log,
- Runnable callback) {
- return new EntitlementManager(ctx, h, log, callback);
- }
-
- /**
- * Generate a new TetheringConfiguration according to input sub Id.
- */
- public TetheringConfiguration generateTetheringConfiguration(Context ctx, SharedLog log,
- int subId) {
- return new TetheringConfiguration(ctx, log, subId);
- }
-
- /**
- * Get a reference to INetd to be used by tethering.
- */
- public INetd getINetd(Context context) {
- return INetd.Stub.asInterface(
- (IBinder) context.getSystemService(Context.NETD_SERVICE));
- }
-
- /**
- * Get a reference to the TetheringNotificationUpdater to be used by tethering.
- */
- public TetheringNotificationUpdater getNotificationUpdater(@NonNull final Context ctx,
- @NonNull final Looper looper) {
- return new TetheringNotificationUpdater(ctx, looper);
- }
-
- /**
- * Get tethering thread looper.
- */
- public abstract Looper getTetheringLooper();
-
- /**
- * Get Context of TetheringSerice.
- */
- public abstract Context getContext();
-
- /**
- * Get a reference to BluetoothAdapter to be used by tethering.
- */
- public abstract BluetoothAdapter getBluetoothAdapter();
-
- /**
- * Get SystemProperties which indicate whether tethering is denied.
- */
- public boolean isTetheringDenied() {
- return TextUtils.equals(SystemProperties.get("ro.tether.denied"), "true");
- }
-
- /**
- * Get a reference to PrivateAddressCoordinator to be used by Tethering.
- */
- public PrivateAddressCoordinator getPrivateAddressCoordinator(Context ctx,
- TetheringConfiguration cfg) {
- return new PrivateAddressCoordinator(ctx, cfg);
- }
-}
diff --git a/packages/Tethering/src/com/android/networkstack/tethering/TetheringInterfaceUtils.java b/packages/Tethering/src/com/android/networkstack/tethering/TetheringInterfaceUtils.java
deleted file mode 100644
index ff38f71..0000000
--- a/packages/Tethering/src/com/android/networkstack/tethering/TetheringInterfaceUtils.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 2018 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;
-
-import android.annotation.Nullable;
-import android.net.LinkProperties;
-import android.net.NetworkCapabilities;
-import android.net.RouteInfo;
-import android.net.util.InterfaceSet;
-
-import com.android.net.module.util.NetUtils;
-
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-
-/**
- * @hide
- */
-public final class TetheringInterfaceUtils {
- private static final InetAddress IN6ADDR_ANY = getByAddress(
- new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});
- private static final InetAddress INADDR_ANY = getByAddress(new byte[] {0, 0, 0, 0});
-
- /**
- * Get upstream interfaces for tethering based on default routes for IPv4/IPv6.
- * @return null if there is no usable interface, or a set of at least one interface otherwise.
- */
- public static @Nullable InterfaceSet getTetheringInterfaces(UpstreamNetworkState ns) {
- if (ns == null) {
- return null;
- }
-
- final LinkProperties lp = ns.linkProperties;
- final String if4 = getInterfaceForDestination(lp, INADDR_ANY);
- final String if6 = getIPv6Interface(ns);
-
- return (if4 == null && if6 == null) ? null : new InterfaceSet(if4, if6);
- }
-
- /**
- * Get the upstream interface for IPv6 tethering.
- * @return null if there is no usable interface, or the interface name otherwise.
- */
- public static @Nullable String getIPv6Interface(UpstreamNetworkState ns) {
- // Broadly speaking:
- //
- // [1] does the upstream have an IPv6 default route?
- //
- // and
- //
- // [2] does the upstream have one or more global IPv6 /64s
- // dedicated to this device?
- //
- // In lieu of Prefix Delegation and other evaluation of whether a
- // prefix may or may not be dedicated to this device, for now just
- // check whether the upstream is TRANSPORT_CELLULAR. This works
- // because "[t]he 3GPP network allocates each default bearer a unique
- // /64 prefix", per RFC 6459, Section 5.2.
- final boolean canTether =
- (ns != null) && (ns.network != null)
- && (ns.linkProperties != null) && (ns.networkCapabilities != null)
- // At least one upstream DNS server:
- && ns.linkProperties.hasIpv6DnsServer()
- // Minimal amount of IPv6 provisioning:
- && ns.linkProperties.hasGlobalIpv6Address()
- // Temporary approximation of "dedicated prefix":
- && ns.networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR);
-
- return canTether
- ? getInterfaceForDestination(ns.linkProperties, IN6ADDR_ANY)
- : null;
- }
-
- private static String getInterfaceForDestination(LinkProperties lp, InetAddress dst) {
- final RouteInfo ri = (lp != null)
- ? NetUtils.selectBestRoute(lp.getAllRoutes(), dst)
- : null;
- return (ri != null) ? ri.getInterface() : null;
- }
-
- private static InetAddress getByAddress(final byte[] addr) {
- try {
- return InetAddress.getByAddress(null, addr);
- } catch (UnknownHostException e) {
- throw new AssertionError("illegal address length" + addr.length);
- }
- }
-}
diff --git a/packages/Tethering/src/com/android/networkstack/tethering/TetheringNotificationUpdater.java b/packages/Tethering/src/com/android/networkstack/tethering/TetheringNotificationUpdater.java
deleted file mode 100644
index a0198cc..0000000
--- a/packages/Tethering/src/com/android/networkstack/tethering/TetheringNotificationUpdater.java
+++ /dev/null
@@ -1,362 +0,0 @@
-/*
- * 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;
-
-import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
-import static android.text.TextUtils.isEmpty;
-
-import android.app.Notification;
-import android.app.Notification.Action;
-import android.app.NotificationChannel;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.net.NetworkCapabilities;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.os.UserHandle;
-import android.provider.Settings;
-import android.telephony.SubscriptionManager;
-import android.telephony.TelephonyManager;
-import android.util.SparseArray;
-
-import androidx.annotation.DrawableRes;
-import androidx.annotation.IntDef;
-import androidx.annotation.IntRange;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * A class to display tethering-related notifications.
- *
- * <p>This class is not thread safe, it is intended to be used only from the tethering handler
- * thread. However the constructor is an exception, as it is called on another thread ;
- * therefore for thread safety all members of this class MUST either be final or initialized
- * to their default value (0, false or null).
- *
- * @hide
- */
-public class TetheringNotificationUpdater {
- private static final String TAG = TetheringNotificationUpdater.class.getSimpleName();
- private static final String CHANNEL_ID = "TETHERING_STATUS";
- private static final String WIFI_DOWNSTREAM = "WIFI";
- private static final String USB_DOWNSTREAM = "USB";
- private static final String BLUETOOTH_DOWNSTREAM = "BT";
- @VisibleForTesting
- static final String ACTION_DISABLE_TETHERING =
- "com.android.server.connectivity.tethering.DISABLE_TETHERING";
- private static final boolean NOTIFY_DONE = true;
- private static final boolean NO_NOTIFY = false;
- @VisibleForTesting
- static final int EVENT_SHOW_NO_UPSTREAM = 1;
- // Id to update and cancel restricted notification. Must be unique within the tethering app.
- @VisibleForTesting
- static final int RESTRICTED_NOTIFICATION_ID = 1001;
- // Id to update and cancel no upstream notification. Must be unique within the tethering app.
- @VisibleForTesting
- static final int NO_UPSTREAM_NOTIFICATION_ID = 1002;
- // Id to update and cancel roaming notification. Must be unique within the tethering app.
- @VisibleForTesting
- static final int ROAMING_NOTIFICATION_ID = 1003;
- @VisibleForTesting
- static final int NO_ICON_ID = 0;
- @VisibleForTesting
- static final int DOWNSTREAM_NONE = 0;
- // Refer to TelephonyManager#getSimCarrierId for more details about carrier id.
- @VisibleForTesting
- static final int VERIZON_CARRIER_ID = 1839;
- private final Context mContext;
- private final NotificationManager mNotificationManager;
- private final NotificationChannel mChannel;
- private final Handler mHandler;
-
- // WARNING : the constructor is called on a different thread. Thread safety therefore
- // relies on these values being initialized to 0, false or null, and not any other value. If you
- // need to change this, you will need to change the thread where the constructor is invoked, or
- // to introduce synchronization.
- // Downstream type is one of ConnectivityManager.TETHERING_* constants, 0 1 or 2.
- // This value has to be made 1 2 and 4, and OR'd with the others.
- private int mDownstreamTypesMask = DOWNSTREAM_NONE;
- private boolean mNoUpstream = false;
- private boolean mRoaming = false;
-
- // WARNING : this value is not able to being initialized to 0 and must have volatile because
- // telephony service is not guaranteed that is up before tethering service starts. If telephony
- // is up later than tethering, TetheringNotificationUpdater will use incorrect and valid
- // subscription id(0) to query resources. Therefore, initialized subscription id must be
- // INVALID_SUBSCRIPTION_ID.
- private volatile int mActiveDataSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
-
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(value = {
- RESTRICTED_NOTIFICATION_ID,
- NO_UPSTREAM_NOTIFICATION_ID,
- ROAMING_NOTIFICATION_ID
- })
- @interface NotificationId {}
-
- private static final class MccMncOverrideInfo {
- public final String visitedMccMnc;
- public final int homeMcc;
- public final int homeMnc;
- MccMncOverrideInfo(String visitedMccMnc, int mcc, int mnc) {
- this.visitedMccMnc = visitedMccMnc;
- this.homeMcc = mcc;
- this.homeMnc = mnc;
- }
- }
-
- private static final SparseArray<MccMncOverrideInfo> sCarrierIdToMccMnc = new SparseArray<>();
-
- static {
- sCarrierIdToMccMnc.put(VERIZON_CARRIER_ID, new MccMncOverrideInfo("20404", 311, 480));
- }
-
- public TetheringNotificationUpdater(@NonNull final Context context,
- @NonNull final Looper looper) {
- mContext = context;
- mNotificationManager = (NotificationManager) context.createContextAsUser(UserHandle.ALL, 0)
- .getSystemService(Context.NOTIFICATION_SERVICE);
- mChannel = new NotificationChannel(
- CHANNEL_ID,
- context.getResources().getString(R.string.notification_channel_tethering_status),
- NotificationManager.IMPORTANCE_LOW);
- mNotificationManager.createNotificationChannel(mChannel);
- mHandler = new NotificationHandler(looper);
- }
-
- private class NotificationHandler extends Handler {
- NotificationHandler(Looper looper) {
- super(looper);
- }
-
- @Override
- public void handleMessage(Message msg) {
- switch(msg.what) {
- case EVENT_SHOW_NO_UPSTREAM:
- notifyTetheringNoUpstream();
- break;
- }
- }
- }
-
- /** Called when downstream has changed */
- public void onDownstreamChanged(@IntRange(from = 0, to = 7) final int downstreamTypesMask) {
- updateActiveNotifications(
- mActiveDataSubId, downstreamTypesMask, mNoUpstream, mRoaming);
- }
-
- /** Called when active data subscription id changed */
- public void onActiveDataSubscriptionIdChanged(final int subId) {
- updateActiveNotifications(subId, mDownstreamTypesMask, mNoUpstream, mRoaming);
- }
-
- /** Called when upstream network capabilities changed */
- public void onUpstreamCapabilitiesChanged(@Nullable final NetworkCapabilities capabilities) {
- final boolean isNoUpstream = (capabilities == null);
- final boolean isRoaming = capabilities != null
- && !capabilities.hasCapability(NET_CAPABILITY_NOT_ROAMING);
- updateActiveNotifications(
- mActiveDataSubId, mDownstreamTypesMask, isNoUpstream, isRoaming);
- }
-
- @NonNull
- @VisibleForTesting
- final Handler getHandler() {
- return mHandler;
- }
-
- @NonNull
- @VisibleForTesting
- Resources getResourcesForSubId(@NonNull final Context context, final int subId) {
- final Resources res = SubscriptionManager.getResourcesForSubId(context, subId);
- final TelephonyManager tm =
- ((TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE))
- .createForSubscriptionId(mActiveDataSubId);
- final int carrierId = tm.getSimCarrierId();
- final String mccmnc = tm.getSimOperator();
- final MccMncOverrideInfo overrideInfo = sCarrierIdToMccMnc.get(carrierId);
- if (overrideInfo != null && overrideInfo.visitedMccMnc.equals(mccmnc)) {
- // Re-configure MCC/MNC value to specific carrier to get right resources.
- final Configuration config = res.getConfiguration();
- config.mcc = overrideInfo.homeMcc;
- config.mnc = overrideInfo.homeMnc;
- return context.createConfigurationContext(config).getResources();
- }
- return res;
- }
-
- private void updateActiveNotifications(final int subId, final int downstreamTypes,
- final boolean noUpstream, final boolean isRoaming) {
- final boolean tetheringActiveChanged =
- (downstreamTypes == DOWNSTREAM_NONE) != (mDownstreamTypesMask == DOWNSTREAM_NONE);
- final boolean subIdChanged = subId != mActiveDataSubId;
- final boolean upstreamChanged = noUpstream != mNoUpstream;
- final boolean roamingChanged = isRoaming != mRoaming;
- final boolean updateAll = tetheringActiveChanged || subIdChanged;
- mActiveDataSubId = subId;
- mDownstreamTypesMask = downstreamTypes;
- mNoUpstream = noUpstream;
- mRoaming = isRoaming;
-
- if (updateAll || upstreamChanged) updateNoUpstreamNotification();
- if (updateAll || roamingChanged) updateRoamingNotification();
- }
-
- private void updateNoUpstreamNotification() {
- final boolean tetheringInactive = mDownstreamTypesMask == DOWNSTREAM_NONE;
-
- if (tetheringInactive || !mNoUpstream || setupNoUpstreamNotification() == NO_NOTIFY) {
- clearNotification(NO_UPSTREAM_NOTIFICATION_ID);
- mHandler.removeMessages(EVENT_SHOW_NO_UPSTREAM);
- }
- }
-
- private void updateRoamingNotification() {
- final boolean tetheringInactive = mDownstreamTypesMask == DOWNSTREAM_NONE;
-
- if (tetheringInactive || !mRoaming || setupRoamingNotification() == NO_NOTIFY) {
- clearNotification(ROAMING_NOTIFICATION_ID);
- }
- }
-
- @VisibleForTesting
- void tetheringRestrictionLifted() {
- clearNotification(RESTRICTED_NOTIFICATION_ID);
- }
-
- private void clearNotification(@NotificationId final int id) {
- mNotificationManager.cancel(null /* tag */, id);
- }
-
- @VisibleForTesting
- static String getSettingsPackageName(@NonNull final PackageManager pm) {
- final Intent settingsIntent = new Intent(Settings.ACTION_SETTINGS);
- final ComponentName settingsComponent = settingsIntent.resolveActivity(pm);
- return settingsComponent != null
- ? settingsComponent.getPackageName() : "com.android.settings";
- }
-
- @VisibleForTesting
- void notifyTetheringDisabledByRestriction() {
- final Resources res = getResourcesForSubId(mContext, mActiveDataSubId);
- final String title = res.getString(R.string.disable_tether_notification_title);
- final String message = res.getString(R.string.disable_tether_notification_message);
- if (isEmpty(title) || isEmpty(message)) return;
-
- final PendingIntent pi = PendingIntent.getActivity(
- mContext.createContextAsUser(UserHandle.CURRENT, 0 /* flags */),
- 0 /* requestCode */,
- new Intent(Settings.ACTION_TETHER_SETTINGS)
- .setPackage(getSettingsPackageName(mContext.getPackageManager()))
- .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK),
- PendingIntent.FLAG_IMMUTABLE,
- null /* options */);
-
- showNotification(R.drawable.stat_sys_tether_general, title, message,
- RESTRICTED_NOTIFICATION_ID, false /* ongoing */, pi, new Action[0]);
- }
-
- private void notifyTetheringNoUpstream() {
- final Resources res = getResourcesForSubId(mContext, mActiveDataSubId);
- final String title = res.getString(R.string.no_upstream_notification_title);
- final String message = res.getString(R.string.no_upstream_notification_message);
- final String disableButton =
- res.getString(R.string.no_upstream_notification_disable_button);
- if (isEmpty(title) || isEmpty(message) || isEmpty(disableButton)) return;
-
- final Intent intent = new Intent(ACTION_DISABLE_TETHERING);
- intent.setPackage(mContext.getPackageName());
- final PendingIntent pi = PendingIntent.getBroadcast(
- mContext.createContextAsUser(UserHandle.CURRENT, 0 /* flags */),
- 0 /* requestCode */,
- intent,
- PendingIntent.FLAG_IMMUTABLE);
- final Action action = new Action.Builder(NO_ICON_ID, disableButton, pi).build();
-
- showNotification(R.drawable.stat_sys_tether_general, title, message,
- NO_UPSTREAM_NOTIFICATION_ID, true /* ongoing */, null /* pendingIntent */, action);
- }
-
- private boolean setupRoamingNotification() {
- final Resources res = getResourcesForSubId(mContext, mActiveDataSubId);
- final boolean upstreamRoamingNotification =
- res.getBoolean(R.bool.config_upstream_roaming_notification);
-
- if (!upstreamRoamingNotification) return NO_NOTIFY;
-
- final String title = res.getString(R.string.upstream_roaming_notification_title);
- final String message = res.getString(R.string.upstream_roaming_notification_message);
- if (isEmpty(title) || isEmpty(message)) return NO_NOTIFY;
-
- final PendingIntent pi = PendingIntent.getActivity(
- mContext.createContextAsUser(UserHandle.CURRENT, 0 /* flags */),
- 0 /* requestCode */,
- new Intent(Settings.ACTION_TETHER_SETTINGS)
- .setPackage(getSettingsPackageName(mContext.getPackageManager()))
- .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK),
- PendingIntent.FLAG_IMMUTABLE,
- null /* options */);
-
- showNotification(R.drawable.stat_sys_tether_general, title, message,
- ROAMING_NOTIFICATION_ID, true /* ongoing */, pi, new Action[0]);
- return NOTIFY_DONE;
- }
-
- private boolean setupNoUpstreamNotification() {
- final Resources res = getResourcesForSubId(mContext, mActiveDataSubId);
- final int delayToShowUpstreamNotification =
- res.getInteger(R.integer.delay_to_show_no_upstream_after_no_backhaul);
-
- if (delayToShowUpstreamNotification < 0) return NO_NOTIFY;
-
- mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_SHOW_NO_UPSTREAM),
- delayToShowUpstreamNotification);
- return NOTIFY_DONE;
- }
-
- private void showNotification(@DrawableRes final int iconId, @NonNull final String title,
- @NonNull final String message, @NotificationId final int id, final boolean ongoing,
- @Nullable PendingIntent pi, @NonNull final Action... actions) {
- final Notification notification =
- new Notification.Builder(mContext, mChannel.getId())
- .setSmallIcon(iconId)
- .setContentTitle(title)
- .setContentText(message)
- .setOngoing(ongoing)
- .setColor(mContext.getColor(
- android.R.color.system_notification_accent_color))
- .setVisibility(Notification.VISIBILITY_PUBLIC)
- .setCategory(Notification.CATEGORY_STATUS)
- .setContentIntent(pi)
- .setActions(actions)
- .build();
-
- mNotificationManager.notify(null /* tag */, id, notification);
- }
-}
diff --git a/packages/Tethering/src/com/android/networkstack/tethering/TetheringService.java b/packages/Tethering/src/com/android/networkstack/tethering/TetheringService.java
deleted file mode 100644
index 613328d..0000000
--- a/packages/Tethering/src/com/android/networkstack/tethering/TetheringService.java
+++ /dev/null
@@ -1,389 +0,0 @@
-/*
- * Copyright (C) 2019 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;
-
-import static android.Manifest.permission.ACCESS_NETWORK_STATE;
-import static android.Manifest.permission.NETWORK_STACK;
-import static android.Manifest.permission.TETHER_PRIVILEGED;
-import static android.content.pm.PackageManager.PERMISSION_GRANTED;
-import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK;
-import static android.net.TetheringManager.TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION;
-import static android.net.TetheringManager.TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION;
-import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
-import static android.net.TetheringManager.TETHER_ERROR_UNSUPPORTED;
-import static android.net.dhcp.IDhcpServer.STATUS_UNKNOWN_ERROR;
-
-import android.app.Service;
-import android.bluetooth.BluetoothAdapter;
-import android.content.Context;
-import android.content.Intent;
-import android.net.IIntResultListener;
-import android.net.INetworkStackConnector;
-import android.net.ITetheringConnector;
-import android.net.ITetheringEventCallback;
-import android.net.NetworkCapabilities;
-import android.net.NetworkRequest;
-import android.net.NetworkStack;
-import android.net.TetheringRequestParcel;
-import android.net.dhcp.DhcpServerCallbacks;
-import android.net.dhcp.DhcpServingParamsParcel;
-import android.net.ip.IpServer;
-import android.os.Binder;
-import android.os.HandlerThread;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.RemoteException;
-import android.os.ResultReceiver;
-import android.provider.Settings;
-import android.util.Log;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-
-/**
- * Android service used to manage tethering.
- *
- * <p>The service returns a binder for the system server to communicate with the tethering.
- */
-public class TetheringService extends Service {
- private static final String TAG = TetheringService.class.getSimpleName();
-
- private TetheringConnector mConnector;
-
- @Override
- public void onCreate() {
- final TetheringDependencies deps = makeTetheringDependencies();
- // The Tethering object needs a fully functional context to start, so this can't be done
- // in the constructor.
- mConnector = new TetheringConnector(makeTethering(deps), TetheringService.this);
- }
-
- /**
- * Make a reference to Tethering object.
- */
- @VisibleForTesting
- public Tethering makeTethering(TetheringDependencies deps) {
- System.loadLibrary("tetherutilsjni");
- return new Tethering(deps);
- }
-
- @NonNull
- @Override
- public IBinder onBind(Intent intent) {
- return mConnector;
- }
-
- private static class TetheringConnector extends ITetheringConnector.Stub {
- private final TetheringService mService;
- private final Tethering mTethering;
-
- TetheringConnector(Tethering tether, TetheringService service) {
- mTethering = tether;
- mService = service;
- }
-
- @Override
- public void tether(String iface, String callerPkg, String callingAttributionTag,
- IIntResultListener listener) {
- if (checkAndNotifyCommonError(callerPkg, callingAttributionTag, listener)) return;
-
- try {
- listener.onResult(mTethering.tether(iface));
- } catch (RemoteException e) { }
- }
-
- @Override
- public void untether(String iface, String callerPkg, String callingAttributionTag,
- IIntResultListener listener) {
- if (checkAndNotifyCommonError(callerPkg, callingAttributionTag, listener)) return;
-
- try {
- listener.onResult(mTethering.untether(iface));
- } catch (RemoteException e) { }
- }
-
- @Override
- public void setUsbTethering(boolean enable, String callerPkg, String callingAttributionTag,
- IIntResultListener listener) {
- if (checkAndNotifyCommonError(callerPkg, callingAttributionTag, listener)) return;
-
- try {
- listener.onResult(mTethering.setUsbTethering(enable));
- } catch (RemoteException e) { }
- }
-
- @Override
- public void startTethering(TetheringRequestParcel request, String callerPkg,
- String callingAttributionTag, IIntResultListener listener) {
- if (checkAndNotifyCommonError(callerPkg,
- callingAttributionTag,
- request.exemptFromEntitlementCheck /* onlyAllowPrivileged */,
- listener)) {
- return;
- }
-
- mTethering.startTethering(request, listener);
- }
-
- @Override
- public void stopTethering(int type, String callerPkg, String callingAttributionTag,
- IIntResultListener listener) {
- if (checkAndNotifyCommonError(callerPkg, callingAttributionTag, listener)) return;
-
- try {
- mTethering.stopTethering(type);
- listener.onResult(TETHER_ERROR_NO_ERROR);
- } catch (RemoteException e) { }
- }
-
- @Override
- public void requestLatestTetheringEntitlementResult(int type, ResultReceiver receiver,
- boolean showEntitlementUi, String callerPkg, String callingAttributionTag) {
- if (checkAndNotifyCommonError(callerPkg, callingAttributionTag, receiver)) return;
-
- mTethering.requestLatestTetheringEntitlementResult(type, receiver, showEntitlementUi);
- }
-
- @Override
- public void registerTetheringEventCallback(ITetheringEventCallback callback,
- String callerPkg) {
- try {
- if (!hasTetherAccessPermission()) {
- callback.onCallbackStopped(TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION);
- return;
- }
- mTethering.registerTetheringEventCallback(callback);
- } catch (RemoteException e) { }
- }
-
- @Override
- public void unregisterTetheringEventCallback(ITetheringEventCallback callback,
- String callerPkg) {
- try {
- if (!hasTetherAccessPermission()) {
- callback.onCallbackStopped(TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION);
- return;
- }
- mTethering.unregisterTetheringEventCallback(callback);
- } catch (RemoteException e) { }
- }
-
- @Override
- public void stopAllTethering(String callerPkg, String callingAttributionTag,
- IIntResultListener listener) {
- if (checkAndNotifyCommonError(callerPkg, callingAttributionTag, listener)) return;
-
- try {
- mTethering.untetherAll();
- listener.onResult(TETHER_ERROR_NO_ERROR);
- } catch (RemoteException e) { }
- }
-
- @Override
- public void isTetheringSupported(String callerPkg, String callingAttributionTag,
- IIntResultListener listener) {
- if (checkAndNotifyCommonError(callerPkg, callingAttributionTag, listener)) return;
-
- try {
- listener.onResult(TETHER_ERROR_NO_ERROR);
- } catch (RemoteException e) { }
- }
-
- @Override
- protected void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter writer,
- @Nullable String[] args) {
- mTethering.dump(fd, writer, args);
- }
-
- private boolean checkAndNotifyCommonError(final String callerPkg,
- final String callingAttributionTag, final IIntResultListener listener) {
- return checkAndNotifyCommonError(callerPkg, callingAttributionTag,
- false /* onlyAllowPrivileged */, listener);
- }
-
- private boolean checkAndNotifyCommonError(final String callerPkg,
- final String callingAttributionTag, final boolean onlyAllowPrivileged,
- final IIntResultListener listener) {
- try {
- if (!hasTetherChangePermission(callerPkg, callingAttributionTag,
- onlyAllowPrivileged)) {
- listener.onResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION);
- return true;
- }
- if (!mTethering.isTetheringSupported()) {
- listener.onResult(TETHER_ERROR_UNSUPPORTED);
- return true;
- }
- } catch (RemoteException e) {
- return true;
- }
-
- return false;
- }
-
- private boolean checkAndNotifyCommonError(final String callerPkg,
- final String callingAttributionTag, final ResultReceiver receiver) {
- if (!hasTetherChangePermission(callerPkg, callingAttributionTag,
- false /* onlyAllowPrivileged */)) {
- receiver.send(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION, null);
- return true;
- }
- if (!mTethering.isTetheringSupported()) {
- receiver.send(TETHER_ERROR_UNSUPPORTED, null);
- return true;
- }
-
- return false;
- }
-
- private boolean hasNetworkStackPermission() {
- return checkCallingOrSelfPermission(NETWORK_STACK)
- || checkCallingOrSelfPermission(PERMISSION_MAINLINE_NETWORK_STACK);
- }
-
- private boolean hasTetherPrivilegedPermission() {
- return checkCallingOrSelfPermission(TETHER_PRIVILEGED);
- }
-
- private boolean checkCallingOrSelfPermission(final String permission) {
- return mService.checkCallingOrSelfPermission(permission) == PERMISSION_GRANTED;
- }
-
- private boolean hasTetherChangePermission(final String callerPkg,
- final String callingAttributionTag, final boolean onlyAllowPrivileged) {
- if (onlyAllowPrivileged && !hasNetworkStackPermission()) return false;
-
- if (hasTetherPrivilegedPermission()) return true;
-
- if (mTethering.isTetherProvisioningRequired()) return false;
-
- int uid = Binder.getCallingUid();
-
- // If callerPkg's uid is not same as Binder.getCallingUid(),
- // checkAndNoteWriteSettingsOperation will return false and the operation will be
- // denied.
- return mService.checkAndNoteWriteSettingsOperation(mService, uid, callerPkg,
- callingAttributionTag, false /* throwException */);
- }
-
- private boolean hasTetherAccessPermission() {
- if (hasTetherPrivilegedPermission()) return true;
-
- return mService.checkCallingOrSelfPermission(
- ACCESS_NETWORK_STATE) == PERMISSION_GRANTED;
- }
- }
-
- /**
- * Check if the package is a allowed to write settings. This also accounts that such an access
- * happened.
- *
- * @return {@code true} iff the package is allowed to write settings.
- */
- @VisibleForTesting
- boolean checkAndNoteWriteSettingsOperation(@NonNull Context context, int uid,
- @NonNull String callingPackage, @Nullable String callingAttributionTag,
- boolean throwException) {
- return Settings.checkAndNoteWriteSettingsOperation(context, uid, callingPackage,
- throwException);
- }
-
- /**
- * An injection method for testing.
- */
- @VisibleForTesting
- public TetheringDependencies makeTetheringDependencies() {
- return new TetheringDependencies() {
- @Override
- public NetworkRequest getDefaultNetworkRequest() {
- // TODO: b/147280869, add a proper system API to replace this.
- final NetworkRequest trackDefaultRequest = new NetworkRequest.Builder()
- .clearCapabilities()
- .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
- .build();
- return trackDefaultRequest;
- }
-
- @Override
- public Looper getTetheringLooper() {
- final HandlerThread tetherThread = new HandlerThread("android.tethering");
- tetherThread.start();
- return tetherThread.getLooper();
- }
-
- @Override
- public Context getContext() {
- return TetheringService.this;
- }
-
- @Override
- public IpServer.Dependencies getIpServerDependencies() {
- return new IpServer.Dependencies() {
- @Override
- public void makeDhcpServer(String ifName, DhcpServingParamsParcel params,
- DhcpServerCallbacks cb) {
- try {
- final INetworkStackConnector service = getNetworkStackConnector();
- if (service == null) return;
-
- service.makeDhcpServer(ifName, params, cb);
- } catch (RemoteException e) {
- Log.e(TAG, "Fail to make dhcp server");
- try {
- cb.onDhcpServerCreated(STATUS_UNKNOWN_ERROR, null);
- } catch (RemoteException re) { }
- }
- }
- };
- }
-
- // TODO: replace this by NetworkStackClient#getRemoteConnector after refactoring
- // networkStackClient.
- static final int NETWORKSTACK_TIMEOUT_MS = 60_000;
- private INetworkStackConnector getNetworkStackConnector() {
- IBinder connector;
- try {
- final long before = System.currentTimeMillis();
- while ((connector = NetworkStack.getService()) == null) {
- if (System.currentTimeMillis() - before > NETWORKSTACK_TIMEOUT_MS) {
- Log.wtf(TAG, "Timeout, fail to get INetworkStackConnector");
- return null;
- }
- Thread.sleep(200);
- }
- } catch (InterruptedException e) {
- Log.wtf(TAG, "Interrupted, fail to get INetworkStackConnector");
- return null;
- }
- return INetworkStackConnector.Stub.asInterface(connector);
- }
-
- @Override
- public BluetoothAdapter getBluetoothAdapter() {
- return BluetoothAdapter.getDefaultAdapter();
- }
- };
- }
-}
diff --git a/packages/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkMonitor.java b/packages/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkMonitor.java
deleted file mode 100644
index b17065c..0000000
--- a/packages/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkMonitor.java
+++ /dev/null
@@ -1,607 +0,0 @@
-/*
- * Copyright (C) 2017 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;
-
-import static android.net.ConnectivityManager.TYPE_BLUETOOTH;
-import static android.net.ConnectivityManager.TYPE_ETHERNET;
-import static android.net.ConnectivityManager.TYPE_MOBILE;
-import static android.net.ConnectivityManager.TYPE_MOBILE_DUN;
-import static android.net.ConnectivityManager.TYPE_MOBILE_HIPRI;
-import static android.net.ConnectivityManager.TYPE_WIFI;
-import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
-import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
-import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
-import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
-import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
-
-import android.content.Context;
-import android.net.ConnectivityManager;
-import android.net.ConnectivityManager.NetworkCallback;
-import android.net.IpPrefix;
-import android.net.LinkProperties;
-import android.net.Network;
-import android.net.NetworkCapabilities;
-import android.net.NetworkRequest;
-import android.net.util.PrefixUtils;
-import android.net.util.SharedLog;
-import android.os.Handler;
-import android.util.Log;
-import android.util.SparseIntArray;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.StateMachine;
-
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Set;
-
-
-/**
- * A class to centralize all the network and link properties information
- * pertaining to the current and any potential upstream network.
- *
- * The owner of UNM gets it to register network callbacks by calling the
- * following methods :
- * Calling #startTrackDefaultNetwork() to track the system default network.
- * Calling #startObserveAllNetworks() to observe all networks. Listening all
- * networks is necessary while the expression of preferred upstreams remains
- * a list of legacy connectivity types. In future, this can be revisited.
- * Calling #registerMobileNetworkRequest() to bring up mobile DUN/HIPRI network.
- *
- * The methods and data members of this class are only to be accessed and
- * modified from the tethering main state machine thread. Any other
- * access semantics would necessitate the addition of locking.
- *
- * TODO: Move upstream selection logic here.
- *
- * All callback methods are run on the same thread as the specified target
- * state machine. This class does not require locking when accessed from this
- * thread. Access from other threads is not advised.
- *
- * @hide
- */
-public class UpstreamNetworkMonitor {
- private static final String TAG = UpstreamNetworkMonitor.class.getSimpleName();
- private static final boolean DBG = false;
- private static final boolean VDBG = false;
-
- public static final int EVENT_ON_CAPABILITIES = 1;
- public static final int EVENT_ON_LINKPROPERTIES = 2;
- public static final int EVENT_ON_LOST = 3;
- public static final int NOTIFY_LOCAL_PREFIXES = 10;
- // This value is used by deprecated preferredUpstreamIfaceTypes selection which is default
- // disabled.
- @VisibleForTesting
- public static final int TYPE_NONE = -1;
-
- private static final int CALLBACK_LISTEN_ALL = 1;
- private static final int CALLBACK_DEFAULT_INTERNET = 2;
- private static final int CALLBACK_MOBILE_REQUEST = 3;
-
- private static final SparseIntArray sLegacyTypeToTransport = new SparseIntArray();
- static {
- sLegacyTypeToTransport.put(TYPE_MOBILE, NetworkCapabilities.TRANSPORT_CELLULAR);
- sLegacyTypeToTransport.put(TYPE_MOBILE_DUN, NetworkCapabilities.TRANSPORT_CELLULAR);
- sLegacyTypeToTransport.put(TYPE_MOBILE_HIPRI, NetworkCapabilities.TRANSPORT_CELLULAR);
- sLegacyTypeToTransport.put(TYPE_WIFI, NetworkCapabilities.TRANSPORT_WIFI);
- sLegacyTypeToTransport.put(TYPE_BLUETOOTH, NetworkCapabilities.TRANSPORT_BLUETOOTH);
- sLegacyTypeToTransport.put(TYPE_ETHERNET, NetworkCapabilities.TRANSPORT_ETHERNET);
- }
-
- private final Context mContext;
- private final SharedLog mLog;
- private final StateMachine mTarget;
- private final Handler mHandler;
- private final int mWhat;
- private final HashMap<Network, UpstreamNetworkState> mNetworkMap = new HashMap<>();
- private HashSet<IpPrefix> mLocalPrefixes;
- private ConnectivityManager mCM;
- private EntitlementManager mEntitlementMgr;
- private NetworkCallback mListenAllCallback;
- private NetworkCallback mDefaultNetworkCallback;
- private NetworkCallback mMobileNetworkCallback;
- private boolean mDunRequired;
- // Whether the current default upstream is mobile or not.
- private boolean mIsDefaultCellularUpstream;
- // The current system default network (not really used yet).
- private Network mDefaultInternetNetwork;
- // The current upstream network used for tethering.
- private Network mTetheringUpstreamNetwork;
-
- public UpstreamNetworkMonitor(Context ctx, StateMachine tgt, SharedLog log, int what) {
- mContext = ctx;
- mTarget = tgt;
- mHandler = mTarget.getHandler();
- mLog = log.forSubComponent(TAG);
- mWhat = what;
- mLocalPrefixes = new HashSet<>();
- mIsDefaultCellularUpstream = false;
- }
-
- @VisibleForTesting
- public UpstreamNetworkMonitor(
- ConnectivityManager cm, StateMachine tgt, SharedLog log, int what) {
- this((Context) null, tgt, log, what);
- mCM = cm;
- }
-
- /**
- * Tracking the system default network. This method should be called when system is ready.
- *
- * @param defaultNetworkRequest should be the same as ConnectivityService default request
- * @param entitle a EntitlementManager object to communicate between EntitlementManager and
- * UpstreamNetworkMonitor
- */
- public void startTrackDefaultNetwork(NetworkRequest defaultNetworkRequest,
- EntitlementManager entitle) {
-
- // defaultNetworkRequest is not really a "request", just a way of tracking the system
- // default network. It's guaranteed not to actually bring up any networks because it's
- // the should be the same request as the ConnectivityService default request, and thus
- // shares fate with it. We can't use registerDefaultNetworkCallback because it will not
- // track the system default network if there is a VPN that applies to our UID.
- if (mDefaultNetworkCallback == null) {
- mDefaultNetworkCallback = new UpstreamNetworkCallback(CALLBACK_DEFAULT_INTERNET);
- cm().requestNetwork(defaultNetworkRequest, mDefaultNetworkCallback, mHandler);
- }
- if (mEntitlementMgr == null) {
- mEntitlementMgr = entitle;
- }
- }
-
- /** Listen all networks. */
- public void startObserveAllNetworks() {
- stop();
-
- final NetworkRequest listenAllRequest = new NetworkRequest.Builder()
- .clearCapabilities().build();
- mListenAllCallback = new UpstreamNetworkCallback(CALLBACK_LISTEN_ALL);
- cm().registerNetworkCallback(listenAllRequest, mListenAllCallback, mHandler);
- }
-
- /**
- * Stop tracking candidate tethering upstreams and release mobile network request.
- * Note: this function is used when tethering is stopped because tethering do not need to
- * choose upstream anymore. But it would not stop default network tracking because
- * EntitlementManager may need to know default network to decide whether to request entitlement
- * check even tethering is not active yet.
- */
- public void stop() {
- releaseMobileNetworkRequest();
-
- releaseCallback(mListenAllCallback);
- mListenAllCallback = null;
-
- mTetheringUpstreamNetwork = null;
- mNetworkMap.clear();
- }
-
- /** Setup or teardown DUN connection according to |dunRequired|. */
- public void updateMobileRequiresDun(boolean dunRequired) {
- final boolean valueChanged = (mDunRequired != dunRequired);
- mDunRequired = dunRequired;
- if (valueChanged && mobileNetworkRequested()) {
- releaseMobileNetworkRequest();
- registerMobileNetworkRequest();
- }
- }
-
- /** Whether mobile network is requested. */
- public boolean mobileNetworkRequested() {
- return (mMobileNetworkCallback != null);
- }
-
- /** Request mobile network if mobile upstream is permitted. */
- public void registerMobileNetworkRequest() {
- if (!isCellularUpstreamPermitted()) {
- mLog.i("registerMobileNetworkRequest() is not permitted");
- releaseMobileNetworkRequest();
- return;
- }
- if (mMobileNetworkCallback != null) {
- mLog.e("registerMobileNetworkRequest() already registered");
- return;
- }
-
- final NetworkRequest mobileUpstreamRequest;
- if (mDunRequired) {
- mobileUpstreamRequest = new NetworkRequest.Builder()
- .addCapability(NET_CAPABILITY_DUN)
- .removeCapability(NET_CAPABILITY_NOT_RESTRICTED)
- .addTransportType(TRANSPORT_CELLULAR).build();
- } else {
- mobileUpstreamRequest = new NetworkRequest.Builder()
- .addCapability(NET_CAPABILITY_INTERNET)
- .addTransportType(TRANSPORT_CELLULAR).build();
- }
-
- // The existing default network and DUN callbacks will be notified.
- // Therefore, to avoid duplicate notifications, we only register a no-op.
- mMobileNetworkCallback = new UpstreamNetworkCallback(CALLBACK_MOBILE_REQUEST);
-
- // The following use of the legacy type system cannot be removed until
- // upstream selection no longer finds networks by legacy type.
- // See also http://b/34364553 .
- final int legacyType = mDunRequired ? TYPE_MOBILE_DUN : TYPE_MOBILE_HIPRI;
-
- // TODO: Change the timeout from 0 (no onUnavailable callback) to some
- // moderate callback timeout. This might be useful for updating some UI.
- // Additionally, we log a message to aid in any subsequent debugging.
- mLog.i("requesting mobile upstream network: " + mobileUpstreamRequest);
-
- cm().requestNetwork(mobileUpstreamRequest, 0, legacyType, mHandler,
- mMobileNetworkCallback);
- }
-
- /** Release mobile network request. */
- public void releaseMobileNetworkRequest() {
- if (mMobileNetworkCallback == null) return;
-
- cm().unregisterNetworkCallback(mMobileNetworkCallback);
- mMobileNetworkCallback = null;
- }
-
- // So many TODOs here, but chief among them is: make this functionality an
- // integral part of this class such that whenever a higher priority network
- // becomes available and useful we (a) file a request to keep it up as
- // necessary and (b) change all upstream tracking state accordingly (by
- // passing LinkProperties up to Tethering).
- /**
- * Select the first available network from |perferredTypes|.
- */
- public UpstreamNetworkState selectPreferredUpstreamType(Iterable<Integer> preferredTypes) {
- final TypeStatePair typeStatePair = findFirstAvailableUpstreamByType(
- mNetworkMap.values(), preferredTypes, isCellularUpstreamPermitted());
-
- mLog.log("preferred upstream type: " + typeStatePair.type);
-
- switch (typeStatePair.type) {
- case TYPE_MOBILE_DUN:
- case TYPE_MOBILE_HIPRI:
- // Tethering just selected mobile upstream in spite of the default network being
- // not mobile. This can happen because of the priority list.
- // Notify EntitlementManager to check permission for using mobile upstream.
- if (!mIsDefaultCellularUpstream) {
- mEntitlementMgr.maybeRunProvisioning();
- }
- // If we're on DUN, put our own grab on it.
- registerMobileNetworkRequest();
- break;
- case TYPE_NONE:
- // If we found NONE and mobile upstream is permitted we don't want to do this
- // as we want any previous requests to keep trying to bring up something we can use.
- if (!isCellularUpstreamPermitted()) releaseMobileNetworkRequest();
- break;
- default:
- // If we've found an active upstream connection that's not DUN/HIPRI
- // we should stop any outstanding DUN/HIPRI requests.
- releaseMobileNetworkRequest();
- break;
- }
-
- return typeStatePair.ns;
- }
-
- /**
- * Get current preferred upstream network. If default network is cellular and DUN is required,
- * preferred upstream would be DUN otherwise preferred upstream is the same as default network.
- * Returns null if no current upstream is available.
- */
- public UpstreamNetworkState getCurrentPreferredUpstream() {
- final UpstreamNetworkState dfltState = (mDefaultInternetNetwork != null)
- ? mNetworkMap.get(mDefaultInternetNetwork)
- : null;
- if (isNetworkUsableAndNotCellular(dfltState)) return dfltState;
-
- if (!isCellularUpstreamPermitted()) return null;
-
- if (!mDunRequired) return dfltState;
-
- // Find a DUN network. Note that code in Tethering causes a DUN request
- // to be filed, but this might be moved into this class in future.
- return findFirstDunNetwork(mNetworkMap.values());
- }
-
- /** Tell UpstreamNetworkMonitor which network is the current upstream of tethering. */
- public void setCurrentUpstream(Network upstream) {
- mTetheringUpstreamNetwork = upstream;
- }
-
- /** Return local prefixes. */
- public Set<IpPrefix> getLocalPrefixes() {
- return (Set<IpPrefix>) mLocalPrefixes.clone();
- }
-
- private boolean isCellularUpstreamPermitted() {
- if (mEntitlementMgr != null) {
- return mEntitlementMgr.isCellularUpstreamPermitted();
- } else {
- // This flow should only happens in testing.
- return true;
- }
- }
-
- private void handleAvailable(Network network) {
- if (mNetworkMap.containsKey(network)) return;
-
- if (VDBG) Log.d(TAG, "onAvailable for " + network);
- mNetworkMap.put(network, new UpstreamNetworkState(null, null, network));
- }
-
- private void handleNetCap(Network network, NetworkCapabilities newNc) {
- final UpstreamNetworkState prev = mNetworkMap.get(network);
- if (prev == null || newNc.equals(prev.networkCapabilities)) {
- // Ignore notifications about networks for which we have not yet
- // received onAvailable() (should never happen) and any duplicate
- // notifications (e.g. matching more than one of our callbacks).
- return;
- }
-
- if (VDBG) {
- Log.d(TAG, String.format("EVENT_ON_CAPABILITIES for %s: %s",
- network, newNc));
- }
-
- mNetworkMap.put(network, new UpstreamNetworkState(
- prev.linkProperties, newNc, network));
- // TODO: If sufficient information is available to select a more
- // preferable upstream, do so now and notify the target.
- notifyTarget(EVENT_ON_CAPABILITIES, network);
- }
-
- private void handleLinkProp(Network network, LinkProperties newLp) {
- final UpstreamNetworkState prev = mNetworkMap.get(network);
- if (prev == null || newLp.equals(prev.linkProperties)) {
- // Ignore notifications about networks for which we have not yet
- // received onAvailable() (should never happen) and any duplicate
- // notifications (e.g. matching more than one of our callbacks).
- return;
- }
-
- if (VDBG) {
- Log.d(TAG, String.format("EVENT_ON_LINKPROPERTIES for %s: %s",
- network, newLp));
- }
-
- mNetworkMap.put(network, new UpstreamNetworkState(
- newLp, prev.networkCapabilities, network));
- // TODO: If sufficient information is available to select a more
- // preferable upstream, do so now and notify the target.
- notifyTarget(EVENT_ON_LINKPROPERTIES, network);
- }
-
- private void handleLost(Network network) {
- // There are few TODOs within ConnectivityService's rematching code
- // pertaining to spurious onLost() notifications.
- //
- // TODO: simplify this, probably if favor of code that:
- // - selects a new upstream if mTetheringUpstreamNetwork has
- // been lost (by any callback)
- // - deletes the entry from the map only when the LISTEN_ALL
- // callback gets notified.
-
- if (!mNetworkMap.containsKey(network)) {
- // Ignore loss of networks about which we had not previously
- // learned any information or for which we have already processed
- // an onLost() notification.
- return;
- }
-
- if (VDBG) Log.d(TAG, "EVENT_ON_LOST for " + network);
-
- // TODO: If sufficient information is available to select a more
- // preferable upstream, do so now and notify the target. Likewise,
- // if the current upstream network is gone, notify the target of the
- // fact that we now have no upstream at all.
- notifyTarget(EVENT_ON_LOST, mNetworkMap.remove(network));
- }
-
- private void recomputeLocalPrefixes() {
- final HashSet<IpPrefix> localPrefixes = allLocalPrefixes(mNetworkMap.values());
- if (!mLocalPrefixes.equals(localPrefixes)) {
- mLocalPrefixes = localPrefixes;
- notifyTarget(NOTIFY_LOCAL_PREFIXES, localPrefixes.clone());
- }
- }
-
- // Fetch (and cache) a ConnectivityManager only if and when we need one.
- private ConnectivityManager cm() {
- if (mCM == null) {
- // MUST call the String variant to be able to write unittests.
- mCM = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
- }
- return mCM;
- }
-
- /**
- * A NetworkCallback class that handles information of interest directly
- * in the thread on which it is invoked. To avoid locking, this MUST be
- * run on the same thread as the target state machine's handler.
- */
- private class UpstreamNetworkCallback extends NetworkCallback {
- private final int mCallbackType;
-
- UpstreamNetworkCallback(int callbackType) {
- mCallbackType = callbackType;
- }
-
- @Override
- public void onAvailable(Network network) {
- handleAvailable(network);
- }
-
- @Override
- public void onCapabilitiesChanged(Network network, NetworkCapabilities newNc) {
- if (mCallbackType == CALLBACK_DEFAULT_INTERNET) {
- mDefaultInternetNetwork = network;
- final boolean newIsCellular = isCellular(newNc);
- if (mIsDefaultCellularUpstream != newIsCellular) {
- mIsDefaultCellularUpstream = newIsCellular;
- mEntitlementMgr.notifyUpstream(newIsCellular);
- }
- return;
- }
-
- handleNetCap(network, newNc);
- }
-
- @Override
- public void onLinkPropertiesChanged(Network network, LinkProperties newLp) {
- if (mCallbackType == CALLBACK_DEFAULT_INTERNET) return;
-
- handleLinkProp(network, newLp);
- // Any non-LISTEN_ALL callback will necessarily concern a network that will
- // also match the LISTEN_ALL callback by construction of the LISTEN_ALL callback.
- // So it's not useful to do this work for non-LISTEN_ALL callbacks.
- if (mCallbackType == CALLBACK_LISTEN_ALL) {
- recomputeLocalPrefixes();
- }
- }
-
- @Override
- public void onLost(Network network) {
- if (mCallbackType == CALLBACK_DEFAULT_INTERNET) {
- mDefaultInternetNetwork = null;
- mIsDefaultCellularUpstream = false;
- mEntitlementMgr.notifyUpstream(false);
- return;
- }
-
- handleLost(network);
- // Any non-LISTEN_ALL callback will necessarily concern a network that will
- // also match the LISTEN_ALL callback by construction of the LISTEN_ALL callback.
- // So it's not useful to do this work for non-LISTEN_ALL callbacks.
- if (mCallbackType == CALLBACK_LISTEN_ALL) {
- recomputeLocalPrefixes();
- }
- }
- }
-
- private void releaseCallback(NetworkCallback cb) {
- if (cb != null) cm().unregisterNetworkCallback(cb);
- }
-
- private void notifyTarget(int which, Network network) {
- notifyTarget(which, mNetworkMap.get(network));
- }
-
- private void notifyTarget(int which, Object obj) {
- mTarget.sendMessage(mWhat, which, 0, obj);
- }
-
- private static class TypeStatePair {
- public int type = TYPE_NONE;
- public UpstreamNetworkState ns = null;
- }
-
- private static TypeStatePair findFirstAvailableUpstreamByType(
- Iterable<UpstreamNetworkState> netStates, Iterable<Integer> preferredTypes,
- boolean isCellularUpstreamPermitted) {
- final TypeStatePair result = new TypeStatePair();
-
- for (int type : preferredTypes) {
- NetworkCapabilities nc;
- try {
- nc = networkCapabilitiesForType(type);
- } catch (IllegalArgumentException iae) {
- Log.e(TAG, "No NetworkCapabilities mapping for legacy type: " + type);
- continue;
- }
- if (!isCellularUpstreamPermitted && isCellular(nc)) {
- continue;
- }
-
- for (UpstreamNetworkState value : netStates) {
- if (!nc.satisfiedByNetworkCapabilities(value.networkCapabilities)) {
- continue;
- }
-
- result.type = type;
- result.ns = value;
- return result;
- }
- }
-
- return result;
- }
-
- private static HashSet<IpPrefix> allLocalPrefixes(Iterable<UpstreamNetworkState> netStates) {
- final HashSet<IpPrefix> prefixSet = new HashSet<>();
-
- for (UpstreamNetworkState ns : netStates) {
- final LinkProperties lp = ns.linkProperties;
- if (lp == null) continue;
- prefixSet.addAll(PrefixUtils.localPrefixesFrom(lp));
- }
-
- return prefixSet;
- }
-
- private static boolean isCellular(UpstreamNetworkState ns) {
- return (ns != null) && isCellular(ns.networkCapabilities);
- }
-
- private static boolean isCellular(NetworkCapabilities nc) {
- return (nc != null) && nc.hasTransport(TRANSPORT_CELLULAR)
- && nc.hasCapability(NET_CAPABILITY_NOT_VPN);
- }
-
- private static boolean hasCapability(UpstreamNetworkState ns, int netCap) {
- return (ns != null) && (ns.networkCapabilities != null)
- && ns.networkCapabilities.hasCapability(netCap);
- }
-
- private static boolean isNetworkUsableAndNotCellular(UpstreamNetworkState ns) {
- return (ns != null) && (ns.networkCapabilities != null) && (ns.linkProperties != null)
- && !isCellular(ns.networkCapabilities);
- }
-
- private static UpstreamNetworkState findFirstDunNetwork(
- Iterable<UpstreamNetworkState> netStates) {
- for (UpstreamNetworkState ns : netStates) {
- if (isCellular(ns) && hasCapability(ns, NET_CAPABILITY_DUN)) return ns;
- }
-
- return null;
- }
-
- /**
- * Given a legacy type (TYPE_WIFI, ...) returns the corresponding NetworkCapabilities instance.
- * This function is used for deprecated legacy type and be disabled by default.
- */
- @VisibleForTesting
- public static NetworkCapabilities networkCapabilitiesForType(int type) {
- final NetworkCapabilities.Builder builder = new NetworkCapabilities.Builder();
-
- // Map from type to transports.
- final int notFound = -1;
- final int transport = sLegacyTypeToTransport.get(type, notFound);
- if (transport == notFound) {
- throw new IllegalArgumentException("unknown legacy type: " + type);
- }
- builder.addTransportType(transport);
-
- if (type == TYPE_MOBILE_DUN) {
- builder.addCapability(NetworkCapabilities.NET_CAPABILITY_DUN);
- // DUN is restricted network, see NetworkCapabilities#FORCE_RESTRICTED_CAPABILITIES.
- builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
- } else {
- builder.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
- }
- return builder.build();
- }
-}
diff --git a/packages/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkState.java b/packages/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkState.java
deleted file mode 100644
index bab9f84..0000000
--- a/packages/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkState.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2019 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;
-
-import android.net.LinkProperties;
-import android.net.Network;
-import android.net.NetworkCapabilities;
-
-import androidx.annotation.NonNull;
-
-/**
- * Snapshot of tethering upstream network state.
- */
-public class UpstreamNetworkState {
- /** {@link LinkProperties}. */
- public final LinkProperties linkProperties;
- /** {@link NetworkCapabilities}. */
- public final NetworkCapabilities networkCapabilities;
- /** {@link Network}. */
- public final Network network;
-
- /** Constructs a new UpstreamNetworkState. */
- public UpstreamNetworkState(LinkProperties linkProperties,
- NetworkCapabilities networkCapabilities, Network network) {
- this.linkProperties = linkProperties;
- this.networkCapabilities = networkCapabilities;
- this.network = network;
- }
-
- @NonNull
- @Override
- public String toString() {
- return String.format("UpstreamNetworkState{%s, %s, %s}",
- network == null ? "null" : network,
- networkCapabilities == null ? "null" : networkCapabilities,
- linkProperties == null ? "null" : linkProperties);
- }
-}
diff --git a/packages/Tethering/tests/Android.bp b/packages/Tethering/tests/Android.bp
deleted file mode 100644
index cb0a20b..0000000
--- a/packages/Tethering/tests/Android.bp
+++ /dev/null
@@ -1,23 +0,0 @@
-//
-// 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.
-//
-
-filegroup {
- name: "TetheringTestsJarJarRules",
- srcs: ["jarjar-rules.txt"],
- visibility: [
- "//frameworks/base/packages/Tethering/tests:__subpackages__",
- ]
-}
diff --git a/packages/Tethering/tests/integration/Android.bp b/packages/Tethering/tests/integration/Android.bp
deleted file mode 100644
index 5765c01..0000000
--- a/packages/Tethering/tests/integration/Android.bp
+++ /dev/null
@@ -1,85 +0,0 @@
-//
-// 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.
-//
-java_defaults {
- name: "TetheringIntegrationTestsDefaults",
- srcs: [
- "src/**/*.java",
- "src/**/*.kt",
- ],
- static_libs: [
- "NetworkStackApiStableLib",
- "androidx.test.rules",
- "mockito-target-extended-minus-junit4",
- "net-tests-utils",
- "testables",
- ],
- libs: [
- "android.test.runner",
- "android.test.base",
- "android.test.mock",
- ],
- jni_libs: [
- // For mockito extended
- "libdexmakerjvmtiagent",
- "libstaticjvmtiagent",
- ],
- jarjar_rules: ":NetworkStackJarJarRules",
-}
-
-android_library {
- name: "TetheringIntegrationTestsLib",
- platform_apis: true,
- defaults: ["TetheringIntegrationTestsDefaults"],
- visibility: ["//cts/tests/tests/tethering"]
-}
-
-android_test {
- name: "TetheringIntegrationTests",
- platform_apis: true,
- defaults: ["TetheringIntegrationTestsDefaults"],
- test_suites: [
- "device-tests",
- "mts",
- ],
- compile_multilib: "both",
-}
-
-// Special version of the tethering tests that includes all tests necessary for code coverage
-// purposes. This is currently the union of TetheringTests, TetheringIntegrationTests and
-// NetworkStackTests.
-android_test {
- name: "TetheringCoverageTests",
- platform_apis: true,
- test_suites: ["device-tests", "mts"],
- test_config: "AndroidTest_Coverage.xml",
- defaults: ["libnetworkstackutilsjni_deps"],
- static_libs: [
- "NetworkStaticLibTestsLib",
- "NetworkStackTestsLib",
- "TetheringTestsLib",
- "TetheringIntegrationTestsLib",
- ],
- jni_libs: [
- // For mockito extended
- "libdexmakerjvmtiagent",
- "libstaticjvmtiagent",
- // For NetworkStackUtils included in NetworkStackBase
- "libnetworkstackutilsjni",
- ],
- jarjar_rules: ":TetheringTestsJarJarRules",
- compile_multilib: "both",
- manifest: "AndroidManifest_coverage.xml",
-}
diff --git a/packages/Tethering/tests/integration/AndroidManifest.xml b/packages/Tethering/tests/integration/AndroidManifest.xml
deleted file mode 100644
index fddfaad..0000000
--- a/packages/Tethering/tests/integration/AndroidManifest.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.networkstack.tethering.tests.integration">
-
- <uses-permission android:name="android.permission.INTERNET"/>
-
- <application android:debuggable="true">
- <uses-library android:name="android.test.runner" />
- </application>
- <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.networkstack.tethering.tests.integration"
- android:label="Tethering integration tests">
- </instrumentation>
-</manifest>
diff --git a/packages/Tethering/tests/integration/AndroidManifest_coverage.xml b/packages/Tethering/tests/integration/AndroidManifest_coverage.xml
deleted file mode 100644
index 06de00d..0000000
--- a/packages/Tethering/tests/integration/AndroidManifest_coverage.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- package="com.android.networkstack.tethering.tests.coverage">
-
- <application tools:replace="android:label"
- android:debuggable="true"
- android:label="Tethering coverage tests">
- <uses-library android:name="android.test.runner" />
- </application>
- <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.networkstack.tethering.tests.coverage"
- android:label="Tethering coverage tests">
- </instrumentation>
-</manifest>
diff --git a/packages/Tethering/tests/integration/AndroidTest_Coverage.xml b/packages/Tethering/tests/integration/AndroidTest_Coverage.xml
deleted file mode 100644
index 3def209..0000000
--- a/packages/Tethering/tests/integration/AndroidTest_Coverage.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-<configuration description="Runs coverage tests for Tethering">
- <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
- <option name="test-file-name" value="TetheringCoverageTests.apk" />
- </target_preparer>
-
- <option name="test-tag" value="TetheringCoverageTests" />
- <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
- <option name="package" value="com.android.networkstack.tethering.tests.coverage" />
- <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
- <option name="hidden-api-checks" value="false"/>
- </test>
-</configuration>
\ No newline at end of file
diff --git a/packages/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java b/packages/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java
deleted file mode 100644
index d206ea0..0000000
--- a/packages/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java
+++ /dev/null
@@ -1,566 +0,0 @@
-/*
- * 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 android.net;
-
-import static android.Manifest.permission.MANAGE_TEST_NETWORKS;
-import static android.Manifest.permission.NETWORK_SETTINGS;
-import static android.Manifest.permission.TETHER_PRIVILEGED;
-import static android.net.TetheringManager.TETHERING_ETHERNET;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import static org.junit.Assume.assumeFalse;
-import static org.junit.Assume.assumeTrue;
-
-import android.app.UiAutomation;
-import android.content.Context;
-import android.net.EthernetManager.TetheredInterfaceCallback;
-import android.net.EthernetManager.TetheredInterfaceRequest;
-import android.net.TetheringManager.StartTetheringCallback;
-import android.net.TetheringManager.TetheringEventCallback;
-import android.net.TetheringManager.TetheringRequest;
-import android.net.dhcp.DhcpAckPacket;
-import android.net.dhcp.DhcpOfferPacket;
-import android.net.dhcp.DhcpPacket;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.SystemClock;
-import android.os.SystemProperties;
-import android.system.Os;
-import android.util.Log;
-
-import androidx.test.InstrumentationRegistry;
-import androidx.test.filters.MediumTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import com.android.testutils.HandlerUtils;
-import com.android.testutils.TapPacketReader;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.io.FileDescriptor;
-import java.net.Inet4Address;
-import java.net.InterfaceAddress;
-import java.net.NetworkInterface;
-import java.net.SocketException;
-import java.nio.ByteBuffer;
-import java.util.Collection;
-import java.util.List;
-import java.util.Random;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-
-@RunWith(AndroidJUnit4.class)
-@MediumTest
-public class EthernetTetheringTest {
-
- private static final String TAG = EthernetTetheringTest.class.getSimpleName();
- private static final int TIMEOUT_MS = 5000;
- private static final int PACKET_READ_TIMEOUT_MS = 100;
- private static final int DHCP_DISCOVER_ATTEMPTS = 10;
- private static final byte[] DHCP_REQUESTED_PARAMS = new byte[] {
- DhcpPacket.DHCP_SUBNET_MASK,
- DhcpPacket.DHCP_ROUTER,
- DhcpPacket.DHCP_DNS_SERVER,
- DhcpPacket.DHCP_LEASE_TIME,
- };
- private static final String DHCP_HOSTNAME = "testhostname";
-
- private final Context mContext = InstrumentationRegistry.getContext();
- private final EthernetManager mEm = mContext.getSystemService(EthernetManager.class);
- private final TetheringManager mTm = mContext.getSystemService(TetheringManager.class);
-
- private TestNetworkInterface mTestIface;
- private HandlerThread mHandlerThread;
- private Handler mHandler;
- private TapPacketReader mTapPacketReader;
-
- private TetheredInterfaceRequester mTetheredInterfaceRequester;
- private MyTetheringEventCallback mTetheringEventCallback;
-
- private UiAutomation mUiAutomation =
- InstrumentationRegistry.getInstrumentation().getUiAutomation();
- private boolean mRunTests;
-
- @Before
- public void setUp() throws Exception {
- // Needed to create a TestNetworkInterface, to call requestTetheredInterface, and to receive
- // tethered client callbacks.
- mUiAutomation.adoptShellPermissionIdentity(
- MANAGE_TEST_NETWORKS, NETWORK_SETTINGS, TETHER_PRIVILEGED);
- mRunTests = mTm.isTetheringSupported() && mEm != null;
- assumeTrue(mRunTests);
-
- mHandlerThread = new HandlerThread(getClass().getSimpleName());
- mHandlerThread.start();
- mHandler = new Handler(mHandlerThread.getLooper());
- mTetheredInterfaceRequester = new TetheredInterfaceRequester(mHandler, mEm);
- }
-
- private void cleanUp() throws Exception {
- mTm.stopTethering(TETHERING_ETHERNET);
- if (mTetheringEventCallback != null) {
- mTetheringEventCallback.awaitInterfaceUntethered();
- mTetheringEventCallback.unregister();
- mTetheringEventCallback = null;
- }
- if (mTapPacketReader != null) {
- TapPacketReader reader = mTapPacketReader;
- mHandler.post(() -> reader.stop());
- mTapPacketReader = null;
- }
- mHandlerThread.quitSafely();
- mTetheredInterfaceRequester.release();
- mEm.setIncludeTestInterfaces(false);
- maybeDeleteTestInterface();
- }
-
- @After
- public void tearDown() throws Exception {
- try {
- if (mRunTests) cleanUp();
- } finally {
- mUiAutomation.dropShellPermissionIdentity();
- }
- }
-
- @Test
- public void testVirtualEthernetAlreadyExists() throws Exception {
- // This test requires manipulating packets. Skip if there is a physical Ethernet connected.
- assumeFalse(mEm.isAvailable());
-
- mTestIface = createTestInterface();
- // This must be done now because as soon as setIncludeTestInterfaces(true) is called, the
- // interface will be placed in client mode, which will delete the link-local address.
- // At that point NetworkInterface.getByName() will cease to work on the interface, because
- // starting in R NetworkInterface can no longer see interfaces without IP addresses.
- int mtu = getMTU(mTestIface);
-
- Log.d(TAG, "Including test interfaces");
- mEm.setIncludeTestInterfaces(true);
-
- final String iface = mTetheredInterfaceRequester.getInterface();
- assertEquals("TetheredInterfaceCallback for unexpected interface",
- mTestIface.getInterfaceName(), iface);
-
- checkVirtualEthernet(mTestIface, mtu);
- }
-
- @Test
- public void testVirtualEthernet() throws Exception {
- // This test requires manipulating packets. Skip if there is a physical Ethernet connected.
- assumeFalse(mEm.isAvailable());
-
- CompletableFuture<String> futureIface = mTetheredInterfaceRequester.requestInterface();
-
- mEm.setIncludeTestInterfaces(true);
-
- mTestIface = createTestInterface();
-
- final String iface = futureIface.get(TIMEOUT_MS, TimeUnit.MILLISECONDS);
- assertEquals("TetheredInterfaceCallback for unexpected interface",
- mTestIface.getInterfaceName(), iface);
-
- checkVirtualEthernet(mTestIface, getMTU(mTestIface));
- }
-
- @Test
- public void testStaticIpv4() throws Exception {
- assumeFalse(mEm.isAvailable());
-
- mEm.setIncludeTestInterfaces(true);
-
- mTestIface = createTestInterface();
-
- final String iface = mTetheredInterfaceRequester.getInterface();
- assertEquals("TetheredInterfaceCallback for unexpected interface",
- mTestIface.getInterfaceName(), iface);
-
- assertInvalidStaticIpv4Request(iface, null, null);
- assertInvalidStaticIpv4Request(iface, "2001:db8::1/64", "2001:db8:2::/64");
- assertInvalidStaticIpv4Request(iface, "192.0.2.2/28", "2001:db8:2::/28");
- assertInvalidStaticIpv4Request(iface, "2001:db8:2::/28", "192.0.2.2/28");
- assertInvalidStaticIpv4Request(iface, "192.0.2.2/28", null);
- assertInvalidStaticIpv4Request(iface, null, "192.0.2.2/28");
- assertInvalidStaticIpv4Request(iface, "192.0.2.3/27", "192.0.2.2/28");
-
- final String localAddr = "192.0.2.3/28";
- final String clientAddr = "192.0.2.2/28";
- mTetheringEventCallback = enableEthernetTethering(iface,
- requestWithStaticIpv4(localAddr, clientAddr));
-
- mTetheringEventCallback.awaitInterfaceTethered();
- assertInterfaceHasIpAddress(iface, localAddr);
-
- byte[] client1 = MacAddress.fromString("1:2:3:4:5:6").toByteArray();
- byte[] client2 = MacAddress.fromString("a:b:c:d:e:f").toByteArray();
-
- FileDescriptor fd = mTestIface.getFileDescriptor().getFileDescriptor();
- mTapPacketReader = makePacketReader(fd, getMTU(mTestIface));
- DhcpResults dhcpResults = runDhcp(fd, client1);
- assertEquals(new LinkAddress(clientAddr), dhcpResults.ipAddress);
-
- try {
- runDhcp(fd, client2);
- fail("Only one client should get an IP address");
- } catch (TimeoutException expected) { }
-
- }
-
- private boolean isAdbOverNetwork() {
- // If adb TCP port opened, this test may running by adb over network.
- return (SystemProperties.getInt("persist.adb.tcp.port", -1) > -1)
- || (SystemProperties.getInt("service.adb.tcp.port", -1) > -1);
- }
-
- @Test
- public void testPhysicalEthernet() throws Exception {
- assumeTrue(mEm.isAvailable());
- // Do not run this test if adb is over network and ethernet is connected.
- // It is likely the adb run over ethernet, the adb would break when ethernet is switching
- // from client mode to server mode. See b/160389275.
- assumeFalse(isAdbOverNetwork());
-
- // Get an interface to use.
- final String iface = mTetheredInterfaceRequester.getInterface();
-
- // Enable Ethernet tethering and check that it starts.
- mTetheringEventCallback = enableEthernetTethering(iface);
-
- // There is nothing more we can do on a physical interface without connecting an actual
- // client, which is not possible in this test.
- }
-
- private static final class MyTetheringEventCallback implements TetheringEventCallback {
- private final TetheringManager mTm;
- private final CountDownLatch mTetheringStartedLatch = new CountDownLatch(1);
- private final CountDownLatch mTetheringStoppedLatch = new CountDownLatch(1);
- private final CountDownLatch mClientConnectedLatch = new CountDownLatch(1);
- private final String mIface;
-
- private volatile boolean mInterfaceWasTethered = false;
- private volatile boolean mUnregistered = false;
- private volatile Collection<TetheredClient> mClients = null;
-
- MyTetheringEventCallback(TetheringManager tm, String iface) {
- mTm = tm;
- mIface = iface;
- }
-
- public void unregister() {
- mTm.unregisterTetheringEventCallback(this);
- mUnregistered = true;
- }
-
- @Override
- public void onTetheredInterfacesChanged(List<String> interfaces) {
- // Ignore stale callbacks registered by previous test cases.
- if (mUnregistered) return;
-
- final boolean wasTethered = mTetheringStartedLatch.getCount() == 0;
- if (!mInterfaceWasTethered && (mIface == null || interfaces.contains(mIface))) {
- // This interface is being tethered for the first time.
- Log.d(TAG, "Tethering started: " + interfaces);
- mInterfaceWasTethered = true;
- mTetheringStartedLatch.countDown();
- } else if (mInterfaceWasTethered && !interfaces.contains(mIface)) {
- Log.d(TAG, "Tethering stopped: " + interfaces);
- mTetheringStoppedLatch.countDown();
- }
- }
-
- public void awaitInterfaceTethered() throws Exception {
- assertTrue("Ethernet not tethered after " + TIMEOUT_MS + "ms",
- mTetheringStartedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
- }
-
- public void awaitInterfaceUntethered() throws Exception {
- // Don't block teardown if the interface was never tethered.
- // This is racy because the interface might become tethered right after this check, but
- // that can only happen in tearDown if startTethering timed out, which likely means
- // the test has already failed.
- if (!mInterfaceWasTethered) return;
-
- assertTrue(mIface + " not untethered after " + TIMEOUT_MS + "ms",
- mTetheringStoppedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
- }
-
- @Override
- public void onError(String ifName, int error) {
- // Ignore stale callbacks registered by previous test cases.
- if (mUnregistered) return;
-
- fail("TetheringEventCallback got error:" + error + " on iface " + ifName);
- }
-
- @Override
- public void onClientsChanged(Collection<TetheredClient> clients) {
- // Ignore stale callbacks registered by previous test cases.
- if (mUnregistered) return;
-
- Log.d(TAG, "Got clients changed: " + clients);
- mClients = clients;
- if (clients.size() > 0) {
- mClientConnectedLatch.countDown();
- }
- }
-
- public Collection<TetheredClient> awaitClientConnected() throws Exception {
- assertTrue("Did not receive client connected callback after " + TIMEOUT_MS + "ms",
- mClientConnectedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
- return mClients;
- }
- }
-
- private MyTetheringEventCallback enableEthernetTethering(String iface,
- TetheringRequest request) throws Exception {
- MyTetheringEventCallback callback = new MyTetheringEventCallback(mTm, iface);
- mTm.registerTetheringEventCallback(mHandler::post, callback);
-
- StartTetheringCallback startTetheringCallback = new StartTetheringCallback() {
- @Override
- public void onTetheringFailed(int resultCode) {
- fail("Unexpectedly got onTetheringFailed");
- }
- };
- Log.d(TAG, "Starting Ethernet tethering");
- mTm.startTethering(request, mHandler::post /* executor */, startTetheringCallback);
- callback.awaitInterfaceTethered();
- return callback;
- }
-
- private MyTetheringEventCallback enableEthernetTethering(String iface) throws Exception {
- return enableEthernetTethering(iface,
- new TetheringRequest.Builder(TETHERING_ETHERNET)
- .setShouldShowEntitlementUi(false).build());
- }
-
- private int getMTU(TestNetworkInterface iface) throws SocketException {
- NetworkInterface nif = NetworkInterface.getByName(iface.getInterfaceName());
- assertNotNull("Can't get NetworkInterface object for " + iface.getInterfaceName(), nif);
- return nif.getMTU();
- }
-
- private TapPacketReader makePacketReader(FileDescriptor fd, int mtu) {
- final TapPacketReader reader = new TapPacketReader(mHandler, fd, mtu);
- mHandler.post(() -> reader.start());
- HandlerUtils.waitForIdle(mHandler, TIMEOUT_MS);
- return reader;
- }
-
- private void checkVirtualEthernet(TestNetworkInterface iface, int mtu) throws Exception {
- FileDescriptor fd = iface.getFileDescriptor().getFileDescriptor();
- mTapPacketReader = makePacketReader(fd, mtu);
- mTetheringEventCallback = enableEthernetTethering(iface.getInterfaceName());
- checkTetheredClientCallbacks(fd);
- }
-
- private DhcpResults runDhcp(FileDescriptor fd, byte[] clientMacAddr) throws Exception {
- // We have to retransmit DHCP requests because IpServer declares itself to be ready before
- // its DhcpServer is actually started. TODO: fix this race and remove this loop.
- DhcpPacket offerPacket = null;
- for (int i = 0; i < DHCP_DISCOVER_ATTEMPTS; i++) {
- Log.d(TAG, "Sending DHCP discover");
- sendDhcpDiscover(fd, clientMacAddr);
- offerPacket = getNextDhcpPacket();
- if (offerPacket instanceof DhcpOfferPacket) break;
- }
- if (!(offerPacket instanceof DhcpOfferPacket)) {
- throw new TimeoutException("No DHCPOFFER received on interface within timeout");
- }
-
- sendDhcpRequest(fd, offerPacket, clientMacAddr);
- DhcpPacket ackPacket = getNextDhcpPacket();
- if (!(ackPacket instanceof DhcpAckPacket)) {
- throw new TimeoutException("No DHCPACK received on interface within timeout");
- }
-
- return ackPacket.toDhcpResults();
- }
-
- private void checkTetheredClientCallbacks(FileDescriptor fd) throws Exception {
- // Create a fake client.
- byte[] clientMacAddr = new byte[6];
- new Random().nextBytes(clientMacAddr);
-
- DhcpResults dhcpResults = runDhcp(fd, clientMacAddr);
-
- final Collection<TetheredClient> clients = mTetheringEventCallback.awaitClientConnected();
- assertEquals(1, clients.size());
- final TetheredClient client = clients.iterator().next();
-
- // Check the MAC address.
- assertEquals(MacAddress.fromBytes(clientMacAddr), client.getMacAddress());
- assertEquals(TETHERING_ETHERNET, client.getTetheringType());
-
- // Check the hostname.
- assertEquals(1, client.getAddresses().size());
- TetheredClient.AddressInfo info = client.getAddresses().get(0);
- assertEquals(DHCP_HOSTNAME, info.getHostname());
-
- // Check the address is the one that was handed out in the DHCP ACK.
- assertLinkAddressMatches(dhcpResults.ipAddress, info.getAddress());
-
- // Check that the lifetime is correct +/- 10s.
- final long now = SystemClock.elapsedRealtime();
- final long actualLeaseDuration = (info.getAddress().getExpirationTime() - now) / 1000;
- final String msg = String.format("IP address should have lifetime of %d, got %d",
- dhcpResults.leaseDuration, actualLeaseDuration);
- assertTrue(msg, Math.abs(dhcpResults.leaseDuration - actualLeaseDuration) < 10);
- }
-
- private DhcpPacket getNextDhcpPacket() throws ParseException {
- byte[] packet;
- while ((packet = mTapPacketReader.popPacket(PACKET_READ_TIMEOUT_MS)) != null) {
- try {
- return DhcpPacket.decodeFullPacket(packet, packet.length, DhcpPacket.ENCAP_L2);
- } catch (DhcpPacket.ParseException e) {
- // Not a DHCP packet. Continue.
- }
- }
- return null;
- }
-
- private static final class TetheredInterfaceRequester implements TetheredInterfaceCallback {
- private final CountDownLatch mInterfaceAvailableLatch = new CountDownLatch(1);
- private final Handler mHandler;
- private final EthernetManager mEm;
-
- private TetheredInterfaceRequest mRequest;
- private final CompletableFuture<String> mFuture = new CompletableFuture<>();
-
- TetheredInterfaceRequester(Handler handler, EthernetManager em) {
- mHandler = handler;
- mEm = em;
- }
-
- @Override
- public void onAvailable(String iface) {
- Log.d(TAG, "Ethernet interface available: " + iface);
- mFuture.complete(iface);
- }
-
- @Override
- public void onUnavailable() {
- mFuture.completeExceptionally(new IllegalStateException("onUnavailable received"));
- }
-
- public CompletableFuture<String> requestInterface() {
- assertNull("BUG: more than one tethered interface request", mRequest);
- Log.d(TAG, "Requesting tethered interface");
- mRequest = mEm.requestTetheredInterface(mHandler::post, this);
- return mFuture;
- }
-
- public String getInterface() throws Exception {
- return requestInterface().get(TIMEOUT_MS, TimeUnit.MILLISECONDS);
- }
-
- public void release() {
- if (mRequest != null) {
- mFuture.obtrudeException(new IllegalStateException("Request already released"));
- mRequest.release();
- mRequest = null;
- }
- }
- }
-
- private void sendDhcpDiscover(FileDescriptor fd, byte[] macAddress) throws Exception {
- ByteBuffer packet = DhcpPacket.buildDiscoverPacket(DhcpPacket.ENCAP_L2,
- new Random().nextInt() /* transactionId */, (short) 0 /* secs */,
- macAddress, false /* unicast */, DHCP_REQUESTED_PARAMS,
- false /* rapid commit */, DHCP_HOSTNAME);
- sendPacket(fd, packet);
- }
-
- private void sendDhcpRequest(FileDescriptor fd, DhcpPacket offerPacket, byte[] macAddress)
- throws Exception {
- DhcpResults results = offerPacket.toDhcpResults();
- Inet4Address clientIp = (Inet4Address) results.ipAddress.getAddress();
- Inet4Address serverIdentifier = results.serverAddress;
- ByteBuffer packet = DhcpPacket.buildRequestPacket(DhcpPacket.ENCAP_L2,
- 0 /* transactionId */, (short) 0 /* secs */, DhcpPacket.INADDR_ANY /* clientIp */,
- false /* broadcast */, macAddress, clientIp /* requestedIpAddress */,
- serverIdentifier, DHCP_REQUESTED_PARAMS, DHCP_HOSTNAME);
- sendPacket(fd, packet);
- }
-
- private void sendPacket(FileDescriptor fd, ByteBuffer packet) throws Exception {
- assertNotNull("Only tests on virtual interfaces can send packets", fd);
- Os.write(fd, packet);
- }
-
- public void assertLinkAddressMatches(LinkAddress l1, LinkAddress l2) {
- // Check all fields except the deprecation and expiry times.
- String msg = String.format("LinkAddresses do not match. expected: %s actual: %s", l1, l2);
- assertTrue(msg, l1.isSameAddressAs(l2));
- assertEquals("LinkAddress flags do not match", l1.getFlags(), l2.getFlags());
- assertEquals("LinkAddress scope does not match", l1.getScope(), l2.getScope());
- }
-
- private TetheringRequest requestWithStaticIpv4(String local, String client) {
- LinkAddress localAddr = local == null ? null : new LinkAddress(local);
- LinkAddress clientAddr = client == null ? null : new LinkAddress(client);
- return new TetheringRequest.Builder(TETHERING_ETHERNET)
- .setStaticIpv4Addresses(localAddr, clientAddr)
- .setShouldShowEntitlementUi(false).build();
- }
-
- private void assertInvalidStaticIpv4Request(String iface, String local, String client)
- throws Exception {
- try {
- enableEthernetTethering(iface, requestWithStaticIpv4(local, client));
- fail("Unexpectedly accepted invalid IPv4 configuration: " + local + ", " + client);
- } catch (IllegalArgumentException | NullPointerException expected) { }
- }
-
- private void assertInterfaceHasIpAddress(String iface, String expected) throws Exception {
- LinkAddress expectedAddr = new LinkAddress(expected);
- NetworkInterface nif = NetworkInterface.getByName(iface);
- for (InterfaceAddress ia : nif.getInterfaceAddresses()) {
- final LinkAddress addr = new LinkAddress(ia.getAddress(), ia.getNetworkPrefixLength());
- if (expectedAddr.equals(addr)) {
- return;
- }
- }
- fail("Expected " + iface + " to have IP address " + expected + ", found "
- + nif.getInterfaceAddresses());
- }
-
- private TestNetworkInterface createTestInterface() throws Exception {
- TestNetworkManager tnm = mContext.getSystemService(TestNetworkManager.class);
- TestNetworkInterface iface = tnm.createTapInterface();
- Log.d(TAG, "Created test interface " + iface.getInterfaceName());
- return iface;
- }
-
- private void maybeDeleteTestInterface() throws Exception {
- if (mTestIface != null) {
- mTestIface.getFileDescriptor().close();
- Log.d(TAG, "Deleted test interface " + mTestIface.getInterfaceName());
- mTestIface = null;
- }
- }
-}
diff --git a/packages/Tethering/tests/jarjar-rules.txt b/packages/Tethering/tests/jarjar-rules.txt
deleted file mode 100644
index c99ff7f..0000000
--- a/packages/Tethering/tests/jarjar-rules.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-# Don't jar-jar the entire package because this test use some
-# internal classes (like ArrayUtils in com.android.internal.util)
-rule com.android.internal.util.BitUtils* com.android.networkstack.tethering.util.BitUtils@1
-rule com.android.internal.util.IndentingPrintWriter.java* com.android.networkstack.tethering.util.IndentingPrintWriter.java@1
-rule com.android.internal.util.IState.java* com.android.networkstack.tethering.util.IState.java@1
-rule com.android.internal.util.MessageUtils* com.android.networkstack.tethering.util.MessageUtils@1
-rule com.android.internal.util.State* com.android.networkstack.tethering.util.State@1
-rule com.android.internal.util.StateMachine* com.android.networkstack.tethering.util.StateMachine@1
-rule com.android.internal.util.TrafficStatsConstants* com.android.networkstack.tethering.util.TrafficStatsConstants@1
-
-rule android.util.LocalLog* com.android.networkstack.tethering.util.LocalLog@1
-
-# Classes from net-utils-framework-common
-rule com.android.net.module.util.** com.android.networkstack.tethering.util.@1
-
-# TODO: either stop using frameworks-base-testutils or remove the unit test classes it contains.
-# TestableLooper from "testables" can be used instead of TestLooper from frameworks-base-testutils.
-zap android.os.test.TestLooperTest*
-zap com.android.test.filters.SelectTestTests*
diff --git a/packages/Tethering/tests/mts/Android.bp b/packages/Tethering/tests/mts/Android.bp
deleted file mode 100644
index f925b0a..0000000
--- a/packages/Tethering/tests/mts/Android.bp
+++ /dev/null
@@ -1,56 +0,0 @@
-// 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.
-
-android_test {
- // This tests for functionality that is not required for devices that
- // don't use Tethering mainline module.
- name: "MtsTetheringTest",
-
- libs: [
- "android.test.base",
- ],
-
- srcs: [
- "src/**/*.java",
- ],
-
- static_libs: [
- "androidx.test.rules",
- // mockito-target-extended-minus-junit4 used in this lib have dependency with
- // jni_libs libdexmakerjvmtiagent and libstaticjvmtiagent.
- "cts-net-utils",
- // This is needed for androidx.test.runner.AndroidJUnitRunner.
- "ctstestrunner-axt",
- "junit",
- "junit-params",
- ],
-
- jni_libs: [
- // For mockito extended which is pulled in from -net-utils -> net-tests-utils
- // (mockito-target-extended-minus-junit4).
- "libdexmakerjvmtiagent",
- "libstaticjvmtiagent",
- ],
-
- platform_apis: true,
-
- // Tag this module as a mts test artifact
- test_suites: [
- "general-tests",
- "mts",
- ],
-
- // Include both the 32 and 64 bit versions
- compile_multilib: "both",
-}
diff --git a/packages/Tethering/tests/mts/AndroidManifest.xml b/packages/Tethering/tests/mts/AndroidManifest.xml
deleted file mode 100644
index 6d2abca..0000000
--- a/packages/Tethering/tests/mts/AndroidManifest.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * 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.
- -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.tethering.mts">
-
- <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
- <uses-permission android:name="android.permission.INTERNET"/>
-
- <application android:debuggable="true">
- <uses-library android:name="android.test.runner" />
- </application>
- <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
- android:targetPackage="android.tethering.mts"
- android:label="MTS tests of android.tethering">
- <meta-data android:name="listener"
- android:value="com.android.cts.runner.CtsTestRunListener" />
- </instrumentation>
-
-</manifest>
diff --git a/packages/Tethering/tests/mts/AndroidTest.xml b/packages/Tethering/tests/mts/AndroidTest.xml
deleted file mode 100644
index 80788df..0000000
--- a/packages/Tethering/tests/mts/AndroidTest.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2019 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.
--->
-<configuration description="Config for MTS Tethering test cases">
- <option name="test-suite-tag" value="mts" />
- <option name="config-descriptor:metadata" key="component" value="networking" />
- <!-- Instant app do not have INTERNET permission. -->
- <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
- <!-- Feature is not backed by native code. -->
- <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
- <!-- Allow running this against a secondary user. -->
- <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
- <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
- <option name="cleanup-apks" value="true" />
- <option name="test-file-name" value="MtsTetheringTest.apk" />
- </target_preparer>
- <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
- <option name="package" value="android.tethering.mts" />
- </test>
-
- <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
- <option name="mainline-module-package-name" value="com.google.android.tethering" />
- </object>
-</configuration>
diff --git a/packages/Tethering/tests/mts/src/android/tethering/mts/TetheringModuleTest.java b/packages/Tethering/tests/mts/src/android/tethering/mts/TetheringModuleTest.java
deleted file mode 100644
index 7ffe37a..0000000
--- a/packages/Tethering/tests/mts/src/android/tethering/mts/TetheringModuleTest.java
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * 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 android.tethering.mts;
-
-import static android.Manifest.permission.MANAGE_TEST_NETWORKS;
-import static android.Manifest.permission.NETWORK_SETTINGS;
-import static android.Manifest.permission.READ_DEVICE_CONFIG;
-import static android.Manifest.permission.TETHER_PRIVILEGED;
-import static android.Manifest.permission.WRITE_SETTINGS;
-import static android.net.cts.util.CtsTetheringUtils.isWifiTetheringSupported;
-import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY;
-
-import static com.android.testutils.TestNetworkTrackerKt.initTestNetwork;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.fail;
-import static org.junit.Assume.assumeTrue;
-
-import android.app.UiAutomation;
-import android.content.Context;
-import android.net.IpPrefix;
-import android.net.LinkAddress;
-import android.net.TetheringManager;
-import android.net.cts.util.CtsTetheringUtils;
-import android.net.cts.util.CtsTetheringUtils.TestTetheringEventCallback;
-import android.provider.DeviceConfig;
-
-import androidx.annotation.NonNull;
-import androidx.test.InstrumentationRegistry;
-import androidx.test.runner.AndroidJUnit4;
-
-import com.android.testutils.TestNetworkTracker;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.net.InterfaceAddress;
-import java.net.NetworkInterface;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-@RunWith(AndroidJUnit4.class)
-public class TetheringModuleTest {
- private Context mContext;
- private TetheringManager mTm;
- private CtsTetheringUtils mCtsTetheringUtils;
-
- private UiAutomation mUiAutomation =
- InstrumentationRegistry.getInstrumentation().getUiAutomation();
-
- @Before
- public void setUp() throws Exception {
- mUiAutomation.adoptShellPermissionIdentity(MANAGE_TEST_NETWORKS, NETWORK_SETTINGS,
- WRITE_SETTINGS, READ_DEVICE_CONFIG, TETHER_PRIVILEGED);
- mContext = InstrumentationRegistry.getContext();
- mTm = mContext.getSystemService(TetheringManager.class);
- mCtsTetheringUtils = new CtsTetheringUtils(mContext);
- }
-
- @After
- public void tearDown() throws Exception {
- mUiAutomation.dropShellPermissionIdentity();
- }
-
- private static final String TETHER_ENABLE_SELECT_ALL_PREFIX_RANGES =
- "tether_enable_select_all_prefix_ranges";
- @Test
- public void testSwitchBasePrefixRangeWhenConflict() throws Exception {
- assumeTrue(isFeatureEnabled(TETHER_ENABLE_SELECT_ALL_PREFIX_RANGES, true));
-
- addressConflictTest(true);
- }
-
- @Test
- public void testSwitchPrefixRangeWhenConflict() throws Exception {
- addressConflictTest(false);
- }
-
- private void addressConflictTest(final boolean wholeRangeConflict) throws Exception {
- final TestTetheringEventCallback tetherEventCallback =
- mCtsTetheringUtils.registerTetheringEventCallback();
-
- TestNetworkTracker tnt = null;
- try {
- tetherEventCallback.assumeTetheringSupported();
- assumeTrue(isWifiTetheringSupported(tetherEventCallback));
-
- mCtsTetheringUtils.startWifiTethering(tetherEventCallback);
-
- final List<String> tetheredIfaces = tetherEventCallback.getTetheredInterfaces();
- assertEquals(1, tetheredIfaces.size());
- final String wifiTetheringIface = tetheredIfaces.get(0);
-
- NetworkInterface nif = NetworkInterface.getByName(wifiTetheringIface);
- // Tethering downstream only have one ipv4 address.
- final LinkAddress hotspotAddr = getFirstIpv4Address(nif);
- assertNotNull(hotspotAddr);
-
- final IpPrefix testPrefix = getConflictingPrefix(hotspotAddr, wholeRangeConflict);
- assertNotNull(testPrefix);
-
- tnt = setUpTestNetwork(
- new LinkAddress(testPrefix.getAddress(), testPrefix.getPrefixLength()));
-
- tetherEventCallback.expectTetheredInterfacesChanged(null);
- final List<String> wifiRegexs =
- tetherEventCallback.getTetheringInterfaceRegexps().getTetherableWifiRegexs();
-
- tetherEventCallback.expectTetheredInterfacesChanged(wifiRegexs);
- nif = NetworkInterface.getByName(wifiTetheringIface);
- final LinkAddress newHotspotAddr = getFirstIpv4Address(nif);
- assertNotNull(newHotspotAddr);
-
- assertFalse(testPrefix.containsPrefix(
- new IpPrefix(newHotspotAddr.getAddress(), newHotspotAddr.getPrefixLength())));
-
- mCtsTetheringUtils.stopWifiTethering(tetherEventCallback);
- } finally {
- if (tnt != null) {
- tnt.teardown();
- }
- mTm.stopAllTethering();
- mCtsTetheringUtils.unregisterTetheringEventCallback(tetherEventCallback);
- }
- }
-
- private LinkAddress getFirstIpv4Address(final NetworkInterface nif) {
- for (InterfaceAddress ia : nif.getInterfaceAddresses()) {
- final LinkAddress addr = new LinkAddress(ia.getAddress(), ia.getNetworkPrefixLength());
- if (addr.isIpv4()) return addr;
- }
- return null;
- }
-
- @NonNull
- private IpPrefix getConflictingPrefix(final LinkAddress address,
- final boolean wholeRangeConflict) {
- if (!wholeRangeConflict) {
- return new IpPrefix(address.getAddress(), address.getPrefixLength());
- }
-
- final ArrayList<IpPrefix> prefixPool = new ArrayList<>(Arrays.asList(
- new IpPrefix("192.168.0.0/16"),
- new IpPrefix("172.16.0.0/12"),
- new IpPrefix("10.0.0.0/8")));
-
- for (IpPrefix prefix : prefixPool) {
- if (prefix.contains(address.getAddress())) return prefix;
- }
-
- fail("Could not find sutiable conflict prefix");
-
- // Never go here.
- return null;
- }
-
- private TestNetworkTracker setUpTestNetwork(final LinkAddress address) throws Exception {
- return initTestNetwork(mContext, address, 10_000L /* test timeout ms*/);
-
- }
-
- public static boolean isFeatureEnabled(final String name, final boolean defaultValue) {
- return DeviceConfig.getBoolean(NAMESPACE_CONNECTIVITY, name, defaultValue);
- }
-}
diff --git a/packages/Tethering/tests/privileged/Android.bp b/packages/Tethering/tests/privileged/Android.bp
deleted file mode 100644
index 9217345..0000000
--- a/packages/Tethering/tests/privileged/Android.bp
+++ /dev/null
@@ -1,49 +0,0 @@
-//
-// 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.
-//
-
-java_defaults {
- name: "TetheringPrivilegedTestsJniDefaults",
- jni_libs: [
- "libdexmakerjvmtiagent",
- "libstaticjvmtiagent",
- "libtetherutilsjni",
- ],
- jni_uses_sdk_apis: true,
- visibility: ["//visibility:private"],
-}
-
-android_test {
- name: "TetheringPrivilegedTests",
- defaults: [
- "TetheringPrivilegedTestsJniDefaults",
- ],
- srcs: [
- "src/**/*.java",
- "src/**/*.kt",
- ],
- certificate: "networkstack",
- platform_apis: true,
- test_suites: [
- "device-tests",
- "mts",
- ],
- static_libs: [
- "androidx.test.rules",
- "net-tests-utils",
- "TetheringApiCurrentLib",
- ],
- compile_multilib: "both",
-}
diff --git a/packages/Tethering/tests/privileged/AndroidManifest.xml b/packages/Tethering/tests/privileged/AndroidManifest.xml
deleted file mode 100644
index 49eba15d..0000000
--- a/packages/Tethering/tests/privileged/AndroidManifest.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.networkstack.tethering.tests.privileged"
- android:sharedUserId="android.uid.networkstack">
-
- <!-- Note: do not add any privileged or signature permissions that are granted
- to the network stack and its shared uid apps. Otherwise, the test APK will
- install, but when the device is rebooted, it will bootloop because this
- test APK is not in the privileged permission allow list -->
-
- <application android:debuggable="true">
- <uses-library android:name="android.test.runner" />
- </application>
- <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.networkstack.tethering.tests.privileged"
- android:label="Tethering privileged tests">
- </instrumentation>
-</manifest>
diff --git a/packages/Tethering/tests/privileged/src/android/net/ip/DadProxyTest.java b/packages/Tethering/tests/privileged/src/android/net/ip/DadProxyTest.java
deleted file mode 100644
index 42a91aa..0000000
--- a/packages/Tethering/tests/privileged/src/android/net/ip/DadProxyTest.java
+++ /dev/null
@@ -1,276 +0,0 @@
-/*
- * 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 android.net.ip;
-
-import static android.system.OsConstants.IPPROTO_ICMPV6;
-
-import static com.android.net.module.util.IpUtils.icmpv6Checksum;
-import static com.android.net.module.util.NetworkStackConstants.ETHER_SRC_ADDR_OFFSET;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-import android.app.Instrumentation;
-import android.content.Context;
-import android.net.INetd;
-import android.net.InetAddresses;
-import android.net.MacAddress;
-import android.net.util.InterfaceParams;
-import android.net.util.TetheringUtils;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.IBinder;
-import android.os.Looper;
-
-import androidx.test.InstrumentationRegistry;
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import com.android.testutils.TapPacketReader;
-import com.android.testutils.TapPacketReaderRule;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.MockitoAnnotations;
-
-import java.nio.ByteBuffer;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class DadProxyTest {
- private static final int DATA_BUFFER_LEN = 4096;
- private static final int PACKET_TIMEOUT_MS = 5_000;
-
- // Start the readers manually on a common handler shared with DadProxy, for simplicity
- @Rule
- public final TapPacketReaderRule mUpstreamReader = new TapPacketReaderRule(
- DATA_BUFFER_LEN, false /* autoStart */);
- @Rule
- public final TapPacketReaderRule mTetheredReader = new TapPacketReaderRule(
- DATA_BUFFER_LEN, false /* autoStart */);
-
- private InterfaceParams mUpstreamParams, mTetheredParams;
- private HandlerThread mHandlerThread;
- private Handler mHandler;
- private TapPacketReader mUpstreamPacketReader, mTetheredPacketReader;
-
- private static INetd sNetd;
-
- @BeforeClass
- public static void setupOnce() {
- System.loadLibrary("tetherutilsjni");
-
- final Instrumentation inst = InstrumentationRegistry.getInstrumentation();
- final IBinder netdIBinder =
- (IBinder) inst.getContext().getSystemService(Context.NETD_SERVICE);
- sNetd = INetd.Stub.asInterface(netdIBinder);
- }
-
- @Before
- public void setUp() throws Exception {
- MockitoAnnotations.initMocks(this);
-
- mHandlerThread = new HandlerThread(getClass().getSimpleName());
- mHandlerThread.start();
- mHandler = new Handler(mHandlerThread.getLooper());
-
- setupTapInterfaces();
-
- // Looper must be prepared here since AndroidJUnitRunner runs tests on separate threads.
- if (Looper.myLooper() == null) Looper.prepare();
-
- DadProxy mProxy = setupProxy();
- }
-
- @After
- public void tearDown() throws Exception {
- mUpstreamReader.stop();
- mTetheredReader.stop();
-
- if (mHandlerThread != null) {
- mHandlerThread.quitSafely();
- mHandlerThread.join(PACKET_TIMEOUT_MS);
- }
-
- if (mTetheredParams != null) {
- sNetd.networkRemoveInterface(INetd.LOCAL_NET_ID, mTetheredParams.name);
- }
- if (mUpstreamParams != null) {
- sNetd.networkRemoveInterface(INetd.LOCAL_NET_ID, mUpstreamParams.name);
- }
- }
-
- private void setupTapInterfaces() {
- // Create upstream test iface.
- mUpstreamReader.start(mHandler);
- mUpstreamParams = InterfaceParams.getByName(mUpstreamReader.iface.getInterfaceName());
- assertNotNull(mUpstreamParams);
- mUpstreamPacketReader = mUpstreamReader.getReader();
-
- // Create tethered test iface.
- mTetheredReader.start(mHandler);
- mTetheredParams = InterfaceParams.getByName(mTetheredReader.getIface().getInterfaceName());
- assertNotNull(mTetheredParams);
- mTetheredPacketReader = mTetheredReader.getReader();
- }
-
- private static final int IPV6_HEADER_LEN = 40;
- private static final int ETH_HEADER_LEN = 14;
- private static final int ICMPV6_NA_NS_LEN = 24;
- private static final int LL_TARGET_OPTION_LEN = 8;
- private static final int ICMPV6_CHECKSUM_OFFSET = 2;
- private static final int ETHER_TYPE_IPV6 = 0x86dd;
-
- private static ByteBuffer createDadPacket(int type) {
- // Refer to buildArpPacket()
- int icmpLen = ICMPV6_NA_NS_LEN
- + (type == NeighborPacketForwarder.ICMPV6_NEIGHBOR_ADVERTISEMENT
- ? LL_TARGET_OPTION_LEN : 0);
- final ByteBuffer buf = ByteBuffer.allocate(icmpLen + IPV6_HEADER_LEN + ETH_HEADER_LEN);
-
- // Ethernet header.
- final MacAddress srcMac = MacAddress.fromString("33:33:ff:66:77:88");
- buf.put(srcMac.toByteArray());
- final MacAddress dstMac = MacAddress.fromString("01:02:03:04:05:06");
- buf.put(dstMac.toByteArray());
- buf.putShort((short) ETHER_TYPE_IPV6);
-
- // IPv6 header
- byte[] version = {(byte) 0x60, 0x00, 0x00, 0x00};
- buf.put(version); // Version
- buf.putShort((byte) icmpLen); // Length
- buf.put((byte) IPPROTO_ICMPV6); // Next header
- buf.put((byte) 0xff); // Hop limit
-
- final byte[] target =
- InetAddresses.parseNumericAddress("fe80::1122:3344:5566:7788").getAddress();
- final byte[] src;
- final byte[] dst;
- if (type == NeighborPacketForwarder.ICMPV6_NEIGHBOR_SOLICITATION) {
- src = InetAddresses.parseNumericAddress("::").getAddress();
- dst = InetAddresses.parseNumericAddress("ff02::1:ff66:7788").getAddress();
- } else {
- src = target;
- dst = TetheringUtils.ALL_NODES;
- }
- buf.put(src);
- buf.put(dst);
-
- // ICMPv6 Header
- buf.put((byte) type); // Type
- buf.put((byte) 0x00); // Code
- buf.putShort((short) 0); // Checksum
- buf.putInt(0); // Reserved
- buf.put(target);
-
- if (type == NeighborPacketForwarder.ICMPV6_NEIGHBOR_ADVERTISEMENT) {
- //NA packet has LL target address
- //ICMPv6 Option
- buf.put((byte) 0x02); // Type
- buf.put((byte) 0x01); // Length
- byte[] ll_target = MacAddress.fromString("01:02:03:04:05:06").toByteArray();
- buf.put(ll_target);
- }
-
- // Populate checksum field
- final int transportOffset = ETH_HEADER_LEN + IPV6_HEADER_LEN;
- final short checksum = icmpv6Checksum(buf, ETH_HEADER_LEN, transportOffset, icmpLen);
- buf.putShort(transportOffset + ICMPV6_CHECKSUM_OFFSET, checksum);
-
- buf.flip();
- return buf;
- }
-
- private DadProxy setupProxy() throws Exception {
- DadProxy proxy = new DadProxy(mHandler, mTetheredParams);
- mHandler.post(() -> proxy.setUpstreamIface(mUpstreamParams));
-
- // Upstream iface is added to local network to simplify test case.
- // Otherwise the test needs to create and destroy a network for the upstream iface.
- sNetd.networkAddInterface(INetd.LOCAL_NET_ID, mUpstreamParams.name);
- sNetd.networkAddInterface(INetd.LOCAL_NET_ID, mTetheredParams.name);
-
- return proxy;
- }
-
- // TODO: change to assert.
- private boolean waitForPacket(ByteBuffer packet, TapPacketReader reader) {
- byte[] p;
-
- while ((p = reader.popPacket(PACKET_TIMEOUT_MS)) != null) {
- final ByteBuffer buffer = ByteBuffer.wrap(p);
-
- if (buffer.compareTo(packet) == 0) return true;
- }
- return false;
- }
-
- private void updateDstMac(ByteBuffer buf, MacAddress mac) {
- buf.put(mac.toByteArray());
- buf.rewind();
- }
- private void updateSrcMac(ByteBuffer buf, InterfaceParams ifaceParams) {
- buf.position(ETHER_SRC_ADDR_OFFSET);
- buf.put(ifaceParams.macAddr.toByteArray());
- buf.rewind();
- }
-
- @Test
- public void testNaForwardingFromUpstreamToTether() throws Exception {
- ByteBuffer na = createDadPacket(NeighborPacketForwarder.ICMPV6_NEIGHBOR_ADVERTISEMENT);
-
- mUpstreamPacketReader.sendResponse(na);
- updateDstMac(na, MacAddress.fromString("33:33:00:00:00:01"));
- updateSrcMac(na, mTetheredParams);
- assertTrue(waitForPacket(na, mTetheredPacketReader));
- }
-
- @Test
- // TODO: remove test once DAD works in both directions.
- public void testNaForwardingFromTetherToUpstream() throws Exception {
- ByteBuffer na = createDadPacket(NeighborPacketForwarder.ICMPV6_NEIGHBOR_ADVERTISEMENT);
-
- mTetheredPacketReader.sendResponse(na);
- updateDstMac(na, MacAddress.fromString("33:33:00:00:00:01"));
- updateSrcMac(na, mTetheredParams);
- assertFalse(waitForPacket(na, mUpstreamPacketReader));
- }
-
- @Test
- public void testNsForwardingFromTetherToUpstream() throws Exception {
- ByteBuffer ns = createDadPacket(NeighborPacketForwarder.ICMPV6_NEIGHBOR_SOLICITATION);
-
- mTetheredPacketReader.sendResponse(ns);
- updateSrcMac(ns, mUpstreamParams);
- assertTrue(waitForPacket(ns, mUpstreamPacketReader));
- }
-
- @Test
- // TODO: remove test once DAD works in both directions.
- public void testNsForwardingFromUpstreamToTether() throws Exception {
- ByteBuffer ns = createDadPacket(NeighborPacketForwarder.ICMPV6_NEIGHBOR_SOLICITATION);
-
- mUpstreamPacketReader.sendResponse(ns);
- updateSrcMac(ns, mUpstreamParams);
- assertFalse(waitForPacket(ns, mTetheredPacketReader));
- }
-}
diff --git a/packages/Tethering/tests/privileged/src/com/android/networkstack/tethering/ConntrackSocketTest.java b/packages/Tethering/tests/privileged/src/com/android/networkstack/tethering/ConntrackSocketTest.java
deleted file mode 100644
index 57c28fc..0000000
--- a/packages/Tethering/tests/privileged/src/com/android/networkstack/tethering/ConntrackSocketTest.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * 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;
-
-import static android.net.netlink.NetlinkSocket.DEFAULT_RECV_BUFSIZE;
-import static android.net.netlink.StructNlMsgHdr.NLM_F_DUMP;
-import static android.net.netlink.StructNlMsgHdr.NLM_F_REQUEST;
-
-import static com.android.networkstack.tethering.OffloadHardwareInterface.IPCTNL_MSG_CT_GET;
-import static com.android.networkstack.tethering.OffloadHardwareInterface.IPCTNL_MSG_CT_NEW;
-import static com.android.networkstack.tethering.OffloadHardwareInterface.NFNL_SUBSYS_CTNETLINK;
-import static com.android.networkstack.tethering.OffloadHardwareInterface.NF_NETLINK_CONNTRACK_DESTROY;
-import static com.android.networkstack.tethering.OffloadHardwareInterface.NF_NETLINK_CONNTRACK_NEW;
-
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-import android.net.netlink.StructNlMsgHdr;
-import android.net.util.SharedLog;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.Looper;
-import android.os.NativeHandle;
-import android.system.Os;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.MockitoAnnotations;
-
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.net.ServerSocket;
-import java.net.Socket;
-import java.net.SocketAddress;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class ConntrackSocketTest {
- private static final long TIMEOUT = 500;
-
- private HandlerThread mHandlerThread;
- private Handler mHandler;
- private final SharedLog mLog = new SharedLog("privileged-test");
-
- private OffloadHardwareInterface mOffloadHw;
- private OffloadHardwareInterface.Dependencies mDeps;
-
- @Before
- public void setUp() throws Exception {
- MockitoAnnotations.initMocks(this);
-
- mHandlerThread = new HandlerThread(getClass().getSimpleName());
- mHandlerThread.start();
- mHandler = new Handler(mHandlerThread.getLooper());
-
- // Looper must be prepared here since AndroidJUnitRunner runs tests on separate threads.
- if (Looper.myLooper() == null) Looper.prepare();
-
- mDeps = new OffloadHardwareInterface.Dependencies(mLog);
- mOffloadHw = new OffloadHardwareInterface(mHandler, mLog, mDeps);
- }
-
- @Test
- public void testIpv4ConntrackSocket() throws Exception {
- // Set up server and connect.
- final InetSocketAddress anyAddress = new InetSocketAddress(
- InetAddress.getByName("127.0.0.1"), 0);
- final ServerSocket serverSocket = new ServerSocket();
- serverSocket.bind(anyAddress);
- final SocketAddress theAddress = serverSocket.getLocalSocketAddress();
-
- // Make a connection to the server.
- final Socket socket = new Socket();
- socket.connect(theAddress);
- final Socket acceptedSocket = serverSocket.accept();
-
- final NativeHandle handle = mDeps.createConntrackSocket(
- NF_NETLINK_CONNTRACK_NEW | NF_NETLINK_CONNTRACK_DESTROY);
- mOffloadHw.sendIpv4NfGenMsg(handle,
- (short) ((NFNL_SUBSYS_CTNETLINK << 8) | IPCTNL_MSG_CT_GET),
- (short) (NLM_F_REQUEST | NLM_F_DUMP));
-
- boolean foundConntrackEntry = false;
- ByteBuffer buffer = ByteBuffer.allocate(DEFAULT_RECV_BUFSIZE);
- buffer.order(ByteOrder.nativeOrder());
-
- try {
- while (Os.read(handle.getFileDescriptor(), buffer) > 0) {
- buffer.flip();
-
- // TODO: ConntrackMessage should get a parse API like StructNlMsgHdr
- // so we can confirm that the conntrack added is for the TCP connection above.
- final StructNlMsgHdr nlmsghdr = StructNlMsgHdr.parse(buffer);
- assertNotNull(nlmsghdr);
-
- // As long as 1 conntrack entry is found test case will pass, even if it's not
- // the from the TCP connection above.
- if (nlmsghdr.nlmsg_type == ((NFNL_SUBSYS_CTNETLINK << 8) | IPCTNL_MSG_CT_NEW)) {
- foundConntrackEntry = true;
- break;
- }
- }
- } finally {
- socket.close();
- serverSocket.close();
- }
- assertTrue("Did not receive any NFNL_SUBSYS_CTNETLINK/IPCTNL_MSG_CT_NEW message",
- foundConntrackEntry);
- }
-}
diff --git a/packages/Tethering/tests/unit/Android.bp b/packages/Tethering/tests/unit/Android.bp
deleted file mode 100644
index 3589725..0000000
--- a/packages/Tethering/tests/unit/Android.bp
+++ /dev/null
@@ -1,93 +0,0 @@
-//
-// Copyright (C) 2019 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.
-//
-
-// Tests in this folder are included both in unit tests and CTS.
-java_library {
- name: "TetheringCommonTests",
- srcs: [
- "common/**/*.java",
- "common/**/*.kt"
- ],
- static_libs: [
- "androidx.test.rules",
- "net-tests-utils",
- ],
- // TODO(b/147200698) change sdk_version to module-current and remove framework-minus-apex
- sdk_version: "core_platform",
- libs: [
- "framework-minus-apex",
- "framework-tethering.impl",
- ],
- visibility: ["//cts/tests/tests/tethering"],
-}
-
-java_defaults {
- name: "TetheringTestsDefaults",
- srcs: [
- "src/**/*.java",
- "src/**/*.kt",
- ],
- static_libs: [
- "TetheringApiCurrentLib",
- "TetheringCommonTests",
- "androidx.test.rules",
- "frameworks-base-testutils",
- "mockito-target-extended-minus-junit4",
- "net-tests-utils",
- "testables",
- ],
- // TODO(b/147200698) change sdk_version to module-current and
- // remove framework-minus-apex, ext, and framework-res
- sdk_version: "core_platform",
- libs: [
- "android.test.runner",
- "android.test.base",
- "android.test.mock",
- "ext",
- "framework-minus-apex",
- "framework-res",
- "framework-tethering.impl",
- "framework-wifi.stubs.module_lib",
- ],
- jni_libs: [
- // For mockito extended
- "libdexmakerjvmtiagent",
- "libstaticjvmtiagent",
- ],
-}
-
-// Library containing the unit tests. This is used by the coverage test target to pull in the
-// unit test code. It is not currently used by the tests themselves because all the build
-// configuration needed by the tests is in the TetheringTestsDefaults rule.
-android_library {
- name: "TetheringTestsLib",
- defaults: ["TetheringTestsDefaults"],
- visibility: [
- "//frameworks/base/packages/Tethering/tests/integration",
- ]
-}
-
-android_test {
- name: "TetheringTests",
- platform_apis: true,
- test_suites: [
- "device-tests",
- "mts",
- ],
- jarjar_rules: ":TetheringTestsJarJarRules",
- defaults: ["TetheringTestsDefaults"],
- compile_multilib: "both",
-}
diff --git a/packages/Tethering/tests/unit/AndroidManifest.xml b/packages/Tethering/tests/unit/AndroidManifest.xml
deleted file mode 100644
index 355342f..0000000
--- a/packages/Tethering/tests/unit/AndroidManifest.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2019 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.
--->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.networkstack.tethering.tests.unit">
-
- <application android:debuggable="true">
- <uses-library android:name="android.test.runner" />
- <service
- android:name="com.android.networkstack.tethering.MockTetheringService"
- android:permission="android.permission.TETHER_PRIVILEGED"
- android:exported="true">
- <intent-filter>
- <action android:name="com.android.networkstack.tethering.TetheringService"/>
- </intent-filter>
- </service>
- </application>
-
- <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.networkstack.tethering.tests.unit"
- android:label="Tethering service tests">
- </instrumentation>
-</manifest>
diff --git a/packages/Tethering/tests/unit/common/android/net/TetheredClientTest.kt b/packages/Tethering/tests/unit/common/android/net/TetheredClientTest.kt
deleted file mode 100644
index 55c59dd..0000000
--- a/packages/Tethering/tests/unit/common/android/net/TetheredClientTest.kt
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * 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 android.net
-
-import android.net.InetAddresses.parseNumericAddress
-import android.net.TetheredClient.AddressInfo
-import android.net.TetheringManager.TETHERING_BLUETOOTH
-import android.net.TetheringManager.TETHERING_USB
-import android.system.OsConstants.RT_SCOPE_UNIVERSE
-import androidx.test.filters.SmallTest
-import androidx.test.runner.AndroidJUnit4
-import com.android.testutils.assertParcelSane
-import org.junit.Test
-import org.junit.runner.RunWith
-import kotlin.test.assertEquals
-import kotlin.test.assertNotEquals
-
-private val TEST_MACADDR = MacAddress.fromBytes(byteArrayOf(12, 23, 34, 45, 56, 67))
-private val TEST_OTHER_MACADDR = MacAddress.fromBytes(byteArrayOf(23, 34, 45, 56, 67, 78))
-private val TEST_ADDR1 = makeLinkAddress("192.168.113.3", prefixLength = 24, expTime = 123L)
-private val TEST_ADDR2 = makeLinkAddress("fe80::1:2:3", prefixLength = 64, expTime = 456L)
-private val TEST_HOSTNAME = "test_hostname"
-private val TEST_OTHER_HOSTNAME = "test_other_hostname"
-private val TEST_ADDRINFO1 = AddressInfo(TEST_ADDR1, TEST_HOSTNAME)
-private val TEST_ADDRINFO2 = AddressInfo(TEST_ADDR2, null)
-
-private fun makeLinkAddress(addr: String, prefixLength: Int, expTime: Long) = LinkAddress(
- parseNumericAddress(addr),
- prefixLength,
- 0 /* flags */,
- RT_SCOPE_UNIVERSE,
- expTime /* deprecationTime */,
- expTime /* expirationTime */)
-
-@RunWith(AndroidJUnit4::class)
-@SmallTest
-class TetheredClientTest {
- @Test
- fun testParceling() {
- assertParcelSane(TEST_ADDRINFO1, fieldCount = 2)
- assertParcelSane(makeTestClient(), fieldCount = 3)
- }
-
- @Test
- fun testEquals() {
- assertEquals(makeTestClient(), makeTestClient())
-
- // Different mac address
- assertNotEquals(makeTestClient(), TetheredClient(
- TEST_OTHER_MACADDR,
- listOf(TEST_ADDRINFO1, TEST_ADDRINFO2),
- TETHERING_BLUETOOTH))
-
- // Different hostname
- assertNotEquals(makeTestClient(), TetheredClient(
- TEST_MACADDR,
- listOf(AddressInfo(TEST_ADDR1, TEST_OTHER_HOSTNAME), TEST_ADDRINFO2),
- TETHERING_BLUETOOTH))
-
- // Null hostname
- assertNotEquals(makeTestClient(), TetheredClient(
- TEST_MACADDR,
- listOf(AddressInfo(TEST_ADDR1, null), TEST_ADDRINFO2),
- TETHERING_BLUETOOTH))
-
- // Missing address
- assertNotEquals(makeTestClient(), TetheredClient(
- TEST_MACADDR,
- listOf(TEST_ADDRINFO2),
- TETHERING_BLUETOOTH))
-
- // Different type
- assertNotEquals(makeTestClient(), TetheredClient(
- TEST_MACADDR,
- listOf(TEST_ADDRINFO1, TEST_ADDRINFO2),
- TETHERING_USB))
- }
-
- @Test
- fun testAddAddresses() {
- val client1 = TetheredClient(TEST_MACADDR, listOf(TEST_ADDRINFO1), TETHERING_USB)
- val client2 = TetheredClient(TEST_OTHER_MACADDR, listOf(TEST_ADDRINFO2), TETHERING_USB)
- assertEquals(TetheredClient(
- TEST_MACADDR,
- listOf(TEST_ADDRINFO1, TEST_ADDRINFO2),
- TETHERING_USB), client1.addAddresses(client2))
- }
-
- @Test
- fun testGetters() {
- assertEquals(TEST_MACADDR, makeTestClient().macAddress)
- assertEquals(listOf(TEST_ADDRINFO1, TEST_ADDRINFO2), makeTestClient().addresses)
- assertEquals(TETHERING_BLUETOOTH, makeTestClient().tetheringType)
- }
-
- @Test
- fun testAddressInfo_Getters() {
- assertEquals(TEST_ADDR1, TEST_ADDRINFO1.address)
- assertEquals(TEST_ADDR2, TEST_ADDRINFO2.address)
- assertEquals(TEST_HOSTNAME, TEST_ADDRINFO1.hostname)
- assertEquals(null, TEST_ADDRINFO2.hostname)
- }
-
- private fun makeTestClient() = TetheredClient(
- TEST_MACADDR,
- listOf(TEST_ADDRINFO1, TEST_ADDRINFO2),
- TETHERING_BLUETOOTH)
-}
\ No newline at end of file
diff --git a/packages/Tethering/tests/unit/src/android/net/dhcp/DhcpServingParamsParcelExtTest.java b/packages/Tethering/tests/unit/src/android/net/dhcp/DhcpServingParamsParcelExtTest.java
deleted file mode 100644
index a8857b2..0000000
--- a/packages/Tethering/tests/unit/src/android/net/dhcp/DhcpServingParamsParcelExtTest.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright (C) 2018 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 android.net.dhcp;
-
-import static android.net.InetAddresses.parseNumericAddress;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import android.net.LinkAddress;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.net.Inet4Address;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.stream.Collectors;
-import java.util.stream.IntStream;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class DhcpServingParamsParcelExtTest {
- private static final Inet4Address TEST_ADDRESS = inet4Addr("192.168.0.123");
- private static final Inet4Address TEST_CLIENT_ADDRESS = inet4Addr("192.168.0.42");
- private static final int TEST_ADDRESS_PARCELED = 0xc0a8007b;
- private static final int TEST_CLIENT_ADDRESS_PARCELED = 0xc0a8002a;
- private static final int TEST_PREFIX_LENGTH = 17;
- private static final int TEST_LEASE_TIME_SECS = 120;
- private static final int TEST_MTU = 1000;
- private static final Set<Inet4Address> TEST_ADDRESS_SET =
- new HashSet<Inet4Address>(Arrays.asList(
- new Inet4Address[] {inet4Addr("192.168.1.123"), inet4Addr("192.168.1.124")}));
- private static final Set<Integer> TEST_ADDRESS_SET_PARCELED =
- new HashSet<Integer>(Arrays.asList(new Integer[] {0xc0a8017b, 0xc0a8017c}));
-
- private DhcpServingParamsParcelExt mParcel;
-
- @Before
- public void setUp() {
- mParcel = new DhcpServingParamsParcelExt();
- }
-
- @Test
- public void testSetServerAddr() {
- mParcel.setServerAddr(new LinkAddress(TEST_ADDRESS, TEST_PREFIX_LENGTH));
-
- assertEquals(TEST_ADDRESS_PARCELED, mParcel.serverAddr);
- assertEquals(TEST_PREFIX_LENGTH, mParcel.serverAddrPrefixLength);
- }
-
- @Test
- public void testSetDefaultRouters() {
- mParcel.setDefaultRouters(TEST_ADDRESS_SET);
- assertEquals(TEST_ADDRESS_SET_PARCELED, asSet(mParcel.defaultRouters));
- }
-
- @Test
- public void testSetDnsServers() {
- mParcel.setDnsServers(TEST_ADDRESS_SET);
- assertEquals(TEST_ADDRESS_SET_PARCELED, asSet(mParcel.dnsServers));
- }
-
- @Test
- public void testSetExcludedAddrs() {
- mParcel.setExcludedAddrs(TEST_ADDRESS_SET);
- assertEquals(TEST_ADDRESS_SET_PARCELED, asSet(mParcel.excludedAddrs));
- }
-
- @Test
- public void testSetDhcpLeaseTimeSecs() {
- mParcel.setDhcpLeaseTimeSecs(TEST_LEASE_TIME_SECS);
- assertEquals(TEST_LEASE_TIME_SECS, mParcel.dhcpLeaseTimeSecs);
- }
-
- @Test
- public void testSetLinkMtu() {
- mParcel.setLinkMtu(TEST_MTU);
- assertEquals(TEST_MTU, mParcel.linkMtu);
- }
-
- @Test
- public void testSetMetered() {
- mParcel.setMetered(true);
- assertTrue(mParcel.metered);
- mParcel.setMetered(false);
- assertFalse(mParcel.metered);
- }
-
- @Test
- public void testSetClientAddr() {
- mParcel.setSingleClientAddr(TEST_CLIENT_ADDRESS);
- assertEquals(TEST_CLIENT_ADDRESS_PARCELED, mParcel.singleClientAddr);
- }
-
- private static Inet4Address inet4Addr(String addr) {
- return (Inet4Address) parseNumericAddress(addr);
- }
-
- private static Set<Integer> asSet(int[] ints) {
- return IntStream.of(ints).boxed().collect(Collectors.toSet());
- }
-}
diff --git a/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java b/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
deleted file mode 100644
index 2eb7589..0000000
--- a/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
+++ /dev/null
@@ -1,1201 +0,0 @@
-/*
- * Copyright (C) 2016 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 android.net.ip;
-
-import static android.net.INetd.IF_STATE_UP;
-import static android.net.RouteInfo.RTN_UNICAST;
-import static android.net.TetheringManager.TETHERING_BLUETOOTH;
-import static android.net.TetheringManager.TETHERING_NCM;
-import static android.net.TetheringManager.TETHERING_USB;
-import static android.net.TetheringManager.TETHERING_WIFI;
-import static android.net.TetheringManager.TETHERING_WIFI_P2P;
-import static android.net.TetheringManager.TETHER_ERROR_ENABLE_FORWARDING_ERROR;
-import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
-import static android.net.TetheringManager.TETHER_ERROR_TETHER_IFACE_ERROR;
-import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS;
-import static android.net.ip.IpServer.STATE_AVAILABLE;
-import static android.net.ip.IpServer.STATE_LOCAL_ONLY;
-import static android.net.ip.IpServer.STATE_TETHERED;
-import static android.net.ip.IpServer.STATE_UNAVAILABLE;
-import static android.net.netlink.NetlinkConstants.RTM_DELNEIGH;
-import static android.net.netlink.NetlinkConstants.RTM_NEWNEIGH;
-import static android.net.netlink.StructNdMsg.NUD_FAILED;
-import static android.net.netlink.StructNdMsg.NUD_REACHABLE;
-import static android.net.netlink.StructNdMsg.NUD_STALE;
-
-import static com.android.net.module.util.Inet4AddressUtils.intToInet4AddressHTH;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import static org.mockito.ArgumentMatchers.argThat;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyBoolean;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.doThrow;
-import static org.mockito.Mockito.inOrder;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.timeout;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.mockito.Mockito.when;
-
-import android.app.usage.NetworkStatsManager;
-import android.net.INetd;
-import android.net.InetAddresses;
-import android.net.InterfaceConfigurationParcel;
-import android.net.IpPrefix;
-import android.net.LinkAddress;
-import android.net.LinkProperties;
-import android.net.MacAddress;
-import android.net.RouteInfo;
-import android.net.TetherOffloadRuleParcel;
-import android.net.TetherStatsParcel;
-import android.net.dhcp.DhcpServerCallbacks;
-import android.net.dhcp.DhcpServingParamsParcel;
-import android.net.dhcp.IDhcpEventCallbacks;
-import android.net.dhcp.IDhcpServer;
-import android.net.dhcp.IDhcpServerCallbacks;
-import android.net.ip.IpNeighborMonitor.NeighborEvent;
-import android.net.ip.IpNeighborMonitor.NeighborEventConsumer;
-import android.net.ip.RouterAdvertisementDaemon.RaParams;
-import android.net.util.InterfaceParams;
-import android.net.util.InterfaceSet;
-import android.net.util.PrefixUtils;
-import android.net.util.SharedLog;
-import android.os.Build;
-import android.os.Handler;
-import android.os.RemoteException;
-import android.os.test.TestLooper;
-import android.text.TextUtils;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import com.android.networkstack.tethering.BpfCoordinator;
-import com.android.networkstack.tethering.BpfCoordinator.Ipv6ForwardingRule;
-import com.android.networkstack.tethering.PrivateAddressCoordinator;
-import com.android.networkstack.tethering.TetheringConfiguration;
-import com.android.testutils.DevSdkIgnoreRule;
-import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter;
-import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.ArgumentMatcher;
-import org.mockito.Captor;
-import org.mockito.InOrder;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-import java.net.Inet4Address;
-import java.net.Inet6Address;
-import java.net.InetAddress;
-import java.util.Arrays;
-import java.util.List;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class IpServerTest {
- @Rule
- public final DevSdkIgnoreRule mIgnoreRule = new DevSdkIgnoreRule();
-
- private static final String IFACE_NAME = "testnet1";
- private static final String UPSTREAM_IFACE = "upstream0";
- private static final String UPSTREAM_IFACE2 = "upstream1";
- private static final int UPSTREAM_IFINDEX = 101;
- private static final int UPSTREAM_IFINDEX2 = 102;
- private static final String BLUETOOTH_IFACE_ADDR = "192.168.44.1";
- private static final int BLUETOOTH_DHCP_PREFIX_LENGTH = 24;
- private static final int DHCP_LEASE_TIME_SECS = 3600;
- private static final boolean DEFAULT_USING_BPF_OFFLOAD = true;
-
- private static final InterfaceParams TEST_IFACE_PARAMS = new InterfaceParams(
- IFACE_NAME, 42 /* index */, MacAddress.ALL_ZEROS_ADDRESS, 1500 /* defaultMtu */);
- private static final InterfaceParams UPSTREAM_IFACE_PARAMS = new InterfaceParams(
- UPSTREAM_IFACE, UPSTREAM_IFINDEX, MacAddress.ALL_ZEROS_ADDRESS, 1500 /* defaultMtu */);
- private static final InterfaceParams UPSTREAM_IFACE_PARAMS2 = new InterfaceParams(
- UPSTREAM_IFACE2, UPSTREAM_IFINDEX2, MacAddress.ALL_ZEROS_ADDRESS,
- 1500 /* defaultMtu */);
-
- private static final int MAKE_DHCPSERVER_TIMEOUT_MS = 1000;
-
- private final LinkAddress mTestAddress = new LinkAddress("192.168.42.5/24");
- private final IpPrefix mBluetoothPrefix = new IpPrefix("192.168.44.0/24");
-
- @Mock private INetd mNetd;
- @Mock private IpServer.Callback mCallback;
- @Mock private SharedLog mSharedLog;
- @Mock private IDhcpServer mDhcpServer;
- @Mock private DadProxy mDadProxy;
- @Mock private RouterAdvertisementDaemon mRaDaemon;
- @Mock private IpNeighborMonitor mIpNeighborMonitor;
- @Mock private IpServer.Dependencies mDependencies;
- @Mock private PrivateAddressCoordinator mAddressCoordinator;
- @Mock private NetworkStatsManager mStatsManager;
- @Mock private TetheringConfiguration mTetherConfig;
-
- @Captor private ArgumentCaptor<DhcpServingParamsParcel> mDhcpParamsCaptor;
-
- private final TestLooper mLooper = new TestLooper();
- private final ArgumentCaptor<LinkProperties> mLinkPropertiesCaptor =
- ArgumentCaptor.forClass(LinkProperties.class);
- private IpServer mIpServer;
- private InterfaceConfigurationParcel mInterfaceConfiguration;
- private NeighborEventConsumer mNeighborEventConsumer;
- private BpfCoordinator mBpfCoordinator;
-
- private void initStateMachine(int interfaceType) throws Exception {
- initStateMachine(interfaceType, false /* usingLegacyDhcp */, DEFAULT_USING_BPF_OFFLOAD);
- }
-
- private void initStateMachine(int interfaceType, boolean usingLegacyDhcp,
- boolean usingBpfOffload) throws Exception {
- when(mDependencies.getDadProxy(any(), any())).thenReturn(mDadProxy);
- when(mDependencies.getRouterAdvertisementDaemon(any())).thenReturn(mRaDaemon);
- when(mDependencies.getInterfaceParams(IFACE_NAME)).thenReturn(TEST_IFACE_PARAMS);
- when(mDependencies.getInterfaceParams(UPSTREAM_IFACE)).thenReturn(UPSTREAM_IFACE_PARAMS);
- when(mDependencies.getInterfaceParams(UPSTREAM_IFACE2)).thenReturn(UPSTREAM_IFACE_PARAMS2);
-
- when(mDependencies.getIfindex(eq(UPSTREAM_IFACE))).thenReturn(UPSTREAM_IFINDEX);
- when(mDependencies.getIfindex(eq(UPSTREAM_IFACE2))).thenReturn(UPSTREAM_IFINDEX2);
-
- mInterfaceConfiguration = new InterfaceConfigurationParcel();
- mInterfaceConfiguration.flags = new String[0];
- if (interfaceType == TETHERING_BLUETOOTH) {
- mInterfaceConfiguration.ipv4Addr = BLUETOOTH_IFACE_ADDR;
- mInterfaceConfiguration.prefixLength = BLUETOOTH_DHCP_PREFIX_LENGTH;
- }
-
- ArgumentCaptor<NeighborEventConsumer> neighborCaptor =
- ArgumentCaptor.forClass(NeighborEventConsumer.class);
- doReturn(mIpNeighborMonitor).when(mDependencies).getIpNeighborMonitor(any(), any(),
- neighborCaptor.capture());
-
- mIpServer = new IpServer(
- IFACE_NAME, mLooper.getLooper(), interfaceType, mSharedLog, mNetd, mBpfCoordinator,
- mCallback, usingLegacyDhcp, usingBpfOffload, mAddressCoordinator, mDependencies);
- mIpServer.start();
- mNeighborEventConsumer = neighborCaptor.getValue();
-
- // Starting the state machine always puts us in a consistent state and notifies
- // the rest of the world that we've changed from an unknown to available state.
- mLooper.dispatchAll();
- reset(mNetd, mCallback);
-
- when(mRaDaemon.start()).thenReturn(true);
- }
-
- private void initTetheredStateMachine(int interfaceType, String upstreamIface)
- throws Exception {
- initTetheredStateMachine(interfaceType, upstreamIface, false,
- DEFAULT_USING_BPF_OFFLOAD);
- }
-
- private void initTetheredStateMachine(int interfaceType, String upstreamIface,
- boolean usingLegacyDhcp, boolean usingBpfOffload) throws Exception {
- initStateMachine(interfaceType, usingLegacyDhcp, usingBpfOffload);
- dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED);
- if (upstreamIface != null) {
- LinkProperties lp = new LinkProperties();
- lp.setInterfaceName(upstreamIface);
- dispatchTetherConnectionChanged(upstreamIface, lp, 0);
- }
- reset(mNetd, mCallback, mAddressCoordinator);
- when(mAddressCoordinator.requestDownstreamAddress(any(), anyBoolean())).thenReturn(
- mTestAddress);
- }
-
- private void setUpDhcpServer() throws Exception {
- doAnswer(inv -> {
- final IDhcpServerCallbacks cb = inv.getArgument(2);
- new Thread(() -> {
- try {
- cb.onDhcpServerCreated(STATUS_SUCCESS, mDhcpServer);
- } catch (RemoteException e) {
- fail(e.getMessage());
- }
- }).run();
- return null;
- }).when(mDependencies).makeDhcpServer(any(), mDhcpParamsCaptor.capture(), any());
- }
-
- @Before public void setUp() throws Exception {
- MockitoAnnotations.initMocks(this);
- when(mSharedLog.forSubComponent(anyString())).thenReturn(mSharedLog);
- when(mAddressCoordinator.requestDownstreamAddress(any(), anyBoolean())).thenReturn(
- mTestAddress);
- when(mTetherConfig.isBpfOffloadEnabled()).thenReturn(true /* default value */);
-
- mBpfCoordinator = spy(new BpfCoordinator(
- new BpfCoordinator.Dependencies() {
- @NonNull
- public Handler getHandler() {
- return new Handler(mLooper.getLooper());
- }
-
- @NonNull
- public INetd getNetd() {
- return mNetd;
- }
-
- @NonNull
- public NetworkStatsManager getNetworkStatsManager() {
- return mStatsManager;
- }
-
- @NonNull
- public SharedLog getSharedLog() {
- return mSharedLog;
- }
-
- @Nullable
- public TetheringConfiguration getTetherConfig() {
- return mTetherConfig;
- }
- }));
-
- setUpDhcpServer();
- }
-
- @Test
- public void startsOutAvailable() {
- when(mDependencies.getIpNeighborMonitor(any(), any(), any()))
- .thenReturn(mIpNeighborMonitor);
- mIpServer = new IpServer(IFACE_NAME, mLooper.getLooper(), TETHERING_BLUETOOTH, mSharedLog,
- mNetd, mBpfCoordinator, mCallback, false /* usingLegacyDhcp */,
- DEFAULT_USING_BPF_OFFLOAD, mAddressCoordinator, mDependencies);
- mIpServer.start();
- mLooper.dispatchAll();
- verify(mCallback).updateInterfaceState(
- mIpServer, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR);
- verify(mCallback).updateLinkProperties(eq(mIpServer), any(LinkProperties.class));
- verifyNoMoreInteractions(mCallback, mNetd);
- }
-
- @Test
- public void shouldDoNothingUntilRequested() throws Exception {
- initStateMachine(TETHERING_BLUETOOTH);
- final int [] noOp_commands = {
- IpServer.CMD_TETHER_UNREQUESTED,
- IpServer.CMD_IP_FORWARDING_ENABLE_ERROR,
- IpServer.CMD_IP_FORWARDING_DISABLE_ERROR,
- IpServer.CMD_START_TETHERING_ERROR,
- IpServer.CMD_STOP_TETHERING_ERROR,
- IpServer.CMD_SET_DNS_FORWARDERS_ERROR,
- IpServer.CMD_TETHER_CONNECTION_CHANGED
- };
- for (int command : noOp_commands) {
- // None of these commands should trigger us to request action from
- // the rest of the system.
- dispatchCommand(command);
- verifyNoMoreInteractions(mNetd, mCallback);
- }
- }
-
- @Test
- public void handlesImmediateInterfaceDown() throws Exception {
- initStateMachine(TETHERING_BLUETOOTH);
-
- dispatchCommand(IpServer.CMD_INTERFACE_DOWN);
- verify(mCallback).updateInterfaceState(
- mIpServer, STATE_UNAVAILABLE, TETHER_ERROR_NO_ERROR);
- verify(mCallback).updateLinkProperties(eq(mIpServer), any(LinkProperties.class));
- verifyNoMoreInteractions(mNetd, mCallback);
- }
-
- @Test
- public void canBeTethered() throws Exception {
- initStateMachine(TETHERING_BLUETOOTH);
-
- dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED);
- InOrder inOrder = inOrder(mCallback, mNetd);
- inOrder.verify(mNetd).tetherInterfaceAdd(IFACE_NAME);
- inOrder.verify(mNetd).networkAddInterface(INetd.LOCAL_NET_ID, IFACE_NAME);
- // One for ipv4 route, one for ipv6 link local route.
- inOrder.verify(mNetd, times(2)).networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(IFACE_NAME),
- any(), any());
- inOrder.verify(mCallback).updateInterfaceState(
- mIpServer, STATE_TETHERED, TETHER_ERROR_NO_ERROR);
- inOrder.verify(mCallback).updateLinkProperties(
- eq(mIpServer), any(LinkProperties.class));
- verifyNoMoreInteractions(mNetd, mCallback);
- }
-
- @Test
- public void canUnrequestTethering() throws Exception {
- initTetheredStateMachine(TETHERING_BLUETOOTH, null);
-
- dispatchCommand(IpServer.CMD_TETHER_UNREQUESTED);
- InOrder inOrder = inOrder(mCallback, mNetd, mAddressCoordinator);
- inOrder.verify(mNetd).tetherApplyDnsInterfaces();
- inOrder.verify(mNetd).tetherInterfaceRemove(IFACE_NAME);
- inOrder.verify(mNetd).networkRemoveInterface(INetd.LOCAL_NET_ID, IFACE_NAME);
- inOrder.verify(mNetd).interfaceSetCfg(argThat(cfg -> IFACE_NAME.equals(cfg.ifName)));
- inOrder.verify(mAddressCoordinator).releaseDownstream(any());
- inOrder.verify(mCallback).updateInterfaceState(
- mIpServer, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR);
- inOrder.verify(mCallback).updateLinkProperties(
- eq(mIpServer), any(LinkProperties.class));
- verifyNoMoreInteractions(mNetd, mCallback, mAddressCoordinator);
- }
-
- @Test
- public void canBeTetheredAsUsb() throws Exception {
- initStateMachine(TETHERING_USB);
-
- dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED);
- InOrder inOrder = inOrder(mCallback, mNetd, mAddressCoordinator);
- inOrder.verify(mAddressCoordinator).requestDownstreamAddress(any(), eq(true));
- inOrder.verify(mNetd).interfaceSetCfg(argThat(cfg ->
- IFACE_NAME.equals(cfg.ifName) && assertContainsFlag(cfg.flags, IF_STATE_UP)));
- inOrder.verify(mNetd).tetherInterfaceAdd(IFACE_NAME);
- inOrder.verify(mNetd).networkAddInterface(INetd.LOCAL_NET_ID, IFACE_NAME);
- inOrder.verify(mNetd, times(2)).networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(IFACE_NAME),
- any(), any());
- inOrder.verify(mCallback).updateInterfaceState(
- mIpServer, STATE_TETHERED, TETHER_ERROR_NO_ERROR);
- inOrder.verify(mCallback).updateLinkProperties(
- eq(mIpServer), mLinkPropertiesCaptor.capture());
- assertIPv4AddressAndDirectlyConnectedRoute(mLinkPropertiesCaptor.getValue());
- verifyNoMoreInteractions(mNetd, mCallback, mAddressCoordinator);
- }
-
- @Test
- public void canBeTetheredAsWifiP2p() throws Exception {
- initStateMachine(TETHERING_WIFI_P2P);
-
- dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_LOCAL_ONLY);
- InOrder inOrder = inOrder(mCallback, mNetd, mAddressCoordinator);
- inOrder.verify(mAddressCoordinator).requestDownstreamAddress(any(), eq(true));
- inOrder.verify(mNetd).interfaceSetCfg(argThat(cfg ->
- IFACE_NAME.equals(cfg.ifName) && assertNotContainsFlag(cfg.flags, IF_STATE_UP)));
- inOrder.verify(mNetd).tetherInterfaceAdd(IFACE_NAME);
- inOrder.verify(mNetd).networkAddInterface(INetd.LOCAL_NET_ID, IFACE_NAME);
- inOrder.verify(mNetd, times(2)).networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(IFACE_NAME),
- any(), any());
- inOrder.verify(mCallback).updateInterfaceState(
- mIpServer, STATE_LOCAL_ONLY, TETHER_ERROR_NO_ERROR);
- inOrder.verify(mCallback).updateLinkProperties(
- eq(mIpServer), mLinkPropertiesCaptor.capture());
- assertIPv4AddressAndDirectlyConnectedRoute(mLinkPropertiesCaptor.getValue());
- verifyNoMoreInteractions(mNetd, mCallback, mAddressCoordinator);
- }
-
- @Test
- public void handlesFirstUpstreamChange() throws Exception {
- initTetheredStateMachine(TETHERING_BLUETOOTH, null);
-
- // Telling the state machine about its upstream interface triggers
- // a little more configuration.
- dispatchTetherConnectionChanged(UPSTREAM_IFACE);
- InOrder inOrder = inOrder(mNetd);
- inOrder.verify(mNetd).tetherAddForward(IFACE_NAME, UPSTREAM_IFACE);
- inOrder.verify(mNetd).ipfwdAddInterfaceForward(IFACE_NAME, UPSTREAM_IFACE);
- verifyNoMoreInteractions(mNetd, mCallback);
- }
-
- @Test
- public void handlesChangingUpstream() throws Exception {
- initTetheredStateMachine(TETHERING_BLUETOOTH, UPSTREAM_IFACE);
-
- dispatchTetherConnectionChanged(UPSTREAM_IFACE2);
- InOrder inOrder = inOrder(mNetd);
- inOrder.verify(mNetd).ipfwdRemoveInterfaceForward(IFACE_NAME, UPSTREAM_IFACE);
- inOrder.verify(mNetd).tetherRemoveForward(IFACE_NAME, UPSTREAM_IFACE);
- inOrder.verify(mNetd).tetherAddForward(IFACE_NAME, UPSTREAM_IFACE2);
- inOrder.verify(mNetd).ipfwdAddInterfaceForward(IFACE_NAME, UPSTREAM_IFACE2);
- verifyNoMoreInteractions(mNetd, mCallback);
- }
-
- @Test
- public void handlesChangingUpstreamNatFailure() throws Exception {
- initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE);
-
- doThrow(RemoteException.class).when(mNetd).tetherAddForward(IFACE_NAME, UPSTREAM_IFACE2);
-
- dispatchTetherConnectionChanged(UPSTREAM_IFACE2);
- InOrder inOrder = inOrder(mNetd);
- inOrder.verify(mNetd).ipfwdRemoveInterfaceForward(IFACE_NAME, UPSTREAM_IFACE);
- inOrder.verify(mNetd).tetherRemoveForward(IFACE_NAME, UPSTREAM_IFACE);
- inOrder.verify(mNetd).tetherAddForward(IFACE_NAME, UPSTREAM_IFACE2);
- inOrder.verify(mNetd).ipfwdRemoveInterfaceForward(IFACE_NAME, UPSTREAM_IFACE2);
- inOrder.verify(mNetd).tetherRemoveForward(IFACE_NAME, UPSTREAM_IFACE2);
- }
-
- @Test
- public void handlesChangingUpstreamInterfaceForwardingFailure() throws Exception {
- initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE);
-
- doThrow(RemoteException.class).when(mNetd).ipfwdAddInterfaceForward(
- IFACE_NAME, UPSTREAM_IFACE2);
-
- dispatchTetherConnectionChanged(UPSTREAM_IFACE2);
- InOrder inOrder = inOrder(mNetd);
- inOrder.verify(mNetd).ipfwdRemoveInterfaceForward(IFACE_NAME, UPSTREAM_IFACE);
- inOrder.verify(mNetd).tetherRemoveForward(IFACE_NAME, UPSTREAM_IFACE);
- inOrder.verify(mNetd).tetherAddForward(IFACE_NAME, UPSTREAM_IFACE2);
- inOrder.verify(mNetd).ipfwdAddInterfaceForward(IFACE_NAME, UPSTREAM_IFACE2);
- inOrder.verify(mNetd).ipfwdRemoveInterfaceForward(IFACE_NAME, UPSTREAM_IFACE2);
- inOrder.verify(mNetd).tetherRemoveForward(IFACE_NAME, UPSTREAM_IFACE2);
- }
-
- @Test
- public void canUnrequestTetheringWithUpstream() throws Exception {
- initTetheredStateMachine(TETHERING_BLUETOOTH, UPSTREAM_IFACE);
-
- dispatchCommand(IpServer.CMD_TETHER_UNREQUESTED);
- InOrder inOrder = inOrder(mNetd, mCallback, mAddressCoordinator);
- inOrder.verify(mNetd).ipfwdRemoveInterfaceForward(IFACE_NAME, UPSTREAM_IFACE);
- inOrder.verify(mNetd).tetherRemoveForward(IFACE_NAME, UPSTREAM_IFACE);
- inOrder.verify(mNetd).tetherApplyDnsInterfaces();
- inOrder.verify(mNetd).tetherInterfaceRemove(IFACE_NAME);
- inOrder.verify(mNetd).networkRemoveInterface(INetd.LOCAL_NET_ID, IFACE_NAME);
- inOrder.verify(mNetd).interfaceSetCfg(argThat(cfg -> IFACE_NAME.equals(cfg.ifName)));
- inOrder.verify(mAddressCoordinator).releaseDownstream(any());
- inOrder.verify(mCallback).updateInterfaceState(
- mIpServer, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR);
- inOrder.verify(mCallback).updateLinkProperties(
- eq(mIpServer), any(LinkProperties.class));
- verifyNoMoreInteractions(mNetd, mCallback, mAddressCoordinator);
- }
-
- @Test
- public void interfaceDownLeadsToUnavailable() throws Exception {
- for (boolean shouldThrow : new boolean[]{true, false}) {
- initTetheredStateMachine(TETHERING_USB, null);
-
- if (shouldThrow) {
- doThrow(RemoteException.class).when(mNetd).tetherInterfaceRemove(IFACE_NAME);
- }
- dispatchCommand(IpServer.CMD_INTERFACE_DOWN);
- InOrder usbTeardownOrder = inOrder(mNetd, mCallback);
- // Currently IpServer interfaceSetCfg twice to stop IPv4. One just set interface down
- // Another one is set IPv4 to 0.0.0.0/0 as clearng ipv4 address.
- usbTeardownOrder.verify(mNetd, times(2)).interfaceSetCfg(
- argThat(cfg -> IFACE_NAME.equals(cfg.ifName)));
- usbTeardownOrder.verify(mCallback).updateInterfaceState(
- mIpServer, STATE_UNAVAILABLE, TETHER_ERROR_NO_ERROR);
- usbTeardownOrder.verify(mCallback).updateLinkProperties(
- eq(mIpServer), mLinkPropertiesCaptor.capture());
- assertNoAddressesNorRoutes(mLinkPropertiesCaptor.getValue());
- }
- }
-
- @Test
- public void usbShouldBeTornDownOnTetherError() throws Exception {
- initStateMachine(TETHERING_USB);
-
- doThrow(RemoteException.class).when(mNetd).tetherInterfaceAdd(IFACE_NAME);
- dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED);
- InOrder usbTeardownOrder = inOrder(mNetd, mCallback);
- usbTeardownOrder.verify(mNetd).interfaceSetCfg(
- argThat(cfg -> IFACE_NAME.equals(cfg.ifName)));
- usbTeardownOrder.verify(mNetd).tetherInterfaceAdd(IFACE_NAME);
-
- usbTeardownOrder.verify(mNetd, times(2)).interfaceSetCfg(
- argThat(cfg -> IFACE_NAME.equals(cfg.ifName)));
- usbTeardownOrder.verify(mCallback).updateInterfaceState(
- mIpServer, STATE_AVAILABLE, TETHER_ERROR_TETHER_IFACE_ERROR);
- usbTeardownOrder.verify(mCallback).updateLinkProperties(
- eq(mIpServer), mLinkPropertiesCaptor.capture());
- assertNoAddressesNorRoutes(mLinkPropertiesCaptor.getValue());
- }
-
- @Test
- public void shouldTearDownUsbOnUpstreamError() throws Exception {
- initTetheredStateMachine(TETHERING_USB, null);
-
- doThrow(RemoteException.class).when(mNetd).tetherAddForward(anyString(), anyString());
- dispatchTetherConnectionChanged(UPSTREAM_IFACE);
- InOrder usbTeardownOrder = inOrder(mNetd, mCallback);
- usbTeardownOrder.verify(mNetd).tetherAddForward(IFACE_NAME, UPSTREAM_IFACE);
-
- usbTeardownOrder.verify(mNetd, times(2)).interfaceSetCfg(
- argThat(cfg -> IFACE_NAME.equals(cfg.ifName)));
- usbTeardownOrder.verify(mCallback).updateInterfaceState(
- mIpServer, STATE_AVAILABLE, TETHER_ERROR_ENABLE_FORWARDING_ERROR);
- usbTeardownOrder.verify(mCallback).updateLinkProperties(
- eq(mIpServer), mLinkPropertiesCaptor.capture());
- assertNoAddressesNorRoutes(mLinkPropertiesCaptor.getValue());
- }
-
- @Test
- public void ignoresDuplicateUpstreamNotifications() throws Exception {
- initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE);
-
- verifyNoMoreInteractions(mNetd, mCallback);
-
- for (int i = 0; i < 5; i++) {
- dispatchTetherConnectionChanged(UPSTREAM_IFACE);
- verifyNoMoreInteractions(mNetd, mCallback);
- }
- }
-
- @Test
- public void startsDhcpServer() throws Exception {
- initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE);
- dispatchTetherConnectionChanged(UPSTREAM_IFACE);
-
- assertDhcpStarted(PrefixUtils.asIpPrefix(mTestAddress));
- }
-
- @Test
- public void startsDhcpServerOnBluetooth() throws Exception {
- initTetheredStateMachine(TETHERING_BLUETOOTH, UPSTREAM_IFACE);
- dispatchTetherConnectionChanged(UPSTREAM_IFACE);
-
- assertDhcpStarted(mBluetoothPrefix);
- }
-
- @Test
- public void startsDhcpServerOnWifiP2p() throws Exception {
- initTetheredStateMachine(TETHERING_WIFI_P2P, UPSTREAM_IFACE);
- dispatchTetherConnectionChanged(UPSTREAM_IFACE);
-
- assertDhcpStarted(PrefixUtils.asIpPrefix(mTestAddress));
- }
-
- @Test
- public void startsDhcpServerOnNcm() throws Exception {
- initStateMachine(TETHERING_NCM);
- dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_LOCAL_ONLY);
- dispatchTetherConnectionChanged(UPSTREAM_IFACE);
-
- assertDhcpStarted(new IpPrefix("192.168.42.0/24"));
- }
-
- @Test
- public void testOnNewPrefixRequest() throws Exception {
- initStateMachine(TETHERING_NCM);
- dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_LOCAL_ONLY);
-
- final IDhcpEventCallbacks eventCallbacks;
- final ArgumentCaptor<IDhcpEventCallbacks> dhcpEventCbsCaptor =
- ArgumentCaptor.forClass(IDhcpEventCallbacks.class);
- verify(mDhcpServer, timeout(MAKE_DHCPSERVER_TIMEOUT_MS).times(1)).startWithCallbacks(
- any(), dhcpEventCbsCaptor.capture());
- eventCallbacks = dhcpEventCbsCaptor.getValue();
- assertDhcpStarted(new IpPrefix("192.168.42.0/24"));
-
- final ArgumentCaptor<LinkProperties> lpCaptor =
- ArgumentCaptor.forClass(LinkProperties.class);
- InOrder inOrder = inOrder(mNetd, mCallback, mAddressCoordinator);
- inOrder.verify(mAddressCoordinator).requestDownstreamAddress(any(), eq(true));
- inOrder.verify(mNetd).networkAddInterface(INetd.LOCAL_NET_ID, IFACE_NAME);
- // One for ipv4 route, one for ipv6 link local route.
- inOrder.verify(mNetd, times(2)).networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(IFACE_NAME),
- any(), any());
- inOrder.verify(mCallback).updateInterfaceState(
- mIpServer, STATE_LOCAL_ONLY, TETHER_ERROR_NO_ERROR);
- inOrder.verify(mCallback).updateLinkProperties(eq(mIpServer), lpCaptor.capture());
- verifyNoMoreInteractions(mCallback, mAddressCoordinator);
-
- // Simulate the DHCP server receives DHCPDECLINE on MirrorLink and then signals
- // onNewPrefixRequest callback.
- final LinkAddress newAddress = new LinkAddress("192.168.100.125/24");
- when(mAddressCoordinator.requestDownstreamAddress(any(), anyBoolean())).thenReturn(
- newAddress);
- eventCallbacks.onNewPrefixRequest(new IpPrefix("192.168.42.0/24"));
- mLooper.dispatchAll();
-
- inOrder.verify(mAddressCoordinator).requestDownstreamAddress(any(), eq(false));
- inOrder.verify(mNetd).tetherApplyDnsInterfaces();
- inOrder.verify(mCallback).updateLinkProperties(eq(mIpServer), lpCaptor.capture());
- verifyNoMoreInteractions(mCallback);
-
- final LinkProperties linkProperties = lpCaptor.getValue();
- final List<LinkAddress> linkAddresses = linkProperties.getLinkAddresses();
- assertEquals(1, linkProperties.getLinkAddresses().size());
- assertEquals(1, linkProperties.getRoutes().size());
- final IpPrefix prefix = new IpPrefix(linkAddresses.get(0).getAddress(),
- linkAddresses.get(0).getPrefixLength());
- assertNotEquals(prefix, new IpPrefix("192.168.42.0/24"));
-
- verify(mDhcpServer).updateParams(mDhcpParamsCaptor.capture(), any());
- assertDhcpServingParams(mDhcpParamsCaptor.getValue(), prefix);
- }
-
- @Test
- public void doesNotStartDhcpServerIfDisabled() throws Exception {
- initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE, true /* usingLegacyDhcp */,
- DEFAULT_USING_BPF_OFFLOAD);
- dispatchTetherConnectionChanged(UPSTREAM_IFACE);
-
- verify(mDependencies, never()).makeDhcpServer(any(), any(), any());
- }
-
- private InetAddress addr(String addr) throws Exception {
- return InetAddresses.parseNumericAddress(addr);
- }
-
- private void recvNewNeigh(int ifindex, InetAddress addr, short nudState, MacAddress mac) {
- mNeighborEventConsumer.accept(new NeighborEvent(0, RTM_NEWNEIGH, ifindex, addr,
- nudState, mac));
- mLooper.dispatchAll();
- }
-
- private void recvDelNeigh(int ifindex, InetAddress addr, short nudState, MacAddress mac) {
- mNeighborEventConsumer.accept(new NeighborEvent(0, RTM_DELNEIGH, ifindex, addr,
- nudState, mac));
- mLooper.dispatchAll();
- }
-
- /**
- * Custom ArgumentMatcher for TetherOffloadRuleParcel. This is needed because generated stable
- * AIDL classes don't have equals(), so we cannot just use eq(). A custom assert, such as:
- *
- * private void checkFooCalled(StableParcelable p, ...) {
- * ArgumentCaptor<FooParam> captor = ArgumentCaptor.forClass(FooParam.class);
- * verify(mMock).foo(captor.capture());
- * Foo foo = captor.getValue();
- * assertFooMatchesExpectations(foo);
- * }
- *
- * almost works, but not quite. This is because if the code under test calls foo() twice, the
- * first call to checkFooCalled() matches both the calls, putting both calls into the captor,
- * and then fails with TooManyActualInvocations. It also makes it harder to use other mockito
- * features such as never(), inOrder(), etc.
- *
- * This approach isn't great because if the match fails, the error message is unhelpful
- * (actual: "android.net.TetherOffloadRuleParcel@8c827b0" or some such), but at least it does
- * work.
- *
- * TODO: consider making the error message more readable by adding a method that catching the
- * AssertionFailedError and throwing a new assertion with more details. See
- * NetworkMonitorTest#verifyNetworkTested.
- *
- * See ConnectivityServiceTest#assertRoutesAdded for an alternative approach which solves the
- * TooManyActualInvocations problem described above by forcing the caller of the custom assert
- * method to specify all expected invocations in one call. This is useful when the stable
- * parcelable class being asserted on has a corresponding Java object (eg., RouteInfo and
- * RouteInfoParcelable), and the caller can just pass in a list of them. It not useful here
- * because there is no such object.
- */
- private static class TetherOffloadRuleParcelMatcher implements
- ArgumentMatcher<TetherOffloadRuleParcel> {
- public final int upstreamIfindex;
- public final InetAddress dst;
- public final MacAddress dstMac;
-
- TetherOffloadRuleParcelMatcher(int upstreamIfindex, InetAddress dst, MacAddress dstMac) {
- this.upstreamIfindex = upstreamIfindex;
- this.dst = dst;
- this.dstMac = dstMac;
- }
-
- public boolean matches(TetherOffloadRuleParcel parcel) {
- return upstreamIfindex == parcel.inputInterfaceIndex
- && (TEST_IFACE_PARAMS.index == parcel.outputInterfaceIndex)
- && Arrays.equals(dst.getAddress(), parcel.destination)
- && (128 == parcel.prefixLength)
- && Arrays.equals(TEST_IFACE_PARAMS.macAddr.toByteArray(), parcel.srcL2Address)
- && Arrays.equals(dstMac.toByteArray(), parcel.dstL2Address);
- }
-
- public String toString() {
- return String.format("TetherOffloadRuleParcelMatcher(%d, %s, %s",
- upstreamIfindex, dst.getHostAddress(), dstMac);
- }
- }
-
- @NonNull
- private static TetherOffloadRuleParcel matches(
- int upstreamIfindex, InetAddress dst, MacAddress dstMac) {
- return argThat(new TetherOffloadRuleParcelMatcher(upstreamIfindex, dst, dstMac));
- }
-
- @NonNull
- private static Ipv6ForwardingRule makeForwardingRule(
- int upstreamIfindex, @NonNull InetAddress dst, @NonNull MacAddress dstMac) {
- return new Ipv6ForwardingRule(upstreamIfindex, TEST_IFACE_PARAMS.index,
- (Inet6Address) dst, TEST_IFACE_PARAMS.macAddr, dstMac);
- }
-
- @NonNull
- private static TetherStatsParcel buildEmptyTetherStatsParcel(int ifIndex) {
- TetherStatsParcel parcel = new TetherStatsParcel();
- parcel.ifIndex = ifIndex;
- return parcel;
- }
-
- private void resetNetdAndBpfCoordinator() throws Exception {
- reset(mNetd, mBpfCoordinator);
- when(mNetd.tetherOffloadGetStats()).thenReturn(new TetherStatsParcel[0]);
- when(mNetd.tetherOffloadGetAndClearStats(UPSTREAM_IFINDEX))
- .thenReturn(buildEmptyTetherStatsParcel(UPSTREAM_IFINDEX));
- when(mNetd.tetherOffloadGetAndClearStats(UPSTREAM_IFINDEX2))
- .thenReturn(buildEmptyTetherStatsParcel(UPSTREAM_IFINDEX2));
- }
-
- @Test
- public void addRemoveipv6ForwardingRules() throws Exception {
- initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE, false /* usingLegacyDhcp */,
- DEFAULT_USING_BPF_OFFLOAD);
-
- final int myIfindex = TEST_IFACE_PARAMS.index;
- final int notMyIfindex = myIfindex - 1;
-
- final MacAddress myMac = TEST_IFACE_PARAMS.macAddr;
- final InetAddress neighA = InetAddresses.parseNumericAddress("2001:db8::1");
- final InetAddress neighB = InetAddresses.parseNumericAddress("2001:db8::2");
- final InetAddress neighLL = InetAddresses.parseNumericAddress("fe80::1");
- final InetAddress neighMC = InetAddresses.parseNumericAddress("ff02::1234");
- final MacAddress macNull = MacAddress.fromString("00:00:00:00:00:00");
- final MacAddress macA = MacAddress.fromString("00:00:00:00:00:0a");
- final MacAddress macB = MacAddress.fromString("11:22:33:00:00:0b");
-
- resetNetdAndBpfCoordinator();
- verifyNoMoreInteractions(mBpfCoordinator, mNetd);
-
- // TODO: Perhaps verify the interaction of tetherOffloadSetInterfaceQuota and
- // tetherOffloadGetAndClearStats in netd while the rules are changed.
-
- // Events on other interfaces are ignored.
- recvNewNeigh(notMyIfindex, neighA, NUD_REACHABLE, macA);
- verifyNoMoreInteractions(mBpfCoordinator, mNetd);
-
- // Events on this interface are received and sent to netd.
- recvNewNeigh(myIfindex, neighA, NUD_REACHABLE, macA);
- verify(mBpfCoordinator).tetherOffloadRuleAdd(
- mIpServer, makeForwardingRule(UPSTREAM_IFINDEX, neighA, macA));
- verify(mNetd).tetherOffloadRuleAdd(matches(UPSTREAM_IFINDEX, neighA, macA));
- resetNetdAndBpfCoordinator();
-
- recvNewNeigh(myIfindex, neighB, NUD_REACHABLE, macB);
- verify(mBpfCoordinator).tetherOffloadRuleAdd(
- mIpServer, makeForwardingRule(UPSTREAM_IFINDEX, neighB, macB));
- verify(mNetd).tetherOffloadRuleAdd(matches(UPSTREAM_IFINDEX, neighB, macB));
- resetNetdAndBpfCoordinator();
-
- // Link-local and multicast neighbors are ignored.
- recvNewNeigh(myIfindex, neighLL, NUD_REACHABLE, macA);
- verifyNoMoreInteractions(mBpfCoordinator, mNetd);
- recvNewNeigh(myIfindex, neighMC, NUD_REACHABLE, macA);
- verifyNoMoreInteractions(mBpfCoordinator, mNetd);
-
- // A neighbor that is no longer valid causes the rule to be removed.
- // NUD_FAILED events do not have a MAC address.
- recvNewNeigh(myIfindex, neighA, NUD_FAILED, null);
- verify(mBpfCoordinator).tetherOffloadRuleRemove(
- mIpServer, makeForwardingRule(UPSTREAM_IFINDEX, neighA, macNull));
- verify(mNetd).tetherOffloadRuleRemove(matches(UPSTREAM_IFINDEX, neighA, macNull));
- resetNetdAndBpfCoordinator();
-
- // A neighbor that is deleted causes the rule to be removed.
- recvDelNeigh(myIfindex, neighB, NUD_STALE, macB);
- verify(mBpfCoordinator).tetherOffloadRuleRemove(
- mIpServer, makeForwardingRule(UPSTREAM_IFINDEX, neighB, macNull));
- verify(mNetd).tetherOffloadRuleRemove(matches(UPSTREAM_IFINDEX, neighB, macNull));
- resetNetdAndBpfCoordinator();
-
- // Upstream changes result in updating the rules.
- recvNewNeigh(myIfindex, neighA, NUD_REACHABLE, macA);
- recvNewNeigh(myIfindex, neighB, NUD_REACHABLE, macB);
- resetNetdAndBpfCoordinator();
-
- InOrder inOrder = inOrder(mNetd);
- LinkProperties lp = new LinkProperties();
- lp.setInterfaceName(UPSTREAM_IFACE2);
- dispatchTetherConnectionChanged(UPSTREAM_IFACE2, lp, -1);
- verify(mBpfCoordinator).tetherOffloadRuleUpdate(mIpServer, UPSTREAM_IFINDEX2);
- inOrder.verify(mNetd).tetherOffloadRuleRemove(matches(UPSTREAM_IFINDEX, neighA, macA));
- inOrder.verify(mNetd).tetherOffloadRuleAdd(matches(UPSTREAM_IFINDEX2, neighA, macA));
- inOrder.verify(mNetd).tetherOffloadRuleRemove(matches(UPSTREAM_IFINDEX, neighB, macB));
- inOrder.verify(mNetd).tetherOffloadRuleAdd(matches(UPSTREAM_IFINDEX2, neighB, macB));
- resetNetdAndBpfCoordinator();
-
- // When the upstream is lost, rules are removed.
- dispatchTetherConnectionChanged(null, null, 0);
- // Clear function is called two times by:
- // - processMessage CMD_TETHER_CONNECTION_CHANGED for the upstream is lost.
- // - processMessage CMD_IPV6_TETHER_UPDATE for the IPv6 upstream is lost.
- // See dispatchTetherConnectionChanged.
- verify(mBpfCoordinator, times(2)).tetherOffloadRuleClear(mIpServer);
- verify(mNetd).tetherOffloadRuleRemove(matches(UPSTREAM_IFINDEX2, neighA, macA));
- verify(mNetd).tetherOffloadRuleRemove(matches(UPSTREAM_IFINDEX2, neighB, macB));
- resetNetdAndBpfCoordinator();
-
- // If the upstream is IPv4-only, no rules are added.
- dispatchTetherConnectionChanged(UPSTREAM_IFACE);
- resetNetdAndBpfCoordinator();
- recvNewNeigh(myIfindex, neighA, NUD_REACHABLE, macA);
- // Clear function is called by #updateIpv6ForwardingRules for the IPv6 upstream is lost.
- verify(mBpfCoordinator).tetherOffloadRuleClear(mIpServer);
- verifyNoMoreInteractions(mBpfCoordinator, mNetd);
-
- // Rules can be added again once upstream IPv6 connectivity is available.
- lp.setInterfaceName(UPSTREAM_IFACE);
- dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, -1);
- recvNewNeigh(myIfindex, neighB, NUD_REACHABLE, macB);
- verify(mBpfCoordinator).tetherOffloadRuleAdd(
- mIpServer, makeForwardingRule(UPSTREAM_IFINDEX, neighB, macB));
- verify(mNetd).tetherOffloadRuleAdd(matches(UPSTREAM_IFINDEX, neighB, macB));
- verify(mBpfCoordinator, never()).tetherOffloadRuleAdd(
- mIpServer, makeForwardingRule(UPSTREAM_IFINDEX, neighA, macA));
- verify(mNetd, never()).tetherOffloadRuleAdd(matches(UPSTREAM_IFINDEX, neighA, macA));
-
- // If upstream IPv6 connectivity is lost, rules are removed.
- resetNetdAndBpfCoordinator();
- dispatchTetherConnectionChanged(UPSTREAM_IFACE, null, 0);
- verify(mBpfCoordinator).tetherOffloadRuleClear(mIpServer);
- verify(mNetd).tetherOffloadRuleRemove(matches(UPSTREAM_IFINDEX, neighB, macB));
-
- // When the interface goes down, rules are removed.
- lp.setInterfaceName(UPSTREAM_IFACE);
- dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, -1);
- recvNewNeigh(myIfindex, neighA, NUD_REACHABLE, macA);
- recvNewNeigh(myIfindex, neighB, NUD_REACHABLE, macB);
- verify(mBpfCoordinator).tetherOffloadRuleAdd(
- mIpServer, makeForwardingRule(UPSTREAM_IFINDEX, neighA, macA));
- verify(mNetd).tetherOffloadRuleAdd(matches(UPSTREAM_IFINDEX, neighA, macA));
- verify(mBpfCoordinator).tetherOffloadRuleAdd(
- mIpServer, makeForwardingRule(UPSTREAM_IFINDEX, neighB, macB));
- verify(mNetd).tetherOffloadRuleAdd(matches(UPSTREAM_IFINDEX, neighB, macB));
- resetNetdAndBpfCoordinator();
-
- mIpServer.stop();
- mLooper.dispatchAll();
- verify(mBpfCoordinator).tetherOffloadRuleClear(mIpServer);
- verify(mNetd).tetherOffloadRuleRemove(matches(UPSTREAM_IFINDEX, neighA, macA));
- verify(mNetd).tetherOffloadRuleRemove(matches(UPSTREAM_IFINDEX, neighB, macB));
- verify(mIpNeighborMonitor).stop();
- resetNetdAndBpfCoordinator();
- }
-
- @Test
- public void enableDisableUsingBpfOffload() throws Exception {
- final int myIfindex = TEST_IFACE_PARAMS.index;
- final InetAddress neigh = InetAddresses.parseNumericAddress("2001:db8::1");
- final MacAddress macA = MacAddress.fromString("00:00:00:00:00:0a");
- final MacAddress macNull = MacAddress.fromString("00:00:00:00:00:00");
-
- // Expect that rules can be only added/removed when the BPF offload config is enabled.
- // Note that the BPF offload disabled case is not a realistic test case. Because IP
- // neighbor monitor doesn't start if BPF offload is disabled, there should have no
- // neighbor event listening. This is used for testing the protection check just in case.
- // TODO: Perhaps remove the BPF offload disabled case test once this check isn't needed
- // anymore.
-
- // [1] Enable BPF offload.
- // A neighbor that is added or deleted causes the rule to be added or removed.
- initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE, false /* usingLegacyDhcp */,
- true /* usingBpfOffload */);
- resetNetdAndBpfCoordinator();
-
- recvNewNeigh(myIfindex, neigh, NUD_REACHABLE, macA);
- verify(mBpfCoordinator).tetherOffloadRuleAdd(
- mIpServer, makeForwardingRule(UPSTREAM_IFINDEX, neigh, macA));
- verify(mNetd).tetherOffloadRuleAdd(matches(UPSTREAM_IFINDEX, neigh, macA));
- resetNetdAndBpfCoordinator();
-
- recvDelNeigh(myIfindex, neigh, NUD_STALE, macA);
- verify(mBpfCoordinator).tetherOffloadRuleRemove(
- mIpServer, makeForwardingRule(UPSTREAM_IFINDEX, neigh, macNull));
- verify(mNetd).tetherOffloadRuleRemove(matches(UPSTREAM_IFINDEX, neigh, macNull));
- resetNetdAndBpfCoordinator();
-
- // [2] Disable BPF offload.
- // A neighbor that is added or deleted doesn’t cause the rule to be added or removed.
- initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE, false /* usingLegacyDhcp */,
- false /* usingBpfOffload */);
- resetNetdAndBpfCoordinator();
-
- recvNewNeigh(myIfindex, neigh, NUD_REACHABLE, macA);
- verify(mBpfCoordinator, never()).tetherOffloadRuleAdd(any(), any());
- verify(mNetd, never()).tetherOffloadRuleAdd(any());
- resetNetdAndBpfCoordinator();
-
- recvDelNeigh(myIfindex, neigh, NUD_STALE, macA);
- verify(mBpfCoordinator, never()).tetherOffloadRuleRemove(any(), any());
- verify(mNetd, never()).tetherOffloadRuleRemove(any());
- resetNetdAndBpfCoordinator();
- }
-
- @Test
- public void doesNotStartIpNeighborMonitorIfBpfOffloadDisabled() throws Exception {
- initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE, false /* usingLegacyDhcp */,
- false /* usingBpfOffload */);
-
- // IP neighbor monitor doesn't start if BPF offload is disabled.
- verify(mIpNeighborMonitor, never()).start();
- }
-
- private LinkProperties buildIpv6OnlyLinkProperties(final String iface) {
- final LinkProperties linkProp = new LinkProperties();
- linkProp.setInterfaceName(iface);
- linkProp.addLinkAddress(new LinkAddress("2001:db8::1/64"));
- linkProp.addRoute(new RouteInfo(new IpPrefix("::/0"), null, iface, RTN_UNICAST));
- final InetAddress dns = InetAddresses.parseNumericAddress("2001:4860:4860::8888");
- linkProp.addDnsServer(dns);
-
- return linkProp;
- }
-
- @Test
- public void testAdjustTtlValue() throws Exception {
- final ArgumentCaptor<RaParams> raParamsCaptor =
- ArgumentCaptor.forClass(RaParams.class);
- initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE);
- verify(mRaDaemon).buildNewRa(any(), raParamsCaptor.capture());
- final RaParams noV6Params = raParamsCaptor.getValue();
- assertEquals(65, noV6Params.hopLimit);
- reset(mRaDaemon);
-
- when(mNetd.getProcSysNet(
- INetd.IPV6, INetd.CONF, UPSTREAM_IFACE, "hop_limit")).thenReturn("64");
- final LinkProperties lp = buildIpv6OnlyLinkProperties(UPSTREAM_IFACE);
- dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, 1);
- verify(mRaDaemon).buildNewRa(any(), raParamsCaptor.capture());
- final RaParams nonCellularParams = raParamsCaptor.getValue();
- assertEquals(65, nonCellularParams.hopLimit);
- reset(mRaDaemon);
-
- dispatchTetherConnectionChanged(UPSTREAM_IFACE, null, 0);
- verify(mRaDaemon).buildNewRa(any(), raParamsCaptor.capture());
- final RaParams noUpstream = raParamsCaptor.getValue();
- assertEquals(65, nonCellularParams.hopLimit);
- reset(mRaDaemon);
-
- dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, -1);
- verify(mRaDaemon).buildNewRa(any(), raParamsCaptor.capture());
- final RaParams cellularParams = raParamsCaptor.getValue();
- assertEquals(63, cellularParams.hopLimit);
- reset(mRaDaemon);
- }
-
- @Test
- public void testStopObsoleteDhcpServer() throws Exception {
- final ArgumentCaptor<DhcpServerCallbacks> cbCaptor =
- ArgumentCaptor.forClass(DhcpServerCallbacks.class);
- doNothing().when(mDependencies).makeDhcpServer(any(), mDhcpParamsCaptor.capture(),
- cbCaptor.capture());
- initStateMachine(TETHERING_WIFI);
- dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED);
- verify(mDhcpServer, never()).startWithCallbacks(any(), any());
-
- // No stop dhcp server because dhcp server is not created yet.
- dispatchCommand(IpServer.CMD_TETHER_UNREQUESTED);
- verify(mDhcpServer, never()).stop(any());
-
- // Stop obsolete dhcp server.
- try {
- final DhcpServerCallbacks cb = cbCaptor.getValue();
- cb.onDhcpServerCreated(STATUS_SUCCESS, mDhcpServer);
- mLooper.dispatchAll();
- } catch (RemoteException e) {
- fail(e.getMessage());
- }
- verify(mDhcpServer).stop(any());
- }
-
- private void assertDhcpServingParams(final DhcpServingParamsParcel params,
- final IpPrefix prefix) {
- // Last address byte is random
- assertTrue(prefix.contains(intToInet4AddressHTH(params.serverAddr)));
- assertEquals(prefix.getPrefixLength(), params.serverAddrPrefixLength);
- assertEquals(1, params.defaultRouters.length);
- assertEquals(params.serverAddr, params.defaultRouters[0]);
- assertEquals(1, params.dnsServers.length);
- assertEquals(params.serverAddr, params.dnsServers[0]);
- assertEquals(DHCP_LEASE_TIME_SECS, params.dhcpLeaseTimeSecs);
- if (mIpServer.interfaceType() == TETHERING_NCM) {
- assertTrue(params.changePrefixOnDecline);
- }
- }
-
- private void assertDhcpStarted(IpPrefix expectedPrefix) throws Exception {
- verify(mDependencies, times(1)).makeDhcpServer(eq(IFACE_NAME), any(), any());
- verify(mDhcpServer, timeout(MAKE_DHCPSERVER_TIMEOUT_MS).times(1)).startWithCallbacks(
- any(), any());
- assertDhcpServingParams(mDhcpParamsCaptor.getValue(), expectedPrefix);
- }
-
- /**
- * Send a command to the state machine under test, and run the event loop to idle.
- *
- * @param command One of the IpServer.CMD_* constants.
- * @param arg1 An additional argument to pass.
- */
- private void dispatchCommand(int command, int arg1) {
- mIpServer.sendMessage(command, arg1);
- mLooper.dispatchAll();
- }
-
- /**
- * Send a command to the state machine under test, and run the event loop to idle.
- *
- * @param command One of the IpServer.CMD_* constants.
- */
- private void dispatchCommand(int command) {
- mIpServer.sendMessage(command);
- mLooper.dispatchAll();
- }
-
- /**
- * Special override to tell the state machine that the upstream interface has changed.
- *
- * @see #dispatchCommand(int)
- * @param upstreamIface String name of upstream interface (or null)
- * @param v6lp IPv6 LinkProperties of the upstream interface, or null for an IPv4-only upstream.
- */
- private void dispatchTetherConnectionChanged(String upstreamIface, LinkProperties v6lp,
- int ttlAdjustment) {
- dispatchTetherConnectionChanged(upstreamIface);
- mIpServer.sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, ttlAdjustment, 0, v6lp);
- mLooper.dispatchAll();
- }
-
- private void dispatchTetherConnectionChanged(String upstreamIface) {
- final InterfaceSet ifs = (upstreamIface != null) ? new InterfaceSet(upstreamIface) : null;
- mIpServer.sendMessage(IpServer.CMD_TETHER_CONNECTION_CHANGED, ifs);
- mLooper.dispatchAll();
- }
-
- private void assertIPv4AddressAndDirectlyConnectedRoute(LinkProperties lp) {
- // Find the first IPv4 LinkAddress.
- LinkAddress addr4 = null;
- for (LinkAddress addr : lp.getLinkAddresses()) {
- if (!(addr.getAddress() instanceof Inet4Address)) continue;
- addr4 = addr;
- break;
- }
- assertNotNull("missing IPv4 address", addr4);
-
- final IpPrefix destination = new IpPrefix(addr4.getAddress(), addr4.getPrefixLength());
- // Assert the presence of the associated directly connected route.
- final RouteInfo directlyConnected = new RouteInfo(destination, null, lp.getInterfaceName(),
- RouteInfo.RTN_UNICAST);
- assertTrue("missing directly connected route: '" + directlyConnected.toString() + "'",
- lp.getRoutes().contains(directlyConnected));
- }
-
- private void assertNoAddressesNorRoutes(LinkProperties lp) {
- assertTrue(lp.getLinkAddresses().isEmpty());
- assertTrue(lp.getRoutes().isEmpty());
- // We also check that interface name is non-empty, because we should
- // never see an empty interface name in any LinkProperties update.
- assertFalse(TextUtils.isEmpty(lp.getInterfaceName()));
- }
-
- private boolean assertContainsFlag(String[] flags, String match) {
- for (String flag : flags) {
- if (flag.equals(match)) return true;
- }
- fail("Missing flag: " + match);
- return false;
- }
-
- private boolean assertNotContainsFlag(String[] flags, String match) {
- for (String flag : flags) {
- if (flag.equals(match)) {
- fail("Unexpected flag: " + match);
- return false;
- }
- }
- return true;
- }
-
- @Test @IgnoreUpTo(Build.VERSION_CODES.R)
- public void dadProxyUpdates() throws Exception {
- InOrder inOrder = inOrder(mDadProxy);
- initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE);
- inOrder.verify(mDadProxy).setUpstreamIface(UPSTREAM_IFACE_PARAMS);
-
- // Add an upstream without IPv6.
- dispatchTetherConnectionChanged(UPSTREAM_IFACE, null, 0);
- inOrder.verify(mDadProxy).setUpstreamIface(null);
-
- // Add IPv6 to the upstream.
- LinkProperties lp = new LinkProperties();
- lp.setInterfaceName(UPSTREAM_IFACE);
- dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, 0);
- inOrder.verify(mDadProxy).setUpstreamIface(UPSTREAM_IFACE_PARAMS);
-
- // Change upstream.
- // New linkproperties is needed, otherwise changing the iface has no impact.
- LinkProperties lp2 = new LinkProperties();
- lp2.setInterfaceName(UPSTREAM_IFACE2);
- dispatchTetherConnectionChanged(UPSTREAM_IFACE2, lp2, 0);
- inOrder.verify(mDadProxy).setUpstreamIface(UPSTREAM_IFACE_PARAMS2);
-
- // Lose IPv6 on the upstream...
- dispatchTetherConnectionChanged(UPSTREAM_IFACE2, null, 0);
- inOrder.verify(mDadProxy).setUpstreamIface(null);
-
- // ... and regain it on a different upstream.
- dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, 0);
- inOrder.verify(mDadProxy).setUpstreamIface(UPSTREAM_IFACE_PARAMS);
-
- // Lose upstream.
- dispatchTetherConnectionChanged(null, null, 0);
- inOrder.verify(mDadProxy).setUpstreamIface(null);
-
- // Regain upstream.
- dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, 0);
- inOrder.verify(mDadProxy).setUpstreamIface(UPSTREAM_IFACE_PARAMS);
-
- // Stop tethering.
- mIpServer.stop();
- mLooper.dispatchAll();
- }
-
- private void checkDadProxyEnabled(boolean expectEnabled) throws Exception {
- initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE);
- InOrder inOrder = inOrder(mDadProxy);
- // Add IPv6 to the upstream.
- LinkProperties lp = new LinkProperties();
- lp.setInterfaceName(UPSTREAM_IFACE);
- if (expectEnabled) {
- inOrder.verify(mDadProxy).setUpstreamIface(UPSTREAM_IFACE_PARAMS);
- } else {
- inOrder.verifyNoMoreInteractions();
- }
- // Stop tethering.
- mIpServer.stop();
- mLooper.dispatchAll();
- if (expectEnabled) {
- inOrder.verify(mDadProxy).stop();
- }
- else {
- verify(mDependencies, never()).getDadProxy(any(), any());
- }
- }
- @Test @IgnoreAfter(Build.VERSION_CODES.R)
- public void testDadProxyUpdates_DisabledUpToR() throws Exception {
- checkDadProxyEnabled(false);
- }
- @Test @IgnoreUpTo(Build.VERSION_CODES.R)
- public void testDadProxyUpdates_EnabledAfterR() throws Exception {
- checkDadProxyEnabled(true);
- }
-}
diff --git a/packages/Tethering/tests/unit/src/android/net/util/InterfaceSetTest.java b/packages/Tethering/tests/unit/src/android/net/util/InterfaceSetTest.java
deleted file mode 100644
index ea084b6..0000000
--- a/packages/Tethering/tests/unit/src/android/net/util/InterfaceSetTest.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2018 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 android.net.util;
-
-import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertFalse;
-import static junit.framework.Assert.assertTrue;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class InterfaceSetTest {
- @Test
- public void testNullNamesIgnored() {
- final InterfaceSet set = new InterfaceSet(null, "if1", null, "if2", null);
- assertEquals(2, set.ifnames.size());
- assertTrue(set.ifnames.contains("if1"));
- assertTrue(set.ifnames.contains("if2"));
- }
-
- @Test
- public void testToString() {
- final InterfaceSet set = new InterfaceSet("if1", "if2");
- final String setString = set.toString();
- assertTrue(setString.equals("[if1,if2]") || setString.equals("[if2,if1]"));
- }
-
- @Test
- public void testToString_Empty() {
- final InterfaceSet set = new InterfaceSet(null, null);
- assertEquals("[]", set.toString());
- }
-
- @Test
- public void testEquals() {
- assertEquals(new InterfaceSet(null, "if1", "if2"), new InterfaceSet("if2", "if1"));
- assertEquals(new InterfaceSet(null, null), new InterfaceSet());
- assertFalse(new InterfaceSet("if1", "if3").equals(new InterfaceSet("if1", "if2")));
- assertFalse(new InterfaceSet("if1", "if2").equals(new InterfaceSet("if1")));
- assertFalse(new InterfaceSet().equals(null));
- }
-}
diff --git a/packages/Tethering/tests/unit/src/android/net/util/TetheringUtilsTest.java b/packages/Tethering/tests/unit/src/android/net/util/TetheringUtilsTest.java
deleted file mode 100644
index 91c7771..0000000
--- a/packages/Tethering/tests/unit/src/android/net/util/TetheringUtilsTest.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2019 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 android.net.util;
-
-import static android.net.TetheringManager.TETHERING_USB;
-import static android.net.TetheringManager.TETHERING_WIFI;
-
-import static junit.framework.Assert.assertFalse;
-import static junit.framework.Assert.assertTrue;
-
-import android.net.LinkAddress;
-import android.net.TetheringRequestParcel;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import com.android.testutils.MiscAsserts;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class TetheringUtilsTest {
- private static final LinkAddress TEST_SERVER_ADDR = new LinkAddress("192.168.43.1/24");
- private static final LinkAddress TEST_CLIENT_ADDR = new LinkAddress("192.168.43.5/24");
- private TetheringRequestParcel mTetheringRequest;
-
- @Before
- public void setUp() {
- mTetheringRequest = makeTetheringRequestParcel();
- }
-
- public TetheringRequestParcel makeTetheringRequestParcel() {
- final TetheringRequestParcel request = new TetheringRequestParcel();
- request.tetheringType = TETHERING_WIFI;
- request.localIPv4Address = TEST_SERVER_ADDR;
- request.staticClientAddress = TEST_CLIENT_ADDR;
- request.exemptFromEntitlementCheck = false;
- request.showProvisioningUi = true;
- return request;
- }
-
- @Test
- public void testIsTetheringRequestEquals() throws Exception {
- TetheringRequestParcel request = makeTetheringRequestParcel();
-
- assertTrue(TetheringUtils.isTetheringRequestEquals(mTetheringRequest, mTetheringRequest));
- assertTrue(TetheringUtils.isTetheringRequestEquals(mTetheringRequest, request));
- assertTrue(TetheringUtils.isTetheringRequestEquals(null, null));
- assertFalse(TetheringUtils.isTetheringRequestEquals(mTetheringRequest, null));
- assertFalse(TetheringUtils.isTetheringRequestEquals(null, mTetheringRequest));
-
- request = makeTetheringRequestParcel();
- request.tetheringType = TETHERING_USB;
- assertFalse(TetheringUtils.isTetheringRequestEquals(mTetheringRequest, request));
-
- request = makeTetheringRequestParcel();
- request.localIPv4Address = null;
- request.staticClientAddress = null;
- assertFalse(TetheringUtils.isTetheringRequestEquals(mTetheringRequest, request));
-
- request = makeTetheringRequestParcel();
- request.exemptFromEntitlementCheck = true;
- assertFalse(TetheringUtils.isTetheringRequestEquals(mTetheringRequest, request));
-
- request = makeTetheringRequestParcel();
- request.showProvisioningUi = false;
- assertFalse(TetheringUtils.isTetheringRequestEquals(mTetheringRequest, request));
-
- MiscAsserts.assertFieldCountEquals(5, TetheringRequestParcel.class);
- }
-}
diff --git a/packages/Tethering/tests/unit/src/android/net/util/VersionedBroadcastListenerTest.java b/packages/Tethering/tests/unit/src/android/net/util/VersionedBroadcastListenerTest.java
deleted file mode 100644
index 5a9b6e3..0000000
--- a/packages/Tethering/tests/unit/src/android/net/util/VersionedBroadcastListenerTest.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright (C) 2017 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 android.net.util;
-
-import static org.junit.Assert.assertEquals;
-import static org.mockito.Mockito.reset;
-
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.UserHandle;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import com.android.internal.util.test.BroadcastInterceptingContext;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class VersionedBroadcastListenerTest {
- private static final String TAG = VersionedBroadcastListenerTest.class.getSimpleName();
- private static final String ACTION_TEST = "action.test.happy.broadcasts";
-
- @Mock private Context mContext;
- private BroadcastInterceptingContext mServiceContext;
- private Handler mHandler;
- private VersionedBroadcastListener mListener;
- private int mCallbackCount;
-
- private void doCallback() {
- mCallbackCount++;
- }
-
- private class MockContext extends BroadcastInterceptingContext {
- MockContext(Context base) {
- super(base);
- }
- }
-
- @BeforeClass
- public static void setUpBeforeClass() throws Exception {
- if (Looper.myLooper() == null) {
- Looper.prepare();
- }
- }
-
- @Before public void setUp() throws Exception {
- MockitoAnnotations.initMocks(this);
- reset(mContext);
- mServiceContext = new MockContext(mContext);
- mHandler = new Handler(Looper.myLooper());
- mCallbackCount = 0;
- final IntentFilter filter = new IntentFilter();
- filter.addAction(ACTION_TEST);
- mListener = new VersionedBroadcastListener(
- TAG, mServiceContext, mHandler, filter, (Intent intent) -> doCallback());
- }
-
- @After public void tearDown() throws Exception {
- if (mListener != null) {
- mListener.stopListening();
- mListener = null;
- }
- }
-
- private void sendBroadcast() {
- final Intent intent = new Intent(ACTION_TEST);
- mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
- }
-
- @Test
- public void testBasicListening() {
- assertEquals(0, mCallbackCount);
- mListener.startListening();
- for (int i = 0; i < 5; i++) {
- sendBroadcast();
- assertEquals(i + 1, mCallbackCount);
- }
- mListener.stopListening();
- }
-
- @Test
- public void testBroadcastsBeforeStartAreIgnored() {
- assertEquals(0, mCallbackCount);
- for (int i = 0; i < 5; i++) {
- sendBroadcast();
- assertEquals(0, mCallbackCount);
- }
-
- mListener.startListening();
- sendBroadcast();
- assertEquals(1, mCallbackCount);
- }
-
- @Test
- public void testBroadcastsAfterStopAreIgnored() {
- mListener.startListening();
- sendBroadcast();
- assertEquals(1, mCallbackCount);
- mListener.stopListening();
-
- for (int i = 0; i < 5; i++) {
- sendBroadcast();
- assertEquals(1, mCallbackCount);
- }
- }
-}
diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java
deleted file mode 100644
index 64242ae..0000000
--- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java
+++ /dev/null
@@ -1,607 +0,0 @@
-/*
- * 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;
-
-import static android.net.NetworkStats.DEFAULT_NETWORK_NO;
-import static android.net.NetworkStats.METERED_NO;
-import static android.net.NetworkStats.ROAMING_NO;
-import static android.net.NetworkStats.SET_DEFAULT;
-import static android.net.NetworkStats.TAG_NONE;
-import static android.net.NetworkStats.UID_ALL;
-import static android.net.NetworkStats.UID_TETHERING;
-import static android.net.netstats.provider.NetworkStatsProvider.QUOTA_UNLIMITED;
-
-import static com.android.networkstack.tethering.BpfCoordinator.StatsType;
-import static com.android.networkstack.tethering.BpfCoordinator.StatsType.STATS_PER_IFACE;
-import static com.android.networkstack.tethering.BpfCoordinator.StatsType.STATS_PER_UID;
-import static com.android.networkstack.tethering.TetheringConfiguration.DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.fail;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyLong;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Mockito.argThat;
-import static org.mockito.Mockito.clearInvocations;
-import static org.mockito.Mockito.inOrder;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.app.usage.NetworkStatsManager;
-import android.net.INetd;
-import android.net.InetAddresses;
-import android.net.MacAddress;
-import android.net.NetworkStats;
-import android.net.TetherOffloadRuleParcel;
-import android.net.TetherStatsParcel;
-import android.net.ip.IpServer;
-import android.net.util.SharedLog;
-import android.os.Handler;
-import android.os.test.TestLooper;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import com.android.networkstack.tethering.BpfCoordinator.Ipv6ForwardingRule;
-import com.android.testutils.TestableNetworkStatsProviderCbBinder;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.ArgumentMatcher;
-import org.mockito.InOrder;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-import java.net.Inet6Address;
-import java.net.InetAddress;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.LinkedHashMap;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class BpfCoordinatorTest {
- private static final int DOWNSTREAM_IFINDEX = 10;
- private static final MacAddress DOWNSTREAM_MAC = MacAddress.ALL_ZEROS_ADDRESS;
- private static final InetAddress NEIGH_A = InetAddresses.parseNumericAddress("2001:db8::1");
- private static final InetAddress NEIGH_B = InetAddresses.parseNumericAddress("2001:db8::2");
- private static final MacAddress MAC_A = MacAddress.fromString("00:00:00:00:00:0a");
- private static final MacAddress MAC_B = MacAddress.fromString("11:22:33:00:00:0b");
-
- @Mock private NetworkStatsManager mStatsManager;
- @Mock private INetd mNetd;
- @Mock private IpServer mIpServer;
- @Mock private TetheringConfiguration mTetherConfig;
-
- // Late init since methods must be called by the thread that created this object.
- private TestableNetworkStatsProviderCbBinder mTetherStatsProviderCb;
- private BpfCoordinator.BpfTetherStatsProvider mTetherStatsProvider;
- private final ArgumentCaptor<ArrayList> mStringArrayCaptor =
- ArgumentCaptor.forClass(ArrayList.class);
- private final TestLooper mTestLooper = new TestLooper();
- private BpfCoordinator.Dependencies mDeps =
- new BpfCoordinator.Dependencies() {
- @NonNull
- public Handler getHandler() {
- return new Handler(mTestLooper.getLooper());
- }
-
- @NonNull
- public INetd getNetd() {
- return mNetd;
- }
-
- @NonNull
- public NetworkStatsManager getNetworkStatsManager() {
- return mStatsManager;
- }
-
- @NonNull
- public SharedLog getSharedLog() {
- return new SharedLog("test");
- }
-
- @Nullable
- public TetheringConfiguration getTetherConfig() {
- return mTetherConfig;
- }
- };
-
- @Before public void setUp() {
- MockitoAnnotations.initMocks(this);
- when(mTetherConfig.isBpfOffloadEnabled()).thenReturn(true /* default value */);
- }
-
- private void waitForIdle() {
- mTestLooper.dispatchAll();
- }
-
- private void setupFunctioningNetdInterface() throws Exception {
- when(mNetd.tetherOffloadGetStats()).thenReturn(new TetherStatsParcel[0]);
- }
-
- @NonNull
- private BpfCoordinator makeBpfCoordinator() throws Exception {
- final BpfCoordinator coordinator = new BpfCoordinator(mDeps);
- final ArgumentCaptor<BpfCoordinator.BpfTetherStatsProvider>
- tetherStatsProviderCaptor =
- ArgumentCaptor.forClass(BpfCoordinator.BpfTetherStatsProvider.class);
- verify(mStatsManager).registerNetworkStatsProvider(anyString(),
- tetherStatsProviderCaptor.capture());
- mTetherStatsProvider = tetherStatsProviderCaptor.getValue();
- assertNotNull(mTetherStatsProvider);
- mTetherStatsProviderCb = new TestableNetworkStatsProviderCbBinder();
- mTetherStatsProvider.setProviderCallbackBinder(mTetherStatsProviderCb);
- return coordinator;
- }
-
- @NonNull
- private static NetworkStats.Entry buildTestEntry(@NonNull StatsType how,
- @NonNull String iface, long rxBytes, long rxPackets, long txBytes, long txPackets) {
- return new NetworkStats.Entry(iface, how == STATS_PER_IFACE ? UID_ALL : UID_TETHERING,
- SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, rxBytes,
- rxPackets, txBytes, txPackets, 0L);
- }
-
- @NonNull
- private static TetherStatsParcel buildTestTetherStatsParcel(@NonNull Integer ifIndex,
- long rxBytes, long rxPackets, long txBytes, long txPackets) {
- final TetherStatsParcel parcel = new TetherStatsParcel();
- parcel.ifIndex = ifIndex;
- parcel.rxBytes = rxBytes;
- parcel.rxPackets = rxPackets;
- parcel.txBytes = txBytes;
- parcel.txPackets = txPackets;
- return parcel;
- }
-
- // Set up specific tether stats list and wait for the stats cache is updated by polling thread
- // in the coordinator. Beware of that it is only used for the default polling interval.
- private void setTetherOffloadStatsList(TetherStatsParcel[] tetherStatsList) throws Exception {
- when(mNetd.tetherOffloadGetStats()).thenReturn(tetherStatsList);
- mTestLooper.moveTimeForward(DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS);
- waitForIdle();
- }
-
- @Test
- public void testGetForwardedStats() throws Exception {
- setupFunctioningNetdInterface();
-
- final BpfCoordinator coordinator = makeBpfCoordinator();
- coordinator.startPolling();
-
- final String wlanIface = "wlan0";
- final Integer wlanIfIndex = 100;
- final String mobileIface = "rmnet_data0";
- final Integer mobileIfIndex = 101;
-
- // Add interface name to lookup table. In realistic case, the upstream interface name will
- // be added by IpServer when IpServer has received with a new IPv6 upstream update event.
- coordinator.addUpstreamNameToLookupTable(wlanIfIndex, wlanIface);
- coordinator.addUpstreamNameToLookupTable(mobileIfIndex, mobileIface);
-
- // [1] Both interface stats are changed.
- // Setup the tether stats of wlan and mobile interface. Note that move forward the time of
- // the looper to make sure the new tether stats has been updated by polling update thread.
- setTetherOffloadStatsList(new TetherStatsParcel[] {
- buildTestTetherStatsParcel(wlanIfIndex, 1000, 100, 2000, 200),
- buildTestTetherStatsParcel(mobileIfIndex, 3000, 300, 4000, 400)});
-
- final NetworkStats expectedIfaceStats = new NetworkStats(0L, 2)
- .addEntry(buildTestEntry(STATS_PER_IFACE, wlanIface, 1000, 100, 2000, 200))
- .addEntry(buildTestEntry(STATS_PER_IFACE, mobileIface, 3000, 300, 4000, 400));
-
- final NetworkStats expectedUidStats = new NetworkStats(0L, 2)
- .addEntry(buildTestEntry(STATS_PER_UID, wlanIface, 1000, 100, 2000, 200))
- .addEntry(buildTestEntry(STATS_PER_UID, mobileIface, 3000, 300, 4000, 400));
-
- // Force pushing stats update to verify the stats reported.
- // TODO: Perhaps make #expectNotifyStatsUpdated to use test TetherStatsParcel object for
- // verifying the notification.
- mTetherStatsProvider.pushTetherStats();
- mTetherStatsProviderCb.expectNotifyStatsUpdated(expectedIfaceStats, expectedUidStats);
-
- // [2] Only one interface stats is changed.
- // The tether stats of mobile interface is accumulated and The tether stats of wlan
- // interface is the same.
- setTetherOffloadStatsList(new TetherStatsParcel[] {
- buildTestTetherStatsParcel(wlanIfIndex, 1000, 100, 2000, 200),
- buildTestTetherStatsParcel(mobileIfIndex, 3010, 320, 4030, 440)});
-
- final NetworkStats expectedIfaceStatsDiff = new NetworkStats(0L, 2)
- .addEntry(buildTestEntry(STATS_PER_IFACE, wlanIface, 0, 0, 0, 0))
- .addEntry(buildTestEntry(STATS_PER_IFACE, mobileIface, 10, 20, 30, 40));
-
- final NetworkStats expectedUidStatsDiff = new NetworkStats(0L, 2)
- .addEntry(buildTestEntry(STATS_PER_UID, wlanIface, 0, 0, 0, 0))
- .addEntry(buildTestEntry(STATS_PER_UID, mobileIface, 10, 20, 30, 40));
-
- // Force pushing stats update to verify that only diff of stats is reported.
- mTetherStatsProvider.pushTetherStats();
- mTetherStatsProviderCb.expectNotifyStatsUpdated(expectedIfaceStatsDiff,
- expectedUidStatsDiff);
-
- // [3] Stop coordinator.
- // Shutdown the coordinator and clear the invocation history, especially the
- // tetherOffloadGetStats() calls.
- coordinator.stopPolling();
- clearInvocations(mNetd);
-
- // Verify the polling update thread stopped.
- mTestLooper.moveTimeForward(DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS);
- waitForIdle();
- verify(mNetd, never()).tetherOffloadGetStats();
- }
-
- @Test
- public void testOnSetAlert() throws Exception {
- setupFunctioningNetdInterface();
-
- final BpfCoordinator coordinator = makeBpfCoordinator();
- coordinator.startPolling();
-
- final String mobileIface = "rmnet_data0";
- final Integer mobileIfIndex = 100;
- coordinator.addUpstreamNameToLookupTable(mobileIfIndex, mobileIface);
-
- // Verify that set quota to 0 will immediately triggers a callback.
- mTetherStatsProvider.onSetAlert(0);
- waitForIdle();
- mTetherStatsProviderCb.expectNotifyAlertReached();
-
- // Verify that notifyAlertReached never fired if quota is not yet reached.
- when(mNetd.tetherOffloadGetStats()).thenReturn(
- new TetherStatsParcel[] {buildTestTetherStatsParcel(mobileIfIndex, 0, 0, 0, 0)});
- mTetherStatsProvider.onSetAlert(100);
- mTestLooper.moveTimeForward(DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS);
- waitForIdle();
- mTetherStatsProviderCb.assertNoCallback();
-
- // Verify that notifyAlertReached fired when quota is reached.
- when(mNetd.tetherOffloadGetStats()).thenReturn(
- new TetherStatsParcel[] {buildTestTetherStatsParcel(mobileIfIndex, 50, 0, 50, 0)});
- mTestLooper.moveTimeForward(DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS);
- waitForIdle();
- mTetherStatsProviderCb.expectNotifyAlertReached();
-
- // Verify that set quota with UNLIMITED won't trigger any callback.
- mTetherStatsProvider.onSetAlert(QUOTA_UNLIMITED);
- mTestLooper.moveTimeForward(DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS);
- waitForIdle();
- mTetherStatsProviderCb.assertNoCallback();
- }
-
- // The custom ArgumentMatcher simply comes from IpServerTest.
- // TODO: move both of them into a common utility class for reusing the code.
- private static class TetherOffloadRuleParcelMatcher implements
- ArgumentMatcher<TetherOffloadRuleParcel> {
- public final int upstreamIfindex;
- public final int downstreamIfindex;
- public final Inet6Address address;
- public final MacAddress srcMac;
- public final MacAddress dstMac;
-
- TetherOffloadRuleParcelMatcher(@NonNull Ipv6ForwardingRule rule) {
- upstreamIfindex = rule.upstreamIfindex;
- downstreamIfindex = rule.downstreamIfindex;
- address = rule.address;
- srcMac = rule.srcMac;
- dstMac = rule.dstMac;
- }
-
- public boolean matches(@NonNull TetherOffloadRuleParcel parcel) {
- return upstreamIfindex == parcel.inputInterfaceIndex
- && (downstreamIfindex == parcel.outputInterfaceIndex)
- && Arrays.equals(address.getAddress(), parcel.destination)
- && (128 == parcel.prefixLength)
- && Arrays.equals(srcMac.toByteArray(), parcel.srcL2Address)
- && Arrays.equals(dstMac.toByteArray(), parcel.dstL2Address);
- }
-
- public String toString() {
- return String.format("TetherOffloadRuleParcelMatcher(%d, %d, %s, %s, %s",
- upstreamIfindex, downstreamIfindex, address.getHostAddress(), srcMac, dstMac);
- }
- }
-
- @NonNull
- private TetherOffloadRuleParcel matches(@NonNull Ipv6ForwardingRule rule) {
- return argThat(new TetherOffloadRuleParcelMatcher(rule));
- }
-
- @NonNull
- private static Ipv6ForwardingRule buildTestForwardingRule(
- int upstreamIfindex, @NonNull InetAddress address, @NonNull MacAddress dstMac) {
- return new Ipv6ForwardingRule(upstreamIfindex, DOWNSTREAM_IFINDEX, (Inet6Address) address,
- DOWNSTREAM_MAC, dstMac);
- }
-
- @Test
- public void testSetDataLimit() throws Exception {
- setupFunctioningNetdInterface();
-
- final BpfCoordinator coordinator = makeBpfCoordinator();
-
- final String mobileIface = "rmnet_data0";
- final Integer mobileIfIndex = 100;
- coordinator.addUpstreamNameToLookupTable(mobileIfIndex, mobileIface);
-
- // [1] Default limit.
- // Set the unlimited quota as default if the service has never applied a data limit for a
- // given upstream. Note that the data limit only be applied on an upstream which has rules.
- final Ipv6ForwardingRule rule = buildTestForwardingRule(mobileIfIndex, NEIGH_A, MAC_A);
- final InOrder inOrder = inOrder(mNetd);
- coordinator.tetherOffloadRuleAdd(mIpServer, rule);
- inOrder.verify(mNetd).tetherOffloadRuleAdd(matches(rule));
- inOrder.verify(mNetd).tetherOffloadSetInterfaceQuota(mobileIfIndex, QUOTA_UNLIMITED);
- inOrder.verifyNoMoreInteractions();
-
- // [2] Specific limit.
- // Applying the data limit boundary {min, 1gb, max, infinity} on current upstream.
- for (final long quota : new long[] {0, 1048576000, Long.MAX_VALUE, QUOTA_UNLIMITED}) {
- mTetherStatsProvider.onSetLimit(mobileIface, quota);
- waitForIdle();
- inOrder.verify(mNetd).tetherOffloadSetInterfaceQuota(mobileIfIndex, quota);
- inOrder.verifyNoMoreInteractions();
- }
-
- // [3] Invalid limit.
- // The valid range of quota is 0..max_int64 or -1 (unlimited).
- final long invalidLimit = Long.MIN_VALUE;
- try {
- mTetherStatsProvider.onSetLimit(mobileIface, invalidLimit);
- waitForIdle();
- fail("No exception thrown for invalid limit " + invalidLimit + ".");
- } catch (IllegalArgumentException expected) {
- assertEquals(expected.getMessage(), "invalid quota value " + invalidLimit);
- }
- }
-
- // TODO: Test the case in which the rules are changed from different IpServer objects.
- @Test
- public void testSetDataLimitOnRuleChange() throws Exception {
- setupFunctioningNetdInterface();
-
- final BpfCoordinator coordinator = makeBpfCoordinator();
-
- final String mobileIface = "rmnet_data0";
- final Integer mobileIfIndex = 100;
- coordinator.addUpstreamNameToLookupTable(mobileIfIndex, mobileIface);
-
- // Applying a data limit to the current upstream does not take any immediate action.
- // The data limit could be only set on an upstream which has rules.
- final long limit = 12345;
- final InOrder inOrder = inOrder(mNetd);
- mTetherStatsProvider.onSetLimit(mobileIface, limit);
- waitForIdle();
- inOrder.verify(mNetd, never()).tetherOffloadSetInterfaceQuota(anyInt(), anyLong());
-
- // Adding the first rule on current upstream immediately sends the quota to netd.
- final Ipv6ForwardingRule ruleA = buildTestForwardingRule(mobileIfIndex, NEIGH_A, MAC_A);
- coordinator.tetherOffloadRuleAdd(mIpServer, ruleA);
- inOrder.verify(mNetd).tetherOffloadRuleAdd(matches(ruleA));
- inOrder.verify(mNetd).tetherOffloadSetInterfaceQuota(mobileIfIndex, limit);
- inOrder.verifyNoMoreInteractions();
-
- // Adding the second rule on current upstream does not send the quota to netd.
- final Ipv6ForwardingRule ruleB = buildTestForwardingRule(mobileIfIndex, NEIGH_B, MAC_B);
- coordinator.tetherOffloadRuleAdd(mIpServer, ruleB);
- inOrder.verify(mNetd).tetherOffloadRuleAdd(matches(ruleB));
- inOrder.verify(mNetd, never()).tetherOffloadSetInterfaceQuota(anyInt(), anyLong());
-
- // Removing the second rule on current upstream does not send the quota to netd.
- coordinator.tetherOffloadRuleRemove(mIpServer, ruleB);
- inOrder.verify(mNetd).tetherOffloadRuleRemove(matches(ruleB));
- inOrder.verify(mNetd, never()).tetherOffloadSetInterfaceQuota(anyInt(), anyLong());
-
- // Removing the last rule on current upstream immediately sends the cleanup stuff to netd.
- when(mNetd.tetherOffloadGetAndClearStats(mobileIfIndex))
- .thenReturn(buildTestTetherStatsParcel(mobileIfIndex, 0, 0, 0, 0));
- coordinator.tetherOffloadRuleRemove(mIpServer, ruleA);
- inOrder.verify(mNetd).tetherOffloadRuleRemove(matches(ruleA));
- inOrder.verify(mNetd).tetherOffloadGetAndClearStats(mobileIfIndex);
- inOrder.verifyNoMoreInteractions();
- }
-
- @Test
- public void testTetherOffloadRuleUpdateAndClear() throws Exception {
- setupFunctioningNetdInterface();
-
- final BpfCoordinator coordinator = makeBpfCoordinator();
-
- final String ethIface = "eth1";
- final String mobileIface = "rmnet_data0";
- final Integer ethIfIndex = 100;
- final Integer mobileIfIndex = 101;
- coordinator.addUpstreamNameToLookupTable(ethIfIndex, ethIface);
- coordinator.addUpstreamNameToLookupTable(mobileIfIndex, mobileIface);
-
- final InOrder inOrder = inOrder(mNetd);
-
- // Before the rule test, here are the additional actions while the rules are changed.
- // - After adding the first rule on a given upstream, the coordinator adds a data limit.
- // If the service has never applied the data limit, set an unlimited quota as default.
- // - After removing the last rule on a given upstream, the coordinator gets the last stats.
- // Then, it clears the stats and the limit entry from BPF maps.
- // See tetherOffloadRule{Add, Remove, Clear, Clean}.
-
- // [1] Adding rules on the upstream Ethernet.
- // Note that the default data limit is applied after the first rule is added.
- final Ipv6ForwardingRule ethernetRuleA = buildTestForwardingRule(
- ethIfIndex, NEIGH_A, MAC_A);
- final Ipv6ForwardingRule ethernetRuleB = buildTestForwardingRule(
- ethIfIndex, NEIGH_B, MAC_B);
-
- coordinator.tetherOffloadRuleAdd(mIpServer, ethernetRuleA);
- inOrder.verify(mNetd).tetherOffloadRuleAdd(matches(ethernetRuleA));
- inOrder.verify(mNetd).tetherOffloadSetInterfaceQuota(ethIfIndex, QUOTA_UNLIMITED);
-
- coordinator.tetherOffloadRuleAdd(mIpServer, ethernetRuleB);
- inOrder.verify(mNetd).tetherOffloadRuleAdd(matches(ethernetRuleB));
-
- // [2] Update the existing rules from Ethernet to cellular.
- final Ipv6ForwardingRule mobileRuleA = buildTestForwardingRule(
- mobileIfIndex, NEIGH_A, MAC_A);
- final Ipv6ForwardingRule mobileRuleB = buildTestForwardingRule(
- mobileIfIndex, NEIGH_B, MAC_B);
- when(mNetd.tetherOffloadGetAndClearStats(ethIfIndex))
- .thenReturn(buildTestTetherStatsParcel(ethIfIndex, 10, 20, 30, 40));
-
- // Update the existing rules for upstream changes. The rules are removed and re-added one
- // by one for updating upstream interface index by #tetherOffloadRuleUpdate.
- coordinator.tetherOffloadRuleUpdate(mIpServer, mobileIfIndex);
- inOrder.verify(mNetd).tetherOffloadRuleRemove(matches(ethernetRuleA));
- inOrder.verify(mNetd).tetherOffloadRuleAdd(matches(mobileRuleA));
- inOrder.verify(mNetd).tetherOffloadSetInterfaceQuota(mobileIfIndex, QUOTA_UNLIMITED);
- inOrder.verify(mNetd).tetherOffloadRuleRemove(matches(ethernetRuleB));
- inOrder.verify(mNetd).tetherOffloadGetAndClearStats(ethIfIndex);
- inOrder.verify(mNetd).tetherOffloadRuleAdd(matches(mobileRuleB));
-
- // [3] Clear all rules for a given IpServer.
- when(mNetd.tetherOffloadGetAndClearStats(mobileIfIndex))
- .thenReturn(buildTestTetherStatsParcel(mobileIfIndex, 50, 60, 70, 80));
- coordinator.tetherOffloadRuleClear(mIpServer);
- inOrder.verify(mNetd).tetherOffloadRuleRemove(matches(mobileRuleA));
- inOrder.verify(mNetd).tetherOffloadRuleRemove(matches(mobileRuleB));
- inOrder.verify(mNetd).tetherOffloadGetAndClearStats(mobileIfIndex);
-
- // [4] Force pushing stats update to verify that the last diff of stats is reported on all
- // upstreams.
- mTetherStatsProvider.pushTetherStats();
- mTetherStatsProviderCb.expectNotifyStatsUpdated(
- new NetworkStats(0L, 2)
- .addEntry(buildTestEntry(STATS_PER_IFACE, ethIface, 10, 20, 30, 40))
- .addEntry(buildTestEntry(STATS_PER_IFACE, mobileIface, 50, 60, 70, 80)),
- new NetworkStats(0L, 2)
- .addEntry(buildTestEntry(STATS_PER_UID, ethIface, 10, 20, 30, 40))
- .addEntry(buildTestEntry(STATS_PER_UID, mobileIface, 50, 60, 70, 80)));
- }
-
- @Test
- public void testTetheringConfigDisable() throws Exception {
- setupFunctioningNetdInterface();
- when(mTetherConfig.isBpfOffloadEnabled()).thenReturn(false);
-
- final BpfCoordinator coordinator = makeBpfCoordinator();
- coordinator.startPolling();
-
- // The tether stats polling task should not be scheduled.
- mTestLooper.moveTimeForward(DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS);
- waitForIdle();
- verify(mNetd, never()).tetherOffloadGetStats();
-
- // The interface name lookup table can't be added.
- final String iface = "rmnet_data0";
- final Integer ifIndex = 100;
- coordinator.addUpstreamNameToLookupTable(ifIndex, iface);
- assertEquals(0, coordinator.getInterfaceNamesForTesting().size());
-
- // The rule can't be added.
- final InetAddress neigh = InetAddresses.parseNumericAddress("2001:db8::1");
- final MacAddress mac = MacAddress.fromString("00:00:00:00:00:0a");
- final Ipv6ForwardingRule rule = buildTestForwardingRule(ifIndex, neigh, mac);
- coordinator.tetherOffloadRuleAdd(mIpServer, rule);
- verify(mNetd, never()).tetherOffloadRuleAdd(any());
- LinkedHashMap<Inet6Address, Ipv6ForwardingRule> rules =
- coordinator.getForwardingRulesForTesting().get(mIpServer);
- assertNull(rules);
-
- // The rule can't be removed. This is not a realistic case because adding rule is not
- // allowed. That implies no rule could be removed, cleared or updated. Verify these
- // cases just in case.
- rules = new LinkedHashMap<Inet6Address, Ipv6ForwardingRule>();
- rules.put(rule.address, rule);
- coordinator.getForwardingRulesForTesting().put(mIpServer, rules);
- coordinator.tetherOffloadRuleRemove(mIpServer, rule);
- verify(mNetd, never()).tetherOffloadRuleRemove(any());
- rules = coordinator.getForwardingRulesForTesting().get(mIpServer);
- assertNotNull(rules);
- assertEquals(1, rules.size());
-
- // The rule can't be cleared.
- coordinator.tetherOffloadRuleClear(mIpServer);
- verify(mNetd, never()).tetherOffloadRuleRemove(any());
- rules = coordinator.getForwardingRulesForTesting().get(mIpServer);
- assertNotNull(rules);
- assertEquals(1, rules.size());
-
- // The rule can't be updated.
- coordinator.tetherOffloadRuleUpdate(mIpServer, rule.upstreamIfindex + 1 /* new */);
- verify(mNetd, never()).tetherOffloadRuleRemove(any());
- verify(mNetd, never()).tetherOffloadRuleAdd(any());
- rules = coordinator.getForwardingRulesForTesting().get(mIpServer);
- assertNotNull(rules);
- assertEquals(1, rules.size());
- }
-
- @Test
- public void testTetheringConfigSetPollingInterval() throws Exception {
- setupFunctioningNetdInterface();
-
- final BpfCoordinator coordinator = makeBpfCoordinator();
-
- // [1] The default polling interval.
- coordinator.startPolling();
- assertEquals(DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS, coordinator.getPollingInterval());
- coordinator.stopPolling();
-
- // [2] Expect the invalid polling interval isn't applied. The valid range of interval is
- // DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS..max_long.
- for (final int interval
- : new int[] {0, 100, DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS - 1}) {
- when(mTetherConfig.getOffloadPollInterval()).thenReturn(interval);
- coordinator.startPolling();
- assertEquals(DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS, coordinator.getPollingInterval());
- coordinator.stopPolling();
- }
-
- // [3] Set a specific polling interval which is larger than default value.
- // Use a large polling interval to avoid flaky test because the time forwarding
- // approximation is used to verify the scheduled time of the polling thread.
- final int pollingInterval = 100_000;
- when(mTetherConfig.getOffloadPollInterval()).thenReturn(pollingInterval);
- coordinator.startPolling();
-
- // Expect the specific polling interval to be applied.
- assertEquals(pollingInterval, coordinator.getPollingInterval());
-
- // Start on a new polling time slot.
- mTestLooper.moveTimeForward(pollingInterval);
- waitForIdle();
- clearInvocations(mNetd);
-
- // Move time forward to 90% polling interval time. Expect that the polling thread has not
- // scheduled yet.
- mTestLooper.moveTimeForward((long) (pollingInterval * 0.9));
- waitForIdle();
- verify(mNetd, never()).tetherOffloadGetStats();
-
- // Move time forward to the remaining 10% polling interval time. Expect that the polling
- // thread has scheduled.
- mTestLooper.moveTimeForward((long) (pollingInterval * 0.1));
- waitForIdle();
- verify(mNetd).tetherOffloadGetStats();
- }
-}
diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/ConnectedClientsTrackerTest.kt b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/ConnectedClientsTrackerTest.kt
deleted file mode 100644
index d915354..0000000
--- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/ConnectedClientsTrackerTest.kt
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * 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
-
-import android.net.LinkAddress
-import android.net.MacAddress
-import android.net.TetheredClient
-import android.net.TetheredClient.AddressInfo
-import android.net.TetheringManager.TETHERING_USB
-import android.net.TetheringManager.TETHERING_WIFI
-import android.net.ip.IpServer
-import android.net.wifi.WifiClient
-import androidx.test.filters.SmallTest
-import androidx.test.runner.AndroidJUnit4
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.Mockito.doReturn
-import org.mockito.Mockito.mock
-import kotlin.test.assertEquals
-import kotlin.test.assertFalse
-import kotlin.test.assertTrue
-
-@RunWith(AndroidJUnit4::class)
-@SmallTest
-class ConnectedClientsTrackerTest {
-
- private val server1 = mock(IpServer::class.java)
- private val server2 = mock(IpServer::class.java)
- private val servers = listOf(server1, server2)
-
- private val clock = TestClock(1324L)
-
- private val client1Addr = MacAddress.fromString("01:23:45:67:89:0A")
- private val client1 = TetheredClient(client1Addr, listOf(
- makeAddrInfo("192.168.43.44/32", null /* hostname */, clock.time + 20)),
- TETHERING_WIFI)
- private val wifiClient1 = makeWifiClient(client1Addr)
- private val client2Addr = MacAddress.fromString("02:34:56:78:90:AB")
- private val client2Exp30AddrInfo = makeAddrInfo(
- "192.168.43.45/32", "my_hostname", clock.time + 30)
- private val client2 = TetheredClient(client2Addr, listOf(
- client2Exp30AddrInfo,
- makeAddrInfo("2001:db8:12::34/72", "other_hostname", clock.time + 10)),
- TETHERING_WIFI)
- private val wifiClient2 = makeWifiClient(client2Addr)
- private val client3Addr = MacAddress.fromString("03:45:67:89:0A:BC")
- private val client3 = TetheredClient(client3Addr,
- listOf(makeAddrInfo("2001:db8:34::34/72", "other_other_hostname", clock.time + 10)),
- TETHERING_USB)
-
- private fun makeAddrInfo(addr: String, hostname: String?, expTime: Long) =
- LinkAddress(addr).let {
- AddressInfo(LinkAddress(it.address, it.prefixLength, it.flags, it.scope,
- expTime /* deprecationTime */, expTime /* expirationTime */), hostname)
- }
-
- @Test
- fun testUpdateConnectedClients() {
- doReturn(emptyList<TetheredClient>()).`when`(server1).allLeases
- doReturn(emptyList<TetheredClient>()).`when`(server2).allLeases
-
- val tracker = ConnectedClientsTracker(clock)
- assertFalse(tracker.updateConnectedClients(servers, null))
-
- // Obtain a lease for client 1
- doReturn(listOf(client1)).`when`(server1).allLeases
- assertSameClients(listOf(client1), assertNewClients(tracker, servers, listOf(wifiClient1)))
-
- // Client 2 L2-connected, no lease yet
- val client2WithoutAddr = TetheredClient(client2Addr, emptyList(), TETHERING_WIFI)
- assertSameClients(listOf(client1, client2WithoutAddr),
- assertNewClients(tracker, servers, listOf(wifiClient1, wifiClient2)))
-
- // Client 2 lease obtained
- doReturn(listOf(client1, client2)).`when`(server1).allLeases
- assertSameClients(listOf(client1, client2), assertNewClients(tracker, servers, null))
-
- // Client 3 lease obtained
- doReturn(listOf(client3)).`when`(server2).allLeases
- assertSameClients(listOf(client1, client2, client3),
- assertNewClients(tracker, servers, null))
-
- // Client 2 L2-disconnected
- assertSameClients(listOf(client1, client3),
- assertNewClients(tracker, servers, listOf(wifiClient1)))
-
- // Client 1 L2-disconnected
- assertSameClients(listOf(client3), assertNewClients(tracker, servers, emptyList()))
-
- // Client 1 comes back
- assertSameClients(listOf(client1, client3),
- assertNewClients(tracker, servers, listOf(wifiClient1)))
-
- // Leases lost, client 1 still L2-connected
- doReturn(emptyList<TetheredClient>()).`when`(server1).allLeases
- doReturn(emptyList<TetheredClient>()).`when`(server2).allLeases
- assertSameClients(listOf(TetheredClient(client1Addr, emptyList(), TETHERING_WIFI)),
- assertNewClients(tracker, servers, null))
- }
-
- @Test
- fun testUpdateConnectedClients_LeaseExpiration() {
- val tracker = ConnectedClientsTracker(clock)
- doReturn(listOf(client1, client2)).`when`(server1).allLeases
- doReturn(listOf(client3)).`when`(server2).allLeases
- assertSameClients(listOf(client1, client2, client3), assertNewClients(
- tracker, servers, listOf(wifiClient1, wifiClient2)))
-
- clock.time += 20
- // Client 3 has no remaining lease: removed
- val expectedClients = listOf(
- // Client 1 has no remaining lease but is L2-connected
- TetheredClient(client1Addr, emptyList(), TETHERING_WIFI),
- // Client 2 has some expired leases
- TetheredClient(
- client2Addr,
- // Only the "t + 30" address is left, the "t + 10" address expired
- listOf(client2Exp30AddrInfo),
- TETHERING_WIFI))
- assertSameClients(expectedClients, assertNewClients(tracker, servers, null))
- }
-
- private fun assertNewClients(
- tracker: ConnectedClientsTracker,
- ipServers: Iterable<IpServer>,
- wifiClients: List<WifiClient>?
- ): List<TetheredClient> {
- assertTrue(tracker.updateConnectedClients(ipServers, wifiClients))
- return tracker.lastTetheredClients
- }
-
- private fun assertSameClients(expected: List<TetheredClient>, actual: List<TetheredClient>) {
- val expectedSet = HashSet(expected)
- assertEquals(expected.size, expectedSet.size)
- assertEquals(expectedSet, HashSet(actual))
- }
-
- private fun makeWifiClient(macAddr: MacAddress): WifiClient {
- // Use a mock WifiClient as the constructor is not part of the WiFi module exported API.
- return mock(WifiClient::class.java).apply { doReturn(macAddr).`when`(this).macAddress }
- }
-
- private class TestClock(var time: Long) : ConnectedClientsTracker.Clock() {
- override fun elapsedRealtime(): Long {
- return time
- }
- }
-}
diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/EntitlementManagerTest.java b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/EntitlementManagerTest.java
deleted file mode 100644
index 354e753..0000000
--- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/EntitlementManagerTest.java
+++ /dev/null
@@ -1,623 +0,0 @@
-/*
- * Copyright (C) 2018 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;
-
-import static android.net.TetheringConstants.EXTRA_ADD_TETHER_TYPE;
-import static android.net.TetheringConstants.EXTRA_PROVISION_CALLBACK;
-import static android.net.TetheringConstants.EXTRA_RUN_PROVISION;
-import static android.net.TetheringConstants.EXTRA_TETHER_PROVISIONING_RESPONSE;
-import static android.net.TetheringConstants.EXTRA_TETHER_SILENT_PROVISIONING_ACTION;
-import static android.net.TetheringConstants.EXTRA_TETHER_SUBID;
-import static android.net.TetheringConstants.EXTRA_TETHER_UI_PROVISIONING_APP_NAME;
-import static android.net.TetheringManager.TETHERING_BLUETOOTH;
-import static android.net.TetheringManager.TETHERING_ETHERNET;
-import static android.net.TetheringManager.TETHERING_INVALID;
-import static android.net.TetheringManager.TETHERING_USB;
-import static android.net.TetheringManager.TETHERING_WIFI;
-import static android.net.TetheringManager.TETHERING_WIFI_P2P;
-import static android.net.TetheringManager.TETHER_ERROR_ENTITLEMENT_UNKNOWN;
-import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
-import static android.net.TetheringManager.TETHER_ERROR_PROVISIONING_FAILED;
-import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY;
-import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
-
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.anyBoolean;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.inOrder;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.content.Intent;
-import android.content.res.Resources;
-import android.net.util.SharedLog;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.PersistableBundle;
-import android.os.ResultReceiver;
-import android.os.SystemProperties;
-import android.os.test.TestLooper;
-import android.provider.DeviceConfig;
-import android.provider.Settings;
-import android.telephony.CarrierConfigManager;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import com.android.internal.util.test.BroadcastInterceptingContext;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.InOrder;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.mockito.MockitoSession;
-import org.mockito.quality.Strictness;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public final class EntitlementManagerTest {
-
- private static final String[] PROVISIONING_APP_NAME = {"some", "app"};
- private static final String PROVISIONING_NO_UI_APP_NAME = "no_ui_app";
- private static final String PROVISIONING_APP_RESPONSE = "app_response";
-
- @Mock private CarrierConfigManager mCarrierConfigManager;
- @Mock private Context mContext;
- @Mock private Resources mResources;
- @Mock private SharedLog mLog;
- @Mock private EntitlementManager.OnUiEntitlementFailedListener mEntitlementFailedListener;
-
- // Like so many Android system APIs, these cannot be mocked because it is marked final.
- // We have to use the real versions.
- private final PersistableBundle mCarrierConfig = new PersistableBundle();
- private final TestLooper mLooper = new TestLooper();
- private Context mMockContext;
- private Runnable mPermissionChangeCallback;
-
- private WrappedEntitlementManager mEnMgr;
- private TetheringConfiguration mConfig;
- private MockitoSession mMockingSession;
-
- private class MockContext extends BroadcastInterceptingContext {
- MockContext(Context base) {
- super(base);
- }
-
- @Override
- public Resources getResources() {
- return mResources;
- }
- }
-
- public class WrappedEntitlementManager extends EntitlementManager {
- public int fakeEntitlementResult = TETHER_ERROR_ENTITLEMENT_UNKNOWN;
- public int uiProvisionCount = 0;
- public int silentProvisionCount = 0;
-
- public WrappedEntitlementManager(Context ctx, Handler h, SharedLog log,
- Runnable callback) {
- super(ctx, h, log, callback);
- }
-
- public void reset() {
- fakeEntitlementResult = TETHER_ERROR_ENTITLEMENT_UNKNOWN;
- uiProvisionCount = 0;
- silentProvisionCount = 0;
- }
-
- @Override
- protected Intent runUiTetherProvisioning(int type,
- final TetheringConfiguration config, final ResultReceiver receiver) {
- Intent intent = super.runUiTetherProvisioning(type, config, receiver);
- assertUiTetherProvisioningIntent(type, config, receiver, intent);
- uiProvisionCount++;
- receiver.send(fakeEntitlementResult, null);
- return intent;
- }
-
- private void assertUiTetherProvisioningIntent(int type, final TetheringConfiguration config,
- final ResultReceiver receiver, final Intent intent) {
- assertEquals(Settings.ACTION_TETHER_PROVISIONING_UI, intent.getAction());
- assertEquals(type, intent.getIntExtra(EXTRA_ADD_TETHER_TYPE, TETHERING_INVALID));
- final String[] appName = intent.getStringArrayExtra(
- EXTRA_TETHER_UI_PROVISIONING_APP_NAME);
- assertEquals(PROVISIONING_APP_NAME.length, appName.length);
- for (int i = 0; i < PROVISIONING_APP_NAME.length; i++) {
- assertEquals(PROVISIONING_APP_NAME[i], appName[i]);
- }
- assertEquals(receiver, intent.getParcelableExtra(EXTRA_PROVISION_CALLBACK));
- assertEquals(config.activeDataSubId,
- intent.getIntExtra(EXTRA_TETHER_SUBID, INVALID_SUBSCRIPTION_ID));
- }
-
- @Override
- protected Intent runSilentTetherProvisioning(int type,
- final TetheringConfiguration config) {
- Intent intent = super.runSilentTetherProvisioning(type, config);
- assertSilentTetherProvisioning(type, config, intent);
- silentProvisionCount++;
- addDownstreamMapping(type, fakeEntitlementResult);
- return intent;
- }
-
- private void assertSilentTetherProvisioning(int type, final TetheringConfiguration config,
- final Intent intent) {
- assertEquals(type, intent.getIntExtra(EXTRA_ADD_TETHER_TYPE, TETHERING_INVALID));
- assertEquals(true, intent.getBooleanExtra(EXTRA_RUN_PROVISION, false));
- assertEquals(PROVISIONING_NO_UI_APP_NAME,
- intent.getStringExtra(EXTRA_TETHER_SILENT_PROVISIONING_ACTION));
- assertEquals(PROVISIONING_APP_RESPONSE,
- intent.getStringExtra(EXTRA_TETHER_PROVISIONING_RESPONSE));
- assertTrue(intent.hasExtra(EXTRA_PROVISION_CALLBACK));
- assertEquals(config.activeDataSubId,
- intent.getIntExtra(EXTRA_TETHER_SUBID, INVALID_SUBSCRIPTION_ID));
- }
- }
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- mMockingSession = mockitoSession()
- .initMocks(this)
- .mockStatic(SystemProperties.class)
- .mockStatic(DeviceConfig.class)
- .strictness(Strictness.WARN)
- .startMocking();
- // Don't disable tethering provisioning unless requested.
- doReturn(false).when(
- () -> SystemProperties.getBoolean(
- eq(EntitlementManager.DISABLE_PROVISIONING_SYSPROP_KEY), anyBoolean()));
- doReturn(null).when(
- () -> DeviceConfig.getProperty(eq(NAMESPACE_CONNECTIVITY), anyString()));
-
- when(mResources.getStringArray(R.array.config_tether_dhcp_range))
- .thenReturn(new String[0]);
- when(mResources.getStringArray(R.array.config_tether_usb_regexs))
- .thenReturn(new String[0]);
- when(mResources.getStringArray(R.array.config_tether_wifi_regexs))
- .thenReturn(new String[0]);
- when(mResources.getStringArray(R.array.config_tether_bluetooth_regexs))
- .thenReturn(new String[0]);
- when(mResources.getIntArray(R.array.config_tether_upstream_types))
- .thenReturn(new int[0]);
- when(mResources.getBoolean(R.bool.config_tether_enable_legacy_dhcp_server)).thenReturn(
- false);
- when(mResources.getString(R.string.config_wifi_tether_enable)).thenReturn("");
- when(mLog.forSubComponent(anyString())).thenReturn(mLog);
-
- mMockContext = new MockContext(mContext);
- mPermissionChangeCallback = spy(() -> { });
- mEnMgr = new WrappedEntitlementManager(mMockContext, new Handler(mLooper.getLooper()), mLog,
- mPermissionChangeCallback);
- mEnMgr.setOnUiEntitlementFailedListener(mEntitlementFailedListener);
- mConfig = new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
- mEnMgr.setTetheringConfigurationFetcher(() -> {
- return mConfig;
- });
- }
-
- @After
- public void tearDown() throws Exception {
- mMockingSession.finishMocking();
- }
-
- private void setupForRequiredProvisioning() {
- // Produce some acceptable looking provision app setting if requested.
- when(mResources.getStringArray(R.array.config_mobile_hotspot_provision_app))
- .thenReturn(PROVISIONING_APP_NAME);
- when(mResources.getString(R.string.config_mobile_hotspot_provision_app_no_ui))
- .thenReturn(PROVISIONING_NO_UI_APP_NAME);
- when(mResources.getString(R.string.config_mobile_hotspot_provision_response)).thenReturn(
- PROVISIONING_APP_RESPONSE);
- // Act like the CarrierConfigManager is present and ready unless told otherwise.
- when(mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE))
- .thenReturn(mCarrierConfigManager);
- when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(mCarrierConfig);
- mCarrierConfig.putBoolean(CarrierConfigManager.KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL, true);
- mCarrierConfig.putBoolean(CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL, true);
- mConfig = new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
- }
-
- @Test
- public void canRequireProvisioning() {
- setupForRequiredProvisioning();
- assertTrue(mEnMgr.isTetherProvisioningRequired(mConfig));
- }
-
- @Test
- public void toleratesCarrierConfigManagerMissing() {
- setupForRequiredProvisioning();
- when(mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE))
- .thenReturn(null);
- mConfig = new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
- // Couldn't get the CarrierConfigManager, but still had a declared provisioning app.
- // Therefore provisioning still be required.
- assertTrue(mEnMgr.isTetherProvisioningRequired(mConfig));
- }
-
- @Test
- public void toleratesCarrierConfigMissing() {
- setupForRequiredProvisioning();
- when(mCarrierConfigManager.getConfig()).thenReturn(null);
- mConfig = new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
- // We still have a provisioning app configured, so still require provisioning.
- assertTrue(mEnMgr.isTetherProvisioningRequired(mConfig));
- }
-
- @Test
- public void toleratesCarrierConfigNotLoaded() {
- setupForRequiredProvisioning();
- mCarrierConfig.putBoolean(CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL, false);
- // We still have a provisioning app configured, so still require provisioning.
- assertTrue(mEnMgr.isTetherProvisioningRequired(mConfig));
- }
-
- @Test
- public void provisioningNotRequiredWhenAppNotFound() {
- setupForRequiredProvisioning();
- when(mResources.getStringArray(R.array.config_mobile_hotspot_provision_app))
- .thenReturn(null);
- mConfig = new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
- assertFalse(mEnMgr.isTetherProvisioningRequired(mConfig));
- when(mResources.getStringArray(R.array.config_mobile_hotspot_provision_app))
- .thenReturn(new String[] {"malformedApp"});
- mConfig = new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
- assertFalse(mEnMgr.isTetherProvisioningRequired(mConfig));
- }
-
- @Test
- public void testRequestLastEntitlementCacheValue() throws Exception {
- // 1. Entitlement check is not required.
- mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR;
- ResultReceiver receiver = new ResultReceiver(null) {
- @Override
- protected void onReceiveResult(int resultCode, Bundle resultData) {
- assertEquals(TETHER_ERROR_NO_ERROR, resultCode);
- }
- };
- mEnMgr.requestLatestTetheringEntitlementResult(TETHERING_WIFI, receiver, true);
- mLooper.dispatchAll();
- assertEquals(0, mEnMgr.uiProvisionCount);
- mEnMgr.reset();
-
- setupForRequiredProvisioning();
- // 2. No cache value and don't need to run entitlement check.
- receiver = new ResultReceiver(null) {
- @Override
- protected void onReceiveResult(int resultCode, Bundle resultData) {
- assertEquals(TETHER_ERROR_ENTITLEMENT_UNKNOWN, resultCode);
- }
- };
- mEnMgr.requestLatestTetheringEntitlementResult(TETHERING_WIFI, receiver, false);
- mLooper.dispatchAll();
- assertEquals(0, mEnMgr.uiProvisionCount);
- mEnMgr.reset();
- // 3. No cache value and ui entitlement check is needed.
- mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISIONING_FAILED;
- receiver = new ResultReceiver(null) {
- @Override
- protected void onReceiveResult(int resultCode, Bundle resultData) {
- assertEquals(TETHER_ERROR_PROVISIONING_FAILED, resultCode);
- }
- };
- mEnMgr.requestLatestTetheringEntitlementResult(TETHERING_WIFI, receiver, true);
- mLooper.dispatchAll();
- assertEquals(1, mEnMgr.uiProvisionCount);
- mEnMgr.reset();
- // 4. Cache value is TETHER_ERROR_PROVISIONING_FAILED and don't need to run entitlement
- // check.
- mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR;
- receiver = new ResultReceiver(null) {
- @Override
- protected void onReceiveResult(int resultCode, Bundle resultData) {
- assertEquals(TETHER_ERROR_PROVISIONING_FAILED, resultCode);
- }
- };
- mEnMgr.requestLatestTetheringEntitlementResult(TETHERING_WIFI, receiver, false);
- mLooper.dispatchAll();
- assertEquals(0, mEnMgr.uiProvisionCount);
- mEnMgr.reset();
- // 5. Cache value is TETHER_ERROR_PROVISIONING_FAILED and ui entitlement check is needed.
- mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR;
- receiver = new ResultReceiver(null) {
- @Override
- protected void onReceiveResult(int resultCode, Bundle resultData) {
- assertEquals(TETHER_ERROR_NO_ERROR, resultCode);
- }
- };
- mEnMgr.requestLatestTetheringEntitlementResult(TETHERING_WIFI, receiver, true);
- mLooper.dispatchAll();
- assertEquals(1, mEnMgr.uiProvisionCount);
- mEnMgr.reset();
- // 6. Cache value is TETHER_ERROR_NO_ERROR.
- mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR;
- receiver = new ResultReceiver(null) {
- @Override
- protected void onReceiveResult(int resultCode, Bundle resultData) {
- assertEquals(TETHER_ERROR_NO_ERROR, resultCode);
- }
- };
- mEnMgr.requestLatestTetheringEntitlementResult(TETHERING_WIFI, receiver, true);
- mLooper.dispatchAll();
- assertEquals(0, mEnMgr.uiProvisionCount);
- mEnMgr.reset();
- // 7. Test get value for other downstream type.
- receiver = new ResultReceiver(null) {
- @Override
- protected void onReceiveResult(int resultCode, Bundle resultData) {
- assertEquals(TETHER_ERROR_ENTITLEMENT_UNKNOWN, resultCode);
- }
- };
- mEnMgr.requestLatestTetheringEntitlementResult(TETHERING_USB, receiver, false);
- mLooper.dispatchAll();
- assertEquals(0, mEnMgr.uiProvisionCount);
- mEnMgr.reset();
- // 8. Test get value for invalid downstream type.
- mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR;
- receiver = new ResultReceiver(null) {
- @Override
- protected void onReceiveResult(int resultCode, Bundle resultData) {
- assertEquals(TETHER_ERROR_ENTITLEMENT_UNKNOWN, resultCode);
- }
- };
- mEnMgr.requestLatestTetheringEntitlementResult(TETHERING_WIFI_P2P, receiver, true);
- mLooper.dispatchAll();
- assertEquals(0, mEnMgr.uiProvisionCount);
- mEnMgr.reset();
- }
-
- private void assertPermissionChangeCallback(InOrder inOrder) {
- inOrder.verify(mPermissionChangeCallback, times(1)).run();
- }
-
- private void assertNoPermissionChange(InOrder inOrder) {
- inOrder.verifyNoMoreInteractions();
- }
-
- @Test
- public void verifyPermissionResult() {
- final InOrder inOrder = inOrder(mPermissionChangeCallback);
- setupForRequiredProvisioning();
- mEnMgr.notifyUpstream(true);
- mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISIONING_FAILED;
- mEnMgr.startProvisioningIfNeeded(TETHERING_WIFI, true);
- mLooper.dispatchAll();
- // Permitted: true -> false
- assertPermissionChangeCallback(inOrder);
- assertFalse(mEnMgr.isCellularUpstreamPermitted());
-
- mEnMgr.stopProvisioningIfNeeded(TETHERING_WIFI);
- mLooper.dispatchAll();
- // Permitted: false -> false
- assertNoPermissionChange(inOrder);
-
- mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR;
- mEnMgr.startProvisioningIfNeeded(TETHERING_WIFI, true);
- mLooper.dispatchAll();
- // Permitted: false -> true
- assertPermissionChangeCallback(inOrder);
- assertTrue(mEnMgr.isCellularUpstreamPermitted());
- }
-
- @Test
- public void verifyPermissionIfAllNotApproved() {
- final InOrder inOrder = inOrder(mPermissionChangeCallback);
- setupForRequiredProvisioning();
- mEnMgr.notifyUpstream(true);
- mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISIONING_FAILED;
- mEnMgr.startProvisioningIfNeeded(TETHERING_WIFI, true);
- mLooper.dispatchAll();
- // Permitted: true -> false
- assertPermissionChangeCallback(inOrder);
- assertFalse(mEnMgr.isCellularUpstreamPermitted());
-
- mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISIONING_FAILED;
- mEnMgr.startProvisioningIfNeeded(TETHERING_USB, true);
- mLooper.dispatchAll();
- // Permitted: false -> false
- assertNoPermissionChange(inOrder);
- assertFalse(mEnMgr.isCellularUpstreamPermitted());
-
- mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISIONING_FAILED;
- mEnMgr.startProvisioningIfNeeded(TETHERING_BLUETOOTH, true);
- mLooper.dispatchAll();
- // Permitted: false -> false
- assertNoPermissionChange(inOrder);
- assertFalse(mEnMgr.isCellularUpstreamPermitted());
- }
-
- @Test
- public void verifyPermissionIfAnyApproved() {
- final InOrder inOrder = inOrder(mPermissionChangeCallback);
- setupForRequiredProvisioning();
- mEnMgr.notifyUpstream(true);
- mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR;
- mEnMgr.startProvisioningIfNeeded(TETHERING_WIFI, true);
- mLooper.dispatchAll();
- // Permitted: true -> true
- assertNoPermissionChange(inOrder);
- assertTrue(mEnMgr.isCellularUpstreamPermitted());
-
- mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISIONING_FAILED;
- mEnMgr.startProvisioningIfNeeded(TETHERING_USB, true);
- mLooper.dispatchAll();
- // Permitted: true -> true
- assertNoPermissionChange(inOrder);
- assertTrue(mEnMgr.isCellularUpstreamPermitted());
-
- mEnMgr.stopProvisioningIfNeeded(TETHERING_WIFI);
- mLooper.dispatchAll();
- // Permitted: true -> false
- assertPermissionChangeCallback(inOrder);
- assertFalse(mEnMgr.isCellularUpstreamPermitted());
- }
-
- @Test
- public void verifyPermissionWhenProvisioningNotStarted() {
- final InOrder inOrder = inOrder(mPermissionChangeCallback);
- assertTrue(mEnMgr.isCellularUpstreamPermitted());
- assertNoPermissionChange(inOrder);
- setupForRequiredProvisioning();
- assertFalse(mEnMgr.isCellularUpstreamPermitted());
- assertNoPermissionChange(inOrder);
- }
-
- @Test
- public void testRunTetherProvisioning() {
- final InOrder inOrder = inOrder(mPermissionChangeCallback);
- setupForRequiredProvisioning();
- // 1. start ui provisioning, upstream is mobile
- mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR;
- mEnMgr.notifyUpstream(true);
- mLooper.dispatchAll();
- mEnMgr.startProvisioningIfNeeded(TETHERING_USB, true);
- mLooper.dispatchAll();
- assertEquals(1, mEnMgr.uiProvisionCount);
- assertEquals(0, mEnMgr.silentProvisionCount);
- // Permitted: true -> true
- assertNoPermissionChange(inOrder);
- assertTrue(mEnMgr.isCellularUpstreamPermitted());
- mEnMgr.reset();
-
- // 2. start no-ui provisioning
- mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR;
- mEnMgr.startProvisioningIfNeeded(TETHERING_WIFI, false);
- mLooper.dispatchAll();
- assertEquals(0, mEnMgr.uiProvisionCount);
- assertEquals(1, mEnMgr.silentProvisionCount);
- // Permitted: true -> true
- assertNoPermissionChange(inOrder);
- assertTrue(mEnMgr.isCellularUpstreamPermitted());
- mEnMgr.reset();
-
- // 3. tear down mobile, then start ui provisioning
- mEnMgr.notifyUpstream(false);
- mLooper.dispatchAll();
- mEnMgr.startProvisioningIfNeeded(TETHERING_BLUETOOTH, true);
- mLooper.dispatchAll();
- assertEquals(0, mEnMgr.uiProvisionCount);
- assertEquals(0, mEnMgr.silentProvisionCount);
- assertNoPermissionChange(inOrder);
- mEnMgr.reset();
-
- // 4. switch upstream back to mobile
- mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR;
- mEnMgr.notifyUpstream(true);
- mLooper.dispatchAll();
- assertEquals(1, mEnMgr.uiProvisionCount);
- assertEquals(0, mEnMgr.silentProvisionCount);
- // Permitted: true -> true
- assertNoPermissionChange(inOrder);
- assertTrue(mEnMgr.isCellularUpstreamPermitted());
- mEnMgr.reset();
-
- // 5. tear down mobile, then switch SIM
- mEnMgr.notifyUpstream(false);
- mLooper.dispatchAll();
- mEnMgr.reevaluateSimCardProvisioning(mConfig);
- assertEquals(0, mEnMgr.uiProvisionCount);
- assertEquals(0, mEnMgr.silentProvisionCount);
- assertNoPermissionChange(inOrder);
- mEnMgr.reset();
-
- // 6. switch upstream back to mobile again
- mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISIONING_FAILED;
- mEnMgr.notifyUpstream(true);
- mLooper.dispatchAll();
- assertEquals(0, mEnMgr.uiProvisionCount);
- assertEquals(3, mEnMgr.silentProvisionCount);
- // Permitted: true -> false
- assertPermissionChangeCallback(inOrder);
- assertFalse(mEnMgr.isCellularUpstreamPermitted());
- mEnMgr.reset();
-
- // 7. start ui provisioning, upstream is mobile, downstream is ethernet
- mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR;
- mEnMgr.startProvisioningIfNeeded(TETHERING_ETHERNET, true);
- mLooper.dispatchAll();
- assertEquals(1, mEnMgr.uiProvisionCount);
- assertEquals(0, mEnMgr.silentProvisionCount);
- // Permitted: false -> true
- assertPermissionChangeCallback(inOrder);
- assertTrue(mEnMgr.isCellularUpstreamPermitted());
- mEnMgr.reset();
-
- // 8. downstream is invalid
- mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR;
- mEnMgr.startProvisioningIfNeeded(TETHERING_WIFI_P2P, true);
- mLooper.dispatchAll();
- assertEquals(0, mEnMgr.uiProvisionCount);
- assertEquals(0, mEnMgr.silentProvisionCount);
- assertNoPermissionChange(inOrder);
- mEnMgr.reset();
- }
-
- @Test
- public void testCallStopTetheringWhenUiProvisioningFail() {
- setupForRequiredProvisioning();
- verify(mEntitlementFailedListener, times(0)).onUiEntitlementFailed(TETHERING_WIFI);
- mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISIONING_FAILED;
- mEnMgr.notifyUpstream(true);
- mLooper.dispatchAll();
- mEnMgr.startProvisioningIfNeeded(TETHERING_WIFI, true);
- mLooper.dispatchAll();
- assertEquals(1, mEnMgr.uiProvisionCount);
- verify(mEntitlementFailedListener, times(1)).onUiEntitlementFailed(TETHERING_WIFI);
- }
-
- @Test
- public void testsetExemptedDownstreamType() throws Exception {
- setupForRequiredProvisioning();
- // Cellular upstream is not permitted when no entitlement result.
- assertFalse(mEnMgr.isCellularUpstreamPermitted());
-
- // If there is exempted downstream and no other non-exempted downstreams, cellular is
- // permitted.
- mEnMgr.setExemptedDownstreamType(TETHERING_WIFI);
- assertTrue(mEnMgr.isCellularUpstreamPermitted());
-
- // If second downstream run entitlement check fail, cellular upstream is not permitted.
- mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISIONING_FAILED;
- mEnMgr.notifyUpstream(true);
- mLooper.dispatchAll();
- mEnMgr.startProvisioningIfNeeded(TETHERING_USB, true);
- mLooper.dispatchAll();
- assertFalse(mEnMgr.isCellularUpstreamPermitted());
-
- // When second downstream is down, exempted downstream can use cellular upstream.
- assertEquals(1, mEnMgr.uiProvisionCount);
- verify(mEntitlementFailedListener).onUiEntitlementFailed(TETHERING_USB);
- mEnMgr.stopProvisioningIfNeeded(TETHERING_USB);
- assertTrue(mEnMgr.isCellularUpstreamPermitted());
-
- mEnMgr.stopProvisioningIfNeeded(TETHERING_WIFI);
- assertFalse(mEnMgr.isCellularUpstreamPermitted());
- }
-}
diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/IPv6TetheringCoordinatorTest.java b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/IPv6TetheringCoordinatorTest.java
deleted file mode 100644
index f2b5314..0000000
--- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/IPv6TetheringCoordinatorTest.java
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * 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;
-
-import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
-import static android.net.RouteInfo.RTN_UNICAST;
-import static android.net.ip.IpServer.STATE_LOCAL_ONLY;
-import static android.net.ip.IpServer.STATE_TETHERED;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.mockito.Mockito.when;
-
-import android.net.InetAddresses;
-import android.net.IpPrefix;
-import android.net.LinkAddress;
-import android.net.LinkProperties;
-import android.net.Network;
-import android.net.NetworkCapabilities;
-import android.net.RouteInfo;
-import android.net.ip.IpServer;
-import android.net.util.SharedLog;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-import java.net.InetAddress;
-import java.util.ArrayList;
-import java.util.List;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class IPv6TetheringCoordinatorTest {
- private static final String TEST_DNS_SERVER = "2001:4860:4860::8888";
- private static final String TEST_INTERFACE = "test_rmnet0";
- private static final String TEST_IPV6_ADDRESS = "2001:db8::1/64";
- private static final String TEST_IPV4_ADDRESS = "192.168.100.1/24";
-
- private IPv6TetheringCoordinator mIPv6TetheringCoordinator;
- private ArrayList<IpServer> mNotifyList;
-
- @Mock private SharedLog mSharedLog;
-
- @Before
- public void setUp() throws Exception {
- MockitoAnnotations.initMocks(this);
- when(mSharedLog.forSubComponent(anyString())).thenReturn(mSharedLog);
- mNotifyList = new ArrayList<IpServer>();
- mIPv6TetheringCoordinator = new IPv6TetheringCoordinator(mNotifyList, mSharedLog);
- }
-
- private UpstreamNetworkState createDualStackUpstream(final int transportType) {
- final Network network = mock(Network.class);
- final NetworkCapabilities netCap =
- new NetworkCapabilities.Builder().addTransportType(transportType).build();
- final InetAddress dns = InetAddresses.parseNumericAddress(TEST_DNS_SERVER);
- final LinkProperties linkProp = new LinkProperties();
- linkProp.setInterfaceName(TEST_INTERFACE);
- linkProp.addLinkAddress(new LinkAddress(TEST_IPV6_ADDRESS));
- linkProp.addLinkAddress(new LinkAddress(TEST_IPV4_ADDRESS));
- linkProp.addRoute(new RouteInfo(new IpPrefix("::/0"), null, TEST_INTERFACE, RTN_UNICAST));
- linkProp.addRoute(new RouteInfo(new IpPrefix("0.0.0.0/0"), null, TEST_INTERFACE,
- RTN_UNICAST));
- linkProp.addDnsServer(dns);
- return new UpstreamNetworkState(linkProp, netCap, network);
- }
-
- private void assertOnlyOneV6AddressAndNoV4(LinkProperties lp) {
- assertEquals(lp.getInterfaceName(), TEST_INTERFACE);
- assertFalse(lp.hasIpv4Address());
- final List<LinkAddress> addresses = lp.getLinkAddresses();
- assertEquals(addresses.size(), 1);
- final LinkAddress v6Address = addresses.get(0);
- assertEquals(v6Address, new LinkAddress(TEST_IPV6_ADDRESS));
- }
-
- @Test
- public void testUpdateIpv6Upstream() throws Exception {
- // 1. Add first IpServer.
- final IpServer firstServer = mock(IpServer.class);
- mNotifyList.add(firstServer);
- mIPv6TetheringCoordinator.addActiveDownstream(firstServer, STATE_TETHERED);
- verify(firstServer).sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, 0, 0, null);
- verifyNoMoreInteractions(firstServer);
-
- // 2. Add second IpServer and it would not have ipv6 tethering.
- final IpServer secondServer = mock(IpServer.class);
- mNotifyList.add(secondServer);
- mIPv6TetheringCoordinator.addActiveDownstream(secondServer, STATE_LOCAL_ONLY);
- verifyNoMoreInteractions(secondServer);
- reset(firstServer, secondServer);
-
- // 3. No upstream.
- mIPv6TetheringCoordinator.updateUpstreamNetworkState(null);
- verify(secondServer).sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, 0, 0, null);
- reset(firstServer, secondServer);
-
- // 4. Update ipv6 mobile upstream.
- final UpstreamNetworkState mobileUpstream = createDualStackUpstream(TRANSPORT_CELLULAR);
- final ArgumentCaptor<LinkProperties> lp = ArgumentCaptor.forClass(LinkProperties.class);
- mIPv6TetheringCoordinator.updateUpstreamNetworkState(mobileUpstream);
- verify(firstServer).sendMessage(eq(IpServer.CMD_IPV6_TETHER_UPDATE), eq(-1), eq(0),
- lp.capture());
- final LinkProperties v6OnlyLink = lp.getValue();
- assertOnlyOneV6AddressAndNoV4(v6OnlyLink);
- verifyNoMoreInteractions(firstServer);
- verifyNoMoreInteractions(secondServer);
- reset(firstServer, secondServer);
-
- // 5. Remove first IpServer.
- mNotifyList.remove(firstServer);
- mIPv6TetheringCoordinator.removeActiveDownstream(firstServer);
- verify(firstServer).sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, 0, 0, null);
- verify(secondServer).sendMessage(eq(IpServer.CMD_IPV6_TETHER_UPDATE), eq(-1), eq(0),
- lp.capture());
- final LinkProperties localOnlyLink = lp.getValue();
- assertNotNull(localOnlyLink);
- assertNotEquals(localOnlyLink, v6OnlyLink);
- reset(firstServer, secondServer);
-
- // 6. Remove second IpServer.
- mNotifyList.remove(secondServer);
- mIPv6TetheringCoordinator.removeActiveDownstream(secondServer);
- verifyNoMoreInteractions(firstServer);
- verify(secondServer).sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, 0, 0, null);
- }
-}
diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/MockTetheringService.java b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/MockTetheringService.java
deleted file mode 100644
index 071a290e..0000000
--- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/MockTetheringService.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * 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;
-
-import static android.Manifest.permission.WRITE_SETTINGS;
-import static android.content.pm.PackageManager.PERMISSION_GRANTED;
-
-import static org.mockito.Mockito.mock;
-
-import android.content.Context;
-import android.content.Intent;
-import android.net.ITetheringConnector;
-import android.os.Binder;
-import android.os.IBinder;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-public class MockTetheringService extends TetheringService {
- private final Tethering mTethering = mock(Tethering.class);
-
- @Override
- public IBinder onBind(Intent intent) {
- return new MockTetheringConnector(super.onBind(intent));
- }
-
- @Override
- public Tethering makeTethering(TetheringDependencies deps) {
- return mTethering;
- }
-
- @Override
- boolean checkAndNoteWriteSettingsOperation(@NonNull Context context, int uid,
- @NonNull String callingPackage, @Nullable String callingAttributionTag,
- boolean throwException) {
- // Test this does not verify the calling package / UID, as calling package could be shell
- // and not match the UID.
- return context.checkCallingOrSelfPermission(WRITE_SETTINGS) == PERMISSION_GRANTED;
- }
-
- public Tethering getTethering() {
- return mTethering;
- }
-
- public class MockTetheringConnector extends Binder {
- final IBinder mBase;
- MockTetheringConnector(IBinder base) {
- mBase = base;
- }
-
- public ITetheringConnector getTetheringConnector() {
- return ITetheringConnector.Stub.asInterface(mBase);
- }
-
- public MockTetheringService getService() {
- return MockTetheringService.this;
- }
- }
-}
diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadControllerTest.java b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadControllerTest.java
deleted file mode 100644
index ce52ae2..0000000
--- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadControllerTest.java
+++ /dev/null
@@ -1,827 +0,0 @@
-/*
- * Copyright (C) 2017 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;
-
-import static android.net.NetworkStats.DEFAULT_NETWORK_NO;
-import static android.net.NetworkStats.METERED_NO;
-import static android.net.NetworkStats.ROAMING_NO;
-import static android.net.NetworkStats.SET_DEFAULT;
-import static android.net.NetworkStats.TAG_NONE;
-import static android.net.NetworkStats.UID_ALL;
-import static android.net.NetworkStats.UID_TETHERING;
-import static android.net.RouteInfo.RTN_UNICAST;
-import static android.provider.Settings.Global.TETHER_OFFLOAD_DISABLED;
-
-import static com.android.networkstack.tethering.OffloadController.StatsType.STATS_PER_IFACE;
-import static com.android.networkstack.tethering.OffloadController.StatsType.STATS_PER_UID;
-import static com.android.networkstack.tethering.OffloadHardwareInterface.ForwardedStats;
-import static com.android.networkstack.tethering.TetheringConfiguration.DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS;
-import static com.android.testutils.MiscAsserts.assertContainsAll;
-import static com.android.testutils.MiscAsserts.assertThrows;
-import static com.android.testutils.NetworkStatsUtilsKt.assertNetworkStatsEquals;
-
-import static junit.framework.Assert.assertNotNull;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyLong;
-import static org.mockito.Matchers.anyObject;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.clearInvocations;
-import static org.mockito.Mockito.inOrder;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.mockito.Mockito.when;
-
-import android.annotation.NonNull;
-import android.app.usage.NetworkStatsManager;
-import android.content.Context;
-import android.content.pm.ApplicationInfo;
-import android.net.ITetheringStatsProvider;
-import android.net.IpPrefix;
-import android.net.LinkAddress;
-import android.net.LinkProperties;
-import android.net.NetworkStats;
-import android.net.NetworkStats.Entry;
-import android.net.RouteInfo;
-import android.net.netstats.provider.NetworkStatsProvider;
-import android.net.util.SharedLog;
-import android.os.Handler;
-import android.os.test.TestLooper;
-import android.provider.Settings;
-import android.provider.Settings.SettingNotFoundException;
-import android.test.mock.MockContentResolver;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import com.android.internal.util.test.FakeSettingsProvider;
-import com.android.testutils.TestableNetworkStatsProviderCbBinder;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.InOrder;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-import java.net.InetAddress;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.Set;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class OffloadControllerTest {
- private static final String RNDIS0 = "test_rndis0";
- private static final String RMNET0 = "test_rmnet_data0";
- private static final String WLAN0 = "test_wlan0";
-
- private static final String IPV6_LINKLOCAL = "fe80::/64";
- private static final String IPV6_DOC_PREFIX = "2001:db8::/64";
- private static final String IPV6_DISCARD_PREFIX = "100::/64";
- private static final String USB_PREFIX = "192.168.42.0/24";
- private static final String WIFI_PREFIX = "192.168.43.0/24";
- private static final long WAIT_FOR_IDLE_TIMEOUT = 2 * 1000;
-
- @Mock private OffloadHardwareInterface mHardware;
- @Mock private ApplicationInfo mApplicationInfo;
- @Mock private Context mContext;
- @Mock private NetworkStatsManager mStatsManager;
- @Mock private TetheringConfiguration mTetherConfig;
- // Late init since methods must be called by the thread that created this object.
- private TestableNetworkStatsProviderCbBinder mTetherStatsProviderCb;
- private OffloadController.OffloadTetheringStatsProvider mTetherStatsProvider;
- private final ArgumentCaptor<ArrayList> mStringArrayCaptor =
- ArgumentCaptor.forClass(ArrayList.class);
- private final ArgumentCaptor<OffloadHardwareInterface.ControlCallback> mControlCallbackCaptor =
- ArgumentCaptor.forClass(OffloadHardwareInterface.ControlCallback.class);
- private MockContentResolver mContentResolver;
- private final TestLooper mTestLooper = new TestLooper();
- private OffloadController.Dependencies mDeps = new OffloadController.Dependencies() {
- @Override
- public TetheringConfiguration getTetherConfig() {
- return mTetherConfig;
- }
- };
-
- @Before public void setUp() {
- MockitoAnnotations.initMocks(this);
- when(mContext.getApplicationInfo()).thenReturn(mApplicationInfo);
- when(mContext.getPackageName()).thenReturn("OffloadControllerTest");
- mContentResolver = new MockContentResolver(mContext);
- mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
- when(mContext.getContentResolver()).thenReturn(mContentResolver);
- FakeSettingsProvider.clearSettingsProvider();
- when(mTetherConfig.getOffloadPollInterval()).thenReturn(-1); // Disabled.
- }
-
- @After public void tearDown() throws Exception {
- FakeSettingsProvider.clearSettingsProvider();
- }
-
- private void setupFunctioningHardwareInterface() {
- when(mHardware.initOffloadConfig()).thenReturn(true);
- when(mHardware.initOffloadControl(mControlCallbackCaptor.capture()))
- .thenReturn(true);
- when(mHardware.setUpstreamParameters(anyString(), any(), any(), any())).thenReturn(true);
- when(mHardware.getForwardedStats(any())).thenReturn(new ForwardedStats());
- when(mHardware.setDataLimit(anyString(), anyLong())).thenReturn(true);
- }
-
- private void enableOffload() {
- Settings.Global.putInt(mContentResolver, TETHER_OFFLOAD_DISABLED, 0);
- }
-
- private void setOffloadPollInterval(int interval) {
- when(mTetherConfig.getOffloadPollInterval()).thenReturn(interval);
- }
-
- private void waitForIdle() {
- mTestLooper.dispatchAll();
- }
-
- private OffloadController makeOffloadController() throws Exception {
- OffloadController offload = new OffloadController(new Handler(mTestLooper.getLooper()),
- mHardware, mContentResolver, mStatsManager, new SharedLog("test"), mDeps);
- final ArgumentCaptor<OffloadController.OffloadTetheringStatsProvider>
- tetherStatsProviderCaptor =
- ArgumentCaptor.forClass(OffloadController.OffloadTetheringStatsProvider.class);
- verify(mStatsManager).registerNetworkStatsProvider(anyString(),
- tetherStatsProviderCaptor.capture());
- mTetherStatsProvider = tetherStatsProviderCaptor.getValue();
- assertNotNull(mTetherStatsProvider);
- mTetherStatsProviderCb = new TestableNetworkStatsProviderCbBinder();
- mTetherStatsProvider.setProviderCallbackBinder(mTetherStatsProviderCb);
- return offload;
- }
-
- @Test
- public void testNoSettingsValueDefaultDisabledDoesNotStart() throws Exception {
- setupFunctioningHardwareInterface();
- when(mHardware.getDefaultTetherOffloadDisabled()).thenReturn(1);
- assertThrows(SettingNotFoundException.class, () ->
- Settings.Global.getInt(mContentResolver, TETHER_OFFLOAD_DISABLED));
-
- final OffloadController offload = makeOffloadController();
- offload.start();
-
- final InOrder inOrder = inOrder(mHardware);
- inOrder.verify(mHardware, times(1)).getDefaultTetherOffloadDisabled();
- inOrder.verify(mHardware, never()).initOffloadConfig();
- inOrder.verify(mHardware, never()).initOffloadControl(
- any(OffloadHardwareInterface.ControlCallback.class));
- inOrder.verifyNoMoreInteractions();
- }
-
- @Test
- public void testNoSettingsValueDefaultEnabledDoesStart() throws Exception {
- setupFunctioningHardwareInterface();
- when(mHardware.getDefaultTetherOffloadDisabled()).thenReturn(0);
- assertThrows(SettingNotFoundException.class, () ->
- Settings.Global.getInt(mContentResolver, TETHER_OFFLOAD_DISABLED));
-
- final OffloadController offload = makeOffloadController();
- offload.start();
-
- final InOrder inOrder = inOrder(mHardware);
- inOrder.verify(mHardware, times(1)).getDefaultTetherOffloadDisabled();
- inOrder.verify(mHardware, times(1)).initOffloadConfig();
- inOrder.verify(mHardware, times(1)).initOffloadControl(
- any(OffloadHardwareInterface.ControlCallback.class));
- inOrder.verifyNoMoreInteractions();
- }
-
- @Test
- public void testSettingsAllowsStart() throws Exception {
- setupFunctioningHardwareInterface();
- Settings.Global.putInt(mContentResolver, TETHER_OFFLOAD_DISABLED, 0);
-
- final OffloadController offload = makeOffloadController();
- offload.start();
-
- final InOrder inOrder = inOrder(mHardware);
- inOrder.verify(mHardware, times(1)).getDefaultTetherOffloadDisabled();
- inOrder.verify(mHardware, times(1)).initOffloadConfig();
- inOrder.verify(mHardware, times(1)).initOffloadControl(
- any(OffloadHardwareInterface.ControlCallback.class));
- inOrder.verifyNoMoreInteractions();
- }
-
- @Test
- public void testSettingsDisablesStart() throws Exception {
- setupFunctioningHardwareInterface();
- Settings.Global.putInt(mContentResolver, TETHER_OFFLOAD_DISABLED, 1);
-
- final OffloadController offload = makeOffloadController();
- offload.start();
-
- final InOrder inOrder = inOrder(mHardware);
- inOrder.verify(mHardware, times(1)).getDefaultTetherOffloadDisabled();
- inOrder.verify(mHardware, never()).initOffloadConfig();
- inOrder.verify(mHardware, never()).initOffloadControl(anyObject());
- inOrder.verifyNoMoreInteractions();
- }
-
- @Test
- public void testSetUpstreamLinkPropertiesWorking() throws Exception {
- setupFunctioningHardwareInterface();
- enableOffload();
-
- final OffloadController offload = makeOffloadController();
- offload.start();
-
- final InOrder inOrder = inOrder(mHardware);
- inOrder.verify(mHardware, times(1)).getDefaultTetherOffloadDisabled();
- inOrder.verify(mHardware, times(1)).initOffloadConfig();
- inOrder.verify(mHardware, times(1)).initOffloadControl(
- any(OffloadHardwareInterface.ControlCallback.class));
- inOrder.verifyNoMoreInteractions();
-
- // In reality, the UpstreamNetworkMonitor would have passed down to us
- // a covering set of local prefixes representing a minimum essential
- // set plus all the prefixes on networks with network agents.
- //
- // We simulate that there, and then add upstream elements one by one
- // and watch what happens.
- final Set<IpPrefix> minimumLocalPrefixes = new HashSet<>();
- for (String s : new String[]{
- "127.0.0.0/8", "192.0.2.0/24", "fe80::/64", "2001:db8::/64"}) {
- minimumLocalPrefixes.add(new IpPrefix(s));
- }
- offload.setLocalPrefixes(minimumLocalPrefixes);
- inOrder.verify(mHardware, times(1)).setLocalPrefixes(mStringArrayCaptor.capture());
- ArrayList<String> localPrefixes = mStringArrayCaptor.getValue();
- assertEquals(4, localPrefixes.size());
- assertContainsAll(localPrefixes,
- "127.0.0.0/8", "192.0.2.0/24", "fe80::/64", "2001:db8::/64");
- inOrder.verifyNoMoreInteractions();
-
- offload.setUpstreamLinkProperties(null);
- // No change in local addresses means no call to setLocalPrefixes().
- inOrder.verify(mHardware, never()).setLocalPrefixes(mStringArrayCaptor.capture());
- // This LinkProperties value does not differ from the default upstream.
- // There should be no extraneous call to setUpstreamParameters().
- inOrder.verify(mHardware, never()).setUpstreamParameters(
- anyObject(), anyObject(), anyObject(), anyObject());
- inOrder.verifyNoMoreInteractions();
-
- final LinkProperties lp = new LinkProperties();
-
- final String testIfName = "rmnet_data17";
- lp.setInterfaceName(testIfName);
- offload.setUpstreamLinkProperties(lp);
- // No change in local addresses means no call to setLocalPrefixes().
- inOrder.verify(mHardware, never()).setLocalPrefixes(mStringArrayCaptor.capture());
- inOrder.verify(mHardware, times(1)).setUpstreamParameters(
- eq(testIfName), eq(null), eq(null), eq(null));
- inOrder.verify(mHardware, times(1)).setDataLimit(eq(testIfName), eq(Long.MAX_VALUE));
- inOrder.verifyNoMoreInteractions();
-
- final String ipv4Addr = "192.0.2.5";
- final String linkAddr = ipv4Addr + "/24";
- lp.addLinkAddress(new LinkAddress(linkAddr));
- lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"), null, null, RTN_UNICAST));
- offload.setUpstreamLinkProperties(lp);
- // IPv4 prefixes and addresses on the upstream are simply left as whole
- // prefixes (already passed in from UpstreamNetworkMonitor code). If a
- // tethering client sends traffic to the IPv4 default router or other
- // clients on the upstream this will not be hardware-forwarded, and that
- // should be fine for now. Ergo: no change in local addresses, no call
- // to setLocalPrefixes().
- inOrder.verify(mHardware, never()).setLocalPrefixes(mStringArrayCaptor.capture());
- inOrder.verify(mHardware, times(1)).setUpstreamParameters(
- eq(testIfName), eq(ipv4Addr), eq(null), eq(null));
- inOrder.verify(mHardware, times(1)).getForwardedStats(eq(testIfName));
- inOrder.verify(mHardware, times(1)).setDataLimit(eq(testIfName), eq(Long.MAX_VALUE));
- inOrder.verifyNoMoreInteractions();
-
- final String ipv4Gateway = "192.0.2.1";
- lp.addRoute(new RouteInfo(null, InetAddress.getByName(ipv4Gateway), null, RTN_UNICAST));
- offload.setUpstreamLinkProperties(lp);
- // No change in local addresses means no call to setLocalPrefixes().
- inOrder.verify(mHardware, never()).setLocalPrefixes(mStringArrayCaptor.capture());
- inOrder.verify(mHardware, times(1)).setUpstreamParameters(
- eq(testIfName), eq(ipv4Addr), eq(ipv4Gateway), eq(null));
- inOrder.verify(mHardware, times(1)).getForwardedStats(eq(testIfName));
- inOrder.verify(mHardware, times(1)).setDataLimit(eq(testIfName), eq(Long.MAX_VALUE));
- inOrder.verifyNoMoreInteractions();
-
- final String ipv6Gw1 = "fe80::cafe";
- lp.addRoute(new RouteInfo(null, InetAddress.getByName(ipv6Gw1), null, RTN_UNICAST));
- offload.setUpstreamLinkProperties(lp);
- // No change in local addresses means no call to setLocalPrefixes().
- inOrder.verify(mHardware, never()).setLocalPrefixes(mStringArrayCaptor.capture());
- inOrder.verify(mHardware, times(1)).setUpstreamParameters(
- eq(testIfName), eq(ipv4Addr), eq(ipv4Gateway), mStringArrayCaptor.capture());
- inOrder.verify(mHardware, times(1)).getForwardedStats(eq(testIfName));
- ArrayList<String> v6gws = mStringArrayCaptor.getValue();
- assertEquals(1, v6gws.size());
- assertTrue(v6gws.contains(ipv6Gw1));
- inOrder.verify(mHardware, times(1)).setDataLimit(eq(testIfName), eq(Long.MAX_VALUE));
- inOrder.verifyNoMoreInteractions();
-
- final String ipv6Gw2 = "fe80::d00d";
- lp.addRoute(new RouteInfo(null, InetAddress.getByName(ipv6Gw2), null, RTN_UNICAST));
- offload.setUpstreamLinkProperties(lp);
- // No change in local addresses means no call to setLocalPrefixes().
- inOrder.verify(mHardware, never()).setLocalPrefixes(mStringArrayCaptor.capture());
- inOrder.verify(mHardware, times(1)).setUpstreamParameters(
- eq(testIfName), eq(ipv4Addr), eq(ipv4Gateway), mStringArrayCaptor.capture());
- inOrder.verify(mHardware, times(1)).getForwardedStats(eq(testIfName));
- v6gws = mStringArrayCaptor.getValue();
- assertEquals(2, v6gws.size());
- assertTrue(v6gws.contains(ipv6Gw1));
- assertTrue(v6gws.contains(ipv6Gw2));
- inOrder.verify(mHardware, times(1)).setDataLimit(eq(testIfName), eq(Long.MAX_VALUE));
- inOrder.verifyNoMoreInteractions();
-
- final LinkProperties stacked = new LinkProperties();
- stacked.setInterfaceName("stacked");
- stacked.addLinkAddress(new LinkAddress("192.0.2.129/25"));
- stacked.addRoute(new RouteInfo(null, InetAddress.getByName("192.0.2.254"), null,
- RTN_UNICAST));
- stacked.addRoute(new RouteInfo(null, InetAddress.getByName("fe80::bad:f00"), null,
- RTN_UNICAST));
- assertTrue(lp.addStackedLink(stacked));
- offload.setUpstreamLinkProperties(lp);
- // No change in local addresses means no call to setLocalPrefixes().
- inOrder.verify(mHardware, never()).setLocalPrefixes(mStringArrayCaptor.capture());
- inOrder.verify(mHardware, times(1)).setUpstreamParameters(
- eq(testIfName), eq(ipv4Addr), eq(ipv4Gateway), mStringArrayCaptor.capture());
- inOrder.verify(mHardware, times(1)).getForwardedStats(eq(testIfName));
- v6gws = mStringArrayCaptor.getValue();
- assertEquals(2, v6gws.size());
- assertTrue(v6gws.contains(ipv6Gw1));
- assertTrue(v6gws.contains(ipv6Gw2));
- inOrder.verify(mHardware, times(1)).setDataLimit(eq(testIfName), eq(Long.MAX_VALUE));
- inOrder.verifyNoMoreInteractions();
-
- // Add in some IPv6 upstream info. When there is a tethered downstream
- // making use of the IPv6 prefix we would expect to see the /64 route
- // removed from "local prefixes" and /128s added for the upstream IPv6
- // addresses. This is not yet implemented, and for now we simply
- // expect to see these /128s.
- lp.addRoute(new RouteInfo(new IpPrefix("2001:db8::/64"), null, null, RTN_UNICAST));
- // "2001:db8::/64" plus "assigned" ASCII in hex
- lp.addLinkAddress(new LinkAddress("2001:db8::6173:7369:676e:6564/64"));
- // "2001:db8::/64" plus "random" ASCII in hex
- lp.addLinkAddress(new LinkAddress("2001:db8::7261:6e64:6f6d/64"));
- offload.setUpstreamLinkProperties(lp);
- inOrder.verify(mHardware, times(1)).setLocalPrefixes(mStringArrayCaptor.capture());
- localPrefixes = mStringArrayCaptor.getValue();
- assertEquals(6, localPrefixes.size());
- assertContainsAll(localPrefixes,
- "127.0.0.0/8", "192.0.2.0/24", "fe80::/64", "2001:db8::/64",
- "2001:db8::6173:7369:676e:6564/128", "2001:db8::7261:6e64:6f6d/128");
- // The relevant parts of the LinkProperties have not changed, but at the
- // moment we do not de-dup upstream LinkProperties this carefully.
- inOrder.verify(mHardware, times(1)).setUpstreamParameters(
- eq(testIfName), eq(ipv4Addr), eq(ipv4Gateway), mStringArrayCaptor.capture());
- v6gws = mStringArrayCaptor.getValue();
- assertEquals(2, v6gws.size());
- assertTrue(v6gws.contains(ipv6Gw1));
- assertTrue(v6gws.contains(ipv6Gw2));
- inOrder.verify(mHardware, times(1)).getForwardedStats(eq(testIfName));
- inOrder.verify(mHardware, times(1)).setDataLimit(eq(testIfName), eq(Long.MAX_VALUE));
- inOrder.verifyNoMoreInteractions();
-
- // Completely identical LinkProperties updates are de-duped.
- offload.setUpstreamLinkProperties(lp);
- // This LinkProperties value does not differ from the default upstream.
- // There should be no extraneous call to setUpstreamParameters().
- inOrder.verify(mHardware, never()).setUpstreamParameters(
- anyObject(), anyObject(), anyObject(), anyObject());
- inOrder.verifyNoMoreInteractions();
- }
-
- private static @NonNull Entry buildTestEntry(@NonNull OffloadController.StatsType how,
- @NonNull String iface, long rxBytes, long txBytes) {
- return new Entry(iface, how == STATS_PER_IFACE ? UID_ALL : UID_TETHERING, SET_DEFAULT,
- TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, rxBytes, 0L,
- txBytes, 0L, 0L);
- }
-
- @Test
- public void testGetForwardedStats() throws Exception {
- setupFunctioningHardwareInterface();
- enableOffload();
-
- final OffloadController offload = makeOffloadController();
- offload.start();
-
- final String ethernetIface = "eth1";
- final String mobileIface = "rmnet_data0";
-
- when(mHardware.getForwardedStats(eq(ethernetIface))).thenReturn(
- new ForwardedStats(12345, 54321));
- when(mHardware.getForwardedStats(eq(mobileIface))).thenReturn(
- new ForwardedStats(999, 99999));
-
- InOrder inOrder = inOrder(mHardware);
-
- final LinkProperties lp = new LinkProperties();
- lp.setInterfaceName(ethernetIface);
- offload.setUpstreamLinkProperties(lp);
- // Previous upstream was null, so no stats are fetched.
- inOrder.verify(mHardware, never()).getForwardedStats(any());
-
- lp.setInterfaceName(mobileIface);
- offload.setUpstreamLinkProperties(lp);
- // Expect that we fetch stats from the previous upstream.
- inOrder.verify(mHardware, times(1)).getForwardedStats(eq(ethernetIface));
-
- lp.setInterfaceName(ethernetIface);
- offload.setUpstreamLinkProperties(lp);
- // Expect that we fetch stats from the previous upstream.
- inOrder.verify(mHardware, times(1)).getForwardedStats(eq(mobileIface));
-
- // Verify that the fetched stats are stored.
- final NetworkStats ifaceStats = mTetherStatsProvider.getTetherStats(STATS_PER_IFACE);
- final NetworkStats uidStats = mTetherStatsProvider.getTetherStats(STATS_PER_UID);
- final NetworkStats expectedIfaceStats = new NetworkStats(0L, 2)
- .addEntry(buildTestEntry(STATS_PER_IFACE, mobileIface, 999, 99999))
- .addEntry(buildTestEntry(STATS_PER_IFACE, ethernetIface, 12345, 54321));
-
- final NetworkStats expectedUidStats = new NetworkStats(0L, 2)
- .addEntry(buildTestEntry(STATS_PER_UID, mobileIface, 999, 99999))
- .addEntry(buildTestEntry(STATS_PER_UID, ethernetIface, 12345, 54321));
-
- assertNetworkStatsEquals(expectedIfaceStats, ifaceStats);
- assertNetworkStatsEquals(expectedUidStats, uidStats);
-
- // Force pushing stats update to verify the stats reported.
- mTetherStatsProvider.pushTetherStats();
- mTetherStatsProviderCb.expectNotifyStatsUpdated(expectedIfaceStats, expectedUidStats);
-
- when(mHardware.getForwardedStats(eq(ethernetIface))).thenReturn(
- new ForwardedStats(100000, 100000));
- offload.setUpstreamLinkProperties(null);
- // Expect that we first clear the HAL's upstream parameters.
- inOrder.verify(mHardware, times(1)).setUpstreamParameters(
- eq(""), eq("0.0.0.0"), eq("0.0.0.0"), eq(null));
- // Expect that we fetch stats from the previous upstream.
- inOrder.verify(mHardware, times(1)).getForwardedStats(eq(ethernetIface));
-
- // There is no current upstream, so no stats are fetched.
- inOrder.verify(mHardware, never()).getForwardedStats(any());
- inOrder.verifyNoMoreInteractions();
-
- // Verify that the stored stats is accumulated.
- final NetworkStats ifaceStatsAccu = mTetherStatsProvider.getTetherStats(STATS_PER_IFACE);
- final NetworkStats uidStatsAccu = mTetherStatsProvider.getTetherStats(STATS_PER_UID);
- final NetworkStats expectedIfaceStatsAccu = new NetworkStats(0L, 2)
- .addEntry(buildTestEntry(STATS_PER_IFACE, mobileIface, 999, 99999))
- .addEntry(buildTestEntry(STATS_PER_IFACE, ethernetIface, 112345, 154321));
-
- final NetworkStats expectedUidStatsAccu = new NetworkStats(0L, 2)
- .addEntry(buildTestEntry(STATS_PER_UID, mobileIface, 999, 99999))
- .addEntry(buildTestEntry(STATS_PER_UID, ethernetIface, 112345, 154321));
-
- assertNetworkStatsEquals(expectedIfaceStatsAccu, ifaceStatsAccu);
- assertNetworkStatsEquals(expectedUidStatsAccu, uidStatsAccu);
-
- // Verify that only diff of stats is reported.
- mTetherStatsProvider.pushTetherStats();
- final NetworkStats expectedIfaceStatsDiff = new NetworkStats(0L, 2)
- .addEntry(buildTestEntry(STATS_PER_IFACE, mobileIface, 0, 0))
- .addEntry(buildTestEntry(STATS_PER_IFACE, ethernetIface, 100000, 100000));
-
- final NetworkStats expectedUidStatsDiff = new NetworkStats(0L, 2)
- .addEntry(buildTestEntry(STATS_PER_UID, mobileIface, 0, 0))
- .addEntry(buildTestEntry(STATS_PER_UID, ethernetIface, 100000, 100000));
- mTetherStatsProviderCb.expectNotifyStatsUpdated(expectedIfaceStatsDiff,
- expectedUidStatsDiff);
- }
-
- @Test
- public void testSetInterfaceQuota() throws Exception {
- setupFunctioningHardwareInterface();
- enableOffload();
-
- final OffloadController offload = makeOffloadController();
- offload.start();
-
- final String ethernetIface = "eth1";
- final String mobileIface = "rmnet_data0";
- final long ethernetLimit = 12345;
- final long mobileLimit = 12345678;
-
- final LinkProperties lp = new LinkProperties();
- lp.setInterfaceName(ethernetIface);
- offload.setUpstreamLinkProperties(lp);
-
- final InOrder inOrder = inOrder(mHardware);
- when(mHardware.setUpstreamParameters(any(), any(), any(), any())).thenReturn(true);
- when(mHardware.setDataLimit(anyString(), anyLong())).thenReturn(true);
-
- // Applying an interface quota to the current upstream immediately sends it to the hardware.
- mTetherStatsProvider.onSetLimit(ethernetIface, ethernetLimit);
- waitForIdle();
- inOrder.verify(mHardware).setDataLimit(ethernetIface, ethernetLimit);
- inOrder.verifyNoMoreInteractions();
-
- // Applying an interface quota to another upstream does not take any immediate action.
- mTetherStatsProvider.onSetLimit(mobileIface, mobileLimit);
- waitForIdle();
- inOrder.verify(mHardware, never()).setDataLimit(anyString(), anyLong());
-
- // Switching to that upstream causes the quota to be applied if the parameters were applied
- // correctly.
- lp.setInterfaceName(mobileIface);
- offload.setUpstreamLinkProperties(lp);
- waitForIdle();
- inOrder.verify(mHardware).setDataLimit(mobileIface, mobileLimit);
-
- // Setting a limit of ITetheringStatsProvider.QUOTA_UNLIMITED causes the limit to be set
- // to Long.MAX_VALUE.
- mTetherStatsProvider.onSetLimit(mobileIface, ITetheringStatsProvider.QUOTA_UNLIMITED);
- waitForIdle();
- inOrder.verify(mHardware).setDataLimit(mobileIface, Long.MAX_VALUE);
-
- // If setting upstream parameters fails, then the data limit is not set.
- when(mHardware.setUpstreamParameters(any(), any(), any(), any())).thenReturn(false);
- lp.setInterfaceName(ethernetIface);
- offload.setUpstreamLinkProperties(lp);
- mTetherStatsProvider.onSetLimit(mobileIface, mobileLimit);
- waitForIdle();
- inOrder.verify(mHardware, never()).setDataLimit(anyString(), anyLong());
-
- // If setting the data limit fails while changing upstreams, offload is stopped.
- when(mHardware.setUpstreamParameters(any(), any(), any(), any())).thenReturn(true);
- when(mHardware.setDataLimit(anyString(), anyLong())).thenReturn(false);
- lp.setInterfaceName(mobileIface);
- offload.setUpstreamLinkProperties(lp);
- mTetherStatsProvider.onSetLimit(mobileIface, mobileLimit);
- waitForIdle();
- inOrder.verify(mHardware).getForwardedStats(ethernetIface);
- inOrder.verify(mHardware).stopOffloadControl();
- }
-
- @Test
- public void testDataLimitCallback() throws Exception {
- setupFunctioningHardwareInterface();
- enableOffload();
-
- final OffloadController offload = makeOffloadController();
- offload.start();
-
- OffloadHardwareInterface.ControlCallback callback = mControlCallbackCaptor.getValue();
- callback.onStoppedLimitReached();
- mTetherStatsProviderCb.expectNotifyStatsUpdated();
- }
-
- @Test
- public void testAddRemoveDownstreams() throws Exception {
- setupFunctioningHardwareInterface();
- enableOffload();
-
- final OffloadController offload = makeOffloadController();
- offload.start();
-
- final InOrder inOrder = inOrder(mHardware);
- inOrder.verify(mHardware, times(1)).initOffloadConfig();
- inOrder.verify(mHardware, times(1)).initOffloadControl(
- any(OffloadHardwareInterface.ControlCallback.class));
- inOrder.verifyNoMoreInteractions();
-
- // Tethering makes several calls to setLocalPrefixes() before add/remove
- // downstream calls are made. This is not tested here; only the behavior
- // of notifyDownstreamLinkProperties() and removeDownstreamInterface()
- // are tested.
-
- // [1] USB tethering is started.
- final LinkProperties usbLinkProperties = new LinkProperties();
- usbLinkProperties.setInterfaceName(RNDIS0);
- usbLinkProperties.addLinkAddress(new LinkAddress("192.168.42.1/24"));
- usbLinkProperties.addRoute(
- new RouteInfo(new IpPrefix(USB_PREFIX), null, null, RTN_UNICAST));
- offload.notifyDownstreamLinkProperties(usbLinkProperties);
- inOrder.verify(mHardware, times(1)).addDownstreamPrefix(RNDIS0, USB_PREFIX);
- inOrder.verifyNoMoreInteractions();
-
- // [2] Routes for IPv6 link-local prefixes should never be added.
- usbLinkProperties.addRoute(
- new RouteInfo(new IpPrefix(IPV6_LINKLOCAL), null, null, RTN_UNICAST));
- offload.notifyDownstreamLinkProperties(usbLinkProperties);
- inOrder.verify(mHardware, never()).addDownstreamPrefix(eq(RNDIS0), anyString());
- inOrder.verifyNoMoreInteractions();
-
- // [3] Add an IPv6 prefix for good measure. Only new offload-able
- // prefixes should be passed to the HAL.
- usbLinkProperties.addLinkAddress(new LinkAddress("2001:db8::1/64"));
- usbLinkProperties.addRoute(
- new RouteInfo(new IpPrefix(IPV6_DOC_PREFIX), null, null, RTN_UNICAST));
- offload.notifyDownstreamLinkProperties(usbLinkProperties);
- inOrder.verify(mHardware, times(1)).addDownstreamPrefix(RNDIS0, IPV6_DOC_PREFIX);
- inOrder.verifyNoMoreInteractions();
-
- // [4] Adding addresses doesn't affect notifyDownstreamLinkProperties().
- // The address is passed in by a separate setLocalPrefixes() invocation.
- usbLinkProperties.addLinkAddress(new LinkAddress("2001:db8::2/64"));
- offload.notifyDownstreamLinkProperties(usbLinkProperties);
- inOrder.verify(mHardware, never()).addDownstreamPrefix(eq(RNDIS0), anyString());
-
- // [5] Differences in local routes are converted into addDownstream()
- // and removeDownstream() invocations accordingly.
- usbLinkProperties.removeRoute(
- new RouteInfo(new IpPrefix(IPV6_DOC_PREFIX), null, RNDIS0, RTN_UNICAST));
- usbLinkProperties.addRoute(
- new RouteInfo(new IpPrefix(IPV6_DISCARD_PREFIX), null, null, RTN_UNICAST));
- offload.notifyDownstreamLinkProperties(usbLinkProperties);
- inOrder.verify(mHardware, times(1)).removeDownstreamPrefix(RNDIS0, IPV6_DOC_PREFIX);
- inOrder.verify(mHardware, times(1)).addDownstreamPrefix(RNDIS0, IPV6_DISCARD_PREFIX);
- inOrder.verifyNoMoreInteractions();
-
- // [6] Removing a downstream interface which was never added causes no
- // interactions with the HAL.
- offload.removeDownstreamInterface(WLAN0);
- inOrder.verifyNoMoreInteractions();
-
- // [7] Removing an active downstream removes all remaining prefixes.
- offload.removeDownstreamInterface(RNDIS0);
- inOrder.verify(mHardware, times(1)).removeDownstreamPrefix(RNDIS0, USB_PREFIX);
- inOrder.verify(mHardware, times(1)).removeDownstreamPrefix(RNDIS0, IPV6_DISCARD_PREFIX);
- inOrder.verifyNoMoreInteractions();
- }
-
- @Test
- public void testControlCallbackOnStoppedUnsupportedFetchesAllStats() throws Exception {
- setupFunctioningHardwareInterface();
- enableOffload();
-
- final OffloadController offload = makeOffloadController();
- offload.start();
-
- // Pretend to set a few different upstreams (only the interface name
- // matters for this test; we're ignoring IP and route information).
- final LinkProperties upstreamLp = new LinkProperties();
- for (String ifname : new String[]{RMNET0, WLAN0, RMNET0}) {
- upstreamLp.setInterfaceName(ifname);
- offload.setUpstreamLinkProperties(upstreamLp);
- }
-
- // Clear invocation history, especially the getForwardedStats() calls
- // that happen with setUpstreamParameters().
- clearInvocations(mHardware);
-
- OffloadHardwareInterface.ControlCallback callback = mControlCallbackCaptor.getValue();
- callback.onStoppedUnsupported();
-
- // Verify forwarded stats behaviour.
- verify(mHardware, times(1)).getForwardedStats(eq(RMNET0));
- verify(mHardware, times(1)).getForwardedStats(eq(WLAN0));
- // TODO: verify the exact stats reported.
- mTetherStatsProviderCb.expectNotifyStatsUpdated();
- mTetherStatsProviderCb.assertNoCallback();
- verifyNoMoreInteractions(mHardware);
- }
-
- @Test
- public void testControlCallbackOnSupportAvailableFetchesAllStatsAndPushesAllParameters()
- throws Exception {
- setupFunctioningHardwareInterface();
- enableOffload();
-
- final OffloadController offload = makeOffloadController();
- offload.start();
-
- // Pretend to set a few different upstreams (only the interface name
- // matters for this test; we're ignoring IP and route information).
- final LinkProperties upstreamLp = new LinkProperties();
- for (String ifname : new String[]{RMNET0, WLAN0, RMNET0}) {
- upstreamLp.setInterfaceName(ifname);
- offload.setUpstreamLinkProperties(upstreamLp);
- }
-
- // Pretend that some local prefixes and downstreams have been added
- // (and removed, for good measure).
- final Set<IpPrefix> minimumLocalPrefixes = new HashSet<>();
- for (String s : new String[]{
- "127.0.0.0/8", "192.0.2.0/24", "fe80::/64", "2001:db8::/64"}) {
- minimumLocalPrefixes.add(new IpPrefix(s));
- }
- offload.setLocalPrefixes(minimumLocalPrefixes);
-
- final LinkProperties usbLinkProperties = new LinkProperties();
- usbLinkProperties.setInterfaceName(RNDIS0);
- usbLinkProperties.addLinkAddress(new LinkAddress("192.168.42.1/24"));
- usbLinkProperties.addRoute(
- new RouteInfo(new IpPrefix(USB_PREFIX), null, null, RTN_UNICAST));
- offload.notifyDownstreamLinkProperties(usbLinkProperties);
-
- final LinkProperties wifiLinkProperties = new LinkProperties();
- wifiLinkProperties.setInterfaceName(WLAN0);
- wifiLinkProperties.addLinkAddress(new LinkAddress("192.168.43.1/24"));
- wifiLinkProperties.addRoute(
- new RouteInfo(new IpPrefix(WIFI_PREFIX), null, null, RTN_UNICAST));
- wifiLinkProperties.addRoute(
- new RouteInfo(new IpPrefix(IPV6_LINKLOCAL), null, null, RTN_UNICAST));
- // Use a benchmark prefix (RFC 5180 + erratum), since the documentation
- // prefix is included in the excluded prefix list.
- wifiLinkProperties.addLinkAddress(new LinkAddress("2001:2::1/64"));
- wifiLinkProperties.addLinkAddress(new LinkAddress("2001:2::2/64"));
- wifiLinkProperties.addRoute(
- new RouteInfo(new IpPrefix("2001:2::/64"), null, null, RTN_UNICAST));
- offload.notifyDownstreamLinkProperties(wifiLinkProperties);
-
- offload.removeDownstreamInterface(RNDIS0);
-
- // Clear invocation history, especially the getForwardedStats() calls
- // that happen with setUpstreamParameters().
- clearInvocations(mHardware);
-
- OffloadHardwareInterface.ControlCallback callback = mControlCallbackCaptor.getValue();
- callback.onSupportAvailable();
-
- // Verify forwarded stats behaviour.
- verify(mHardware, times(1)).getForwardedStats(eq(RMNET0));
- verify(mHardware, times(1)).getForwardedStats(eq(WLAN0));
- mTetherStatsProviderCb.expectNotifyStatsUpdated();
- mTetherStatsProviderCb.assertNoCallback();
-
- // TODO: verify local prefixes and downstreams are also pushed to the HAL.
- verify(mHardware, times(1)).setLocalPrefixes(mStringArrayCaptor.capture());
- ArrayList<String> localPrefixes = mStringArrayCaptor.getValue();
- assertEquals(4, localPrefixes.size());
- assertContainsAll(localPrefixes,
- // TODO: The logic to find and exclude downstream IP prefixes
- // is currently in Tethering's OffloadWrapper but must be moved
- // into OffloadController proper. After this, also check for:
- // "192.168.43.1/32", "2001:2::1/128", "2001:2::2/128"
- "127.0.0.0/8", "192.0.2.0/24", "fe80::/64", "2001:db8::/64");
- verify(mHardware, times(1)).addDownstreamPrefix(WLAN0, "192.168.43.0/24");
- verify(mHardware, times(1)).addDownstreamPrefix(WLAN0, "2001:2::/64");
- verify(mHardware, times(1)).setUpstreamParameters(eq(RMNET0), any(), any(), any());
- verify(mHardware, times(1)).setDataLimit(eq(RMNET0), anyLong());
- verifyNoMoreInteractions(mHardware);
- }
-
- @Test
- public void testOnSetAlert() throws Exception {
- setupFunctioningHardwareInterface();
- enableOffload();
- setOffloadPollInterval(DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS);
- final OffloadController offload = makeOffloadController();
- offload.start();
-
- // Initialize with fake eth upstream.
- final String ethernetIface = "eth1";
- InOrder inOrder = inOrder(mHardware);
- final LinkProperties lp = new LinkProperties();
- lp.setInterfaceName(ethernetIface);
- offload.setUpstreamLinkProperties(lp);
- // Previous upstream was null, so no stats are fetched.
- inOrder.verify(mHardware, never()).getForwardedStats(any());
-
- // Verify that set quota to 0 will immediately triggers an callback.
- mTetherStatsProvider.onSetAlert(0);
- waitForIdle();
- mTetherStatsProviderCb.expectNotifyAlertReached();
-
- // Verify that notifyAlertReached never fired if quota is not yet reached.
- when(mHardware.getForwardedStats(eq(ethernetIface))).thenReturn(
- new ForwardedStats(0, 0));
- mTetherStatsProvider.onSetAlert(100);
- mTestLooper.moveTimeForward(DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS);
- waitForIdle();
- mTetherStatsProviderCb.assertNoCallback();
-
- // Verify that notifyAlertReached fired when quota is reached.
- when(mHardware.getForwardedStats(eq(ethernetIface))).thenReturn(
- new ForwardedStats(50, 50));
- mTestLooper.moveTimeForward(DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS);
- waitForIdle();
- mTetherStatsProviderCb.expectNotifyAlertReached();
-
- // Verify that set quota with UNLIMITED won't trigger any callback, and won't fetch
- // any stats since the polling is stopped.
- reset(mHardware);
- mTetherStatsProvider.onSetAlert(NetworkStatsProvider.QUOTA_UNLIMITED);
- mTestLooper.moveTimeForward(DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS);
- waitForIdle();
- mTetherStatsProviderCb.assertNoCallback();
- verify(mHardware, never()).getForwardedStats(any());
- }
-}
diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadHardwareInterfaceTest.java b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadHardwareInterfaceTest.java
deleted file mode 100644
index 38b19dd..0000000
--- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadHardwareInterfaceTest.java
+++ /dev/null
@@ -1,264 +0,0 @@
-/*
- * 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;
-
-import static android.net.util.TetheringUtils.uint16;
-import static android.system.OsConstants.AF_INET;
-import static android.system.OsConstants.AF_UNIX;
-import static android.system.OsConstants.SOCK_STREAM;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.fail;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.hardware.tetheroffload.config.V1_0.IOffloadConfig;
-import android.hardware.tetheroffload.control.V1_0.IOffloadControl;
-import android.hardware.tetheroffload.control.V1_0.ITetheringOffloadCallback;
-import android.hardware.tetheroffload.control.V1_0.NatTimeoutUpdate;
-import android.hardware.tetheroffload.control.V1_0.NetworkProtocol;
-import android.hardware.tetheroffload.control.V1_0.OffloadCallbackEvent;
-import android.net.netlink.StructNfGenMsg;
-import android.net.netlink.StructNlMsgHdr;
-import android.net.util.SharedLog;
-import android.os.Handler;
-import android.os.NativeHandle;
-import android.os.test.TestLooper;
-import android.system.ErrnoException;
-import android.system.Os;
-import android.system.OsConstants;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-import java.io.FileDescriptor;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.util.ArrayList;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public final class OffloadHardwareInterfaceTest {
- private static final String RMNET0 = "test_rmnet_data0";
-
- private final TestLooper mTestLooper = new TestLooper();
-
- private OffloadHardwareInterface mOffloadHw;
- private ITetheringOffloadCallback mTetheringOffloadCallback;
- private OffloadHardwareInterface.ControlCallback mControlCallback;
-
- @Mock private IOffloadConfig mIOffloadConfig;
- @Mock private IOffloadControl mIOffloadControl;
- @Mock private NativeHandle mNativeHandle;
-
- // Random values to test Netlink message.
- private static final short TEST_TYPE = 184;
- private static final short TEST_FLAGS = 263;
-
- class MyDependencies extends OffloadHardwareInterface.Dependencies {
- MyDependencies(SharedLog log) {
- super(log);
- }
-
- @Override
- public IOffloadConfig getOffloadConfig() {
- return mIOffloadConfig;
- }
-
- @Override
- public IOffloadControl getOffloadControl() {
- return mIOffloadControl;
- }
-
- @Override
- public NativeHandle createConntrackSocket(final int groups) {
- return mNativeHandle;
- }
- }
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- final SharedLog log = new SharedLog("test");
- mOffloadHw = new OffloadHardwareInterface(new Handler(mTestLooper.getLooper()), log,
- new MyDependencies(log));
- mControlCallback = spy(new OffloadHardwareInterface.ControlCallback());
- }
-
- private void startOffloadHardwareInterface() throws Exception {
- mOffloadHw.initOffloadConfig();
- mOffloadHw.initOffloadControl(mControlCallback);
- final ArgumentCaptor<ITetheringOffloadCallback> mOffloadCallbackCaptor =
- ArgumentCaptor.forClass(ITetheringOffloadCallback.class);
- verify(mIOffloadControl).initOffload(mOffloadCallbackCaptor.capture(), any());
- mTetheringOffloadCallback = mOffloadCallbackCaptor.getValue();
- }
-
- @Test
- public void testGetForwardedStats() throws Exception {
- startOffloadHardwareInterface();
- final OffloadHardwareInterface.ForwardedStats stats = mOffloadHw.getForwardedStats(RMNET0);
- verify(mIOffloadControl).getForwardedStats(eq(RMNET0), any());
- assertNotNull(stats);
- }
-
- @Test
- public void testSetLocalPrefixes() throws Exception {
- startOffloadHardwareInterface();
- final ArrayList<String> localPrefixes = new ArrayList<>();
- localPrefixes.add("127.0.0.0/8");
- localPrefixes.add("fe80::/64");
- mOffloadHw.setLocalPrefixes(localPrefixes);
- verify(mIOffloadControl).setLocalPrefixes(eq(localPrefixes), any());
- }
-
- @Test
- public void testSetDataLimit() throws Exception {
- startOffloadHardwareInterface();
- final long limit = 12345;
- mOffloadHw.setDataLimit(RMNET0, limit);
- verify(mIOffloadControl).setDataLimit(eq(RMNET0), eq(limit), any());
- }
-
- @Test
- public void testSetUpstreamParameters() throws Exception {
- startOffloadHardwareInterface();
- final String v4addr = "192.168.10.1";
- final String v4gateway = "192.168.10.255";
- final ArrayList<String> v6gws = new ArrayList<>(0);
- v6gws.add("2001:db8::1");
- mOffloadHw.setUpstreamParameters(RMNET0, v4addr, v4gateway, v6gws);
- verify(mIOffloadControl).setUpstreamParameters(eq(RMNET0), eq(v4addr), eq(v4gateway),
- eq(v6gws), any());
-
- final ArgumentCaptor<ArrayList<String>> mArrayListCaptor =
- ArgumentCaptor.forClass(ArrayList.class);
- mOffloadHw.setUpstreamParameters(null, null, null, null);
- verify(mIOffloadControl).setUpstreamParameters(eq(""), eq(""), eq(""),
- mArrayListCaptor.capture(), any());
- assertEquals(mArrayListCaptor.getValue().size(), 0);
- }
-
- @Test
- public void testUpdateDownstreamPrefix() throws Exception {
- startOffloadHardwareInterface();
- final String ifName = "wlan1";
- final String prefix = "192.168.43.0/24";
- mOffloadHw.addDownstreamPrefix(ifName, prefix);
- verify(mIOffloadControl).addDownstream(eq(ifName), eq(prefix), any());
-
- mOffloadHw.removeDownstreamPrefix(ifName, prefix);
- verify(mIOffloadControl).removeDownstream(eq(ifName), eq(prefix), any());
- }
-
- @Test
- public void testTetheringOffloadCallback() throws Exception {
- startOffloadHardwareInterface();
-
- mTetheringOffloadCallback.onEvent(OffloadCallbackEvent.OFFLOAD_STARTED);
- mTestLooper.dispatchAll();
- verify(mControlCallback).onStarted();
-
- mTetheringOffloadCallback.onEvent(OffloadCallbackEvent.OFFLOAD_STOPPED_ERROR);
- mTestLooper.dispatchAll();
- verify(mControlCallback).onStoppedError();
-
- mTetheringOffloadCallback.onEvent(OffloadCallbackEvent.OFFLOAD_STOPPED_UNSUPPORTED);
- mTestLooper.dispatchAll();
- verify(mControlCallback).onStoppedUnsupported();
-
- mTetheringOffloadCallback.onEvent(OffloadCallbackEvent.OFFLOAD_SUPPORT_AVAILABLE);
- mTestLooper.dispatchAll();
- verify(mControlCallback).onSupportAvailable();
-
- mTetheringOffloadCallback.onEvent(OffloadCallbackEvent.OFFLOAD_STOPPED_LIMIT_REACHED);
- mTestLooper.dispatchAll();
- verify(mControlCallback).onStoppedLimitReached();
-
- final NatTimeoutUpdate tcpParams = buildNatTimeoutUpdate(NetworkProtocol.TCP);
- mTetheringOffloadCallback.updateTimeout(tcpParams);
- mTestLooper.dispatchAll();
- verify(mControlCallback).onNatTimeoutUpdate(eq(OsConstants.IPPROTO_TCP),
- eq(tcpParams.src.addr),
- eq(uint16(tcpParams.src.port)),
- eq(tcpParams.dst.addr),
- eq(uint16(tcpParams.dst.port)));
-
- final NatTimeoutUpdate udpParams = buildNatTimeoutUpdate(NetworkProtocol.UDP);
- mTetheringOffloadCallback.updateTimeout(udpParams);
- mTestLooper.dispatchAll();
- verify(mControlCallback).onNatTimeoutUpdate(eq(OsConstants.IPPROTO_UDP),
- eq(udpParams.src.addr),
- eq(uint16(udpParams.src.port)),
- eq(udpParams.dst.addr),
- eq(uint16(udpParams.dst.port)));
- }
-
- @Test
- public void testSendIpv4NfGenMsg() throws Exception {
- FileDescriptor writeSocket = new FileDescriptor();
- FileDescriptor readSocket = new FileDescriptor();
- try {
- Os.socketpair(AF_UNIX, SOCK_STREAM, 0, writeSocket, readSocket);
- } catch (ErrnoException e) {
- fail();
- return;
- }
- when(mNativeHandle.getFileDescriptor()).thenReturn(writeSocket);
-
- mOffloadHw.sendIpv4NfGenMsg(mNativeHandle, TEST_TYPE, TEST_FLAGS);
-
- ByteBuffer buffer = ByteBuffer.allocate(9823); // Arbitrary value > expectedLen.
- buffer.order(ByteOrder.nativeOrder());
-
- int read = Os.read(readSocket, buffer);
- final int expectedLen = StructNlMsgHdr.STRUCT_SIZE + StructNfGenMsg.STRUCT_SIZE;
- assertEquals(expectedLen, read);
-
- buffer.flip();
- assertEquals(expectedLen, buffer.getInt());
- assertEquals(TEST_TYPE, buffer.getShort());
- assertEquals(TEST_FLAGS, buffer.getShort());
- assertEquals(0 /* seq */, buffer.getInt());
- assertEquals(0 /* pid */, buffer.getInt());
- assertEquals(AF_INET, buffer.get()); // nfgen_family
- assertEquals(0 /* error */, buffer.get()); // version
- assertEquals(0 /* error */, buffer.getShort()); // res_id
- assertEquals(expectedLen, buffer.position());
- }
-
- private NatTimeoutUpdate buildNatTimeoutUpdate(final int proto) {
- final NatTimeoutUpdate params = new NatTimeoutUpdate();
- params.proto = proto;
- params.src.addr = "192.168.43.200";
- params.src.port = 100;
- params.dst.addr = "172.50.46.169";
- params.dst.port = 150;
- return params;
- }
-}
diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/PrivateAddressCoordinatorTest.java b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/PrivateAddressCoordinatorTest.java
deleted file mode 100644
index 41d46e5..0000000
--- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/PrivateAddressCoordinatorTest.java
+++ /dev/null
@@ -1,551 +0,0 @@
-/*
- * 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;
-
-import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
-import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
-import static android.net.NetworkCapabilities.TRANSPORT_VPN;
-import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
-import static android.net.TetheringManager.TETHERING_ETHERNET;
-import static android.net.TetheringManager.TETHERING_USB;
-import static android.net.TetheringManager.TETHERING_WIFI;
-import static android.net.TetheringManager.TETHERING_WIFI_P2P;
-import static android.net.util.PrefixUtils.asIpPrefix;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.net.ConnectivityManager;
-import android.net.IpPrefix;
-import android.net.LinkAddress;
-import android.net.LinkProperties;
-import android.net.Network;
-import android.net.NetworkCapabilities;
-import android.net.ip.IpServer;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public final class PrivateAddressCoordinatorTest {
- private static final String TEST_IFNAME = "test0";
-
- @Mock private IpServer mHotspotIpServer;
- @Mock private IpServer mUsbIpServer;
- @Mock private IpServer mEthernetIpServer;
- @Mock private IpServer mWifiP2pIpServer;
- @Mock private Context mContext;
- @Mock private ConnectivityManager mConnectivityMgr;
- @Mock private TetheringConfiguration mConfig;
-
- private PrivateAddressCoordinator mPrivateAddressCoordinator;
- private final LinkAddress mBluetoothAddress = new LinkAddress("192.168.44.1/24");
- private final LinkAddress mLegacyWifiP2pAddress = new LinkAddress("192.168.49.1/24");
- private final Network mWifiNetwork = new Network(1);
- private final Network mMobileNetwork = new Network(2);
- private final Network mVpnNetwork = new Network(3);
- private final Network mMobileNetwork2 = new Network(4);
- private final Network mMobileNetwork3 = new Network(5);
- private final Network mMobileNetwork4 = new Network(6);
- private final Network mMobileNetwork5 = new Network(7);
- private final Network mMobileNetwork6 = new Network(8);
- private final Network[] mAllNetworks = {mMobileNetwork, mWifiNetwork, mVpnNetwork,
- mMobileNetwork2, mMobileNetwork3, mMobileNetwork4, mMobileNetwork5, mMobileNetwork6};
- private final ArrayList<IpPrefix> mTetheringPrefixes = new ArrayList<>(Arrays.asList(
- new IpPrefix("192.168.0.0/16"),
- new IpPrefix("172.16.0.0/12"),
- new IpPrefix("10.0.0.0/8")));
-
- private void setUpIpServers() throws Exception {
- when(mUsbIpServer.interfaceType()).thenReturn(TETHERING_USB);
- when(mEthernetIpServer.interfaceType()).thenReturn(TETHERING_ETHERNET);
- when(mHotspotIpServer.interfaceType()).thenReturn(TETHERING_WIFI);
- when(mWifiP2pIpServer.interfaceType()).thenReturn(TETHERING_WIFI_P2P);
- }
-
- @Before
- public void setUp() throws Exception {
- MockitoAnnotations.initMocks(this);
-
- when(mContext.getSystemService(Context.CONNECTIVITY_SERVICE)).thenReturn(mConnectivityMgr);
- when(mConnectivityMgr.getAllNetworks()).thenReturn(mAllNetworks);
- when(mConfig.shouldEnableWifiP2pDedicatedIp()).thenReturn(false);
- when(mConfig.isSelectAllPrefixRangeEnabled()).thenReturn(true);
- setUpIpServers();
- mPrivateAddressCoordinator = spy(new PrivateAddressCoordinator(mContext, mConfig));
- }
-
- private LinkAddress requestDownstreamAddress(final IpServer ipServer, boolean useLastAddress) {
- final LinkAddress address = mPrivateAddressCoordinator.requestDownstreamAddress(
- ipServer, useLastAddress);
- when(ipServer.getAddress()).thenReturn(address);
- return address;
- }
-
- @Test
- public void testRequestDownstreamAddressWithoutUsingLastAddress() throws Exception {
- final IpPrefix bluetoothPrefix = asIpPrefix(mBluetoothAddress);
- final LinkAddress address = requestDownstreamAddress(mHotspotIpServer,
- false /* useLastAddress */);
- final IpPrefix hotspotPrefix = asIpPrefix(address);
- assertNotEquals(hotspotPrefix, bluetoothPrefix);
-
- final LinkAddress newAddress = requestDownstreamAddress(mHotspotIpServer,
- false /* useLastAddress */);
- final IpPrefix testDupRequest = asIpPrefix(newAddress);
- assertNotEquals(hotspotPrefix, testDupRequest);
- assertNotEquals(bluetoothPrefix, testDupRequest);
- mPrivateAddressCoordinator.releaseDownstream(mHotspotIpServer);
-
- final LinkAddress usbAddress = requestDownstreamAddress(mUsbIpServer,
- false /* useLastAddress */);
- final IpPrefix usbPrefix = asIpPrefix(usbAddress);
- assertNotEquals(usbPrefix, bluetoothPrefix);
- assertNotEquals(usbPrefix, hotspotPrefix);
- mPrivateAddressCoordinator.releaseDownstream(mUsbIpServer);
- }
-
- @Test
- public void testSanitizedAddress() throws Exception {
- int fakeSubAddr = 0x2b00; // 43.0.
- when(mPrivateAddressCoordinator.getRandomInt()).thenReturn(fakeSubAddr);
- LinkAddress actualAddress = requestDownstreamAddress(mHotspotIpServer,
- false /* useLastAddress */);
- assertEquals(new LinkAddress("192.168.43.2/24"), actualAddress);
- mPrivateAddressCoordinator.releaseDownstream(mHotspotIpServer);
-
- fakeSubAddr = 0x2d01; // 45.1.
- when(mPrivateAddressCoordinator.getRandomInt()).thenReturn(fakeSubAddr);
- actualAddress = requestDownstreamAddress(mHotspotIpServer, false /* useLastAddress */);
- assertEquals(new LinkAddress("192.168.45.2/24"), actualAddress);
- mPrivateAddressCoordinator.releaseDownstream(mHotspotIpServer);
-
- fakeSubAddr = 0x2eff; // 46.255.
- when(mPrivateAddressCoordinator.getRandomInt()).thenReturn(fakeSubAddr);
- actualAddress = requestDownstreamAddress(mHotspotIpServer, false /* useLastAddress */);
- assertEquals(new LinkAddress("192.168.46.254/24"), actualAddress);
- mPrivateAddressCoordinator.releaseDownstream(mHotspotIpServer);
-
- fakeSubAddr = 0x2f05; // 47.5.
- when(mPrivateAddressCoordinator.getRandomInt()).thenReturn(fakeSubAddr);
- actualAddress = requestDownstreamAddress(mHotspotIpServer, false /* useLastAddress */);
- assertEquals(new LinkAddress("192.168.47.5/24"), actualAddress);
- mPrivateAddressCoordinator.releaseDownstream(mHotspotIpServer);
- }
-
- @Test
- public void testReservedPrefix() throws Exception {
- // - Test bluetooth prefix is reserved.
- when(mPrivateAddressCoordinator.getRandomInt()).thenReturn(
- getSubAddress(mBluetoothAddress.getAddress().getAddress()));
- final LinkAddress hotspotAddress = requestDownstreamAddress(mHotspotIpServer,
- false /* useLastAddress */);
- final IpPrefix hotspotPrefix = asIpPrefix(hotspotAddress);
- assertNotEquals(asIpPrefix(mBluetoothAddress), hotspotPrefix);
- mPrivateAddressCoordinator.releaseDownstream(mHotspotIpServer);
-
- // - Test previous enabled hotspot prefix(cached prefix) is reserved.
- when(mPrivateAddressCoordinator.getRandomInt()).thenReturn(
- getSubAddress(hotspotAddress.getAddress().getAddress()));
- final LinkAddress usbAddress = requestDownstreamAddress(mUsbIpServer,
- false /* useLastAddress */);
- final IpPrefix usbPrefix = asIpPrefix(usbAddress);
- assertNotEquals(asIpPrefix(mBluetoothAddress), usbPrefix);
- assertNotEquals(hotspotPrefix, usbPrefix);
- mPrivateAddressCoordinator.releaseDownstream(mUsbIpServer);
-
- // - Test wifi p2p prefix is reserved.
- when(mPrivateAddressCoordinator.getRandomInt()).thenReturn(
- getSubAddress(mLegacyWifiP2pAddress.getAddress().getAddress()));
- final LinkAddress etherAddress = requestDownstreamAddress(mEthernetIpServer,
- false /* useLastAddress */);
- final IpPrefix etherPrefix = asIpPrefix(etherAddress);
- assertNotEquals(asIpPrefix(mLegacyWifiP2pAddress), etherPrefix);
- assertNotEquals(asIpPrefix(mBluetoothAddress), etherPrefix);
- assertNotEquals(hotspotPrefix, etherPrefix);
- mPrivateAddressCoordinator.releaseDownstream(mEthernetIpServer);
- }
-
- @Test
- public void testRequestLastDownstreamAddress() throws Exception {
- final int fakeHotspotSubAddr = 0x2b05; // 43.5
- when(mPrivateAddressCoordinator.getRandomInt()).thenReturn(fakeHotspotSubAddr);
- final LinkAddress hotspotAddress = requestDownstreamAddress(mHotspotIpServer,
- true /* useLastAddress */);
- assertEquals("Wrong wifi prefix: ", new LinkAddress("192.168.43.5/24"), hotspotAddress);
-
- final LinkAddress usbAddress = requestDownstreamAddress(mUsbIpServer,
- true /* useLastAddress */);
- assertEquals("Wrong wifi prefix: ", new LinkAddress("192.168.45.5/24"), usbAddress);
-
- mPrivateAddressCoordinator.releaseDownstream(mHotspotIpServer);
- mPrivateAddressCoordinator.releaseDownstream(mUsbIpServer);
-
- final int newFakeSubAddr = 0x3c05;
- when(mPrivateAddressCoordinator.getRandomInt()).thenReturn(fakeHotspotSubAddr);
-
- final LinkAddress newHotspotAddress = requestDownstreamAddress(mHotspotIpServer,
- true /* useLastAddress */);
- assertEquals(hotspotAddress, newHotspotAddress);
- final LinkAddress newUsbAddress = requestDownstreamAddress(mUsbIpServer,
- true /* useLastAddress */);
- assertEquals(usbAddress, newUsbAddress);
-
- final UpstreamNetworkState wifiUpstream = buildUpstreamNetworkState(mWifiNetwork,
- new LinkAddress("192.168.88.23/16"), null,
- makeNetworkCapabilities(TRANSPORT_WIFI));
- mPrivateAddressCoordinator.updateUpstreamPrefix(wifiUpstream);
- verify(mHotspotIpServer).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
- verify(mUsbIpServer).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
- }
-
- private UpstreamNetworkState buildUpstreamNetworkState(final Network network,
- final LinkAddress v4Addr, final LinkAddress v6Addr, final NetworkCapabilities cap) {
- final LinkProperties prop = new LinkProperties();
- prop.setInterfaceName(TEST_IFNAME);
- if (v4Addr != null) prop.addLinkAddress(v4Addr);
-
- if (v6Addr != null) prop.addLinkAddress(v6Addr);
-
- return new UpstreamNetworkState(prop, cap, network);
- }
-
- private NetworkCapabilities makeNetworkCapabilities(final int transportType) {
- final NetworkCapabilities cap = new NetworkCapabilities();
- cap.addTransportType(transportType);
- if (transportType == TRANSPORT_VPN) {
- cap.removeCapability(NET_CAPABILITY_NOT_VPN);
- }
-
- return cap;
- }
-
- @Test
- public void testNoConflictUpstreamPrefix() throws Exception {
- final int fakeHotspotSubAddr = 0x2b05; // 43.5
- final IpPrefix predefinedPrefix = new IpPrefix("192.168.43.0/24");
- // Force always get subAddress "43.5" for conflict testing.
- when(mPrivateAddressCoordinator.getRandomInt()).thenReturn(fakeHotspotSubAddr);
- // - Enable hotspot with prefix 192.168.43.0/24
- final LinkAddress hotspotAddr = requestDownstreamAddress(mHotspotIpServer,
- true /* useLastAddress */);
- final IpPrefix hotspotPrefix = asIpPrefix(hotspotAddr);
- assertEquals("Wrong wifi prefix: ", predefinedPrefix, hotspotPrefix);
- // - test mobile network with null NetworkCapabilities. Ideally this should not happen
- // because NetworkCapabilities update should always happen before LinkProperties update
- // and the UpstreamNetworkState update, just make sure no crash in this case.
- final UpstreamNetworkState noCapUpstream = buildUpstreamNetworkState(mMobileNetwork,
- new LinkAddress("10.0.0.8/24"), null, null);
- mPrivateAddressCoordinator.updateUpstreamPrefix(noCapUpstream);
- verify(mHotspotIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
- // - test mobile upstream with no address.
- final UpstreamNetworkState noAddress = buildUpstreamNetworkState(mMobileNetwork,
- null, null, makeNetworkCapabilities(TRANSPORT_CELLULAR));
- mPrivateAddressCoordinator.updateUpstreamPrefix(noCapUpstream);
- verify(mHotspotIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
- // - Update v6 only mobile network, hotspot prefix should not be removed.
- final UpstreamNetworkState v6OnlyMobile = buildUpstreamNetworkState(mMobileNetwork,
- null, new LinkAddress("2001:db8::/64"),
- makeNetworkCapabilities(TRANSPORT_CELLULAR));
- mPrivateAddressCoordinator.updateUpstreamPrefix(v6OnlyMobile);
- verify(mHotspotIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
- mPrivateAddressCoordinator.removeUpstreamPrefix(mMobileNetwork);
- // - Update v4 only mobile network, hotspot prefix should not be removed.
- final UpstreamNetworkState v4OnlyMobile = buildUpstreamNetworkState(mMobileNetwork,
- new LinkAddress("10.0.0.8/24"), null,
- makeNetworkCapabilities(TRANSPORT_CELLULAR));
- mPrivateAddressCoordinator.updateUpstreamPrefix(v4OnlyMobile);
- verify(mHotspotIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
- // - Update v4v6 mobile network, hotspot prefix should not be removed.
- final UpstreamNetworkState v4v6Mobile = buildUpstreamNetworkState(mMobileNetwork,
- new LinkAddress("10.0.0.8/24"), new LinkAddress("2001:db8::/64"),
- makeNetworkCapabilities(TRANSPORT_CELLULAR));
- mPrivateAddressCoordinator.updateUpstreamPrefix(v4v6Mobile);
- verify(mHotspotIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
- // - Update v6 only wifi network, hotspot prefix should not be removed.
- final UpstreamNetworkState v6OnlyWifi = buildUpstreamNetworkState(mWifiNetwork,
- null, new LinkAddress("2001:db8::/64"), makeNetworkCapabilities(TRANSPORT_WIFI));
- mPrivateAddressCoordinator.updateUpstreamPrefix(v6OnlyWifi);
- verify(mHotspotIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
- mPrivateAddressCoordinator.removeUpstreamPrefix(mWifiNetwork);
- // - Update vpn network, it conflict with hotspot prefix but VPN networks are ignored.
- final UpstreamNetworkState v4OnlyVpn = buildUpstreamNetworkState(mVpnNetwork,
- new LinkAddress("192.168.43.5/24"), null, makeNetworkCapabilities(TRANSPORT_VPN));
- mPrivateAddressCoordinator.updateUpstreamPrefix(v4OnlyVpn);
- verify(mHotspotIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
- // - Update v4 only wifi network, it conflict with hotspot prefix.
- final UpstreamNetworkState v4OnlyWifi = buildUpstreamNetworkState(mWifiNetwork,
- new LinkAddress("192.168.43.5/24"), null, makeNetworkCapabilities(TRANSPORT_WIFI));
- mPrivateAddressCoordinator.updateUpstreamPrefix(v4OnlyWifi);
- verify(mHotspotIpServer).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
- reset(mHotspotIpServer);
- // - Restart hotspot again and its prefix is different previous.
- mPrivateAddressCoordinator.releaseDownstream(mHotspotIpServer);
- final LinkAddress hotspotAddr2 = requestDownstreamAddress(mHotspotIpServer,
- true /* useLastAddress */);
- final IpPrefix hotspotPrefix2 = asIpPrefix(hotspotAddr2);
- assertNotEquals(hotspotPrefix, hotspotPrefix2);
- mPrivateAddressCoordinator.updateUpstreamPrefix(v4OnlyWifi);
- verify(mHotspotIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
- // - Usb tethering can be enabled and its prefix is different with conflict one.
- final LinkAddress usbAddr = requestDownstreamAddress(mUsbIpServer,
- true /* useLastAddress */);
- final IpPrefix usbPrefix = asIpPrefix(usbAddr);
- assertNotEquals(predefinedPrefix, usbPrefix);
- assertNotEquals(hotspotPrefix2, usbPrefix);
- // - Disable wifi upstream, then wifi's prefix can be selected again.
- mPrivateAddressCoordinator.removeUpstreamPrefix(mWifiNetwork);
- final LinkAddress ethAddr = requestDownstreamAddress(mEthernetIpServer,
- true /* useLastAddress */);
- final IpPrefix ethPrefix = asIpPrefix(ethAddr);
- assertEquals(predefinedPrefix, ethPrefix);
- }
-
- @Test
- public void testChooseAvailablePrefix() throws Exception {
- final int randomAddress = 0x8605; // 134.5
- when(mPrivateAddressCoordinator.getRandomInt()).thenReturn(randomAddress);
- final LinkAddress addr0 = requestDownstreamAddress(mHotspotIpServer,
- true /* useLastAddress */);
- // Check whether return address is prefix 192.168.0.0/16 + subAddress 0.0.134.5.
- assertEquals("Wrong prefix: ", new LinkAddress("192.168.134.5/24"), addr0);
- final UpstreamNetworkState wifiUpstream = buildUpstreamNetworkState(mWifiNetwork,
- new LinkAddress("192.168.134.13/26"), null,
- makeNetworkCapabilities(TRANSPORT_WIFI));
- mPrivateAddressCoordinator.updateUpstreamPrefix(wifiUpstream);
-
- // Check whether return address is next prefix of 192.168.134.0/24.
- final LinkAddress addr1 = requestDownstreamAddress(mHotspotIpServer,
- true /* useLastAddress */);
- assertEquals("Wrong prefix: ", new LinkAddress("192.168.135.5/24"), addr1);
- final UpstreamNetworkState wifiUpstream2 = buildUpstreamNetworkState(mWifiNetwork,
- new LinkAddress("192.168.149.16/19"), null,
- makeNetworkCapabilities(TRANSPORT_WIFI));
- mPrivateAddressCoordinator.updateUpstreamPrefix(wifiUpstream2);
-
-
- // The conflict range is 128 ~ 159, so the address is 192.168.160.5/24.
- final LinkAddress addr2 = requestDownstreamAddress(mHotspotIpServer,
- true /* useLastAddress */);
- assertEquals("Wrong prefix: ", new LinkAddress("192.168.160.5/24"), addr2);
- final UpstreamNetworkState mobileUpstream = buildUpstreamNetworkState(mMobileNetwork,
- new LinkAddress("192.168.129.53/18"), null,
- makeNetworkCapabilities(TRANSPORT_CELLULAR));
- // Update another conflict upstream which is covered by the previous one (but not the first
- // one) and verify whether this would affect the result.
- final UpstreamNetworkState mobileUpstream2 = buildUpstreamNetworkState(mMobileNetwork2,
- new LinkAddress("192.168.170.7/19"), null,
- makeNetworkCapabilities(TRANSPORT_CELLULAR));
- mPrivateAddressCoordinator.updateUpstreamPrefix(mobileUpstream);
- mPrivateAddressCoordinator.updateUpstreamPrefix(mobileUpstream2);
-
- // The conflict range are 128 ~ 159 and 159 ~ 191, so the address is 192.168.192.5/24.
- final LinkAddress addr3 = requestDownstreamAddress(mHotspotIpServer,
- true /* useLastAddress */);
- assertEquals("Wrong prefix: ", new LinkAddress("192.168.192.5/24"), addr3);
- final UpstreamNetworkState mobileUpstream3 = buildUpstreamNetworkState(mMobileNetwork3,
- new LinkAddress("192.168.188.133/17"), null,
- makeNetworkCapabilities(TRANSPORT_CELLULAR));
- mPrivateAddressCoordinator.updateUpstreamPrefix(mobileUpstream3);
-
- // Conflict range: 128 ~ 255. The next available address is 192.168.0.5 because
- // 192.168.134/24 ~ 192.168.255.255/24 is not available.
- final LinkAddress addr4 = requestDownstreamAddress(mHotspotIpServer,
- true /* useLastAddress */);
- assertEquals("Wrong prefix: ", new LinkAddress("192.168.0.5/24"), addr4);
- final UpstreamNetworkState mobileUpstream4 = buildUpstreamNetworkState(mMobileNetwork4,
- new LinkAddress("192.168.3.59/21"), null,
- makeNetworkCapabilities(TRANSPORT_CELLULAR));
- mPrivateAddressCoordinator.updateUpstreamPrefix(mobileUpstream4);
-
- // Conflict ranges: 128 ~ 255 and 0 ~ 7, so the address is 192.168.8.5/24.
- final LinkAddress addr5 = requestDownstreamAddress(mHotspotIpServer,
- true /* useLastAddress */);
- assertEquals("Wrong prefix: ", new LinkAddress("192.168.8.5/24"), addr5);
- final UpstreamNetworkState mobileUpstream5 = buildUpstreamNetworkState(mMobileNetwork5,
- new LinkAddress("192.168.68.43/21"), null,
- makeNetworkCapabilities(TRANSPORT_CELLULAR));
- mPrivateAddressCoordinator.updateUpstreamPrefix(mobileUpstream5);
-
- // Update an upstream that does *not* conflict, check whether return the same address
- // 192.168.5/24.
- final LinkAddress addr6 = requestDownstreamAddress(mHotspotIpServer,
- true /* useLastAddress */);
- assertEquals("Wrong prefix: ", new LinkAddress("192.168.8.5/24"), addr6);
- final UpstreamNetworkState mobileUpstream6 = buildUpstreamNetworkState(mMobileNetwork6,
- new LinkAddress("192.168.10.97/21"), null,
- makeNetworkCapabilities(TRANSPORT_CELLULAR));
- mPrivateAddressCoordinator.updateUpstreamPrefix(mobileUpstream6);
-
- // Conflict ranges: 0 ~ 15 and 128 ~ 255, so the address is 192.168.16.5/24.
- final LinkAddress addr7 = requestDownstreamAddress(mHotspotIpServer,
- true /* useLastAddress */);
- assertEquals("Wrong prefix: ", new LinkAddress("192.168.16.5/24"), addr7);
- final UpstreamNetworkState mobileUpstream7 = buildUpstreamNetworkState(mMobileNetwork6,
- new LinkAddress("192.168.0.0/17"), null,
- makeNetworkCapabilities(TRANSPORT_CELLULAR));
- mPrivateAddressCoordinator.updateUpstreamPrefix(mobileUpstream7);
-
- // Choose prefix from next range(172.16.0.0/12) when no available prefix in 192.168.0.0/16.
- final LinkAddress addr8 = requestDownstreamAddress(mHotspotIpServer,
- true /* useLastAddress */);
- assertEquals("Wrong prefix: ", new LinkAddress("172.16.134.5/24"), addr8);
- }
-
- @Test
- public void testChoosePrefixFromDifferentRanges() throws Exception {
- final int randomAddress = 0x1f2b2a; // 31.43.42
- when(mPrivateAddressCoordinator.getRandomInt()).thenReturn(randomAddress);
- final LinkAddress classC1 = requestDownstreamAddress(mHotspotIpServer,
- true /* useLastAddress */);
- // Check whether return address is prefix 192.168.0.0/16 + subAddress 0.0.43.42.
- assertEquals("Wrong prefix: ", new LinkAddress("192.168.43.42/24"), classC1);
- final UpstreamNetworkState wifiUpstream = buildUpstreamNetworkState(mWifiNetwork,
- new LinkAddress("192.168.88.23/17"), null,
- makeNetworkCapabilities(TRANSPORT_WIFI));
- mPrivateAddressCoordinator.updateUpstreamPrefix(wifiUpstream);
- verifyNotifyConflictAndRelease(mHotspotIpServer);
-
- // Check whether return address is next address of prefix 192.168.128.0/17.
- final LinkAddress classC2 = requestDownstreamAddress(mHotspotIpServer,
- true /* useLastAddress */);
- assertEquals("Wrong prefix: ", new LinkAddress("192.168.128.42/24"), classC2);
- final UpstreamNetworkState mobileUpstream = buildUpstreamNetworkState(mMobileNetwork,
- new LinkAddress("192.1.2.3/8"), null,
- makeNetworkCapabilities(TRANSPORT_CELLULAR));
- mPrivateAddressCoordinator.updateUpstreamPrefix(mobileUpstream);
- verifyNotifyConflictAndRelease(mHotspotIpServer);
-
- // Check whether return address is under prefix 172.16.0.0/12.
- final LinkAddress classB1 = requestDownstreamAddress(mHotspotIpServer,
- true /* useLastAddress */);
- assertEquals("Wrong prefix: ", new LinkAddress("172.31.43.42/24"), classB1);
- final UpstreamNetworkState mobileUpstream2 = buildUpstreamNetworkState(mMobileNetwork2,
- new LinkAddress("172.28.123.100/14"), null,
- makeNetworkCapabilities(TRANSPORT_CELLULAR));
- mPrivateAddressCoordinator.updateUpstreamPrefix(mobileUpstream2);
- verifyNotifyConflictAndRelease(mHotspotIpServer);
-
- // 172.28.0.0 ~ 172.31.255.255 is not available.
- // Check whether return address is next address of prefix 172.16.0.0/14.
- final LinkAddress classB2 = requestDownstreamAddress(mHotspotIpServer,
- true /* useLastAddress */);
- assertEquals("Wrong prefix: ", new LinkAddress("172.16.0.42/24"), classB2);
-
- // Check whether new downstream is next address of address 172.16.0.42/24.
- final LinkAddress classB3 = requestDownstreamAddress(mUsbIpServer,
- true /* useLastAddress */);
- assertEquals("Wrong prefix: ", new LinkAddress("172.16.1.42/24"), classB3);
- final UpstreamNetworkState mobileUpstream3 = buildUpstreamNetworkState(mMobileNetwork3,
- new LinkAddress("172.16.0.1/24"), null,
- makeNetworkCapabilities(TRANSPORT_CELLULAR));
- mPrivateAddressCoordinator.updateUpstreamPrefix(mobileUpstream3);
- verifyNotifyConflictAndRelease(mHotspotIpServer);
- verify(mUsbIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
-
- // Check whether return address is next address of prefix 172.16.1.42/24.
- final LinkAddress classB4 = requestDownstreamAddress(mHotspotIpServer,
- true /* useLastAddress */);
- assertEquals("Wrong prefix: ", new LinkAddress("172.16.2.42/24"), classB4);
- final UpstreamNetworkState mobileUpstream4 = buildUpstreamNetworkState(mMobileNetwork4,
- new LinkAddress("172.16.0.1/13"), null,
- makeNetworkCapabilities(TRANSPORT_CELLULAR));
- mPrivateAddressCoordinator.updateUpstreamPrefix(mobileUpstream4);
- verifyNotifyConflictAndRelease(mHotspotIpServer);
- verifyNotifyConflictAndRelease(mUsbIpServer);
-
- // Check whether return address is next address of prefix 172.16.0.1/13.
- final LinkAddress classB5 = requestDownstreamAddress(mHotspotIpServer,
- true /* useLastAddress */);
- assertEquals("Wrong prefix: ", new LinkAddress("172.24.0.42/24"), classB5);
- // Check whether return address is next address of prefix 172.24.0.42/24.
- final LinkAddress classB6 = requestDownstreamAddress(mUsbIpServer,
- true /* useLastAddress */);
- assertEquals("Wrong prefix: ", new LinkAddress("172.24.1.42/24"), classB6);
- final UpstreamNetworkState mobileUpstream5 = buildUpstreamNetworkState(mMobileNetwork5,
- new LinkAddress("172.24.0.1/12"), null,
- makeNetworkCapabilities(TRANSPORT_CELLULAR));
- mPrivateAddressCoordinator.updateUpstreamPrefix(mobileUpstream5);
- verifyNotifyConflictAndRelease(mHotspotIpServer);
- verifyNotifyConflictAndRelease(mUsbIpServer);
-
- // Check whether return address is prefix 10.0.0.0/8 + subAddress 0.31.43.42.
- final LinkAddress classA1 = requestDownstreamAddress(mHotspotIpServer,
- true /* useLastAddress */);
- assertEquals("Wrong prefix: ", new LinkAddress("10.31.43.42/24"), classA1);
- // Check whether new downstream is next address of address 10.31.43.42/24.
- final LinkAddress classA2 = requestDownstreamAddress(mUsbIpServer,
- true /* useLastAddress */);
- assertEquals("Wrong prefix: ", new LinkAddress("10.31.44.42/24"), classA2);
- }
-
- private void verifyNotifyConflictAndRelease(final IpServer ipServer) throws Exception {
- verify(ipServer).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
- mPrivateAddressCoordinator.releaseDownstream(ipServer);
- reset(ipServer);
- setUpIpServers();
- }
-
- private int getSubAddress(final byte... ipv4Address) {
- assertEquals(4, ipv4Address.length);
-
- int subnet = Byte.toUnsignedInt(ipv4Address[2]);
- return (subnet << 8) + ipv4Address[3];
- }
-
- private void assertReseveredWifiP2pPrefix() throws Exception {
- LinkAddress address = requestDownstreamAddress(mHotspotIpServer,
- true /* useLastAddress */);
- final IpPrefix hotspotPrefix = asIpPrefix(address);
- final IpPrefix legacyWifiP2pPrefix = asIpPrefix(mLegacyWifiP2pAddress);
- assertNotEquals(legacyWifiP2pPrefix, hotspotPrefix);
- mPrivateAddressCoordinator.releaseDownstream(mHotspotIpServer);
- }
-
- @Test
- public void testEnableLegacyWifiP2PAddress() throws Exception {
- when(mPrivateAddressCoordinator.getRandomInt()).thenReturn(
- getSubAddress(mLegacyWifiP2pAddress.getAddress().getAddress()));
- // No matter #shouldEnableWifiP2pDedicatedIp() is enabled or not, legacy wifi p2p prefix
- // is resevered.
- assertReseveredWifiP2pPrefix();
-
- when(mConfig.shouldEnableWifiP2pDedicatedIp()).thenReturn(true);
- assertReseveredWifiP2pPrefix();
-
- // If #shouldEnableWifiP2pDedicatedIp() is enabled, wifi P2P gets the configured address.
- LinkAddress address = requestDownstreamAddress(mWifiP2pIpServer,
- true /* useLastAddress */);
- assertEquals(mLegacyWifiP2pAddress, address);
- mPrivateAddressCoordinator.releaseDownstream(mWifiP2pIpServer);
- }
-}
diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringConfigurationTest.java b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringConfigurationTest.java
deleted file mode 100644
index 237e2c2..0000000
--- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringConfigurationTest.java
+++ /dev/null
@@ -1,458 +0,0 @@
-/*
- * Copyright (C) 2017 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;
-
-import static android.net.ConnectivityManager.TYPE_ETHERNET;
-import static android.net.ConnectivityManager.TYPE_MOBILE;
-import static android.net.ConnectivityManager.TYPE_MOBILE_DUN;
-import static android.net.ConnectivityManager.TYPE_MOBILE_HIPRI;
-import static android.net.ConnectivityManager.TYPE_WIFI;
-import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY;
-import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
-
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.net.util.SharedLog;
-import android.provider.DeviceConfig;
-import android.telephony.TelephonyManager;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import com.android.internal.util.test.BroadcastInterceptingContext;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoSession;
-import org.mockito.quality.Strictness;
-
-import java.util.Arrays;
-import java.util.Iterator;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class TetheringConfigurationTest {
- private final SharedLog mLog = new SharedLog("TetheringConfigurationTest");
-
- private static final String[] PROVISIONING_APP_NAME = {"some", "app"};
- private static final String PROVISIONING_NO_UI_APP_NAME = "no_ui_app";
- private static final String PROVISIONING_APP_RESPONSE = "app_response";
- @Mock private Context mContext;
- @Mock private TelephonyManager mTelephonyManager;
- @Mock private Resources mResources;
- @Mock private Resources mResourcesForSubId;
- private Context mMockContext;
- private boolean mHasTelephonyManager;
- private boolean mEnableLegacyDhcpServer;
- private MockitoSession mMockingSession;
-
- private class MockTetheringConfiguration extends TetheringConfiguration {
- MockTetheringConfiguration(Context ctx, SharedLog log, int id) {
- super(ctx, log, id);
- }
-
- @Override
- protected Resources getResourcesForSubIdWrapper(Context ctx, int subId) {
- return mResourcesForSubId;
- }
- }
-
- private class MockContext extends BroadcastInterceptingContext {
- MockContext(Context base) {
- super(base);
- }
-
- @Override
- public Resources getResources() {
- return mResources;
- }
-
- @Override
- public Object getSystemService(String name) {
- if (Context.TELEPHONY_SERVICE.equals(name)) {
- return mHasTelephonyManager ? mTelephonyManager : null;
- }
- return super.getSystemService(name);
- }
- }
-
- @Before
- public void setUp() throws Exception {
- // TODO: use a dependencies class instead of mock statics.
- mMockingSession = mockitoSession()
- .initMocks(this)
- .mockStatic(DeviceConfig.class)
- .strictness(Strictness.WARN)
- .startMocking();
- doReturn(null).when(
- () -> DeviceConfig.getProperty(eq(NAMESPACE_CONNECTIVITY),
- eq(TetheringConfiguration.TETHER_ENABLE_LEGACY_DHCP_SERVER)));
-
- when(mResources.getStringArray(R.array.config_tether_dhcp_range)).thenReturn(
- new String[0]);
- when(mResources.getInteger(R.integer.config_tether_offload_poll_interval)).thenReturn(
- TetheringConfiguration.DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS);
- when(mResources.getStringArray(R.array.config_tether_usb_regexs)).thenReturn(new String[0]);
- when(mResources.getStringArray(R.array.config_tether_wifi_regexs))
- .thenReturn(new String[]{ "test_wlan\\d" });
- when(mResources.getStringArray(R.array.config_tether_bluetooth_regexs)).thenReturn(
- new String[0]);
- when(mResources.getIntArray(R.array.config_tether_upstream_types)).thenReturn(new int[0]);
- when(mResources.getStringArray(R.array.config_mobile_hotspot_provision_app))
- .thenReturn(new String[0]);
- when(mResources.getBoolean(R.bool.config_tether_enable_legacy_dhcp_server)).thenReturn(
- false);
- when(mResources.getBoolean(R.bool.config_tether_enable_legacy_wifi_p2p_dedicated_ip))
- .thenReturn(false);
- initializeBpfOffloadConfiguration(true, null /* unset */);
- initEnableSelectAllPrefixRangeFlag(null /* unset */);
-
- mHasTelephonyManager = true;
- mMockContext = new MockContext(mContext);
- mEnableLegacyDhcpServer = false;
- }
-
- @After
- public void tearDown() throws Exception {
- mMockingSession.finishMocking();
- }
-
- private TetheringConfiguration getTetheringConfiguration(int... legacyTetherUpstreamTypes) {
- when(mResources.getIntArray(R.array.config_tether_upstream_types)).thenReturn(
- legacyTetherUpstreamTypes);
- return new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
- }
-
- @Test
- public void testNoTelephonyManagerMeansNoDun() {
- mHasTelephonyManager = false;
- final TetheringConfiguration cfg = getTetheringConfiguration(
- new int[]{TYPE_MOBILE_DUN, TYPE_WIFI});
- assertFalse(cfg.isDunRequired);
- assertFalse(cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE_DUN));
- // Just to prove we haven't clobbered Wi-Fi:
- assertTrue(cfg.preferredUpstreamIfaceTypes.contains(TYPE_WIFI));
- }
-
- @Test
- public void testDunFromTelephonyManagerMeansDun() {
- when(mTelephonyManager.isTetheringApnRequired()).thenReturn(true);
-
- final TetheringConfiguration cfgWifi = getTetheringConfiguration(TYPE_WIFI);
- final TetheringConfiguration cfgMobileWifiHipri = getTetheringConfiguration(
- TYPE_MOBILE, TYPE_WIFI, TYPE_MOBILE_HIPRI);
- final TetheringConfiguration cfgWifiDun = getTetheringConfiguration(
- TYPE_WIFI, TYPE_MOBILE_DUN);
- final TetheringConfiguration cfgMobileWifiHipriDun = getTetheringConfiguration(
- TYPE_MOBILE, TYPE_WIFI, TYPE_MOBILE_HIPRI, TYPE_MOBILE_DUN);
-
- for (TetheringConfiguration cfg : Arrays.asList(cfgWifi, cfgMobileWifiHipri,
- cfgWifiDun, cfgMobileWifiHipriDun)) {
- String msg = "config=" + cfg.toString();
- assertTrue(msg, cfg.isDunRequired);
- assertTrue(msg, cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE_DUN));
- assertFalse(msg, cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE));
- assertFalse(msg, cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE_HIPRI));
- // Just to prove we haven't clobbered Wi-Fi:
- assertTrue(msg, cfg.preferredUpstreamIfaceTypes.contains(TYPE_WIFI));
- }
- }
-
- @Test
- public void testDunNotRequiredFromTelephonyManagerMeansNoDun() {
- when(mTelephonyManager.isTetheringApnRequired()).thenReturn(false);
-
- final TetheringConfiguration cfgWifi = getTetheringConfiguration(TYPE_WIFI);
- final TetheringConfiguration cfgMobileWifiHipri = getTetheringConfiguration(
- TYPE_MOBILE, TYPE_WIFI, TYPE_MOBILE_HIPRI);
- final TetheringConfiguration cfgWifiDun = getTetheringConfiguration(
- TYPE_WIFI, TYPE_MOBILE_DUN);
- final TetheringConfiguration cfgWifiMobile = getTetheringConfiguration(
- TYPE_WIFI, TYPE_MOBILE);
- final TetheringConfiguration cfgWifiHipri = getTetheringConfiguration(
- TYPE_WIFI, TYPE_MOBILE_HIPRI);
- final TetheringConfiguration cfgMobileWifiHipriDun = getTetheringConfiguration(
- TYPE_MOBILE, TYPE_WIFI, TYPE_MOBILE_HIPRI, TYPE_MOBILE_DUN);
-
- String msg;
- // TYPE_MOBILE_DUN should be present in none of the combinations.
- // TYPE_WIFI should not be affected.
- for (TetheringConfiguration cfg : Arrays.asList(cfgWifi, cfgMobileWifiHipri, cfgWifiDun,
- cfgWifiMobile, cfgWifiHipri, cfgMobileWifiHipriDun)) {
- msg = "config=" + cfg.toString();
- assertFalse(msg, cfg.isDunRequired);
- assertFalse(msg, cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE_DUN));
- assertTrue(msg, cfg.preferredUpstreamIfaceTypes.contains(TYPE_WIFI));
- }
-
- for (TetheringConfiguration cfg : Arrays.asList(cfgWifi, cfgMobileWifiHipri, cfgWifiDun,
- cfgMobileWifiHipriDun)) {
- msg = "config=" + cfg.toString();
- assertTrue(msg, cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE));
- assertTrue(msg, cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE_HIPRI));
- }
- msg = "config=" + cfgWifiMobile.toString();
- assertTrue(msg, cfgWifiMobile.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE));
- assertFalse(msg, cfgWifiMobile.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE_HIPRI));
- msg = "config=" + cfgWifiHipri.toString();
- assertFalse(msg, cfgWifiHipri.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE));
- assertTrue(msg, cfgWifiHipri.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE_HIPRI));
-
- }
-
- @Test
- public void testNoDefinedUpstreamTypesAddsEthernet() {
- when(mResources.getIntArray(R.array.config_tether_upstream_types)).thenReturn(new int[]{});
- when(mTelephonyManager.isTetheringApnRequired()).thenReturn(false);
-
- final TetheringConfiguration cfg = new TetheringConfiguration(
- mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
- final Iterator<Integer> upstreamIterator = cfg.preferredUpstreamIfaceTypes.iterator();
- assertTrue(upstreamIterator.hasNext());
- assertEquals(TYPE_ETHERNET, upstreamIterator.next().intValue());
- // The following is because the code always adds some kind of mobile
- // upstream, be it DUN or, in this case where DUN is NOT required,
- // make sure there is at least one of MOBILE or HIPRI. With the empty
- // list of the configuration in this test, it will always add both
- // MOBILE and HIPRI, in that order.
- assertTrue(upstreamIterator.hasNext());
- assertEquals(TYPE_MOBILE, upstreamIterator.next().intValue());
- assertTrue(upstreamIterator.hasNext());
- assertEquals(TYPE_MOBILE_HIPRI, upstreamIterator.next().intValue());
- assertFalse(upstreamIterator.hasNext());
- }
-
- @Test
- public void testDefinedUpstreamTypesSansEthernetAddsEthernet() {
- when(mResources.getIntArray(R.array.config_tether_upstream_types)).thenReturn(
- new int[]{TYPE_WIFI, TYPE_MOBILE_HIPRI});
- when(mTelephonyManager.isTetheringApnRequired()).thenReturn(false);
-
- final TetheringConfiguration cfg = new TetheringConfiguration(
- mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
- final Iterator<Integer> upstreamIterator = cfg.preferredUpstreamIfaceTypes.iterator();
- assertTrue(upstreamIterator.hasNext());
- assertEquals(TYPE_ETHERNET, upstreamIterator.next().intValue());
- assertTrue(upstreamIterator.hasNext());
- assertEquals(TYPE_WIFI, upstreamIterator.next().intValue());
- assertTrue(upstreamIterator.hasNext());
- assertEquals(TYPE_MOBILE_HIPRI, upstreamIterator.next().intValue());
- assertFalse(upstreamIterator.hasNext());
- }
-
- @Test
- public void testDefinedUpstreamTypesWithEthernetDoesNotAddEthernet() {
- when(mResources.getIntArray(R.array.config_tether_upstream_types))
- .thenReturn(new int[]{TYPE_WIFI, TYPE_ETHERNET, TYPE_MOBILE_HIPRI});
- when(mTelephonyManager.isTetheringApnRequired()).thenReturn(false);
-
- final TetheringConfiguration cfg = new TetheringConfiguration(
- mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
- final Iterator<Integer> upstreamIterator = cfg.preferredUpstreamIfaceTypes.iterator();
- assertTrue(upstreamIterator.hasNext());
- assertEquals(TYPE_WIFI, upstreamIterator.next().intValue());
- assertTrue(upstreamIterator.hasNext());
- assertEquals(TYPE_ETHERNET, upstreamIterator.next().intValue());
- assertTrue(upstreamIterator.hasNext());
- assertEquals(TYPE_MOBILE_HIPRI, upstreamIterator.next().intValue());
- assertFalse(upstreamIterator.hasNext());
- }
-
- private void initializeBpfOffloadConfiguration(
- final boolean fromRes, final String fromDevConfig) {
- when(mResources.getBoolean(R.bool.config_tether_enable_bpf_offload)).thenReturn(fromRes);
- doReturn(fromDevConfig).when(
- () -> DeviceConfig.getProperty(eq(NAMESPACE_CONNECTIVITY),
- eq(TetheringConfiguration.OVERRIDE_TETHER_ENABLE_BPF_OFFLOAD)));
- }
-
- @Test
- public void testBpfOffloadEnabledByResource() {
- initializeBpfOffloadConfiguration(true, null /* unset */);
- final TetheringConfiguration enableByRes =
- new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
- assertTrue(enableByRes.isBpfOffloadEnabled());
- }
-
- @Test
- public void testBpfOffloadEnabledByDeviceConfigOverride() {
- for (boolean res : new boolean[]{true, false}) {
- initializeBpfOffloadConfiguration(res, "true");
- final TetheringConfiguration enableByDevConOverride =
- new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
- assertTrue(enableByDevConOverride.isBpfOffloadEnabled());
- }
- }
-
- @Test
- public void testBpfOffloadDisabledByResource() {
- initializeBpfOffloadConfiguration(false, null /* unset */);
- final TetheringConfiguration disableByRes =
- new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
- assertFalse(disableByRes.isBpfOffloadEnabled());
- }
-
- @Test
- public void testBpfOffloadDisabledByDeviceConfigOverride() {
- for (boolean res : new boolean[]{true, false}) {
- initializeBpfOffloadConfiguration(res, "false");
- final TetheringConfiguration disableByDevConOverride =
- new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
- assertFalse(disableByDevConOverride.isBpfOffloadEnabled());
- }
- }
-
- @Test
- public void testNewDhcpServerDisabled() {
- when(mResources.getBoolean(R.bool.config_tether_enable_legacy_dhcp_server)).thenReturn(
- true);
- doReturn("false").when(
- () -> DeviceConfig.getProperty(eq(NAMESPACE_CONNECTIVITY),
- eq(TetheringConfiguration.TETHER_ENABLE_LEGACY_DHCP_SERVER)));
-
- final TetheringConfiguration enableByRes =
- new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
- assertTrue(enableByRes.enableLegacyDhcpServer);
-
- when(mResources.getBoolean(R.bool.config_tether_enable_legacy_dhcp_server)).thenReturn(
- false);
- doReturn("true").when(
- () -> DeviceConfig.getProperty(eq(NAMESPACE_CONNECTIVITY),
- eq(TetheringConfiguration.TETHER_ENABLE_LEGACY_DHCP_SERVER)));
-
- final TetheringConfiguration enableByDevConfig =
- new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
- assertTrue(enableByDevConfig.enableLegacyDhcpServer);
- }
-
- @Test
- public void testNewDhcpServerEnabled() {
- when(mResources.getBoolean(R.bool.config_tether_enable_legacy_dhcp_server)).thenReturn(
- false);
- doReturn("false").when(
- () -> DeviceConfig.getProperty(eq(NAMESPACE_CONNECTIVITY),
- eq(TetheringConfiguration.TETHER_ENABLE_LEGACY_DHCP_SERVER)));
-
- final TetheringConfiguration cfg =
- new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
-
- assertFalse(cfg.enableLegacyDhcpServer);
- }
-
- @Test
- public void testOffloadIntervalByResource() {
- final TetheringConfiguration intervalByDefault =
- new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
- assertEquals(TetheringConfiguration.DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS,
- intervalByDefault.getOffloadPollInterval());
-
- final int[] testOverrides = {0, 3000, -1};
- for (final int override : testOverrides) {
- when(mResources.getInteger(R.integer.config_tether_offload_poll_interval)).thenReturn(
- override);
- final TetheringConfiguration overrideByRes =
- new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
- assertEquals(override, overrideByRes.getOffloadPollInterval());
- }
- }
-
- @Test
- public void testGetResourcesBySubId() {
- setUpResourceForSubId();
- final TetheringConfiguration cfg = new TetheringConfiguration(
- mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
- assertTrue(cfg.provisioningApp.length == 0);
- final int anyValidSubId = 1;
- final MockTetheringConfiguration mockCfg =
- new MockTetheringConfiguration(mMockContext, mLog, anyValidSubId);
- assertEquals(mockCfg.provisioningApp[0], PROVISIONING_APP_NAME[0]);
- assertEquals(mockCfg.provisioningApp[1], PROVISIONING_APP_NAME[1]);
- assertEquals(mockCfg.provisioningAppNoUi, PROVISIONING_NO_UI_APP_NAME);
- assertEquals(mockCfg.provisioningResponse, PROVISIONING_APP_RESPONSE);
- }
-
- private void setUpResourceForSubId() {
- when(mResourcesForSubId.getStringArray(
- R.array.config_tether_dhcp_range)).thenReturn(new String[0]);
- when(mResourcesForSubId.getStringArray(
- R.array.config_tether_usb_regexs)).thenReturn(new String[0]);
- when(mResourcesForSubId.getStringArray(
- R.array.config_tether_wifi_regexs)).thenReturn(new String[]{ "test_wlan\\d" });
- when(mResourcesForSubId.getStringArray(
- R.array.config_tether_bluetooth_regexs)).thenReturn(new String[0]);
- when(mResourcesForSubId.getIntArray(R.array.config_tether_upstream_types)).thenReturn(
- new int[0]);
- when(mResourcesForSubId.getStringArray(
- R.array.config_mobile_hotspot_provision_app)).thenReturn(PROVISIONING_APP_NAME);
- when(mResourcesForSubId.getString(R.string.config_mobile_hotspot_provision_app_no_ui))
- .thenReturn(PROVISIONING_NO_UI_APP_NAME);
- when(mResourcesForSubId.getString(
- R.string.config_mobile_hotspot_provision_response)).thenReturn(
- PROVISIONING_APP_RESPONSE);
- }
-
- @Test
- public void testEnableLegacyWifiP2PAddress() throws Exception {
- final TetheringConfiguration defaultCfg = new TetheringConfiguration(
- mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
- assertFalse(defaultCfg.shouldEnableWifiP2pDedicatedIp());
-
- when(mResources.getBoolean(R.bool.config_tether_enable_legacy_wifi_p2p_dedicated_ip))
- .thenReturn(true);
- final TetheringConfiguration testCfg = new TetheringConfiguration(
- mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
- assertTrue(testCfg.shouldEnableWifiP2pDedicatedIp());
- }
-
- private void initEnableSelectAllPrefixRangeFlag(final String value) {
- doReturn(value).when(
- () -> DeviceConfig.getProperty(eq(NAMESPACE_CONNECTIVITY),
- eq(TetheringConfiguration.TETHER_ENABLE_SELECT_ALL_PREFIX_RANGES)));
- }
-
- @Test
- public void testSelectAllPrefixRangeFlag() throws Exception {
- // Test default value.
- final TetheringConfiguration defaultCfg = new TetheringConfiguration(
- mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
- assertTrue(defaultCfg.isSelectAllPrefixRangeEnabled());
-
- // Test disable flag.
- initEnableSelectAllPrefixRangeFlag("false");
- final TetheringConfiguration testDisable = new TetheringConfiguration(
- mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
- assertFalse(testDisable.isSelectAllPrefixRangeEnabled());
-
- // Test enable flag.
- initEnableSelectAllPrefixRangeFlag("true");
- final TetheringConfiguration testEnable = new TetheringConfiguration(
- mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
- assertTrue(testEnable.isSelectAllPrefixRangeEnabled());
- }
-}
diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringNotificationUpdaterTest.kt b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringNotificationUpdaterTest.kt
deleted file mode 100644
index 75c819b..0000000
--- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringNotificationUpdaterTest.kt
+++ /dev/null
@@ -1,444 +0,0 @@
-/*
- * 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
-
-import android.app.Notification
-import android.app.NotificationManager
-import android.app.PendingIntent
-import android.app.PendingIntent.FLAG_IMMUTABLE
-import android.content.Context
-import android.content.Intent
-import android.content.pm.ActivityInfo
-import android.content.pm.ApplicationInfo
-import android.content.pm.PackageManager
-import android.content.pm.ResolveInfo
-import android.content.res.Resources
-import android.net.ConnectivityManager.TETHERING_WIFI
-import android.net.NetworkCapabilities
-import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING
-import android.os.Handler
-import android.os.HandlerThread
-import android.os.Looper
-import android.os.UserHandle
-import android.provider.Settings
-import android.telephony.TelephonyManager
-import androidx.test.filters.SmallTest
-import androidx.test.platform.app.InstrumentationRegistry
-import androidx.test.runner.AndroidJUnit4
-import com.android.internal.util.test.BroadcastInterceptingContext
-import com.android.networkstack.tethering.TetheringNotificationUpdater.ACTION_DISABLE_TETHERING
-import com.android.networkstack.tethering.TetheringNotificationUpdater.DOWNSTREAM_NONE
-import com.android.networkstack.tethering.TetheringNotificationUpdater.EVENT_SHOW_NO_UPSTREAM
-import com.android.networkstack.tethering.TetheringNotificationUpdater.NO_UPSTREAM_NOTIFICATION_ID
-import com.android.networkstack.tethering.TetheringNotificationUpdater.RESTRICTED_NOTIFICATION_ID
-import com.android.networkstack.tethering.TetheringNotificationUpdater.ROAMING_NOTIFICATION_ID
-import com.android.networkstack.tethering.TetheringNotificationUpdater.VERIZON_CARRIER_ID
-import com.android.networkstack.tethering.TetheringNotificationUpdater.getSettingsPackageName
-import com.android.testutils.waitForIdle
-import org.junit.After
-import org.junit.Assert.assertEquals
-import org.junit.Assert.assertNotNull
-import org.junit.Assert.fail
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.ArgumentCaptor
-import org.mockito.ArgumentMatchers.any
-import org.mockito.ArgumentMatchers.anyInt
-import org.mockito.ArgumentMatchers.eq
-import org.mockito.Mock
-import org.mockito.Mockito.doReturn
-import org.mockito.Mockito.mock
-import org.mockito.Mockito.never
-import org.mockito.Mockito.reset
-import org.mockito.Mockito.times
-import org.mockito.Mockito.verify
-import org.mockito.Mockito.verifyZeroInteractions
-import org.mockito.MockitoAnnotations
-
-const val TEST_SUBID = 1
-const val WIFI_MASK = 1 shl TETHERING_WIFI
-const val TEST_DISALLOW_TITLE = "Tether function is disallowed"
-const val TEST_DISALLOW_MESSAGE = "Please contact your admin"
-const val TEST_NO_UPSTREAM_TITLE = "Hotspot has no internet access"
-const val TEST_NO_UPSTREAM_MESSAGE = "Device cannot connect to internet."
-const val TEST_NO_UPSTREAM_BUTTON = "Turn off hotspot"
-const val TEST_ROAMING_TITLE = "Hotspot is on"
-const val TEST_ROAMING_MESSAGE = "Additional charges may apply while roaming."
-
-@RunWith(AndroidJUnit4::class)
-@SmallTest
-class TetheringNotificationUpdaterTest {
- // lateinit used here for mocks as they need to be reinitialized between each test and the test
- // should crash if they are used before being initialized.
- @Mock private lateinit var mockContext: Context
- @Mock private lateinit var notificationManager: NotificationManager
- @Mock private lateinit var telephonyManager: TelephonyManager
- @Mock private lateinit var testResources: Resources
-
- // lateinit for these classes under test, as they should be reset to a different instance for
- // every test but should always be initialized before use (or the test should crash).
- private lateinit var context: TestContext
- private lateinit var notificationUpdater: TetheringNotificationUpdater
-
- // Initializing the following members depends on initializing some of the mocks and
- // is more logically done in setup().
- private lateinit var fakeTetheringThread: HandlerThread
-
- private val ROAMING_CAPABILITIES = NetworkCapabilities()
- private val HOME_CAPABILITIES = NetworkCapabilities().addCapability(NET_CAPABILITY_NOT_ROAMING)
- private val NOTIFICATION_ICON_ID = R.drawable.stat_sys_tether_general
- private val TIMEOUT_MS = 500L
- private val ACTIVITY_PENDING_INTENT = 0
- private val BROADCAST_PENDING_INTENT = 1
-
- private inner class TestContext(c: Context) : BroadcastInterceptingContext(c) {
- override fun createContextAsUser(user: UserHandle, flags: Int) =
- if (user == UserHandle.ALL) mockContext else this
- override fun getSystemService(name: String) =
- if (name == Context.TELEPHONY_SERVICE) telephonyManager
- else super.getSystemService(name)
- }
-
- private inner class WrappedNotificationUpdater(c: Context, looper: Looper)
- : TetheringNotificationUpdater(c, looper) {
- override fun getResourcesForSubId(c: Context, subId: Int) =
- if (subId == TEST_SUBID) testResources else super.getResourcesForSubId(c, subId)
- }
-
- private fun setupResources() {
- doReturn(5).`when`(testResources)
- .getInteger(R.integer.delay_to_show_no_upstream_after_no_backhaul)
- doReturn(true).`when`(testResources)
- .getBoolean(R.bool.config_upstream_roaming_notification)
- doReturn(TEST_DISALLOW_TITLE).`when`(testResources)
- .getString(R.string.disable_tether_notification_title)
- doReturn(TEST_DISALLOW_MESSAGE).`when`(testResources)
- .getString(R.string.disable_tether_notification_message)
- doReturn(TEST_NO_UPSTREAM_TITLE).`when`(testResources)
- .getString(R.string.no_upstream_notification_title)
- doReturn(TEST_NO_UPSTREAM_MESSAGE).`when`(testResources)
- .getString(R.string.no_upstream_notification_message)
- doReturn(TEST_NO_UPSTREAM_BUTTON).`when`(testResources)
- .getString(R.string.no_upstream_notification_disable_button)
- doReturn(TEST_ROAMING_TITLE).`when`(testResources)
- .getString(R.string.upstream_roaming_notification_title)
- doReturn(TEST_ROAMING_MESSAGE).`when`(testResources)
- .getString(R.string.upstream_roaming_notification_message)
- }
-
- @Before
- fun setUp() {
- MockitoAnnotations.initMocks(this)
- context = TestContext(InstrumentationRegistry.getInstrumentation().context)
- doReturn(notificationManager).`when`(mockContext)
- .getSystemService(Context.NOTIFICATION_SERVICE)
- fakeTetheringThread = HandlerThread(this::class.java.simpleName)
- fakeTetheringThread.start()
- notificationUpdater = WrappedNotificationUpdater(context, fakeTetheringThread.looper)
- setupResources()
- }
-
- @After
- fun tearDown() {
- fakeTetheringThread.quitSafely()
- }
-
- private fun verifyActivityPendingIntent(intent: Intent, flags: Int) {
- // Use FLAG_NO_CREATE to verify whether PendingIntent has FLAG_IMMUTABLE flag(forcefully add
- // the flag in creating arguments). If the described PendingIntent does not already exist,
- // getActivity() will return null instead of PendingIntent object.
- val pi = PendingIntent.getActivity(
- context.createContextAsUser(UserHandle.CURRENT, 0 /* flags */),
- 0 /* requestCode */,
- intent,
- flags or FLAG_IMMUTABLE or PendingIntent.FLAG_NO_CREATE,
- null /* options */)
- assertNotNull("Activity PendingIntent with FLAG_IMMUTABLE does not exist.", pi)
- }
-
- private fun verifyBroadcastPendingIntent(intent: Intent, flags: Int) {
- // Use FLAG_NO_CREATE to verify whether PendingIntent has FLAG_IMMUTABLE flag(forcefully add
- // the flag in creating arguments). If the described PendingIntent does not already exist,
- // getBroadcast() will return null instead of PendingIntent object.
- val pi = PendingIntent.getBroadcast(
- context.createContextAsUser(UserHandle.CURRENT, 0 /* flags */),
- 0 /* requestCode */,
- intent,
- flags or FLAG_IMMUTABLE or PendingIntent.FLAG_NO_CREATE)
- assertNotNull("Broadcast PendingIntent with FLAG_IMMUTABLE does not exist.", pi)
- }
-
- private fun Notification.title() = this.extras.getString(Notification.EXTRA_TITLE)
- private fun Notification.text() = this.extras.getString(Notification.EXTRA_TEXT)
-
- private fun verifyNotification(
- iconId: Int,
- title: String,
- text: String,
- id: Int,
- intentSenderType: Int,
- intent: Intent,
- flags: Int
- ) {
- verify(notificationManager, never()).cancel(any(), eq(id))
-
- val notificationCaptor = ArgumentCaptor.forClass(Notification::class.java)
- verify(notificationManager, times(1))
- .notify(any(), eq(id), notificationCaptor.capture())
-
- val notification = notificationCaptor.getValue()
- assertEquals(iconId, notification.smallIcon.resId)
- assertEquals(title, notification.title())
- assertEquals(text, notification.text())
-
- when (intentSenderType) {
- ACTIVITY_PENDING_INTENT -> verifyActivityPendingIntent(intent, flags)
- BROADCAST_PENDING_INTENT -> verifyBroadcastPendingIntent(intent, flags)
- }
-
- reset(notificationManager)
- }
-
- private fun verifyNotificationCancelled(
- notificationIds: List<Int>,
- resetAfterVerified: Boolean = true
- ) {
- notificationIds.forEach {
- verify(notificationManager, times(1)).cancel(any(), eq(it))
- }
- if (resetAfterVerified) reset(notificationManager)
- }
-
- @Test
- fun testRestrictedNotification() {
- val settingsIntent = Intent(Settings.ACTION_TETHER_SETTINGS)
- .setPackage(getSettingsPackageName(context.packageManager))
- .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
-
- // Set test sub id.
- notificationUpdater.onActiveDataSubscriptionIdChanged(TEST_SUBID)
- verifyNotificationCancelled(listOf(NO_UPSTREAM_NOTIFICATION_ID, ROAMING_NOTIFICATION_ID))
-
- // User restrictions on. Show restricted notification.
- notificationUpdater.notifyTetheringDisabledByRestriction()
- verifyNotification(NOTIFICATION_ICON_ID, TEST_DISALLOW_TITLE, TEST_DISALLOW_MESSAGE,
- RESTRICTED_NOTIFICATION_ID, ACTIVITY_PENDING_INTENT, settingsIntent, FLAG_IMMUTABLE)
-
- // User restrictions off. Clear notification.
- notificationUpdater.tetheringRestrictionLifted()
- verifyNotificationCancelled(listOf(RESTRICTED_NOTIFICATION_ID))
-
- // No downstream.
- notificationUpdater.onDownstreamChanged(DOWNSTREAM_NONE)
- verifyZeroInteractions(notificationManager)
-
- // User restrictions on again. Show restricted notification.
- notificationUpdater.notifyTetheringDisabledByRestriction()
- verifyNotification(NOTIFICATION_ICON_ID, TEST_DISALLOW_TITLE, TEST_DISALLOW_MESSAGE,
- RESTRICTED_NOTIFICATION_ID, ACTIVITY_PENDING_INTENT, settingsIntent, FLAG_IMMUTABLE)
- }
-
- val MAX_BACKOFF_MS = 200L
- /**
- * Waits for all messages, including delayed ones, to be processed.
- *
- * This will wait until the handler has no more messages to be processed including
- * delayed ones, or the timeout has expired. It uses an exponential backoff strategy
- * to wait longer and longer to consume less CPU, with the max granularity being
- * MAX_BACKOFF_MS.
- *
- * @return true if all messages have been processed including delayed ones, false if timeout
- *
- * TODO: Move this method to com.android.testutils.HandlerUtils.kt.
- */
- private fun Handler.waitForDelayedMessage(what: Int?, timeoutMs: Long) {
- fun hasMatchingMessages() =
- if (what == null) hasMessagesOrCallbacks() else hasMessages(what)
- val expiry = System.currentTimeMillis() + timeoutMs
- var delay = 5L
- while (System.currentTimeMillis() < expiry && hasMatchingMessages()) {
- // None of Handler, Looper, Message and MessageQueue expose any way to retrieve
- // the time when the next (let alone the last) message will be processed, so
- // short of examining the internals with reflection sleep() is the only solution.
- Thread.sleep(delay)
- delay = (delay * 2)
- .coerceAtMost(expiry - System.currentTimeMillis())
- .coerceAtMost(MAX_BACKOFF_MS)
- }
-
- val timeout = expiry - System.currentTimeMillis()
- if (timeout <= 0) fail("Delayed message did not process yet after ${timeoutMs}ms")
- waitForIdle(timeout)
- }
-
- @Test
- fun testNoUpstreamNotification() {
- val disableIntent = Intent(ACTION_DISABLE_TETHERING).setPackage(context.packageName)
-
- // Set test sub id.
- notificationUpdater.onActiveDataSubscriptionIdChanged(TEST_SUBID)
- verifyNotificationCancelled(listOf(NO_UPSTREAM_NOTIFICATION_ID, ROAMING_NOTIFICATION_ID))
-
- // Wifi downstream.
- notificationUpdater.onDownstreamChanged(WIFI_MASK)
- verifyNotificationCancelled(listOf(NO_UPSTREAM_NOTIFICATION_ID, ROAMING_NOTIFICATION_ID))
-
- // There is no upstream. Show no upstream notification.
- notificationUpdater.onUpstreamCapabilitiesChanged(null)
- notificationUpdater.handler.waitForDelayedMessage(EVENT_SHOW_NO_UPSTREAM, TIMEOUT_MS)
- verifyNotification(NOTIFICATION_ICON_ID, TEST_NO_UPSTREAM_TITLE, TEST_NO_UPSTREAM_MESSAGE,
- NO_UPSTREAM_NOTIFICATION_ID, BROADCAST_PENDING_INTENT, disableIntent,
- FLAG_IMMUTABLE)
-
- // Same capabilities changed. Nothing happened.
- notificationUpdater.onUpstreamCapabilitiesChanged(null)
- verifyZeroInteractions(notificationManager)
-
- // Upstream come back. Clear no upstream notification.
- notificationUpdater.onUpstreamCapabilitiesChanged(HOME_CAPABILITIES)
- verifyNotificationCancelled(listOf(NO_UPSTREAM_NOTIFICATION_ID))
-
- // No upstream again. Show no upstream notification.
- notificationUpdater.onUpstreamCapabilitiesChanged(null)
- notificationUpdater.handler.waitForDelayedMessage(EVENT_SHOW_NO_UPSTREAM, TIMEOUT_MS)
- verifyNotification(NOTIFICATION_ICON_ID, TEST_NO_UPSTREAM_TITLE, TEST_NO_UPSTREAM_MESSAGE,
- NO_UPSTREAM_NOTIFICATION_ID, BROADCAST_PENDING_INTENT, disableIntent,
- FLAG_IMMUTABLE)
-
- // No downstream.
- notificationUpdater.onDownstreamChanged(DOWNSTREAM_NONE)
- verifyNotificationCancelled(listOf(NO_UPSTREAM_NOTIFICATION_ID, ROAMING_NOTIFICATION_ID))
-
- // Wifi downstream and home capabilities.
- notificationUpdater.onDownstreamChanged(WIFI_MASK)
- notificationUpdater.onUpstreamCapabilitiesChanged(HOME_CAPABILITIES)
- verifyNotificationCancelled(listOf(NO_UPSTREAM_NOTIFICATION_ID, ROAMING_NOTIFICATION_ID))
-
- // Set R.integer.delay_to_show_no_upstream_after_no_backhaul to -1 and change to no upstream
- // again. Don't put up no upstream notification.
- doReturn(-1).`when`(testResources)
- .getInteger(R.integer.delay_to_show_no_upstream_after_no_backhaul)
- notificationUpdater.onUpstreamCapabilitiesChanged(null)
- notificationUpdater.handler.waitForDelayedMessage(EVENT_SHOW_NO_UPSTREAM, TIMEOUT_MS)
- verifyNotificationCancelled(listOf(NO_UPSTREAM_NOTIFICATION_ID))
- }
-
- @Test
- fun testGetResourcesForSubId() {
- doReturn(telephonyManager).`when`(telephonyManager).createForSubscriptionId(anyInt())
- doReturn(1234).`when`(telephonyManager).getSimCarrierId()
- doReturn("000000").`when`(telephonyManager).getSimOperator()
-
- val subId = -2 // Use invalid subId to avoid getting resource from cache or real subId.
- val config = context.resources.configuration
- var res = notificationUpdater.getResourcesForSubId(context, subId)
- assertEquals(config.mcc, res.configuration.mcc)
- assertEquals(config.mnc, res.configuration.mnc)
-
- doReturn(VERIZON_CARRIER_ID).`when`(telephonyManager).getSimCarrierId()
- res = notificationUpdater.getResourcesForSubId(context, subId)
- assertEquals(config.mcc, res.configuration.mcc)
- assertEquals(config.mnc, res.configuration.mnc)
-
- doReturn("20404").`when`(telephonyManager).getSimOperator()
- res = notificationUpdater.getResourcesForSubId(context, subId)
- assertEquals(311, res.configuration.mcc)
- assertEquals(480, res.configuration.mnc)
- }
-
- @Test
- fun testRoamingNotification() {
- val disableIntent = Intent(ACTION_DISABLE_TETHERING).setPackage(context.packageName)
- val settingsIntent = Intent(Settings.ACTION_TETHER_SETTINGS)
- .setPackage(getSettingsPackageName(context.packageManager))
- .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
-
- // Set test sub id.
- notificationUpdater.onActiveDataSubscriptionIdChanged(TEST_SUBID)
- verifyNotificationCancelled(listOf(NO_UPSTREAM_NOTIFICATION_ID, ROAMING_NOTIFICATION_ID))
-
- // Wifi downstream.
- notificationUpdater.onDownstreamChanged(WIFI_MASK)
- verifyNotificationCancelled(listOf(NO_UPSTREAM_NOTIFICATION_ID, ROAMING_NOTIFICATION_ID))
-
- // Upstream capabilities changed to roaming state. Show roaming notification.
- notificationUpdater.onUpstreamCapabilitiesChanged(ROAMING_CAPABILITIES)
- verifyNotification(NOTIFICATION_ICON_ID, TEST_ROAMING_TITLE, TEST_ROAMING_MESSAGE,
- ROAMING_NOTIFICATION_ID, ACTIVITY_PENDING_INTENT, settingsIntent, FLAG_IMMUTABLE)
-
- // Same capabilities change. Nothing happened.
- notificationUpdater.onUpstreamCapabilitiesChanged(ROAMING_CAPABILITIES)
- verifyZeroInteractions(notificationManager)
-
- // Upstream capabilities changed to home state. Clear roaming notification.
- notificationUpdater.onUpstreamCapabilitiesChanged(HOME_CAPABILITIES)
- verifyNotificationCancelled(listOf(ROAMING_NOTIFICATION_ID))
-
- // Upstream capabilities changed to roaming state again. Show roaming notification.
- notificationUpdater.onUpstreamCapabilitiesChanged(ROAMING_CAPABILITIES)
- verifyNotification(NOTIFICATION_ICON_ID, TEST_ROAMING_TITLE, TEST_ROAMING_MESSAGE,
- ROAMING_NOTIFICATION_ID, ACTIVITY_PENDING_INTENT, settingsIntent, FLAG_IMMUTABLE)
-
- // No upstream. Clear roaming notification and show no upstream notification.
- notificationUpdater.onUpstreamCapabilitiesChanged(null)
- notificationUpdater.handler.waitForDelayedMessage(EVENT_SHOW_NO_UPSTREAM, TIMEOUT_MS)
- verifyNotificationCancelled(listOf(ROAMING_NOTIFICATION_ID), false)
- verifyNotification(NOTIFICATION_ICON_ID, TEST_NO_UPSTREAM_TITLE, TEST_NO_UPSTREAM_MESSAGE,
- NO_UPSTREAM_NOTIFICATION_ID, BROADCAST_PENDING_INTENT, disableIntent,
- FLAG_IMMUTABLE)
-
- // No downstream.
- notificationUpdater.onDownstreamChanged(DOWNSTREAM_NONE)
- verifyNotificationCancelled(listOf(NO_UPSTREAM_NOTIFICATION_ID, ROAMING_NOTIFICATION_ID))
-
- // Wifi downstream again.
- notificationUpdater.onDownstreamChanged(WIFI_MASK)
- notificationUpdater.handler.waitForDelayedMessage(EVENT_SHOW_NO_UPSTREAM, TIMEOUT_MS)
- verifyNotificationCancelled(listOf(ROAMING_NOTIFICATION_ID), false)
- verifyNotification(NOTIFICATION_ICON_ID, TEST_NO_UPSTREAM_TITLE, TEST_NO_UPSTREAM_MESSAGE,
- NO_UPSTREAM_NOTIFICATION_ID, BROADCAST_PENDING_INTENT, disableIntent,
- FLAG_IMMUTABLE)
-
- // Set R.bool.config_upstream_roaming_notification to false and change upstream
- // network to roaming state again. No roaming notification.
- doReturn(false).`when`(testResources)
- .getBoolean(R.bool.config_upstream_roaming_notification)
- notificationUpdater.onUpstreamCapabilitiesChanged(ROAMING_CAPABILITIES)
- verifyNotificationCancelled(listOf(NO_UPSTREAM_NOTIFICATION_ID, ROAMING_NOTIFICATION_ID))
- }
-
- @Test
- fun testGetSettingsPackageName() {
- val defaultSettingsPackageName = "com.android.settings"
- val testSettingsPackageName = "com.android.test.settings"
- val pm = mock(PackageManager::class.java)
- doReturn(null).`when`(pm).resolveActivity(any(), anyInt())
- assertEquals(defaultSettingsPackageName, getSettingsPackageName(pm))
-
- val resolveInfo = ResolveInfo().apply {
- activityInfo = ActivityInfo().apply {
- name = "test"
- applicationInfo = ApplicationInfo().apply {
- packageName = testSettingsPackageName
- }
- }
- }
- doReturn(resolveInfo).`when`(pm).resolveActivity(any(), anyInt())
- assertEquals(testSettingsPackageName, getSettingsPackageName(pm))
- }
-}
diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringServiceTest.java b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringServiceTest.java
deleted file mode 100644
index 7bba67b..0000000
--- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringServiceTest.java
+++ /dev/null
@@ -1,484 +0,0 @@
-/*
- * 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;
-
-import static android.Manifest.permission.ACCESS_NETWORK_STATE;
-import static android.Manifest.permission.TETHER_PRIVILEGED;
-import static android.Manifest.permission.WRITE_SETTINGS;
-import static android.net.TetheringManager.TETHERING_WIFI;
-import static android.net.TetheringManager.TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION;
-import static android.net.TetheringManager.TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION;
-import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
-
-import static org.junit.Assert.assertEquals;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.mockito.Mockito.when;
-
-import android.app.UiAutomation;
-import android.content.Intent;
-import android.net.IIntResultListener;
-import android.net.ITetheringConnector;
-import android.net.ITetheringEventCallback;
-import android.net.TetheringRequestParcel;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.ResultReceiver;
-
-import androidx.test.InstrumentationRegistry;
-import androidx.test.filters.SmallTest;
-import androidx.test.rule.ServiceTestRule;
-import androidx.test.runner.AndroidJUnit4;
-
-import com.android.networkstack.tethering.MockTetheringService.MockTetheringConnector;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public final class TetheringServiceTest {
- private static final String TEST_IFACE_NAME = "test_wlan0";
- private static final String TEST_CALLER_PKG = "com.android.shell";
- private static final String TEST_ATTRIBUTION_TAG = null;
- @Mock private ITetheringEventCallback mITetheringEventCallback;
- @Rule public ServiceTestRule mServiceTestRule;
- private Tethering mTethering;
- private Intent mMockServiceIntent;
- private ITetheringConnector mTetheringConnector;
- private UiAutomation mUiAutomation;
-
- private class TestTetheringResult extends IIntResultListener.Stub {
- private int mResult = -1; // Default value that does not match any result code.
- @Override
- public void onResult(final int resultCode) {
- mResult = resultCode;
- }
-
- public void assertResult(final int expected) {
- assertEquals(expected, mResult);
- }
- }
-
- private class MyResultReceiver extends ResultReceiver {
- MyResultReceiver(Handler handler) {
- super(handler);
- }
- private int mResult = -1; // Default value that does not match any result code.
- @Override
- protected void onReceiveResult(int resultCode, Bundle resultData) {
- mResult = resultCode;
- }
-
- public void assertResult(int expected) {
- assertEquals(expected, mResult);
- }
- }
-
- @Before
- public void setUp() throws Exception {
- MockitoAnnotations.initMocks(this);
- mUiAutomation =
- InstrumentationRegistry.getInstrumentation().getUiAutomation();
- mServiceTestRule = new ServiceTestRule();
- mMockServiceIntent = new Intent(
- InstrumentationRegistry.getTargetContext(),
- MockTetheringService.class);
- final MockTetheringConnector mockConnector =
- (MockTetheringConnector) mServiceTestRule.bindService(mMockServiceIntent);
- mTetheringConnector = mockConnector.getTetheringConnector();
- final MockTetheringService service = mockConnector.getService();
- mTethering = service.getTethering();
- }
-
- @After
- public void tearDown() throws Exception {
- mServiceTestRule.unbindService();
- mUiAutomation.dropShellPermissionIdentity();
- }
-
- private interface TestTetheringCall {
- void runTetheringCall(TestTetheringResult result) throws Exception;
- }
-
- private void runAsNoPermission(final TestTetheringCall test) throws Exception {
- runTetheringCall(test, new String[0]);
- }
-
- private void runAsTetherPrivileged(final TestTetheringCall test) throws Exception {
- runTetheringCall(test, TETHER_PRIVILEGED);
- }
-
- private void runAsAccessNetworkState(final TestTetheringCall test) throws Exception {
- runTetheringCall(test, ACCESS_NETWORK_STATE);
- }
-
- private void runAsWriteSettings(final TestTetheringCall test) throws Exception {
- runTetheringCall(test, WRITE_SETTINGS);
- }
-
- private void runTetheringCall(final TestTetheringCall test, String... permissions)
- throws Exception {
- if (permissions.length > 0) mUiAutomation.adoptShellPermissionIdentity(permissions);
- try {
- when(mTethering.isTetheringSupported()).thenReturn(true);
- test.runTetheringCall(new TestTetheringResult());
- } finally {
- mUiAutomation.dropShellPermissionIdentity();
- }
- }
-
- private void verifyNoMoreInteractionsForTethering() {
- verifyNoMoreInteractions(mTethering);
- verifyNoMoreInteractions(mITetheringEventCallback);
- reset(mTethering, mITetheringEventCallback);
- }
-
- private void runTether(final TestTetheringResult result) throws Exception {
- when(mTethering.tether(TEST_IFACE_NAME)).thenReturn(TETHER_ERROR_NO_ERROR);
- mTetheringConnector.tether(TEST_IFACE_NAME, TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG, result);
- verify(mTethering).isTetheringSupported();
- verify(mTethering).tether(TEST_IFACE_NAME);
- result.assertResult(TETHER_ERROR_NO_ERROR);
- }
-
- @Test
- public void testTether() throws Exception {
- runAsNoPermission((result) -> {
- mTetheringConnector.tether(TEST_IFACE_NAME, TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG,
- result);
- verify(mTethering).isTetherProvisioningRequired();
- result.assertResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION);
- verifyNoMoreInteractionsForTethering();
- });
-
- runAsTetherPrivileged((result) -> {
- runTether(result);
- verifyNoMoreInteractionsForTethering();
- });
-
- runAsWriteSettings((result) -> {
- runTether(result);
- verify(mTethering).isTetherProvisioningRequired();
- verifyNoMoreInteractionsForTethering();
- });
- }
-
- private void runUnTether(final TestTetheringResult result) throws Exception {
- when(mTethering.untether(TEST_IFACE_NAME)).thenReturn(TETHER_ERROR_NO_ERROR);
- mTetheringConnector.untether(TEST_IFACE_NAME, TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG,
- result);
- verify(mTethering).isTetheringSupported();
- verify(mTethering).untether(TEST_IFACE_NAME);
- result.assertResult(TETHER_ERROR_NO_ERROR);
- }
-
- @Test
- public void testUntether() throws Exception {
- runAsNoPermission((result) -> {
- mTetheringConnector.untether(TEST_IFACE_NAME, TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG,
- result);
- verify(mTethering).isTetherProvisioningRequired();
- result.assertResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION);
- verifyNoMoreInteractionsForTethering();
- });
-
- runAsTetherPrivileged((result) -> {
- runUnTether(result);
- verifyNoMoreInteractionsForTethering();
- });
-
- runAsWriteSettings((result) -> {
- runUnTether(result);
- verify(mTethering).isTetherProvisioningRequired();
- verifyNoMoreInteractionsForTethering();
- });
- }
-
- private void runSetUsbTethering(final TestTetheringResult result) throws Exception {
- when(mTethering.setUsbTethering(true /* enable */)).thenReturn(TETHER_ERROR_NO_ERROR);
- mTetheringConnector.setUsbTethering(true /* enable */, TEST_CALLER_PKG,
- TEST_ATTRIBUTION_TAG, result);
- verify(mTethering).isTetheringSupported();
- verify(mTethering).setUsbTethering(true /* enable */);
- result.assertResult(TETHER_ERROR_NO_ERROR);
- }
-
- @Test
- public void testSetUsbTethering() throws Exception {
- runAsNoPermission((result) -> {
- mTetheringConnector.setUsbTethering(true /* enable */, TEST_CALLER_PKG,
- TEST_ATTRIBUTION_TAG, result);
- verify(mTethering).isTetherProvisioningRequired();
- result.assertResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION);
- verifyNoMoreInteractionsForTethering();
- });
-
- runAsTetherPrivileged((result) -> {
- runSetUsbTethering(result);
- verifyNoMoreInteractionsForTethering();
- });
-
- runAsWriteSettings((result) -> {
- runSetUsbTethering(result);
- verify(mTethering).isTetherProvisioningRequired();
- verifyNoMoreInteractionsForTethering();
- });
-
- }
-
- private void runStartTethering(final TestTetheringResult result,
- final TetheringRequestParcel request) throws Exception {
- mTetheringConnector.startTethering(request, TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG,
- result);
- verify(mTethering).isTetheringSupported();
- verify(mTethering).startTethering(eq(request), eq(result));
- }
-
- @Test
- public void testStartTethering() throws Exception {
- final TetheringRequestParcel request = new TetheringRequestParcel();
- request.tetheringType = TETHERING_WIFI;
-
- runAsNoPermission((result) -> {
- mTetheringConnector.startTethering(request, TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG,
- result);
- verify(mTethering).isTetherProvisioningRequired();
- result.assertResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION);
- verifyNoMoreInteractionsForTethering();
- });
-
- runAsTetherPrivileged((result) -> {
- runStartTethering(result, request);
- verifyNoMoreInteractionsForTethering();
- });
-
- runAsWriteSettings((result) -> {
- runStartTethering(result, request);
- verify(mTethering).isTetherProvisioningRequired();
- verifyNoMoreInteractionsForTethering();
- });
- }
-
- private void runStartTetheringAndVerifyNoPermission(final TestTetheringResult result)
- throws Exception {
- final TetheringRequestParcel request = new TetheringRequestParcel();
- request.tetheringType = TETHERING_WIFI;
- request.exemptFromEntitlementCheck = true;
- mTetheringConnector.startTethering(request, TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG,
- result);
- result.assertResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION);
- verifyNoMoreInteractionsForTethering();
- }
-
- @Test
- public void testFailToBypassEntitlementWithoutNeworkStackPermission() throws Exception {
- final TetheringRequestParcel request = new TetheringRequestParcel();
- request.tetheringType = TETHERING_WIFI;
- request.exemptFromEntitlementCheck = true;
-
- runAsNoPermission((result) -> {
- runStartTetheringAndVerifyNoPermission(result);
- });
-
- runAsTetherPrivileged((result) -> {
- runStartTetheringAndVerifyNoPermission(result);
- });
-
- runAsWriteSettings((result) -> {
- runStartTetheringAndVerifyNoPermission(result);
- });
- }
-
- private void runStopTethering(final TestTetheringResult result) throws Exception {
- mTetheringConnector.stopTethering(TETHERING_WIFI, TEST_CALLER_PKG,
- TEST_ATTRIBUTION_TAG, result);
- verify(mTethering).isTetheringSupported();
- verify(mTethering).stopTethering(TETHERING_WIFI);
- result.assertResult(TETHER_ERROR_NO_ERROR);
- }
-
- @Test
- public void testStopTethering() throws Exception {
- runAsNoPermission((result) -> {
- mTetheringConnector.stopTethering(TETHERING_WIFI, TEST_CALLER_PKG,
- TEST_ATTRIBUTION_TAG, result);
- verify(mTethering).isTetherProvisioningRequired();
- result.assertResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION);
- verifyNoMoreInteractionsForTethering();
- });
-
- runAsTetherPrivileged((result) -> {
- runStopTethering(result);
- verifyNoMoreInteractionsForTethering();
- });
-
- runAsWriteSettings((result) -> {
- runStopTethering(result);
- verify(mTethering).isTetherProvisioningRequired();
- verifyNoMoreInteractionsForTethering();
- });
- }
-
- private void runRequestLatestTetheringEntitlementResult() throws Exception {
- final MyResultReceiver result = new MyResultReceiver(null);
- mTetheringConnector.requestLatestTetheringEntitlementResult(TETHERING_WIFI, result,
- true /* showEntitlementUi */, TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG);
- verify(mTethering).isTetheringSupported();
- verify(mTethering).requestLatestTetheringEntitlementResult(eq(TETHERING_WIFI),
- eq(result), eq(true) /* showEntitlementUi */);
- }
-
- @Test
- public void testRequestLatestTetheringEntitlementResult() throws Exception {
- // Run as no permission.
- final MyResultReceiver result = new MyResultReceiver(null);
- mTetheringConnector.requestLatestTetheringEntitlementResult(TETHERING_WIFI, result,
- true /* showEntitlementUi */, TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG);
- verify(mTethering).isTetherProvisioningRequired();
- result.assertResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION);
- verifyNoMoreInteractions(mTethering);
-
- runAsTetherPrivileged((none) -> {
- runRequestLatestTetheringEntitlementResult();
- verifyNoMoreInteractionsForTethering();
- });
-
- runAsWriteSettings((none) -> {
- runRequestLatestTetheringEntitlementResult();
- verify(mTethering).isTetherProvisioningRequired();
- verifyNoMoreInteractionsForTethering();
- });
- }
-
- private void runRegisterTetheringEventCallback() throws Exception {
- mTetheringConnector.registerTetheringEventCallback(mITetheringEventCallback,
- TEST_CALLER_PKG);
- verify(mTethering).registerTetheringEventCallback(eq(mITetheringEventCallback));
- }
-
- @Test
- public void testRegisterTetheringEventCallback() throws Exception {
- runAsNoPermission((result) -> {
- mTetheringConnector.registerTetheringEventCallback(mITetheringEventCallback,
- TEST_CALLER_PKG);
- verify(mITetheringEventCallback).onCallbackStopped(
- TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION);
- verifyNoMoreInteractionsForTethering();
- });
-
- runAsTetherPrivileged((none) -> {
- runRegisterTetheringEventCallback();
- verifyNoMoreInteractionsForTethering();
- });
-
- runAsAccessNetworkState((none) -> {
- runRegisterTetheringEventCallback();
- verifyNoMoreInteractionsForTethering();
- });
- }
-
- private void runUnregisterTetheringEventCallback() throws Exception {
- mTetheringConnector.unregisterTetheringEventCallback(mITetheringEventCallback,
- TEST_CALLER_PKG);
- verify(mTethering).unregisterTetheringEventCallback(eq(mITetheringEventCallback));
- }
-
- @Test
- public void testUnregisterTetheringEventCallback() throws Exception {
- runAsNoPermission((result) -> {
- mTetheringConnector.unregisterTetheringEventCallback(mITetheringEventCallback,
- TEST_CALLER_PKG);
- verify(mITetheringEventCallback).onCallbackStopped(
- TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION);
- verifyNoMoreInteractionsForTethering();
- });
-
- runAsTetherPrivileged((none) -> {
- runUnregisterTetheringEventCallback();
- verifyNoMoreInteractionsForTethering();
- });
-
- runAsAccessNetworkState((none) -> {
- runUnregisterTetheringEventCallback();
- verifyNoMoreInteractionsForTethering();
- });
- }
-
- private void runStopAllTethering(final TestTetheringResult result) throws Exception {
- mTetheringConnector.stopAllTethering(TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG, result);
- verify(mTethering).isTetheringSupported();
- verify(mTethering).untetherAll();
- result.assertResult(TETHER_ERROR_NO_ERROR);
- }
-
- @Test
- public void testStopAllTethering() throws Exception {
- runAsNoPermission((result) -> {
- mTetheringConnector.stopAllTethering(TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG, result);
- verify(mTethering).isTetherProvisioningRequired();
- result.assertResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION);
- verifyNoMoreInteractionsForTethering();
- });
-
- runAsTetherPrivileged((result) -> {
- runStopAllTethering(result);
- verifyNoMoreInteractionsForTethering();
- });
-
- runAsWriteSettings((result) -> {
- runStopAllTethering(result);
- verify(mTethering).isTetherProvisioningRequired();
- verifyNoMoreInteractionsForTethering();
- });
- }
-
- private void runIsTetheringSupported(final TestTetheringResult result) throws Exception {
- mTetheringConnector.isTetheringSupported(TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG, result);
- verify(mTethering).isTetheringSupported();
- result.assertResult(TETHER_ERROR_NO_ERROR);
- }
-
- @Test
- public void testIsTetheringSupported() throws Exception {
- runAsNoPermission((result) -> {
- mTetheringConnector.isTetheringSupported(TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG,
- result);
- verify(mTethering).isTetherProvisioningRequired();
- result.assertResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION);
- verifyNoMoreInteractionsForTethering();
- });
-
- runAsTetherPrivileged((result) -> {
- runIsTetheringSupported(result);
- verifyNoMoreInteractionsForTethering();
- });
-
- runAsWriteSettings((result) -> {
- runIsTetheringSupported(result);
- verify(mTethering).isTetherProvisioningRequired();
- verifyNoMoreInteractionsForTethering();
- });
- }
-}
diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
deleted file mode 100644
index 114cb7c..0000000
--- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
+++ /dev/null
@@ -1,2019 +0,0 @@
-/*
- * Copyright (C) 2016 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;
-
-import static android.content.pm.PackageManager.GET_ACTIVITIES;
-import static android.hardware.usb.UsbManager.USB_CONFIGURED;
-import static android.hardware.usb.UsbManager.USB_CONNECTED;
-import static android.hardware.usb.UsbManager.USB_FUNCTION_NCM;
-import static android.hardware.usb.UsbManager.USB_FUNCTION_RNDIS;
-import static android.net.ConnectivityManager.ACTION_RESTRICT_BACKGROUND_CHANGED;
-import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_DISABLED;
-import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_ENABLED;
-import static android.net.NetworkCapabilities.TRANSPORT_BLUETOOTH;
-import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
-import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
-import static android.net.RouteInfo.RTN_UNICAST;
-import static android.net.TetheringManager.ACTION_TETHER_STATE_CHANGED;
-import static android.net.TetheringManager.EXTRA_ACTIVE_LOCAL_ONLY;
-import static android.net.TetheringManager.EXTRA_ACTIVE_TETHER;
-import static android.net.TetheringManager.EXTRA_AVAILABLE_TETHER;
-import static android.net.TetheringManager.TETHERING_ETHERNET;
-import static android.net.TetheringManager.TETHERING_NCM;
-import static android.net.TetheringManager.TETHERING_USB;
-import static android.net.TetheringManager.TETHERING_WIFI;
-import static android.net.TetheringManager.TETHER_ERROR_IFACE_CFG_ERROR;
-import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
-import static android.net.TetheringManager.TETHER_ERROR_UNKNOWN_IFACE;
-import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_FAILED;
-import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_STARTED;
-import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_STOPPED;
-import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS;
-import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME;
-import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_MODE;
-import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_STATE;
-import static android.net.wifi.WifiManager.IFACE_IP_MODE_LOCAL_ONLY;
-import static android.net.wifi.WifiManager.IFACE_IP_MODE_TETHERED;
-import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLED;
-import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
-
-import static com.android.net.module.util.Inet4AddressUtils.intToInet4AddressHTH;
-import static com.android.networkstack.tethering.TetheringNotificationUpdater.DOWNSTREAM_NONE;
-import static com.android.networkstack.tethering.UpstreamNetworkMonitor.EVENT_ON_CAPABILITIES;
-
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import static org.mockito.ArgumentMatchers.argThat;
-import static org.mockito.ArgumentMatchers.notNull;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.doThrow;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.timeout;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.mockito.Mockito.when;
-
-import android.app.usage.NetworkStatsManager;
-import android.bluetooth.BluetoothAdapter;
-import android.content.BroadcastReceiver;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.content.res.Resources;
-import android.hardware.usb.UsbManager;
-import android.net.ConnectivityManager;
-import android.net.EthernetManager;
-import android.net.EthernetManager.TetheredInterfaceCallback;
-import android.net.EthernetManager.TetheredInterfaceRequest;
-import android.net.IIntResultListener;
-import android.net.INetd;
-import android.net.ITetheringEventCallback;
-import android.net.InetAddresses;
-import android.net.InterfaceConfigurationParcel;
-import android.net.IpPrefix;
-import android.net.LinkAddress;
-import android.net.LinkProperties;
-import android.net.MacAddress;
-import android.net.Network;
-import android.net.NetworkCapabilities;
-import android.net.NetworkRequest;
-import android.net.RouteInfo;
-import android.net.TetherStatesParcel;
-import android.net.TetheredClient;
-import android.net.TetheringCallbackStartedParcel;
-import android.net.TetheringConfigurationParcel;
-import android.net.TetheringRequestParcel;
-import android.net.dhcp.DhcpServerCallbacks;
-import android.net.dhcp.DhcpServingParamsParcel;
-import android.net.dhcp.IDhcpServer;
-import android.net.ip.DadProxy;
-import android.net.ip.IpNeighborMonitor;
-import android.net.ip.IpServer;
-import android.net.ip.RouterAdvertisementDaemon;
-import android.net.util.InterfaceParams;
-import android.net.util.NetworkConstants;
-import android.net.util.SharedLog;
-import android.net.wifi.SoftApConfiguration;
-import android.net.wifi.WifiManager;
-import android.net.wifi.p2p.WifiP2pGroup;
-import android.net.wifi.p2p.WifiP2pInfo;
-import android.net.wifi.p2p.WifiP2pManager;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.PersistableBundle;
-import android.os.RemoteException;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.os.test.TestLooper;
-import android.provider.Settings;
-import android.telephony.CarrierConfigManager;
-import android.telephony.PhoneStateListener;
-import android.telephony.TelephonyManager;
-import android.test.mock.MockContentResolver;
-
-import androidx.annotation.NonNull;
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import com.android.internal.util.ArrayUtils;
-import com.android.internal.util.StateMachine;
-import com.android.internal.util.test.BroadcastInterceptingContext;
-import com.android.internal.util.test.FakeSettingsProvider;
-import com.android.testutils.MiscAsserts;
-
-import org.junit.After;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.net.Inet4Address;
-import java.net.Inet6Address;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-import java.util.Vector;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class TetheringTest {
- private static final int IFINDEX_OFFSET = 100;
-
- private static final String TEST_MOBILE_IFNAME = "test_rmnet_data0";
- private static final String TEST_XLAT_MOBILE_IFNAME = "v4-test_rmnet_data0";
- private static final String TEST_USB_IFNAME = "test_rndis0";
- private static final String TEST_WIFI_IFNAME = "test_wlan0";
- private static final String TEST_WLAN_IFNAME = "test_wlan1";
- private static final String TEST_P2P_IFNAME = "test_p2p-p2p0-0";
- private static final String TEST_NCM_IFNAME = "test_ncm0";
- private static final String TEST_ETH_IFNAME = "test_eth0";
- private static final String TEST_BT_IFNAME = "test_pan0";
- private static final String TETHERING_NAME = "Tethering";
- private static final String[] PROVISIONING_APP_NAME = {"some", "app"};
- private static final String PROVISIONING_NO_UI_APP_NAME = "no_ui_app";
-
- private static final int DHCPSERVER_START_TIMEOUT_MS = 1000;
-
- @Mock private ApplicationInfo mApplicationInfo;
- @Mock private Context mContext;
- @Mock private NetworkStatsManager mStatsManager;
- @Mock private OffloadHardwareInterface mOffloadHardwareInterface;
- @Mock private OffloadHardwareInterface.ForwardedStats mForwardedStats;
- @Mock private Resources mResources;
- @Mock private TelephonyManager mTelephonyManager;
- @Mock private UsbManager mUsbManager;
- @Mock private WifiManager mWifiManager;
- @Mock private CarrierConfigManager mCarrierConfigManager;
- @Mock private UpstreamNetworkMonitor mUpstreamNetworkMonitor;
- @Mock private IPv6TetheringCoordinator mIPv6TetheringCoordinator;
- @Mock private DadProxy mDadProxy;
- @Mock private RouterAdvertisementDaemon mRouterAdvertisementDaemon;
- @Mock private IpNeighborMonitor mIpNeighborMonitor;
- @Mock private IDhcpServer mDhcpServer;
- @Mock private INetd mNetd;
- @Mock private UserManager mUserManager;
- @Mock private NetworkRequest mNetworkRequest;
- @Mock private ConnectivityManager mCm;
- @Mock private EthernetManager mEm;
- @Mock private TetheringNotificationUpdater mNotificationUpdater;
- @Mock private BpfCoordinator mBpfCoordinator;
- @Mock private PackageManager mPackageManager;
-
- private final MockIpServerDependencies mIpServerDependencies =
- spy(new MockIpServerDependencies());
- private final MockTetheringDependencies mTetheringDependencies =
- new MockTetheringDependencies();
-
- // Like so many Android system APIs, these cannot be mocked because it is marked final.
- // We have to use the real versions.
- private final PersistableBundle mCarrierConfig = new PersistableBundle();
- private final TestLooper mLooper = new TestLooper();
-
- private Vector<Intent> mIntents;
- private BroadcastInterceptingContext mServiceContext;
- private MockContentResolver mContentResolver;
- private BroadcastReceiver mBroadcastReceiver;
- private Tethering mTethering;
- private PhoneStateListener mPhoneStateListener;
- private InterfaceConfigurationParcel mInterfaceConfiguration;
- private TetheringConfiguration mConfig;
- private EntitlementManager mEntitleMgr;
- private OffloadController mOffloadCtrl;
- private PrivateAddressCoordinator mPrivateAddressCoordinator;
-
- private class TestContext extends BroadcastInterceptingContext {
- TestContext(Context base) {
- super(base);
- }
-
- @Override
- public ApplicationInfo getApplicationInfo() {
- return mApplicationInfo;
- }
-
- @Override
- public ContentResolver getContentResolver() {
- return mContentResolver;
- }
-
- @Override
- public String getPackageName() {
- return "TetheringTest";
- }
-
- @Override
- public Resources getResources() {
- return mResources;
- }
-
- @Override
- public Object getSystemService(String name) {
- if (Context.WIFI_SERVICE.equals(name)) return mWifiManager;
- if (Context.USB_SERVICE.equals(name)) return mUsbManager;
- if (Context.TELEPHONY_SERVICE.equals(name)) return mTelephonyManager;
- if (Context.USER_SERVICE.equals(name)) return mUserManager;
- if (Context.NETWORK_STATS_SERVICE.equals(name)) return mStatsManager;
- if (Context.CONNECTIVITY_SERVICE.equals(name)) return mCm;
- if (Context.ETHERNET_SERVICE.equals(name)) return mEm;
- return super.getSystemService(name);
- }
-
- @Override
- public PackageManager getPackageManager() {
- return mPackageManager;
- }
-
- @Override
- public String getSystemServiceName(Class<?> serviceClass) {
- if (TelephonyManager.class.equals(serviceClass)) return Context.TELEPHONY_SERVICE;
- return super.getSystemServiceName(serviceClass);
- }
- }
-
- public class MockIpServerDependencies extends IpServer.Dependencies {
- @Override
- public DadProxy getDadProxy(
- Handler handler, InterfaceParams ifParams) {
- return mDadProxy;
- }
-
- @Override
- public RouterAdvertisementDaemon getRouterAdvertisementDaemon(
- InterfaceParams ifParams) {
- return mRouterAdvertisementDaemon;
- }
-
- @Override
- public InterfaceParams getInterfaceParams(String ifName) {
- assertTrue("Non-mocked interface " + ifName,
- ifName.equals(TEST_USB_IFNAME)
- || ifName.equals(TEST_WLAN_IFNAME)
- || ifName.equals(TEST_MOBILE_IFNAME)
- || ifName.equals(TEST_P2P_IFNAME)
- || ifName.equals(TEST_NCM_IFNAME)
- || ifName.equals(TEST_ETH_IFNAME));
- final String[] ifaces = new String[] {
- TEST_USB_IFNAME, TEST_WLAN_IFNAME, TEST_MOBILE_IFNAME, TEST_P2P_IFNAME,
- TEST_NCM_IFNAME, TEST_ETH_IFNAME};
- return new InterfaceParams(ifName, ArrayUtils.indexOf(ifaces, ifName) + IFINDEX_OFFSET,
- MacAddress.ALL_ZEROS_ADDRESS);
- }
-
- @Override
- public void makeDhcpServer(String ifName, DhcpServingParamsParcel params,
- DhcpServerCallbacks cb) {
- new Thread(() -> {
- try {
- cb.onDhcpServerCreated(STATUS_SUCCESS, mDhcpServer);
- } catch (RemoteException e) {
- fail(e.getMessage());
- }
- }).run();
- }
-
- public IpNeighborMonitor getIpNeighborMonitor(Handler h, SharedLog l,
- IpNeighborMonitor.NeighborEventConsumer c) {
- return mIpNeighborMonitor;
- }
- }
-
- // MyTetheringConfiguration is used to override static method for testing.
- private class MyTetheringConfiguration extends TetheringConfiguration {
- MyTetheringConfiguration(Context ctx, SharedLog log, int id) {
- super(ctx, log, id);
- }
-
- @Override
- protected String getDeviceConfigProperty(final String name) {
- return null;
- }
-
- @Override
- protected Resources getResourcesForSubIdWrapper(Context ctx, int subId) {
- return mResources;
- }
- }
-
- public class MockTetheringDependencies extends TetheringDependencies {
- StateMachine mUpstreamNetworkMonitorSM;
- ArrayList<IpServer> mIpv6CoordinatorNotifyList;
-
- public void reset() {
- mUpstreamNetworkMonitorSM = null;
- mIpv6CoordinatorNotifyList = null;
- }
-
- @Override
- public BpfCoordinator getBpfCoordinator(
- BpfCoordinator.Dependencies deps) {
- return mBpfCoordinator;
- }
-
- @Override
- public OffloadHardwareInterface getOffloadHardwareInterface(Handler h, SharedLog log) {
- return mOffloadHardwareInterface;
- }
-
- @Override
- public OffloadController getOffloadController(Handler h, SharedLog log,
- OffloadController.Dependencies deps) {
- mOffloadCtrl = spy(super.getOffloadController(h, log, deps));
- // Return real object here instead of mock because
- // testReportFailCallbackIfOffloadNotSupported depend on real OffloadController object.
- return mOffloadCtrl;
- }
-
- @Override
- public UpstreamNetworkMonitor getUpstreamNetworkMonitor(Context ctx,
- StateMachine target, SharedLog log, int what) {
- mUpstreamNetworkMonitorSM = target;
- return mUpstreamNetworkMonitor;
- }
-
- @Override
- public IPv6TetheringCoordinator getIPv6TetheringCoordinator(
- ArrayList<IpServer> notifyList, SharedLog log) {
- mIpv6CoordinatorNotifyList = notifyList;
- return mIPv6TetheringCoordinator;
- }
-
- @Override
- public IpServer.Dependencies getIpServerDependencies() {
- return mIpServerDependencies;
- }
-
- @Override
- public NetworkRequest getDefaultNetworkRequest() {
- return mNetworkRequest;
- }
-
- @Override
- public EntitlementManager getEntitlementManager(Context ctx, Handler h, SharedLog log,
- Runnable callback) {
- mEntitleMgr = spy(super.getEntitlementManager(ctx, h, log, callback));
- return mEntitleMgr;
- }
-
- @Override
- public boolean isTetheringSupported() {
- return true;
- }
-
- @Override
- public TetheringConfiguration generateTetheringConfiguration(Context ctx, SharedLog log,
- int subId) {
- mConfig = spy(new MyTetheringConfiguration(ctx, log, subId));
- return mConfig;
- }
-
- @Override
- public INetd getINetd(Context context) {
- return mNetd;
- }
-
- @Override
- public Looper getTetheringLooper() {
- return mLooper.getLooper();
- }
-
- @Override
- public Context getContext() {
- return mServiceContext;
- }
-
- @Override
- public BluetoothAdapter getBluetoothAdapter() {
- // TODO: add test for bluetooth tethering.
- return null;
- }
-
- @Override
- public TetheringNotificationUpdater getNotificationUpdater(Context ctx, Looper looper) {
- return mNotificationUpdater;
- }
-
- @Override
- public boolean isTetheringDenied() {
- return false;
- }
-
-
- @Override
- public PrivateAddressCoordinator getPrivateAddressCoordinator(Context ctx,
- TetheringConfiguration cfg) {
- mPrivateAddressCoordinator = super.getPrivateAddressCoordinator(ctx, cfg);
- return mPrivateAddressCoordinator;
- }
- }
-
- private static UpstreamNetworkState buildMobileUpstreamState(boolean withIPv4,
- boolean withIPv6, boolean with464xlat) {
- final LinkProperties prop = new LinkProperties();
- prop.setInterfaceName(TEST_MOBILE_IFNAME);
-
- if (withIPv4) {
- prop.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0),
- InetAddresses.parseNumericAddress("10.0.0.1"),
- TEST_MOBILE_IFNAME, RTN_UNICAST));
- }
-
- if (withIPv6) {
- prop.addDnsServer(InetAddresses.parseNumericAddress("2001:db8::2"));
- prop.addLinkAddress(
- new LinkAddress(InetAddresses.parseNumericAddress("2001:db8::"),
- NetworkConstants.RFC7421_PREFIX_LENGTH));
- prop.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0),
- InetAddresses.parseNumericAddress("2001:db8::1"),
- TEST_MOBILE_IFNAME, RTN_UNICAST));
- }
-
- if (with464xlat) {
- final LinkProperties stackedLink = new LinkProperties();
- stackedLink.setInterfaceName(TEST_XLAT_MOBILE_IFNAME);
- stackedLink.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0),
- InetAddresses.parseNumericAddress("192.0.0.1"),
- TEST_XLAT_MOBILE_IFNAME, RTN_UNICAST));
-
- prop.addStackedLink(stackedLink);
- }
-
-
- final NetworkCapabilities capabilities = new NetworkCapabilities()
- .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
- return new UpstreamNetworkState(prop, capabilities, new Network(100));
- }
-
- private static UpstreamNetworkState buildMobileIPv4UpstreamState() {
- return buildMobileUpstreamState(true, false, false);
- }
-
- private static UpstreamNetworkState buildMobileIPv6UpstreamState() {
- return buildMobileUpstreamState(false, true, false);
- }
-
- private static UpstreamNetworkState buildMobileDualStackUpstreamState() {
- return buildMobileUpstreamState(true, true, false);
- }
-
- private static UpstreamNetworkState buildMobile464xlatUpstreamState() {
- return buildMobileUpstreamState(false, true, true);
- }
-
- // See FakeSettingsProvider#clearSettingsProvider() that this needs to be called before and
- // after use.
- @BeforeClass
- public static void setupOnce() {
- FakeSettingsProvider.clearSettingsProvider();
- }
-
- @AfterClass
- public static void tearDownOnce() {
- FakeSettingsProvider.clearSettingsProvider();
- }
-
- @Before
- public void setUp() throws Exception {
- MockitoAnnotations.initMocks(this);
- when(mResources.getStringArray(R.array.config_tether_dhcp_range))
- .thenReturn(new String[0]);
- when(mResources.getBoolean(R.bool.config_tether_enable_legacy_dhcp_server)).thenReturn(
- false);
- when(mNetd.interfaceGetList())
- .thenReturn(new String[] {
- TEST_MOBILE_IFNAME, TEST_WLAN_IFNAME, TEST_USB_IFNAME, TEST_P2P_IFNAME,
- TEST_NCM_IFNAME, TEST_ETH_IFNAME});
- when(mResources.getString(R.string.config_wifi_tether_enable)).thenReturn("");
- mInterfaceConfiguration = new InterfaceConfigurationParcel();
- mInterfaceConfiguration.flags = new String[0];
- when(mRouterAdvertisementDaemon.start())
- .thenReturn(true);
- initOffloadConfiguration(true /* offloadConfig */, true /* offloadControl */,
- 0 /* defaultDisabled */);
- when(mOffloadHardwareInterface.getForwardedStats(any())).thenReturn(mForwardedStats);
-
- mServiceContext = new TestContext(mContext);
- mContentResolver = new MockContentResolver(mServiceContext);
- mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
- setTetheringSupported(true /* supported */);
- mIntents = new Vector<>();
- mBroadcastReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- mIntents.addElement(intent);
- }
- };
- mServiceContext.registerReceiver(mBroadcastReceiver,
- new IntentFilter(ACTION_TETHER_STATE_CHANGED));
- mTethering = makeTethering();
- verify(mStatsManager, times(1)).registerNetworkStatsProvider(anyString(), any());
- verify(mNetd).registerUnsolicitedEventListener(any());
- final ArgumentCaptor<PhoneStateListener> phoneListenerCaptor =
- ArgumentCaptor.forClass(PhoneStateListener.class);
- verify(mTelephonyManager).listen(phoneListenerCaptor.capture(),
- eq(PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE));
- verify(mWifiManager).registerSoftApCallback(any(), any());
- mPhoneStateListener = phoneListenerCaptor.getValue();
- }
-
- private void setTetheringSupported(final boolean supported) {
- Settings.Global.putInt(mContentResolver, Settings.Global.TETHER_SUPPORTED,
- supported ? 1 : 0);
- when(mUserManager.hasUserRestriction(
- UserManager.DISALLOW_CONFIG_TETHERING)).thenReturn(!supported);
- // Setup tetherable configuration.
- when(mResources.getStringArray(R.array.config_tether_usb_regexs))
- .thenReturn(new String[] { "test_rndis\\d" });
- when(mResources.getStringArray(R.array.config_tether_wifi_regexs))
- .thenReturn(new String[]{ "test_wlan\\d" });
- when(mResources.getStringArray(R.array.config_tether_wifi_p2p_regexs))
- .thenReturn(new String[]{ "test_p2p-p2p\\d-.*" });
- when(mResources.getStringArray(R.array.config_tether_bluetooth_regexs))
- .thenReturn(new String[0]);
- when(mResources.getStringArray(R.array.config_tether_ncm_regexs))
- .thenReturn(new String[] { "test_ncm\\d" });
- when(mResources.getIntArray(R.array.config_tether_upstream_types)).thenReturn(new int[0]);
- when(mResources.getBoolean(R.bool.config_tether_upstream_automatic)).thenReturn(true);
- }
-
- private void initTetheringUpstream(UpstreamNetworkState upstreamState) {
- when(mUpstreamNetworkMonitor.getCurrentPreferredUpstream()).thenReturn(upstreamState);
- when(mUpstreamNetworkMonitor.selectPreferredUpstreamType(any())).thenReturn(upstreamState);
- }
-
- private Tethering makeTethering() {
- mTetheringDependencies.reset();
- return new Tethering(mTetheringDependencies);
- }
-
- private TetheringRequestParcel createTetheringRequestParcel(final int type) {
- return createTetheringRequestParcel(type, null, null, false);
- }
-
- private TetheringRequestParcel createTetheringRequestParcel(final int type,
- final LinkAddress serverAddr, final LinkAddress clientAddr, final boolean exempt) {
- final TetheringRequestParcel request = new TetheringRequestParcel();
- request.tetheringType = type;
- request.localIPv4Address = serverAddr;
- request.staticClientAddress = clientAddr;
- request.exemptFromEntitlementCheck = exempt;
- request.showProvisioningUi = false;
-
- return request;
- }
-
- @After
- public void tearDown() {
- mServiceContext.unregisterReceiver(mBroadcastReceiver);
- }
-
- private void sendWifiApStateChanged(int state) {
- final Intent intent = new Intent(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
- intent.putExtra(EXTRA_WIFI_AP_STATE, state);
- mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
- }
-
- private void sendWifiApStateChanged(int state, String ifname, int ipmode) {
- final Intent intent = new Intent(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
- intent.putExtra(EXTRA_WIFI_AP_STATE, state);
- intent.putExtra(EXTRA_WIFI_AP_INTERFACE_NAME, ifname);
- intent.putExtra(EXTRA_WIFI_AP_MODE, ipmode);
- mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
- }
-
- private static final String[] P2P_RECEIVER_PERMISSIONS_FOR_BROADCAST = {
- android.Manifest.permission.ACCESS_FINE_LOCATION,
- android.Manifest.permission.ACCESS_WIFI_STATE
- };
-
- private void sendWifiP2pConnectionChanged(
- boolean isGroupFormed, boolean isGroupOwner, String ifname) {
- WifiP2pGroup group = null;
- WifiP2pInfo p2pInfo = new WifiP2pInfo();
- p2pInfo.groupFormed = isGroupFormed;
- if (isGroupFormed) {
- p2pInfo.isGroupOwner = isGroupOwner;
- group = mock(WifiP2pGroup.class);
- when(group.isGroupOwner()).thenReturn(isGroupOwner);
- when(group.getInterface()).thenReturn(ifname);
- }
-
- final Intent intent = mock(Intent.class);
- when(intent.getAction()).thenReturn(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
- when(intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_INFO)).thenReturn(p2pInfo);
- when(intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_GROUP)).thenReturn(group);
-
- mServiceContext.sendBroadcastAsUserMultiplePermissions(intent, UserHandle.ALL,
- P2P_RECEIVER_PERMISSIONS_FOR_BROADCAST);
- }
-
- private void sendUsbBroadcast(boolean connected, boolean configured, boolean function,
- int type) {
- final Intent intent = new Intent(UsbManager.ACTION_USB_STATE);
- intent.putExtra(USB_CONNECTED, connected);
- intent.putExtra(USB_CONFIGURED, configured);
- if (type == TETHERING_USB) {
- intent.putExtra(USB_FUNCTION_RNDIS, function);
- } else {
- intent.putExtra(USB_FUNCTION_NCM, function);
- }
- mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
- }
-
- private void sendConfigurationChanged() {
- final Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
- mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
- }
-
- private void verifyInterfaceServingModeStarted(String ifname) throws Exception {
- verify(mNetd, times(1)).interfaceSetCfg(any(InterfaceConfigurationParcel.class));
- verify(mNetd, times(1)).tetherInterfaceAdd(ifname);
- verify(mNetd, times(1)).networkAddInterface(INetd.LOCAL_NET_ID, ifname);
- verify(mNetd, times(2)).networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(ifname),
- anyString(), anyString());
- }
-
- private void verifyTetheringBroadcast(String ifname, String whichExtra) {
- // Verify that ifname is in the whichExtra array of the tether state changed broadcast.
- final Intent bcast = mIntents.get(0);
- assertEquals(ACTION_TETHER_STATE_CHANGED, bcast.getAction());
- final ArrayList<String> ifnames = bcast.getStringArrayListExtra(whichExtra);
- assertTrue(ifnames.contains(ifname));
- mIntents.remove(bcast);
- }
-
- public void failingLocalOnlyHotspotLegacyApBroadcast(
- boolean emulateInterfaceStatusChanged) throws Exception {
- // Emulate externally-visible WifiManager effects, causing the
- // per-interface state machine to start up, and telling us that
- // hotspot mode is to be started.
- if (emulateInterfaceStatusChanged) {
- mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
- }
- sendWifiApStateChanged(WIFI_AP_STATE_ENABLED);
- mLooper.dispatchAll();
-
- // If, and only if, Tethering received an interface status changed then
- // it creates a IpServer and sends out a broadcast indicating that the
- // interface is "available".
- if (emulateInterfaceStatusChanged) {
- // There is 1 IpServer state change event: STATE_AVAILABLE
- verify(mNotificationUpdater, times(1)).onDownstreamChanged(DOWNSTREAM_NONE);
- verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
- verify(mWifiManager).updateInterfaceIpState(
- TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_UNSPECIFIED);
- }
- verifyNoMoreInteractions(mNetd);
- verifyNoMoreInteractions(mWifiManager);
- }
-
- private void prepareNcmTethering() {
- // Emulate startTethering(TETHERING_NCM) called
- mTethering.startTethering(createTetheringRequestParcel(TETHERING_NCM), null);
- mLooper.dispatchAll();
- verify(mUsbManager, times(1)).setCurrentFunctions(UsbManager.FUNCTION_NCM);
-
- mTethering.interfaceStatusChanged(TEST_NCM_IFNAME, true);
- }
-
- private void prepareUsbTethering(UpstreamNetworkState upstreamState) {
- initTetheringUpstream(upstreamState);
-
- // Emulate pressing the USB tethering button in Settings UI.
- mTethering.startTethering(createTetheringRequestParcel(TETHERING_USB), null);
- mLooper.dispatchAll();
- verify(mUsbManager, times(1)).setCurrentFunctions(UsbManager.FUNCTION_RNDIS);
-
- mTethering.interfaceStatusChanged(TEST_USB_IFNAME, true);
- }
-
- @Test
- public void testUsbConfiguredBroadcastStartsTethering() throws Exception {
- UpstreamNetworkState upstreamState = buildMobileIPv4UpstreamState();
- prepareUsbTethering(upstreamState);
-
- // This should produce no activity of any kind.
- verifyNoMoreInteractions(mNetd);
-
- // Pretend we then receive USB configured broadcast.
- sendUsbBroadcast(true, true, true, TETHERING_USB);
- mLooper.dispatchAll();
- // Now we should see the start of tethering mechanics (in this case:
- // tetherMatchingInterfaces() which starts by fetching all interfaces).
- verify(mNetd, times(1)).interfaceGetList();
-
- // UpstreamNetworkMonitor should receive selected upstream
- verify(mUpstreamNetworkMonitor, times(1)).getCurrentPreferredUpstream();
- verify(mUpstreamNetworkMonitor, times(1)).setCurrentUpstream(upstreamState.network);
- }
-
- @Test
- public void failingLocalOnlyHotspotLegacyApBroadcastWithIfaceStatusChanged() throws Exception {
- failingLocalOnlyHotspotLegacyApBroadcast(true);
- }
-
- @Test
- public void failingLocalOnlyHotspotLegacyApBroadcastSansIfaceStatusChanged() throws Exception {
- failingLocalOnlyHotspotLegacyApBroadcast(false);
- }
-
- public void workingLocalOnlyHotspotEnrichedApBroadcast(
- boolean emulateInterfaceStatusChanged) throws Exception {
- // Emulate externally-visible WifiManager effects, causing the
- // per-interface state machine to start up, and telling us that
- // hotspot mode is to be started.
- if (emulateInterfaceStatusChanged) {
- mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
- }
- sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_LOCAL_ONLY);
- mLooper.dispatchAll();
-
- verifyInterfaceServingModeStarted(TEST_WLAN_IFNAME);
- verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
- verify(mNetd, times(1)).ipfwdEnableForwarding(TETHERING_NAME);
- verify(mNetd, times(1)).tetherStartWithConfiguration(any());
- verifyNoMoreInteractions(mNetd);
- verify(mWifiManager).updateInterfaceIpState(
- TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_UNSPECIFIED);
- verify(mWifiManager).updateInterfaceIpState(
- TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_LOCAL_ONLY);
- verifyNoMoreInteractions(mWifiManager);
- verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_ACTIVE_LOCAL_ONLY);
- verify(mUpstreamNetworkMonitor, times(1)).startObserveAllNetworks();
- // There are 2 IpServer state change events: STATE_AVAILABLE -> STATE_LOCAL_ONLY
- verify(mNotificationUpdater, times(2)).onDownstreamChanged(DOWNSTREAM_NONE);
-
- // Emulate externally-visible WifiManager effects, when hotspot mode
- // is being torn down.
- sendWifiApStateChanged(WifiManager.WIFI_AP_STATE_DISABLED);
- mTethering.interfaceRemoved(TEST_WLAN_IFNAME);
- mLooper.dispatchAll();
-
- verify(mNetd, times(1)).tetherApplyDnsInterfaces();
- verify(mNetd, times(1)).tetherInterfaceRemove(TEST_WLAN_IFNAME);
- verify(mNetd, times(1)).networkRemoveInterface(INetd.LOCAL_NET_ID, TEST_WLAN_IFNAME);
- // interfaceSetCfg() called once for enabling and twice disabling IPv4.
- verify(mNetd, times(3)).interfaceSetCfg(any(InterfaceConfigurationParcel.class));
- verify(mNetd, times(1)).tetherStop();
- verify(mNetd, times(1)).ipfwdDisableForwarding(TETHERING_NAME);
- verify(mWifiManager, times(3)).updateInterfaceIpState(
- TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_UNSPECIFIED);
- verifyNoMoreInteractions(mNetd);
- verifyNoMoreInteractions(mWifiManager);
- // Asking for the last error after the per-interface state machine
- // has been reaped yields an unknown interface error.
- assertEquals(TETHER_ERROR_UNKNOWN_IFACE, mTethering.getLastTetherError(TEST_WLAN_IFNAME));
- }
-
- /**
- * Send CMD_IPV6_TETHER_UPDATE to IpServers as would be done by IPv6TetheringCoordinator.
- */
- private void sendIPv6TetherUpdates(UpstreamNetworkState upstreamState) {
- // IPv6TetheringCoordinator must have been notified of downstream
- verify(mIPv6TetheringCoordinator, times(1)).addActiveDownstream(
- argThat(sm -> sm.linkProperties().getInterfaceName().equals(TEST_USB_IFNAME)),
- eq(IpServer.STATE_TETHERED));
-
- for (IpServer ipSrv : mTetheringDependencies.mIpv6CoordinatorNotifyList) {
- UpstreamNetworkState ipv6OnlyState = buildMobileUpstreamState(false, true, false);
- ipSrv.sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, 0, 0,
- upstreamState.linkProperties.isIpv6Provisioned()
- ? ipv6OnlyState.linkProperties
- : null);
- }
- mLooper.dispatchAll();
- }
-
- private void runUsbTethering(UpstreamNetworkState upstreamState) {
- prepareUsbTethering(upstreamState);
- sendUsbBroadcast(true, true, true, TETHERING_USB);
- mLooper.dispatchAll();
- }
-
- @Test
- public void workingMobileUsbTethering_IPv4() throws Exception {
- UpstreamNetworkState upstreamState = buildMobileIPv4UpstreamState();
- runUsbTethering(upstreamState);
-
- verify(mNetd, times(1)).tetherAddForward(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
- verify(mNetd, times(1)).ipfwdAddInterfaceForward(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
-
- sendIPv6TetherUpdates(upstreamState);
- verify(mDadProxy, never()).setUpstreamIface(notNull());
- verify(mRouterAdvertisementDaemon, never()).buildNewRa(any(), notNull());
- verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS).times(1)).startWithCallbacks(
- any(), any());
- }
-
- @Test
- public void workingMobileUsbTethering_IPv4LegacyDhcp() {
- when(mResources.getBoolean(R.bool.config_tether_enable_legacy_dhcp_server)).thenReturn(
- true);
- sendConfigurationChanged();
- final UpstreamNetworkState upstreamState = buildMobileIPv4UpstreamState();
- runUsbTethering(upstreamState);
- sendIPv6TetherUpdates(upstreamState);
-
- verify(mIpServerDependencies, never()).makeDhcpServer(any(), any(), any());
- }
-
- @Test
- public void workingMobileUsbTethering_IPv6() throws Exception {
- UpstreamNetworkState upstreamState = buildMobileIPv6UpstreamState();
- runUsbTethering(upstreamState);
-
- verify(mNetd, times(1)).tetherAddForward(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
- verify(mNetd, times(1)).ipfwdAddInterfaceForward(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
-
- sendIPv6TetherUpdates(upstreamState);
- // TODO: add interfaceParams to compare in verify.
- verify(mDadProxy, times(1)).setUpstreamIface(notNull());
- verify(mRouterAdvertisementDaemon, times(1)).buildNewRa(any(), notNull());
- verify(mNetd, times(1)).tetherApplyDnsInterfaces();
- }
-
- @Test
- public void workingMobileUsbTethering_DualStack() throws Exception {
- UpstreamNetworkState upstreamState = buildMobileDualStackUpstreamState();
- runUsbTethering(upstreamState);
-
- verify(mNetd, times(1)).tetherAddForward(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
- verify(mNetd, times(1)).ipfwdAddInterfaceForward(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
- verify(mRouterAdvertisementDaemon, times(1)).start();
- verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS).times(1)).startWithCallbacks(
- any(), any());
-
- sendIPv6TetherUpdates(upstreamState);
- verify(mDadProxy, times(1)).setUpstreamIface(notNull());
- verify(mRouterAdvertisementDaemon, times(1)).buildNewRa(any(), notNull());
- verify(mNetd, times(1)).tetherApplyDnsInterfaces();
- }
-
- @Test
- public void workingMobileUsbTethering_MultipleUpstreams() throws Exception {
- UpstreamNetworkState upstreamState = buildMobile464xlatUpstreamState();
- runUsbTethering(upstreamState);
-
- verify(mNetd, times(1)).tetherAddForward(TEST_USB_IFNAME, TEST_XLAT_MOBILE_IFNAME);
- verify(mNetd, times(1)).tetherAddForward(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
- verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS).times(1)).startWithCallbacks(
- any(), any());
- verify(mNetd, times(1)).ipfwdAddInterfaceForward(TEST_USB_IFNAME, TEST_XLAT_MOBILE_IFNAME);
- verify(mNetd, times(1)).ipfwdAddInterfaceForward(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
-
- sendIPv6TetherUpdates(upstreamState);
- verify(mDadProxy, times(1)).setUpstreamIface(notNull());
- verify(mRouterAdvertisementDaemon, times(1)).buildNewRa(any(), notNull());
- verify(mNetd, times(1)).tetherApplyDnsInterfaces();
- }
-
- @Test
- public void workingMobileUsbTethering_v6Then464xlat() throws Exception {
- // Setup IPv6
- UpstreamNetworkState upstreamState = buildMobileIPv6UpstreamState();
- runUsbTethering(upstreamState);
-
- verify(mNetd, times(1)).tetherAddForward(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
- verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS).times(1)).startWithCallbacks(
- any(), any());
- verify(mNetd, times(1)).ipfwdAddInterfaceForward(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
-
- // Then 464xlat comes up
- upstreamState = buildMobile464xlatUpstreamState();
- initTetheringUpstream(upstreamState);
-
- // Upstream LinkProperties changed: UpstreamNetworkMonitor sends EVENT_ON_LINKPROPERTIES.
- mTetheringDependencies.mUpstreamNetworkMonitorSM.sendMessage(
- Tethering.TetherMainSM.EVENT_UPSTREAM_CALLBACK,
- UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES,
- 0,
- upstreamState);
- mLooper.dispatchAll();
-
- // Forwarding is added for 464xlat
- verify(mNetd, times(1)).tetherAddForward(TEST_USB_IFNAME, TEST_XLAT_MOBILE_IFNAME);
- verify(mNetd, times(1)).ipfwdAddInterfaceForward(TEST_USB_IFNAME, TEST_XLAT_MOBILE_IFNAME);
- // Forwarding was not re-added for v6 (still times(1))
- verify(mNetd, times(1)).tetherAddForward(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
- verify(mNetd, times(1)).ipfwdAddInterfaceForward(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
- // DHCP not restarted on downstream (still times(1))
- verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS).times(1)).startWithCallbacks(
- any(), any());
- }
-
- @Test
- public void configTetherUpstreamAutomaticIgnoresConfigTetherUpstreamTypes() throws Exception {
- when(mResources.getBoolean(R.bool.config_tether_upstream_automatic)).thenReturn(true);
- sendConfigurationChanged();
-
- // Setup IPv6
- final UpstreamNetworkState upstreamState = buildMobileIPv6UpstreamState();
- runUsbTethering(upstreamState);
-
- // UpstreamNetworkMonitor should choose upstream automatically
- // (in this specific case: choose the default network).
- verify(mUpstreamNetworkMonitor, times(1)).getCurrentPreferredUpstream();
- verify(mUpstreamNetworkMonitor, never()).selectPreferredUpstreamType(any());
-
- verify(mUpstreamNetworkMonitor, times(1)).setCurrentUpstream(upstreamState.network);
- }
-
- private void runNcmTethering() {
- prepareNcmTethering();
- sendUsbBroadcast(true, true, true, TETHERING_NCM);
- mLooper.dispatchAll();
- }
-
- @Test
- public void workingNcmTethering() throws Exception {
- runNcmTethering();
-
- verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS).times(1)).startWithCallbacks(
- any(), any());
- }
-
- @Test
- public void workingNcmTethering_LegacyDhcp() {
- when(mResources.getBoolean(R.bool.config_tether_enable_legacy_dhcp_server)).thenReturn(
- true);
- sendConfigurationChanged();
- runNcmTethering();
-
- verify(mIpServerDependencies, never()).makeDhcpServer(any(), any(), any());
- }
-
- @Test
- public void workingLocalOnlyHotspotEnrichedApBroadcastWithIfaceChanged() throws Exception {
- workingLocalOnlyHotspotEnrichedApBroadcast(true);
- }
-
- @Test
- public void workingLocalOnlyHotspotEnrichedApBroadcastSansIfaceChanged() throws Exception {
- workingLocalOnlyHotspotEnrichedApBroadcast(false);
- }
-
- // TODO: Test with and without interfaceStatusChanged().
- @Test
- public void failingWifiTetheringLegacyApBroadcast() throws Exception {
- when(mWifiManager.startTetheredHotspot(any(SoftApConfiguration.class))).thenReturn(true);
-
- // Emulate pressing the WiFi tethering button.
- mTethering.startTethering(createTetheringRequestParcel(TETHERING_WIFI), null);
- mLooper.dispatchAll();
- verify(mWifiManager, times(1)).startTetheredHotspot(null);
- verifyNoMoreInteractions(mWifiManager);
- verifyNoMoreInteractions(mNetd);
-
- // Emulate externally-visible WifiManager effects, causing the
- // per-interface state machine to start up, and telling us that
- // tethering mode is to be started.
- mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
- sendWifiApStateChanged(WIFI_AP_STATE_ENABLED);
- mLooper.dispatchAll();
-
- // There is 1 IpServer state change event: STATE_AVAILABLE
- verify(mNotificationUpdater, times(1)).onDownstreamChanged(DOWNSTREAM_NONE);
- verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
- verify(mWifiManager).updateInterfaceIpState(
- TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_UNSPECIFIED);
- verifyNoMoreInteractions(mNetd);
- verifyNoMoreInteractions(mWifiManager);
- }
-
- // TODO: Test with and without interfaceStatusChanged().
- @Test
- public void workingWifiTetheringEnrichedApBroadcast() throws Exception {
- when(mWifiManager.startTetheredHotspot(any(SoftApConfiguration.class))).thenReturn(true);
-
- // Emulate pressing the WiFi tethering button.
- mTethering.startTethering(createTetheringRequestParcel(TETHERING_WIFI), null);
- mLooper.dispatchAll();
- verify(mWifiManager, times(1)).startTetheredHotspot(null);
- verifyNoMoreInteractions(mWifiManager);
- verifyNoMoreInteractions(mNetd);
-
- // Emulate externally-visible WifiManager effects, causing the
- // per-interface state machine to start up, and telling us that
- // tethering mode is to be started.
- mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
- sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_TETHERED);
- mLooper.dispatchAll();
-
- verifyInterfaceServingModeStarted(TEST_WLAN_IFNAME);
- verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
- verify(mNetd, times(1)).ipfwdEnableForwarding(TETHERING_NAME);
- verify(mNetd, times(1)).tetherStartWithConfiguration(any());
- verify(mNetd, times(2)).networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(TEST_WLAN_IFNAME),
- anyString(), anyString());
- verifyNoMoreInteractions(mNetd);
- verify(mWifiManager).updateInterfaceIpState(
- TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_UNSPECIFIED);
- verify(mWifiManager).updateInterfaceIpState(
- TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_TETHERED);
- verifyNoMoreInteractions(mWifiManager);
- verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_ACTIVE_TETHER);
- verify(mUpstreamNetworkMonitor, times(1)).startObserveAllNetworks();
- // In tethering mode, in the default configuration, an explicit request
- // for a mobile network is also made.
- verify(mUpstreamNetworkMonitor, times(1)).registerMobileNetworkRequest();
- // There are 2 IpServer state change events: STATE_AVAILABLE -> STATE_TETHERED
- verify(mNotificationUpdater, times(1)).onDownstreamChanged(DOWNSTREAM_NONE);
- verify(mNotificationUpdater, times(1)).onDownstreamChanged(eq(1 << TETHERING_WIFI));
-
- /////
- // We do not currently emulate any upstream being found.
- //
- // This is why there are no calls to verify mNetd.tetherAddForward() or
- // mNetd.ipfwdAddInterfaceForward().
- /////
-
- // Emulate pressing the WiFi tethering button.
- mTethering.stopTethering(TETHERING_WIFI);
- mLooper.dispatchAll();
- verify(mWifiManager, times(1)).stopSoftAp();
- verifyNoMoreInteractions(mWifiManager);
- verifyNoMoreInteractions(mNetd);
-
- // Emulate externally-visible WifiManager effects, when tethering mode
- // is being torn down.
- sendWifiApStateChanged(WifiManager.WIFI_AP_STATE_DISABLED);
- mTethering.interfaceRemoved(TEST_WLAN_IFNAME);
- mLooper.dispatchAll();
-
- verify(mNetd, times(1)).tetherApplyDnsInterfaces();
- verify(mNetd, times(1)).tetherInterfaceRemove(TEST_WLAN_IFNAME);
- verify(mNetd, times(1)).networkRemoveInterface(INetd.LOCAL_NET_ID, TEST_WLAN_IFNAME);
- // interfaceSetCfg() called once for enabling and twice for disabling IPv4.
- verify(mNetd, times(3)).interfaceSetCfg(any(InterfaceConfigurationParcel.class));
- verify(mNetd, times(1)).tetherStop();
- verify(mNetd, times(1)).ipfwdDisableForwarding(TETHERING_NAME);
- verify(mWifiManager, times(3)).updateInterfaceIpState(
- TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_UNSPECIFIED);
- verifyNoMoreInteractions(mNetd);
- verifyNoMoreInteractions(mWifiManager);
- // Asking for the last error after the per-interface state machine
- // has been reaped yields an unknown interface error.
- assertEquals(TETHER_ERROR_UNKNOWN_IFACE, mTethering.getLastTetherError(TEST_WLAN_IFNAME));
- }
-
- // TODO: Test with and without interfaceStatusChanged().
- @Test
- public void failureEnablingIpForwarding() throws Exception {
- when(mWifiManager.startTetheredHotspot(any(SoftApConfiguration.class))).thenReturn(true);
- doThrow(new RemoteException()).when(mNetd).ipfwdEnableForwarding(TETHERING_NAME);
-
- // Emulate pressing the WiFi tethering button.
- mTethering.startTethering(createTetheringRequestParcel(TETHERING_WIFI), null);
- mLooper.dispatchAll();
- verify(mWifiManager, times(1)).startTetheredHotspot(null);
- verifyNoMoreInteractions(mWifiManager);
- verifyNoMoreInteractions(mNetd);
-
- // Emulate externally-visible WifiManager effects, causing the
- // per-interface state machine to start up, and telling us that
- // tethering mode is to be started.
- mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
- sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_TETHERED);
- mLooper.dispatchAll();
-
- // We verify get/set called three times here: twice for setup and once during
- // teardown because all events happen over the course of the single
- // dispatchAll() above. Note that once the IpServer IPv4 address config
- // code is refactored the two calls during shutdown will revert to one.
- verify(mNetd, times(3)).interfaceSetCfg(argThat(p -> TEST_WLAN_IFNAME.equals(p.ifName)));
- verify(mNetd, times(1)).tetherInterfaceAdd(TEST_WLAN_IFNAME);
- verify(mNetd, times(1)).networkAddInterface(INetd.LOCAL_NET_ID, TEST_WLAN_IFNAME);
- verify(mNetd, times(2)).networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(TEST_WLAN_IFNAME),
- anyString(), anyString());
- verify(mWifiManager).updateInterfaceIpState(
- TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_UNSPECIFIED);
- verify(mWifiManager).updateInterfaceIpState(
- TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_TETHERED);
- // There are 3 IpServer state change event:
- // STATE_AVAILABLE -> STATE_TETHERED -> STATE_AVAILABLE.
- verify(mNotificationUpdater, times(2)).onDownstreamChanged(DOWNSTREAM_NONE);
- verify(mNotificationUpdater, times(1)).onDownstreamChanged(eq(1 << TETHERING_WIFI));
- verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
- // This is called, but will throw.
- verify(mNetd, times(1)).ipfwdEnableForwarding(TETHERING_NAME);
- // This never gets called because of the exception thrown above.
- verify(mNetd, times(0)).tetherStartWithConfiguration(any());
- // When the main state machine transitions to an error state it tells
- // downstream interfaces, which causes us to tell Wi-Fi about the error
- // so it can take down AP mode.
- verify(mNetd, times(1)).tetherApplyDnsInterfaces();
- verify(mNetd, times(1)).tetherInterfaceRemove(TEST_WLAN_IFNAME);
- verify(mNetd, times(1)).networkRemoveInterface(INetd.LOCAL_NET_ID, TEST_WLAN_IFNAME);
- verify(mWifiManager).updateInterfaceIpState(
- TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_CONFIGURATION_ERROR);
-
- verifyNoMoreInteractions(mWifiManager);
- verifyNoMoreInteractions(mNetd);
- }
-
- private void runUserRestrictionsChange(
- boolean currentDisallow, boolean nextDisallow, boolean isTetheringActive,
- int expectedInteractionsWithShowNotification) throws Exception {
- final Bundle newRestrictions = new Bundle();
- newRestrictions.putBoolean(UserManager.DISALLOW_CONFIG_TETHERING, nextDisallow);
- final Tethering mockTethering = mock(Tethering.class);
- when(mockTethering.isTetheringActive()).thenReturn(isTetheringActive);
- when(mUserManager.getUserRestrictions()).thenReturn(newRestrictions);
-
- final Tethering.UserRestrictionActionListener ural =
- new Tethering.UserRestrictionActionListener(
- mUserManager, mockTethering, mNotificationUpdater);
- ural.mDisallowTethering = currentDisallow;
-
- ural.onUserRestrictionsChanged();
-
- verify(mNotificationUpdater, times(expectedInteractionsWithShowNotification))
- .notifyTetheringDisabledByRestriction();
- verify(mockTethering, times(expectedInteractionsWithShowNotification)).untetherAll();
- }
-
- @Test
- public void testDisallowTetheringWhenTetheringIsNotActive() throws Exception {
- final boolean isTetheringActive = false;
- final boolean currDisallow = false;
- final boolean nextDisallow = true;
- final int expectedInteractionsWithShowNotification = 0;
-
- runUserRestrictionsChange(currDisallow, nextDisallow, isTetheringActive,
- expectedInteractionsWithShowNotification);
- }
-
- @Test
- public void testDisallowTetheringWhenTetheringIsActive() throws Exception {
- final boolean isTetheringActive = true;
- final boolean currDisallow = false;
- final boolean nextDisallow = true;
- final int expectedInteractionsWithShowNotification = 1;
-
- runUserRestrictionsChange(currDisallow, nextDisallow, isTetheringActive,
- expectedInteractionsWithShowNotification);
- }
-
- @Test
- public void testAllowTetheringWhenTetheringIsNotActive() throws Exception {
- final boolean isTetheringActive = false;
- final boolean currDisallow = true;
- final boolean nextDisallow = false;
- final int expectedInteractionsWithShowNotification = 0;
-
- runUserRestrictionsChange(currDisallow, nextDisallow, isTetheringActive,
- expectedInteractionsWithShowNotification);
- }
-
- @Test
- public void testAllowTetheringWhenTetheringIsActive() throws Exception {
- final boolean isTetheringActive = true;
- final boolean currDisallow = true;
- final boolean nextDisallow = false;
- final int expectedInteractionsWithShowNotification = 0;
-
- runUserRestrictionsChange(currDisallow, nextDisallow, isTetheringActive,
- expectedInteractionsWithShowNotification);
- }
-
- @Test
- public void testDisallowTetheringUnchanged() throws Exception {
- final boolean isTetheringActive = true;
- final int expectedInteractionsWithShowNotification = 0;
- boolean currDisallow = true;
- boolean nextDisallow = true;
-
- runUserRestrictionsChange(currDisallow, nextDisallow, isTetheringActive,
- expectedInteractionsWithShowNotification);
-
- currDisallow = false;
- nextDisallow = false;
-
- runUserRestrictionsChange(currDisallow, nextDisallow, isTetheringActive,
- expectedInteractionsWithShowNotification);
- }
-
- private class TestTetheringEventCallback extends ITetheringEventCallback.Stub {
- private final ArrayList<Network> mActualUpstreams = new ArrayList<>();
- private final ArrayList<TetheringConfigurationParcel> mTetheringConfigs =
- new ArrayList<>();
- private final ArrayList<TetherStatesParcel> mTetherStates = new ArrayList<>();
- private final ArrayList<Integer> mOffloadStatus = new ArrayList<>();
-
- // This function will remove the recorded callbacks, so it must be called once for
- // each callback. If this is called after multiple callback, the order matters.
- // onCallbackCreated counts as the first call to expectUpstreamChanged with
- // @see onCallbackCreated.
- public void expectUpstreamChanged(Network... networks) {
- if (networks == null) {
- assertNoUpstreamChangeCallback();
- return;
- }
-
- final ArrayList<Network> expectedUpstreams =
- new ArrayList<Network>(Arrays.asList(networks));
- for (Network upstream : expectedUpstreams) {
- // throws OOB if no expectations
- assertEquals(mActualUpstreams.remove(0), upstream);
- }
- assertNoUpstreamChangeCallback();
- }
-
- // This function will remove the recorded callbacks, so it must be called once
- // for each callback. If this is called after multiple callback, the order matters.
- // onCallbackCreated counts as the first call to onConfigurationChanged with
- // @see onCallbackCreated.
- public void expectConfigurationChanged(TetheringConfigurationParcel... tetherConfigs) {
- final ArrayList<TetheringConfigurationParcel> expectedTetherConfig =
- new ArrayList<TetheringConfigurationParcel>(Arrays.asList(tetherConfigs));
- for (TetheringConfigurationParcel config : expectedTetherConfig) {
- // throws OOB if no expectations
- final TetheringConfigurationParcel actualConfig = mTetheringConfigs.remove(0);
- assertTetherConfigParcelEqual(actualConfig, config);
- }
- assertNoConfigChangeCallback();
- }
-
- public void expectOffloadStatusChanged(final int expectedStatus) {
- assertOffloadStatusChangedCallback();
- assertEquals(mOffloadStatus.remove(0), new Integer(expectedStatus));
- }
-
- public TetherStatesParcel pollTetherStatesChanged() {
- assertStateChangeCallback();
- return mTetherStates.remove(0);
- }
-
- @Override
- public void onUpstreamChanged(Network network) {
- mActualUpstreams.add(network);
- }
-
- @Override
- public void onConfigurationChanged(TetheringConfigurationParcel config) {
- mTetheringConfigs.add(config);
- }
-
- @Override
- public void onTetherStatesChanged(TetherStatesParcel states) {
- mTetherStates.add(states);
- }
-
- @Override
- public void onTetherClientsChanged(List<TetheredClient> clients) {
- // TODO: check this
- }
-
- @Override
- public void onOffloadStatusChanged(final int status) {
- mOffloadStatus.add(status);
- }
-
- @Override
- public void onCallbackStarted(TetheringCallbackStartedParcel parcel) {
- mActualUpstreams.add(parcel.upstreamNetwork);
- mTetheringConfigs.add(parcel.config);
- mTetherStates.add(parcel.states);
- mOffloadStatus.add(parcel.offloadStatus);
- }
-
- @Override
- public void onCallbackStopped(int errorCode) { }
-
- public void assertNoUpstreamChangeCallback() {
- assertTrue(mActualUpstreams.isEmpty());
- }
-
- public void assertNoConfigChangeCallback() {
- assertTrue(mTetheringConfigs.isEmpty());
- }
-
- public void assertNoStateChangeCallback() {
- assertTrue(mTetherStates.isEmpty());
- }
-
- public void assertStateChangeCallback() {
- assertFalse(mTetherStates.isEmpty());
- }
-
- public void assertOffloadStatusChangedCallback() {
- assertFalse(mOffloadStatus.isEmpty());
- }
-
- public void assertNoCallback() {
- assertNoUpstreamChangeCallback();
- assertNoConfigChangeCallback();
- assertNoStateChangeCallback();
- }
-
- private void assertTetherConfigParcelEqual(@NonNull TetheringConfigurationParcel actual,
- @NonNull TetheringConfigurationParcel expect) {
- assertEquals(actual.subId, expect.subId);
- assertArrayEquals(actual.tetherableUsbRegexs, expect.tetherableUsbRegexs);
- assertArrayEquals(actual.tetherableWifiRegexs, expect.tetherableWifiRegexs);
- assertArrayEquals(actual.tetherableBluetoothRegexs, expect.tetherableBluetoothRegexs);
- assertEquals(actual.isDunRequired, expect.isDunRequired);
- assertEquals(actual.chooseUpstreamAutomatically, expect.chooseUpstreamAutomatically);
- assertArrayEquals(actual.preferredUpstreamIfaceTypes,
- expect.preferredUpstreamIfaceTypes);
- assertArrayEquals(actual.legacyDhcpRanges, expect.legacyDhcpRanges);
- assertArrayEquals(actual.defaultIPv4DNS, expect.defaultIPv4DNS);
- assertEquals(actual.enableLegacyDhcpServer, expect.enableLegacyDhcpServer);
- assertArrayEquals(actual.provisioningApp, expect.provisioningApp);
- assertEquals(actual.provisioningAppNoUi, expect.provisioningAppNoUi);
- assertEquals(actual.provisioningCheckPeriod, expect.provisioningCheckPeriod);
- }
- }
-
- private void assertTetherStatesNotNullButEmpty(final TetherStatesParcel parcel) {
- assertFalse(parcel == null);
- assertEquals(0, parcel.availableList.length);
- assertEquals(0, parcel.tetheredList.length);
- assertEquals(0, parcel.localOnlyList.length);
- assertEquals(0, parcel.erroredIfaceList.length);
- assertEquals(0, parcel.lastErrorList.length);
- MiscAsserts.assertFieldCountEquals(5, TetherStatesParcel.class);
- }
-
- @Test
- public void testRegisterTetheringEventCallback() throws Exception {
- TestTetheringEventCallback callback = new TestTetheringEventCallback();
- TestTetheringEventCallback callback2 = new TestTetheringEventCallback();
-
- // 1. Register one callback before running any tethering.
- mTethering.registerTetheringEventCallback(callback);
- mLooper.dispatchAll();
- callback.expectUpstreamChanged(new Network[] {null});
- callback.expectConfigurationChanged(
- mTethering.getTetheringConfiguration().toStableParcelable());
- TetherStatesParcel tetherState = callback.pollTetherStatesChanged();
- assertTetherStatesNotNullButEmpty(tetherState);
- callback.expectOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_STOPPED);
- // 2. Enable wifi tethering.
- UpstreamNetworkState upstreamState = buildMobileDualStackUpstreamState();
- initTetheringUpstream(upstreamState);
- when(mWifiManager.startTetheredHotspot(any(SoftApConfiguration.class))).thenReturn(true);
- mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
- mLooper.dispatchAll();
- tetherState = callback.pollTetherStatesChanged();
- assertArrayEquals(tetherState.availableList, new String[] {TEST_WLAN_IFNAME});
-
- mTethering.startTethering(createTetheringRequestParcel(TETHERING_WIFI), null);
- sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_TETHERED);
- mLooper.dispatchAll();
- tetherState = callback.pollTetherStatesChanged();
- assertArrayEquals(tetherState.tetheredList, new String[] {TEST_WLAN_IFNAME});
- callback.expectUpstreamChanged(upstreamState.network);
- callback.expectOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_STARTED);
-
- // 3. Register second callback.
- mTethering.registerTetheringEventCallback(callback2);
- mLooper.dispatchAll();
- callback2.expectUpstreamChanged(upstreamState.network);
- callback2.expectConfigurationChanged(
- mTethering.getTetheringConfiguration().toStableParcelable());
- tetherState = callback2.pollTetherStatesChanged();
- assertEquals(tetherState.tetheredList, new String[] {TEST_WLAN_IFNAME});
- callback2.expectOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_STARTED);
-
- // 4. Unregister first callback and disable wifi tethering
- mTethering.unregisterTetheringEventCallback(callback);
- mLooper.dispatchAll();
- mTethering.stopTethering(TETHERING_WIFI);
- sendWifiApStateChanged(WifiManager.WIFI_AP_STATE_DISABLED);
- mLooper.dispatchAll();
- tetherState = callback2.pollTetherStatesChanged();
- assertArrayEquals(tetherState.availableList, new String[] {TEST_WLAN_IFNAME});
- mLooper.dispatchAll();
- callback2.expectUpstreamChanged(new Network[] {null});
- callback2.expectOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_STOPPED);
- callback.assertNoCallback();
- }
-
- @Test
- public void testReportFailCallbackIfOffloadNotSupported() throws Exception {
- final UpstreamNetworkState upstreamState = buildMobileDualStackUpstreamState();
- TestTetheringEventCallback callback = new TestTetheringEventCallback();
- mTethering.registerTetheringEventCallback(callback);
- mLooper.dispatchAll();
- callback.expectOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_STOPPED);
-
- // 1. Offload fail if no OffloadConfig.
- initOffloadConfiguration(false /* offloadConfig */, true /* offloadControl */,
- 0 /* defaultDisabled */);
- runUsbTethering(upstreamState);
- callback.expectOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_FAILED);
- runStopUSBTethering();
- callback.expectOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_STOPPED);
- reset(mUsbManager);
- // 2. Offload fail if no OffloadControl.
- initOffloadConfiguration(true /* offloadConfig */, false /* offloadControl */,
- 0 /* defaultDisabled */);
- runUsbTethering(upstreamState);
- callback.expectOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_FAILED);
- runStopUSBTethering();
- callback.expectOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_STOPPED);
- reset(mUsbManager);
- // 3. Offload fail if disabled by settings.
- initOffloadConfiguration(true /* offloadConfig */, true /* offloadControl */,
- 1 /* defaultDisabled */);
- runUsbTethering(upstreamState);
- callback.expectOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_FAILED);
- runStopUSBTethering();
- callback.expectOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_STOPPED);
- }
-
- private void runStopUSBTethering() {
- mTethering.stopTethering(TETHERING_USB);
- mLooper.dispatchAll();
- mTethering.interfaceRemoved(TEST_USB_IFNAME);
- mLooper.dispatchAll();
- }
-
- private void initOffloadConfiguration(final boolean offloadConfig,
- final boolean offloadControl, final int defaultDisabled) {
- when(mOffloadHardwareInterface.initOffloadConfig()).thenReturn(offloadConfig);
- when(mOffloadHardwareInterface.initOffloadControl(any())).thenReturn(offloadControl);
- when(mOffloadHardwareInterface.getDefaultTetherOffloadDisabled()).thenReturn(
- defaultDisabled);
- }
-
- @Test
- public void testMultiSimAware() throws Exception {
- final TetheringConfiguration initailConfig = mTethering.getTetheringConfiguration();
- assertEquals(INVALID_SUBSCRIPTION_ID, initailConfig.activeDataSubId);
-
- final int fakeSubId = 1234;
- mPhoneStateListener.onActiveDataSubscriptionIdChanged(fakeSubId);
- final TetheringConfiguration newConfig = mTethering.getTetheringConfiguration();
- assertEquals(fakeSubId, newConfig.activeDataSubId);
- verify(mNotificationUpdater, times(1)).onActiveDataSubscriptionIdChanged(eq(fakeSubId));
- }
-
- @Test
- public void testNoDuplicatedEthernetRequest() throws Exception {
- final TetheredInterfaceRequest mockRequest = mock(TetheredInterfaceRequest.class);
- when(mEm.requestTetheredInterface(any(), any())).thenReturn(mockRequest);
- mTethering.startTethering(createTetheringRequestParcel(TETHERING_ETHERNET), null);
- mLooper.dispatchAll();
- verify(mEm, times(1)).requestTetheredInterface(any(), any());
- mTethering.startTethering(createTetheringRequestParcel(TETHERING_ETHERNET), null);
- mLooper.dispatchAll();
- verifyNoMoreInteractions(mEm);
- mTethering.stopTethering(TETHERING_ETHERNET);
- mLooper.dispatchAll();
- verify(mockRequest, times(1)).release();
- mTethering.stopTethering(TETHERING_ETHERNET);
- mLooper.dispatchAll();
- verifyNoMoreInteractions(mEm);
- }
-
- private void workingWifiP2pGroupOwner(
- boolean emulateInterfaceStatusChanged) throws Exception {
- if (emulateInterfaceStatusChanged) {
- mTethering.interfaceStatusChanged(TEST_P2P_IFNAME, true);
- }
- sendWifiP2pConnectionChanged(true, true, TEST_P2P_IFNAME);
- mLooper.dispatchAll();
-
- verifyInterfaceServingModeStarted(TEST_P2P_IFNAME);
- verifyTetheringBroadcast(TEST_P2P_IFNAME, EXTRA_AVAILABLE_TETHER);
- verify(mNetd, times(1)).ipfwdEnableForwarding(TETHERING_NAME);
- verify(mNetd, times(1)).tetherStartWithConfiguration(any());
- verifyNoMoreInteractions(mNetd);
- verifyTetheringBroadcast(TEST_P2P_IFNAME, EXTRA_ACTIVE_LOCAL_ONLY);
- verify(mUpstreamNetworkMonitor, times(1)).startObserveAllNetworks();
- // There are 2 IpServer state change events: STATE_AVAILABLE -> STATE_LOCAL_ONLY
- verify(mNotificationUpdater, times(2)).onDownstreamChanged(DOWNSTREAM_NONE);
-
- assertEquals(TETHER_ERROR_NO_ERROR, mTethering.getLastTetherError(TEST_P2P_IFNAME));
-
- // Emulate externally-visible WifiP2pManager effects, when wifi p2p group
- // is being removed.
- sendWifiP2pConnectionChanged(false, true, TEST_P2P_IFNAME);
- mTethering.interfaceRemoved(TEST_P2P_IFNAME);
- mLooper.dispatchAll();
-
- verify(mNetd, times(1)).tetherApplyDnsInterfaces();
- verify(mNetd, times(1)).tetherInterfaceRemove(TEST_P2P_IFNAME);
- verify(mNetd, times(1)).networkRemoveInterface(INetd.LOCAL_NET_ID, TEST_P2P_IFNAME);
- // interfaceSetCfg() called once for enabling and twice for disabling IPv4.
- verify(mNetd, times(3)).interfaceSetCfg(any(InterfaceConfigurationParcel.class));
- verify(mNetd, times(1)).tetherStop();
- verify(mNetd, times(1)).ipfwdDisableForwarding(TETHERING_NAME);
- verify(mUpstreamNetworkMonitor, never()).getCurrentPreferredUpstream();
- verify(mUpstreamNetworkMonitor, never()).selectPreferredUpstreamType(any());
- verifyNoMoreInteractions(mNetd);
- // Asking for the last error after the per-interface state machine
- // has been reaped yields an unknown interface error.
- assertEquals(TETHER_ERROR_UNKNOWN_IFACE, mTethering.getLastTetherError(TEST_P2P_IFNAME));
- }
-
- private void workingWifiP2pGroupClient(
- boolean emulateInterfaceStatusChanged) throws Exception {
- if (emulateInterfaceStatusChanged) {
- mTethering.interfaceStatusChanged(TEST_P2P_IFNAME, true);
- }
- sendWifiP2pConnectionChanged(true, false, TEST_P2P_IFNAME);
- mLooper.dispatchAll();
-
- verify(mNetd, never()).interfaceSetCfg(any(InterfaceConfigurationParcel.class));
- verify(mNetd, never()).tetherInterfaceAdd(TEST_P2P_IFNAME);
- verify(mNetd, never()).networkAddInterface(INetd.LOCAL_NET_ID, TEST_P2P_IFNAME);
- verify(mNetd, never()).ipfwdEnableForwarding(TETHERING_NAME);
- verify(mNetd, never()).tetherStartWithConfiguration(any());
-
- // Emulate externally-visible WifiP2pManager effects, when wifi p2p group
- // is being removed.
- sendWifiP2pConnectionChanged(false, false, TEST_P2P_IFNAME);
- mTethering.interfaceRemoved(TEST_P2P_IFNAME);
- mLooper.dispatchAll();
-
- verify(mNetd, never()).tetherApplyDnsInterfaces();
- verify(mNetd, never()).tetherInterfaceRemove(TEST_P2P_IFNAME);
- verify(mNetd, never()).networkRemoveInterface(INetd.LOCAL_NET_ID, TEST_P2P_IFNAME);
- verify(mNetd, never()).interfaceSetCfg(any(InterfaceConfigurationParcel.class));
- verify(mNetd, never()).tetherStop();
- verify(mNetd, never()).ipfwdDisableForwarding(TETHERING_NAME);
- verifyNoMoreInteractions(mNetd);
- // Asking for the last error after the per-interface state machine
- // has been reaped yields an unknown interface error.
- assertEquals(TETHER_ERROR_UNKNOWN_IFACE, mTethering.getLastTetherError(TEST_P2P_IFNAME));
- }
-
- @Test
- public void workingWifiP2pGroupOwnerWithIfaceChanged() throws Exception {
- workingWifiP2pGroupOwner(true);
- }
-
- @Test
- public void workingWifiP2pGroupOwnerSansIfaceChanged() throws Exception {
- workingWifiP2pGroupOwner(false);
- }
-
- private void workingWifiP2pGroupOwnerLegacyMode(
- boolean emulateInterfaceStatusChanged) throws Exception {
- // change to legacy mode and update tethering information by chaning SIM
- when(mResources.getStringArray(R.array.config_tether_wifi_p2p_regexs))
- .thenReturn(new String[]{});
- final int fakeSubId = 1234;
- mPhoneStateListener.onActiveDataSubscriptionIdChanged(fakeSubId);
-
- if (emulateInterfaceStatusChanged) {
- mTethering.interfaceStatusChanged(TEST_P2P_IFNAME, true);
- }
- sendWifiP2pConnectionChanged(true, true, TEST_P2P_IFNAME);
- mLooper.dispatchAll();
-
- verify(mNetd, never()).interfaceSetCfg(any(InterfaceConfigurationParcel.class));
- verify(mNetd, never()).tetherInterfaceAdd(TEST_P2P_IFNAME);
- verify(mNetd, never()).networkAddInterface(INetd.LOCAL_NET_ID, TEST_P2P_IFNAME);
- verify(mNetd, never()).ipfwdEnableForwarding(TETHERING_NAME);
- verify(mNetd, never()).tetherStartWithConfiguration(any());
- assertEquals(TETHER_ERROR_UNKNOWN_IFACE, mTethering.getLastTetherError(TEST_P2P_IFNAME));
- }
- @Test
- public void workingWifiP2pGroupOwnerLegacyModeWithIfaceChanged() throws Exception {
- workingWifiP2pGroupOwnerLegacyMode(true);
- }
-
- @Test
- public void workingWifiP2pGroupOwnerLegacyModeSansIfaceChanged() throws Exception {
- workingWifiP2pGroupOwnerLegacyMode(false);
- }
-
- @Test
- public void workingWifiP2pGroupClientWithIfaceChanged() throws Exception {
- workingWifiP2pGroupClient(true);
- }
-
- @Test
- public void workingWifiP2pGroupClientSansIfaceChanged() throws Exception {
- workingWifiP2pGroupClient(false);
- }
-
- private void setDataSaverEnabled(boolean enabled) {
- final Intent intent = new Intent(ACTION_RESTRICT_BACKGROUND_CHANGED);
- mServiceContext.sendBroadcastAsUser(intent, UserHandle.ALL);
-
- final int status = enabled ? RESTRICT_BACKGROUND_STATUS_ENABLED
- : RESTRICT_BACKGROUND_STATUS_DISABLED;
- when(mCm.getRestrictBackgroundStatus()).thenReturn(status);
- mLooper.dispatchAll();
- }
-
- @Test
- public void testDataSaverChanged() {
- // Start Tethering.
- final UpstreamNetworkState upstreamState = buildMobileIPv4UpstreamState();
- runUsbTethering(upstreamState);
- assertContains(Arrays.asList(mTethering.getTetheredIfaces()), TEST_USB_IFNAME);
- // Data saver is ON.
- setDataSaverEnabled(true);
- // Verify that tethering should be disabled.
- verify(mUsbManager, times(1)).setCurrentFunctions(UsbManager.FUNCTION_NONE);
- mTethering.interfaceRemoved(TEST_USB_IFNAME);
- mLooper.dispatchAll();
- assertEquals(mTethering.getTetheredIfaces(), new String[0]);
- reset(mUsbManager);
-
- runUsbTethering(upstreamState);
- // Verify that user can start tethering again without turning OFF data saver.
- assertContains(Arrays.asList(mTethering.getTetheredIfaces()), TEST_USB_IFNAME);
-
- // If data saver is keep ON with change event, tethering should not be OFF this time.
- setDataSaverEnabled(true);
- verify(mUsbManager, times(0)).setCurrentFunctions(UsbManager.FUNCTION_NONE);
- assertContains(Arrays.asList(mTethering.getTetheredIfaces()), TEST_USB_IFNAME);
-
- // If data saver is turned OFF, it should not change tethering.
- setDataSaverEnabled(false);
- verify(mUsbManager, times(0)).setCurrentFunctions(UsbManager.FUNCTION_NONE);
- assertContains(Arrays.asList(mTethering.getTetheredIfaces()), TEST_USB_IFNAME);
- }
-
- private static <T> void assertContains(Collection<T> collection, T element) {
- assertTrue(element + " not found in " + collection, collection.contains(element));
- }
-
- private class ResultListener extends IIntResultListener.Stub {
- private final int mExpectedResult;
- private boolean mHasResult = false;
- ResultListener(final int expectedResult) {
- mExpectedResult = expectedResult;
- }
-
- @Override
- public void onResult(final int resultCode) {
- mHasResult = true;
- if (resultCode != mExpectedResult) {
- fail("expected result: " + mExpectedResult + " but actual result: " + resultCode);
- }
- }
-
- public void assertHasResult() {
- if (!mHasResult) fail("No callback result");
- }
- }
-
- @Test
- public void testMultipleStartTethering() throws Exception {
- final LinkAddress serverLinkAddr = new LinkAddress("192.168.20.1/24");
- final LinkAddress clientLinkAddr = new LinkAddress("192.168.20.42/24");
- final String serverAddr = "192.168.20.1";
- final ResultListener firstResult = new ResultListener(TETHER_ERROR_NO_ERROR);
- final ResultListener secondResult = new ResultListener(TETHER_ERROR_NO_ERROR);
- final ResultListener thirdResult = new ResultListener(TETHER_ERROR_NO_ERROR);
-
- // Enable USB tethering and check that Tethering starts USB.
- mTethering.startTethering(createTetheringRequestParcel(TETHERING_USB,
- null, null, false), firstResult);
- mLooper.dispatchAll();
- firstResult.assertHasResult();
- verify(mUsbManager, times(1)).setCurrentFunctions(UsbManager.FUNCTION_RNDIS);
- verifyNoMoreInteractions(mUsbManager);
-
- // Enable USB tethering again with the same request and expect no change to USB.
- mTethering.startTethering(createTetheringRequestParcel(TETHERING_USB,
- null, null, false), secondResult);
- mLooper.dispatchAll();
- secondResult.assertHasResult();
- verify(mUsbManager, never()).setCurrentFunctions(UsbManager.FUNCTION_NONE);
- reset(mUsbManager);
-
- // Enable USB tethering with a different request and expect that USB is stopped and
- // started.
- mTethering.startTethering(createTetheringRequestParcel(TETHERING_USB,
- serverLinkAddr, clientLinkAddr, false), thirdResult);
- mLooper.dispatchAll();
- thirdResult.assertHasResult();
- verify(mUsbManager, times(1)).setCurrentFunctions(UsbManager.FUNCTION_NONE);
- verify(mUsbManager, times(1)).setCurrentFunctions(UsbManager.FUNCTION_RNDIS);
-
- // Expect that when USB comes up, the DHCP server is configured with the requested address.
- mTethering.interfaceStatusChanged(TEST_USB_IFNAME, true);
- sendUsbBroadcast(true, true, true, TETHERING_USB);
- mLooper.dispatchAll();
- verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS).times(1)).startWithCallbacks(
- any(), any());
- verify(mNetd).interfaceSetCfg(argThat(cfg -> serverAddr.equals(cfg.ipv4Addr)));
- }
-
- @Test
- public void testRequestStaticIp() throws Exception {
- final LinkAddress serverLinkAddr = new LinkAddress("192.168.0.123/24");
- final LinkAddress clientLinkAddr = new LinkAddress("192.168.0.42/24");
- final String serverAddr = "192.168.0.123";
- final int clientAddrParceled = 0xc0a8002a;
- final ArgumentCaptor<DhcpServingParamsParcel> dhcpParamsCaptor =
- ArgumentCaptor.forClass(DhcpServingParamsParcel.class);
- mTethering.startTethering(createTetheringRequestParcel(TETHERING_USB,
- serverLinkAddr, clientLinkAddr, false), null);
- mLooper.dispatchAll();
- verify(mUsbManager, times(1)).setCurrentFunctions(UsbManager.FUNCTION_RNDIS);
- mTethering.interfaceStatusChanged(TEST_USB_IFNAME, true);
- sendUsbBroadcast(true, true, true, TETHERING_USB);
- mLooper.dispatchAll();
- verify(mNetd).interfaceSetCfg(argThat(cfg -> serverAddr.equals(cfg.ipv4Addr)));
- verify(mIpServerDependencies, times(1)).makeDhcpServer(any(), dhcpParamsCaptor.capture(),
- any());
- final DhcpServingParamsParcel params = dhcpParamsCaptor.getValue();
- assertEquals(serverAddr, intToInet4AddressHTH(params.serverAddr).getHostAddress());
- assertEquals(24, params.serverAddrPrefixLength);
- assertEquals(clientAddrParceled, params.singleClientAddr);
- }
-
- @Test
- public void testUpstreamNetworkChanged() {
- final Tethering.TetherMainSM stateMachine = (Tethering.TetherMainSM)
- mTetheringDependencies.mUpstreamNetworkMonitorSM;
- final UpstreamNetworkState upstreamState = buildMobileIPv4UpstreamState();
- initTetheringUpstream(upstreamState);
- stateMachine.chooseUpstreamType(true);
-
- verify(mUpstreamNetworkMonitor, times(1)).setCurrentUpstream(eq(upstreamState.network));
- verify(mNotificationUpdater, times(1)).onUpstreamCapabilitiesChanged(any());
- }
-
- @Test
- public void testUpstreamCapabilitiesChanged() {
- final Tethering.TetherMainSM stateMachine = (Tethering.TetherMainSM)
- mTetheringDependencies.mUpstreamNetworkMonitorSM;
- final UpstreamNetworkState upstreamState = buildMobileIPv4UpstreamState();
- initTetheringUpstream(upstreamState);
- stateMachine.chooseUpstreamType(true);
-
- stateMachine.handleUpstreamNetworkMonitorCallback(EVENT_ON_CAPABILITIES, upstreamState);
- // Should have two onUpstreamCapabilitiesChanged().
- // One is called by reportUpstreamChanged(). One is called by EVENT_ON_CAPABILITIES.
- verify(mNotificationUpdater, times(2)).onUpstreamCapabilitiesChanged(any());
- reset(mNotificationUpdater);
-
- // Verify that onUpstreamCapabilitiesChanged won't be called if not current upstream network
- // capabilities changed.
- final UpstreamNetworkState upstreamState2 = new UpstreamNetworkState(
- upstreamState.linkProperties, upstreamState.networkCapabilities, new Network(101));
- stateMachine.handleUpstreamNetworkMonitorCallback(EVENT_ON_CAPABILITIES, upstreamState2);
- verify(mNotificationUpdater, never()).onUpstreamCapabilitiesChanged(any());
- }
-
- @Test
- public void testDumpTetheringLog() throws Exception {
- final FileDescriptor mockFd = mock(FileDescriptor.class);
- final PrintWriter mockPw = mock(PrintWriter.class);
- runUsbTethering(null);
- mLooper.startAutoDispatch();
- mTethering.dump(mockFd, mockPw, new String[0]);
- verify(mConfig).dump(any());
- verify(mEntitleMgr).dump(any());
- verify(mOffloadCtrl).dump(any());
- mLooper.stopAutoDispatch();
- }
-
- @Test
- public void testExemptFromEntitlementCheck() throws Exception {
- setupForRequiredProvisioning();
- final TetheringRequestParcel wifiNotExemptRequest =
- createTetheringRequestParcel(TETHERING_WIFI, null, null, false);
- mTethering.startTethering(wifiNotExemptRequest, null);
- mLooper.dispatchAll();
- verify(mEntitleMgr).startProvisioningIfNeeded(TETHERING_WIFI, false);
- verify(mEntitleMgr, never()).setExemptedDownstreamType(TETHERING_WIFI);
- assertFalse(mEntitleMgr.isCellularUpstreamPermitted());
- mTethering.stopTethering(TETHERING_WIFI);
- mLooper.dispatchAll();
- verify(mEntitleMgr).stopProvisioningIfNeeded(TETHERING_WIFI);
- reset(mEntitleMgr);
-
- setupForRequiredProvisioning();
- final TetheringRequestParcel wifiExemptRequest =
- createTetheringRequestParcel(TETHERING_WIFI, null, null, true);
- mTethering.startTethering(wifiExemptRequest, null);
- mLooper.dispatchAll();
- verify(mEntitleMgr, never()).startProvisioningIfNeeded(TETHERING_WIFI, false);
- verify(mEntitleMgr).setExemptedDownstreamType(TETHERING_WIFI);
- assertTrue(mEntitleMgr.isCellularUpstreamPermitted());
- mTethering.stopTethering(TETHERING_WIFI);
- mLooper.dispatchAll();
- verify(mEntitleMgr).stopProvisioningIfNeeded(TETHERING_WIFI);
- reset(mEntitleMgr);
-
- // If one app enables tethering without provisioning check first, then another app enables
- // tethering of the same type but does not disable the provisioning check.
- setupForRequiredProvisioning();
- mTethering.startTethering(wifiExemptRequest, null);
- mLooper.dispatchAll();
- verify(mEntitleMgr, never()).startProvisioningIfNeeded(TETHERING_WIFI, false);
- verify(mEntitleMgr).setExemptedDownstreamType(TETHERING_WIFI);
- assertTrue(mEntitleMgr.isCellularUpstreamPermitted());
- reset(mEntitleMgr);
- setupForRequiredProvisioning();
- mTethering.startTethering(wifiNotExemptRequest, null);
- mLooper.dispatchAll();
- verify(mEntitleMgr).startProvisioningIfNeeded(TETHERING_WIFI, false);
- verify(mEntitleMgr, never()).setExemptedDownstreamType(TETHERING_WIFI);
- assertFalse(mEntitleMgr.isCellularUpstreamPermitted());
- mTethering.stopTethering(TETHERING_WIFI);
- mLooper.dispatchAll();
- verify(mEntitleMgr).stopProvisioningIfNeeded(TETHERING_WIFI);
- reset(mEntitleMgr);
- }
-
- private void setupForRequiredProvisioning() {
- // Produce some acceptable looking provision app setting if requested.
- when(mResources.getStringArray(R.array.config_mobile_hotspot_provision_app))
- .thenReturn(PROVISIONING_APP_NAME);
- when(mResources.getString(R.string.config_mobile_hotspot_provision_app_no_ui))
- .thenReturn(PROVISIONING_NO_UI_APP_NAME);
- // Act like the CarrierConfigManager is present and ready unless told otherwise.
- when(mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE))
- .thenReturn(mCarrierConfigManager);
- when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(mCarrierConfig);
- mCarrierConfig.putBoolean(CarrierConfigManager.KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL, true);
- mCarrierConfig.putBoolean(CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL, true);
- sendConfigurationChanged();
- }
-
- private static UpstreamNetworkState buildV4UpstreamState(final LinkAddress address,
- final Network network, final String iface, final int transportType) {
- final LinkProperties prop = new LinkProperties();
- prop.setInterfaceName(iface);
-
- prop.addLinkAddress(address);
-
- final NetworkCapabilities capabilities = new NetworkCapabilities()
- .addTransportType(transportType);
- return new UpstreamNetworkState(prop, capabilities, network);
- }
-
- private void updateV4Upstream(final LinkAddress ipv4Address, final Network network,
- final String iface, final int transportType) {
- final UpstreamNetworkState upstream = buildV4UpstreamState(ipv4Address, network, iface,
- transportType);
- mTetheringDependencies.mUpstreamNetworkMonitorSM.sendMessage(
- Tethering.TetherMainSM.EVENT_UPSTREAM_CALLBACK,
- UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES,
- 0,
- upstream);
- mLooper.dispatchAll();
- }
-
- @Test
- public void testHandleIpConflict() throws Exception {
- final Network wifiNetwork = new Network(200);
- final Network[] allNetworks = { wifiNetwork };
- when(mCm.getAllNetworks()).thenReturn(allNetworks);
- runUsbTethering(null);
- final ArgumentCaptor<InterfaceConfigurationParcel> ifaceConfigCaptor =
- ArgumentCaptor.forClass(InterfaceConfigurationParcel.class);
- verify(mNetd).interfaceSetCfg(ifaceConfigCaptor.capture());
- final String ipv4Address = ifaceConfigCaptor.getValue().ipv4Addr;
- verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS).times(1)).startWithCallbacks(
- any(), any());
- reset(mNetd, mUsbManager);
-
- // Cause a prefix conflict by assigning a /30 out of the downstream's /24 to the upstream.
- updateV4Upstream(new LinkAddress(InetAddresses.parseNumericAddress(ipv4Address), 30),
- wifiNetwork, TEST_WIFI_IFNAME, TRANSPORT_WIFI);
- // verify turn off usb tethering
- verify(mUsbManager).setCurrentFunctions(UsbManager.FUNCTION_NONE);
- mTethering.interfaceRemoved(TEST_USB_IFNAME);
- mLooper.dispatchAll();
- // verify restart usb tethering
- verify(mUsbManager).setCurrentFunctions(UsbManager.FUNCTION_RNDIS);
- }
-
- @Test
- public void testNoAddressAvailable() throws Exception {
- final Network wifiNetwork = new Network(200);
- final Network btNetwork = new Network(201);
- final Network mobileNetwork = new Network(202);
- final Network[] allNetworks = { wifiNetwork, btNetwork, mobileNetwork };
- when(mCm.getAllNetworks()).thenReturn(allNetworks);
- runUsbTethering(null);
- verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS).times(1)).startWithCallbacks(
- any(), any());
- reset(mUsbManager);
- final TetheredInterfaceRequest mockRequest = mock(TetheredInterfaceRequest.class);
- when(mEm.requestTetheredInterface(any(), any())).thenReturn(mockRequest);
- final ArgumentCaptor<TetheredInterfaceCallback> callbackCaptor =
- ArgumentCaptor.forClass(TetheredInterfaceCallback.class);
- mTethering.startTethering(createTetheringRequestParcel(TETHERING_ETHERNET), null);
- mLooper.dispatchAll();
- verify(mEm).requestTetheredInterface(any(), callbackCaptor.capture());
- TetheredInterfaceCallback ethCallback = callbackCaptor.getValue();
- ethCallback.onAvailable(TEST_ETH_IFNAME);
- mLooper.dispatchAll();
- reset(mUsbManager, mEm);
-
- updateV4Upstream(new LinkAddress("192.168.0.100/16"), wifiNetwork, TEST_WIFI_IFNAME,
- TRANSPORT_WIFI);
- updateV4Upstream(new LinkAddress("172.16.0.0/12"), btNetwork, TEST_BT_IFNAME,
- TRANSPORT_BLUETOOTH);
- updateV4Upstream(new LinkAddress("10.0.0.0/8"), mobileNetwork, TEST_MOBILE_IFNAME,
- TRANSPORT_CELLULAR);
-
- mLooper.dispatchAll();
- // verify turn off usb tethering
- verify(mUsbManager).setCurrentFunctions(UsbManager.FUNCTION_NONE);
- // verify turn off ethernet tethering
- verify(mockRequest).release();
- mTethering.interfaceRemoved(TEST_USB_IFNAME);
- ethCallback.onUnavailable();
- mLooper.dispatchAll();
- // verify restart usb tethering
- verify(mUsbManager).setCurrentFunctions(UsbManager.FUNCTION_RNDIS);
- // verify restart ethernet tethering
- verify(mEm).requestTetheredInterface(any(), callbackCaptor.capture());
- ethCallback = callbackCaptor.getValue();
- ethCallback.onAvailable(TEST_ETH_IFNAME);
-
- reset(mUsbManager, mEm);
- when(mNetd.interfaceGetList())
- .thenReturn(new String[] {
- TEST_MOBILE_IFNAME, TEST_WLAN_IFNAME, TEST_USB_IFNAME, TEST_P2P_IFNAME,
- TEST_NCM_IFNAME, TEST_ETH_IFNAME});
-
- mTethering.interfaceStatusChanged(TEST_USB_IFNAME, true);
- sendUsbBroadcast(true, true, true, TETHERING_USB);
- mLooper.dispatchAll();
- assertContains(Arrays.asList(mTethering.getTetherableIfaces()), TEST_USB_IFNAME);
- assertContains(Arrays.asList(mTethering.getTetherableIfaces()), TEST_ETH_IFNAME);
- assertEquals(TETHER_ERROR_IFACE_CFG_ERROR, mTethering.getLastTetherError(TEST_USB_IFNAME));
- assertEquals(TETHER_ERROR_IFACE_CFG_ERROR, mTethering.getLastTetherError(TEST_ETH_IFNAME));
- }
-
- @Test
- public void testProvisioningNeededButUnavailable() throws Exception {
- assertTrue(mTethering.isTetheringSupported());
- verify(mPackageManager, never()).getPackageInfo(PROVISIONING_APP_NAME[0], GET_ACTIVITIES);
-
- setupForRequiredProvisioning();
- assertTrue(mTethering.isTetheringSupported());
- verify(mPackageManager).getPackageInfo(PROVISIONING_APP_NAME[0], GET_ACTIVITIES);
- reset(mPackageManager);
-
- doThrow(PackageManager.NameNotFoundException.class).when(mPackageManager).getPackageInfo(
- PROVISIONING_APP_NAME[0], GET_ACTIVITIES);
- setupForRequiredProvisioning();
- assertFalse(mTethering.isTetheringSupported());
- verify(mPackageManager).getPackageInfo(PROVISIONING_APP_NAME[0], GET_ACTIVITIES);
- }
-
- // TODO: Test that a request for hotspot mode doesn't interfere with an
- // already operating tethering mode interface.
-}
diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/UpstreamNetworkMonitorTest.java b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/UpstreamNetworkMonitorTest.java
deleted file mode 100644
index 232588c7..0000000
--- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/UpstreamNetworkMonitorTest.java
+++ /dev/null
@@ -1,800 +0,0 @@
-/*
- * Copyright (C) 2017 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;
-
-import static android.net.ConnectivityManager.TYPE_MOBILE_DUN;
-import static android.net.ConnectivityManager.TYPE_MOBILE_HIPRI;
-import static android.net.ConnectivityManager.TYPE_WIFI;
-import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
-import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
-import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
-import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
-
-import static com.android.networkstack.tethering.UpstreamNetworkMonitor.TYPE_NONE;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.anyInt;
-import static org.mockito.Mockito.anyString;
-import static org.mockito.Mockito.eq;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.net.ConnectivityManager;
-import android.net.ConnectivityManager.NetworkCallback;
-import android.net.IConnectivityManager;
-import android.net.IpPrefix;
-import android.net.LinkAddress;
-import android.net.LinkProperties;
-import android.net.Network;
-import android.net.NetworkCapabilities;
-import android.net.NetworkRequest;
-import android.net.util.SharedLog;
-import android.os.Handler;
-import android.os.Message;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import com.android.internal.util.State;
-import com.android.internal.util.StateMachine;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class UpstreamNetworkMonitorTest {
- private static final int EVENT_UNM_UPDATE = 1;
-
- private static final boolean INCLUDES = true;
- private static final boolean EXCLUDES = false;
-
- // Actual contents of the request don't matter for this test. The lack of
- // any specific TRANSPORT_* is sufficient to identify this request.
- private static final NetworkRequest sDefaultRequest = new NetworkRequest.Builder().build();
-
- @Mock private Context mContext;
- @Mock private EntitlementManager mEntitleMgr;
- @Mock private IConnectivityManager mCS;
- @Mock private SharedLog mLog;
-
- private TestStateMachine mSM;
- private TestConnectivityManager mCM;
- private UpstreamNetworkMonitor mUNM;
-
- @Before public void setUp() throws Exception {
- MockitoAnnotations.initMocks(this);
- reset(mContext);
- reset(mCS);
- reset(mLog);
- when(mLog.forSubComponent(anyString())).thenReturn(mLog);
- when(mEntitleMgr.isCellularUpstreamPermitted()).thenReturn(true);
-
- mCM = spy(new TestConnectivityManager(mContext, mCS));
- mSM = new TestStateMachine();
- mUNM = new UpstreamNetworkMonitor(
- (ConnectivityManager) mCM, mSM, mLog, EVENT_UNM_UPDATE);
- }
-
- @After public void tearDown() throws Exception {
- if (mSM != null) {
- mSM.quit();
- mSM = null;
- }
- }
-
- @Test
- public void testStopWithoutStartIsNonFatal() {
- mUNM.stop();
- mUNM.stop();
- mUNM.stop();
- }
-
- @Test
- public void testDoesNothingBeforeTrackDefaultAndStarted() throws Exception {
- assertTrue(mCM.hasNoCallbacks());
- assertFalse(mUNM.mobileNetworkRequested());
-
- mUNM.updateMobileRequiresDun(true);
- assertTrue(mCM.hasNoCallbacks());
- mUNM.updateMobileRequiresDun(false);
- assertTrue(mCM.hasNoCallbacks());
- }
-
- @Test
- public void testDefaultNetworkIsTracked() throws Exception {
- assertTrue(mCM.hasNoCallbacks());
- mUNM.startTrackDefaultNetwork(sDefaultRequest, mEntitleMgr);
-
- mUNM.startObserveAllNetworks();
- assertEquals(1, mCM.trackingDefault.size());
-
- mUNM.stop();
- assertTrue(mCM.onlyHasDefaultCallbacks());
- }
-
- @Test
- public void testListensForAllNetworks() throws Exception {
- assertTrue(mCM.listening.isEmpty());
-
- mUNM.startTrackDefaultNetwork(sDefaultRequest, mEntitleMgr);
- mUNM.startObserveAllNetworks();
- assertFalse(mCM.listening.isEmpty());
- assertTrue(mCM.isListeningForAll());
-
- mUNM.stop();
- assertTrue(mCM.onlyHasDefaultCallbacks());
- }
-
- @Test
- public void testCallbacksRegistered() {
- mUNM.startTrackDefaultNetwork(sDefaultRequest, mEntitleMgr);
- verify(mCM, times(1)).requestNetwork(
- eq(sDefaultRequest), any(NetworkCallback.class), any(Handler.class));
- mUNM.startObserveAllNetworks();
- verify(mCM, times(1)).registerNetworkCallback(
- any(NetworkRequest.class), any(NetworkCallback.class), any(Handler.class));
-
- mUNM.stop();
- verify(mCM, times(1)).unregisterNetworkCallback(any(NetworkCallback.class));
- }
-
- @Test
- public void testRequestsMobileNetwork() throws Exception {
- assertFalse(mUNM.mobileNetworkRequested());
- assertEquals(0, mCM.requested.size());
-
- mUNM.startObserveAllNetworks();
- assertFalse(mUNM.mobileNetworkRequested());
- assertEquals(0, mCM.requested.size());
-
- mUNM.updateMobileRequiresDun(false);
- assertFalse(mUNM.mobileNetworkRequested());
- assertEquals(0, mCM.requested.size());
-
- mUNM.registerMobileNetworkRequest();
- assertTrue(mUNM.mobileNetworkRequested());
- assertUpstreamTypeRequested(TYPE_MOBILE_HIPRI);
- assertFalse(isDunRequested());
-
- mUNM.stop();
- assertFalse(mUNM.mobileNetworkRequested());
- assertTrue(mCM.hasNoCallbacks());
- }
-
- @Test
- public void testDuplicateMobileRequestsIgnored() throws Exception {
- assertFalse(mUNM.mobileNetworkRequested());
- assertEquals(0, mCM.requested.size());
-
- mUNM.startObserveAllNetworks();
- verify(mCM, times(1)).registerNetworkCallback(
- any(NetworkRequest.class), any(NetworkCallback.class), any(Handler.class));
- assertFalse(mUNM.mobileNetworkRequested());
- assertEquals(0, mCM.requested.size());
-
- mUNM.updateMobileRequiresDun(true);
- mUNM.registerMobileNetworkRequest();
- verify(mCM, times(1)).requestNetwork(
- any(NetworkRequest.class), anyInt(), anyInt(), any(Handler.class),
- any(NetworkCallback.class));
-
- assertTrue(mUNM.mobileNetworkRequested());
- assertUpstreamTypeRequested(TYPE_MOBILE_DUN);
- assertTrue(isDunRequested());
-
- // Try a few things that must not result in any state change.
- mUNM.registerMobileNetworkRequest();
- mUNM.updateMobileRequiresDun(true);
- mUNM.registerMobileNetworkRequest();
-
- assertTrue(mUNM.mobileNetworkRequested());
- assertUpstreamTypeRequested(TYPE_MOBILE_DUN);
- assertTrue(isDunRequested());
-
- mUNM.stop();
- verify(mCM, times(2)).unregisterNetworkCallback(any(NetworkCallback.class));
-
- verifyNoMoreInteractions(mCM);
- }
-
- @Test
- public void testRequestsDunNetwork() throws Exception {
- assertFalse(mUNM.mobileNetworkRequested());
- assertEquals(0, mCM.requested.size());
-
- mUNM.startObserveAllNetworks();
- assertFalse(mUNM.mobileNetworkRequested());
- assertEquals(0, mCM.requested.size());
-
- mUNM.updateMobileRequiresDun(true);
- assertFalse(mUNM.mobileNetworkRequested());
- assertEquals(0, mCM.requested.size());
-
- mUNM.registerMobileNetworkRequest();
- assertTrue(mUNM.mobileNetworkRequested());
- assertUpstreamTypeRequested(TYPE_MOBILE_DUN);
- assertTrue(isDunRequested());
-
- mUNM.stop();
- assertFalse(mUNM.mobileNetworkRequested());
- assertTrue(mCM.hasNoCallbacks());
- }
-
- @Test
- public void testUpdateMobileRequiresDun() throws Exception {
- mUNM.startObserveAllNetworks();
-
- // Test going from no-DUN to DUN correctly re-registers callbacks.
- mUNM.updateMobileRequiresDun(false);
- mUNM.registerMobileNetworkRequest();
- assertTrue(mUNM.mobileNetworkRequested());
- assertUpstreamTypeRequested(TYPE_MOBILE_HIPRI);
- assertFalse(isDunRequested());
- mUNM.updateMobileRequiresDun(true);
- assertTrue(mUNM.mobileNetworkRequested());
- assertUpstreamTypeRequested(TYPE_MOBILE_DUN);
- assertTrue(isDunRequested());
-
- // Test going from DUN to no-DUN correctly re-registers callbacks.
- mUNM.updateMobileRequiresDun(false);
- assertTrue(mUNM.mobileNetworkRequested());
- assertUpstreamTypeRequested(TYPE_MOBILE_HIPRI);
- assertFalse(isDunRequested());
-
- mUNM.stop();
- assertFalse(mUNM.mobileNetworkRequested());
- }
-
- @Test
- public void testSelectPreferredUpstreamType() throws Exception {
- final Collection<Integer> preferredTypes = new ArrayList<>();
- preferredTypes.add(TYPE_WIFI);
-
- mUNM.startTrackDefaultNetwork(sDefaultRequest, mEntitleMgr);
- mUNM.startObserveAllNetworks();
- // There are no networks, so there is nothing to select.
- assertSatisfiesLegacyType(TYPE_NONE, mUNM.selectPreferredUpstreamType(preferredTypes));
-
- final TestNetworkAgent wifiAgent = new TestNetworkAgent(mCM, TRANSPORT_WIFI);
- wifiAgent.fakeConnect();
- // WiFi is up, we should prefer it.
- assertSatisfiesLegacyType(TYPE_WIFI, mUNM.selectPreferredUpstreamType(preferredTypes));
- wifiAgent.fakeDisconnect();
- // There are no networks, so there is nothing to select.
- assertSatisfiesLegacyType(TYPE_NONE, mUNM.selectPreferredUpstreamType(preferredTypes));
-
- final TestNetworkAgent cellAgent = new TestNetworkAgent(mCM, TRANSPORT_CELLULAR);
- cellAgent.fakeConnect();
- assertSatisfiesLegacyType(TYPE_NONE, mUNM.selectPreferredUpstreamType(preferredTypes));
-
- preferredTypes.add(TYPE_MOBILE_DUN);
- // This is coupled with preferred types in TetheringConfiguration.
- mUNM.updateMobileRequiresDun(true);
- // DUN is available, but only use regular cell: no upstream selected.
- assertSatisfiesLegacyType(TYPE_NONE, mUNM.selectPreferredUpstreamType(preferredTypes));
- preferredTypes.remove(TYPE_MOBILE_DUN);
- // No WiFi, but our preferred flavour of cell is up.
- preferredTypes.add(TYPE_MOBILE_HIPRI);
- // This is coupled with preferred types in TetheringConfiguration.
- mUNM.updateMobileRequiresDun(false);
- assertSatisfiesLegacyType(TYPE_MOBILE_HIPRI,
- mUNM.selectPreferredUpstreamType(preferredTypes));
- // Check to see we filed an explicit request.
- assertEquals(1, mCM.requested.size());
- NetworkRequest netReq = (NetworkRequest) mCM.requested.values().toArray()[0];
- assertTrue(netReq.networkCapabilities.hasTransport(TRANSPORT_CELLULAR));
- assertFalse(netReq.networkCapabilities.hasCapability(NET_CAPABILITY_DUN));
- // mobile is not permitted, we should not use HIPRI.
- when(mEntitleMgr.isCellularUpstreamPermitted()).thenReturn(false);
- assertSatisfiesLegacyType(TYPE_NONE, mUNM.selectPreferredUpstreamType(preferredTypes));
- assertEquals(0, mCM.requested.size());
- // mobile change back to permitted, HIRPI should come back
- when(mEntitleMgr.isCellularUpstreamPermitted()).thenReturn(true);
- assertSatisfiesLegacyType(TYPE_MOBILE_HIPRI,
- mUNM.selectPreferredUpstreamType(preferredTypes));
-
- wifiAgent.fakeConnect();
- // WiFi is up, and we should prefer it over cell.
- assertSatisfiesLegacyType(TYPE_WIFI, mUNM.selectPreferredUpstreamType(preferredTypes));
- assertEquals(0, mCM.requested.size());
-
- preferredTypes.remove(TYPE_MOBILE_HIPRI);
- preferredTypes.add(TYPE_MOBILE_DUN);
- // This is coupled with preferred types in TetheringConfiguration.
- mUNM.updateMobileRequiresDun(true);
- assertSatisfiesLegacyType(TYPE_WIFI, mUNM.selectPreferredUpstreamType(preferredTypes));
-
- final TestNetworkAgent dunAgent = new TestNetworkAgent(mCM, TRANSPORT_CELLULAR);
- dunAgent.networkCapabilities.addCapability(NET_CAPABILITY_DUN);
- dunAgent.fakeConnect();
-
- // WiFi is still preferred.
- assertSatisfiesLegacyType(TYPE_WIFI, mUNM.selectPreferredUpstreamType(preferredTypes));
-
- // WiFi goes down, cell and DUN are still up but only DUN is preferred.
- wifiAgent.fakeDisconnect();
- assertSatisfiesLegacyType(TYPE_MOBILE_DUN,
- mUNM.selectPreferredUpstreamType(preferredTypes));
- // Check to see we filed an explicit request.
- assertEquals(1, mCM.requested.size());
- netReq = (NetworkRequest) mCM.requested.values().toArray()[0];
- assertTrue(netReq.networkCapabilities.hasTransport(TRANSPORT_CELLULAR));
- assertTrue(netReq.networkCapabilities.hasCapability(NET_CAPABILITY_DUN));
- // mobile is not permitted, we should not use DUN.
- when(mEntitleMgr.isCellularUpstreamPermitted()).thenReturn(false);
- assertSatisfiesLegacyType(TYPE_NONE, mUNM.selectPreferredUpstreamType(preferredTypes));
- assertEquals(0, mCM.requested.size());
- // mobile change back to permitted, DUN should come back
- when(mEntitleMgr.isCellularUpstreamPermitted()).thenReturn(true);
- assertSatisfiesLegacyType(TYPE_MOBILE_DUN,
- mUNM.selectPreferredUpstreamType(preferredTypes));
- }
-
- @Test
- public void testGetCurrentPreferredUpstream() throws Exception {
- mUNM.startTrackDefaultNetwork(sDefaultRequest, mEntitleMgr);
- mUNM.startObserveAllNetworks();
- mUNM.updateMobileRequiresDun(false);
-
- // [0] Mobile connects, DUN not required -> mobile selected.
- final TestNetworkAgent cellAgent = new TestNetworkAgent(mCM, TRANSPORT_CELLULAR);
- cellAgent.fakeConnect();
- mCM.makeDefaultNetwork(cellAgent);
- assertEquals(cellAgent.networkId, mUNM.getCurrentPreferredUpstream().network);
-
- // [1] Mobile connects but not permitted -> null selected
- when(mEntitleMgr.isCellularUpstreamPermitted()).thenReturn(false);
- assertEquals(null, mUNM.getCurrentPreferredUpstream());
- when(mEntitleMgr.isCellularUpstreamPermitted()).thenReturn(true);
-
- // [2] WiFi connects but not validated/promoted to default -> mobile selected.
- final TestNetworkAgent wifiAgent = new TestNetworkAgent(mCM, TRANSPORT_WIFI);
- wifiAgent.fakeConnect();
- assertEquals(cellAgent.networkId, mUNM.getCurrentPreferredUpstream().network);
-
- // [3] WiFi validates and is promoted to the default network -> WiFi selected.
- mCM.makeDefaultNetwork(wifiAgent);
- assertEquals(wifiAgent.networkId, mUNM.getCurrentPreferredUpstream().network);
-
- // [4] DUN required, no other changes -> WiFi still selected
- mUNM.updateMobileRequiresDun(true);
- assertEquals(wifiAgent.networkId, mUNM.getCurrentPreferredUpstream().network);
-
- // [5] WiFi no longer validated, mobile becomes default, DUN required -> null selected.
- mCM.makeDefaultNetwork(cellAgent);
- assertEquals(null, mUNM.getCurrentPreferredUpstream());
- // TODO: make sure that a DUN request has been filed. This is currently
- // triggered by code over in Tethering, but once that has been moved
- // into UNM we should test for this here.
-
- // [6] DUN network arrives -> DUN selected
- final TestNetworkAgent dunAgent = new TestNetworkAgent(mCM, TRANSPORT_CELLULAR);
- dunAgent.networkCapabilities.addCapability(NET_CAPABILITY_DUN);
- dunAgent.networkCapabilities.removeCapability(NET_CAPABILITY_INTERNET);
- dunAgent.fakeConnect();
- assertEquals(dunAgent.networkId, mUNM.getCurrentPreferredUpstream().network);
-
- // [7] Mobile is not permitted -> null selected
- when(mEntitleMgr.isCellularUpstreamPermitted()).thenReturn(false);
- assertEquals(null, mUNM.getCurrentPreferredUpstream());
- }
-
- @Test
- public void testLocalPrefixes() throws Exception {
- mUNM.startTrackDefaultNetwork(sDefaultRequest, mEntitleMgr);
- mUNM.startObserveAllNetworks();
-
- // [0] Test minimum set of local prefixes.
- Set<IpPrefix> local = mUNM.getLocalPrefixes();
- assertTrue(local.isEmpty());
-
- final Set<String> alreadySeen = new HashSet<>();
-
- // [1] Pretend Wi-Fi connects.
- final TestNetworkAgent wifiAgent = new TestNetworkAgent(mCM, TRANSPORT_WIFI);
- final LinkProperties wifiLp = wifiAgent.linkProperties;
- wifiLp.setInterfaceName("wlan0");
- final String[] wifi_addrs = {
- "fe80::827a:bfff:fe6f:374d", "100.112.103.18",
- "2001:db8:4:fd00:827a:bfff:fe6f:374d",
- "2001:db8:4:fd00:6dea:325a:fdae:4ef4",
- "fd6a:a640:60bf:e985::123", // ULA address for good measure.
- };
- for (String addrStr : wifi_addrs) {
- final String cidr = addrStr.contains(":") ? "/64" : "/20";
- wifiLp.addLinkAddress(new LinkAddress(addrStr + cidr));
- }
- wifiAgent.fakeConnect();
- wifiAgent.sendLinkProperties();
-
- local = mUNM.getLocalPrefixes();
- assertPrefixSet(local, INCLUDES, alreadySeen);
- final String[] wifiLinkPrefixes = {
- // Link-local prefixes are excluded and dealt with elsewhere.
- "100.112.96.0/20", "2001:db8:4:fd00::/64", "fd6a:a640:60bf:e985::/64",
- };
- assertPrefixSet(local, INCLUDES, wifiLinkPrefixes);
- Collections.addAll(alreadySeen, wifiLinkPrefixes);
- assertEquals(alreadySeen.size(), local.size());
-
- // [2] Pretend mobile connects.
- final TestNetworkAgent cellAgent = new TestNetworkAgent(mCM, TRANSPORT_CELLULAR);
- final LinkProperties cellLp = cellAgent.linkProperties;
- cellLp.setInterfaceName("rmnet_data0");
- final String[] cell_addrs = {
- "10.102.211.48", "2001:db8:0:1:b50e:70d9:10c9:433d",
- };
- for (String addrStr : cell_addrs) {
- final String cidr = addrStr.contains(":") ? "/64" : "/27";
- cellLp.addLinkAddress(new LinkAddress(addrStr + cidr));
- }
- cellAgent.fakeConnect();
- cellAgent.sendLinkProperties();
-
- local = mUNM.getLocalPrefixes();
- assertPrefixSet(local, INCLUDES, alreadySeen);
- final String[] cellLinkPrefixes = { "10.102.211.32/27", "2001:db8:0:1::/64" };
- assertPrefixSet(local, INCLUDES, cellLinkPrefixes);
- Collections.addAll(alreadySeen, cellLinkPrefixes);
- assertEquals(alreadySeen.size(), local.size());
-
- // [3] Pretend DUN connects.
- final TestNetworkAgent dunAgent = new TestNetworkAgent(mCM, TRANSPORT_CELLULAR);
- dunAgent.networkCapabilities.addCapability(NET_CAPABILITY_DUN);
- dunAgent.networkCapabilities.removeCapability(NET_CAPABILITY_INTERNET);
- final LinkProperties dunLp = dunAgent.linkProperties;
- dunLp.setInterfaceName("rmnet_data1");
- final String[] dun_addrs = {
- "192.0.2.48", "2001:db8:1:2:b50e:70d9:10c9:433d",
- };
- for (String addrStr : dun_addrs) {
- final String cidr = addrStr.contains(":") ? "/64" : "/27";
- dunLp.addLinkAddress(new LinkAddress(addrStr + cidr));
- }
- dunAgent.fakeConnect();
- dunAgent.sendLinkProperties();
-
- local = mUNM.getLocalPrefixes();
- assertPrefixSet(local, INCLUDES, alreadySeen);
- final String[] dunLinkPrefixes = { "192.0.2.32/27", "2001:db8:1:2::/64" };
- assertPrefixSet(local, INCLUDES, dunLinkPrefixes);
- Collections.addAll(alreadySeen, dunLinkPrefixes);
- assertEquals(alreadySeen.size(), local.size());
-
- // [4] Pretend Wi-Fi disconnected. It's addresses/prefixes should no
- // longer be included (should be properly removed).
- wifiAgent.fakeDisconnect();
- local = mUNM.getLocalPrefixes();
- assertPrefixSet(local, EXCLUDES, wifiLinkPrefixes);
- assertPrefixSet(local, INCLUDES, cellLinkPrefixes);
- assertPrefixSet(local, INCLUDES, dunLinkPrefixes);
-
- // [5] Pretend mobile disconnected.
- cellAgent.fakeDisconnect();
- local = mUNM.getLocalPrefixes();
- assertPrefixSet(local, EXCLUDES, wifiLinkPrefixes);
- assertPrefixSet(local, EXCLUDES, cellLinkPrefixes);
- assertPrefixSet(local, INCLUDES, dunLinkPrefixes);
-
- // [6] Pretend DUN disconnected.
- dunAgent.fakeDisconnect();
- local = mUNM.getLocalPrefixes();
- assertTrue(local.isEmpty());
- }
-
- @Test
- public void testSelectMobileWhenMobileIsNotDefault() {
- final Collection<Integer> preferredTypes = new ArrayList<>();
- // Mobile has higher pirority than wifi.
- preferredTypes.add(TYPE_MOBILE_HIPRI);
- preferredTypes.add(TYPE_WIFI);
- mUNM.startTrackDefaultNetwork(sDefaultRequest, mEntitleMgr);
- mUNM.startObserveAllNetworks();
- // Setup wifi and make wifi as default network.
- final TestNetworkAgent wifiAgent = new TestNetworkAgent(mCM, TRANSPORT_WIFI);
- wifiAgent.fakeConnect();
- mCM.makeDefaultNetwork(wifiAgent);
- // Setup mobile network.
- final TestNetworkAgent cellAgent = new TestNetworkAgent(mCM, TRANSPORT_CELLULAR);
- cellAgent.fakeConnect();
-
- assertSatisfiesLegacyType(TYPE_MOBILE_HIPRI,
- mUNM.selectPreferredUpstreamType(preferredTypes));
- verify(mEntitleMgr, times(1)).maybeRunProvisioning();
- }
-
- private void assertSatisfiesLegacyType(int legacyType, UpstreamNetworkState ns) {
- if (legacyType == TYPE_NONE) {
- assertTrue(ns == null);
- return;
- }
-
- final NetworkCapabilities nc =
- UpstreamNetworkMonitor.networkCapabilitiesForType(legacyType);
- assertTrue(nc.satisfiedByNetworkCapabilities(ns.networkCapabilities));
- }
-
- private void assertUpstreamTypeRequested(int upstreamType) throws Exception {
- assertEquals(1, mCM.requested.size());
- assertEquals(1, mCM.legacyTypeMap.size());
- assertEquals(Integer.valueOf(upstreamType),
- mCM.legacyTypeMap.values().iterator().next());
- }
-
- private boolean isDunRequested() {
- for (NetworkRequest req : mCM.requested.values()) {
- if (req.networkCapabilities.hasCapability(NET_CAPABILITY_DUN)) {
- return true;
- }
- }
- return false;
- }
-
- public static class TestConnectivityManager extends ConnectivityManager {
- public Map<NetworkCallback, Handler> allCallbacks = new HashMap<>();
- public Set<NetworkCallback> trackingDefault = new HashSet<>();
- public TestNetworkAgent defaultNetwork = null;
- public Map<NetworkCallback, NetworkRequest> listening = new HashMap<>();
- public Map<NetworkCallback, NetworkRequest> requested = new HashMap<>();
- public Map<NetworkCallback, Integer> legacyTypeMap = new HashMap<>();
-
- private int mNetworkId = 100;
-
- public TestConnectivityManager(Context ctx, IConnectivityManager svc) {
- super(ctx, svc);
- }
-
- boolean hasNoCallbacks() {
- return allCallbacks.isEmpty()
- && trackingDefault.isEmpty()
- && listening.isEmpty()
- && requested.isEmpty()
- && legacyTypeMap.isEmpty();
- }
-
- boolean onlyHasDefaultCallbacks() {
- return (allCallbacks.size() == 1)
- && (trackingDefault.size() == 1)
- && listening.isEmpty()
- && requested.isEmpty()
- && legacyTypeMap.isEmpty();
- }
-
- boolean isListeningForAll() {
- final NetworkCapabilities empty = new NetworkCapabilities();
- empty.clearAll();
-
- for (NetworkRequest req : listening.values()) {
- if (req.networkCapabilities.equalRequestableCapabilities(empty)) {
- return true;
- }
- }
- return false;
- }
-
- int getNetworkId() {
- return ++mNetworkId;
- }
-
- void makeDefaultNetwork(TestNetworkAgent agent) {
- if (Objects.equals(defaultNetwork, agent)) return;
-
- final TestNetworkAgent formerDefault = defaultNetwork;
- defaultNetwork = agent;
-
- for (NetworkCallback cb : trackingDefault) {
- if (defaultNetwork != null) {
- cb.onAvailable(defaultNetwork.networkId);
- cb.onCapabilitiesChanged(
- defaultNetwork.networkId, defaultNetwork.networkCapabilities);
- cb.onLinkPropertiesChanged(
- defaultNetwork.networkId, defaultNetwork.linkProperties);
- }
- }
- }
-
- @Override
- public void requestNetwork(NetworkRequest req, NetworkCallback cb, Handler h) {
- assertFalse(allCallbacks.containsKey(cb));
- allCallbacks.put(cb, h);
- if (sDefaultRequest.equals(req)) {
- assertFalse(trackingDefault.contains(cb));
- trackingDefault.add(cb);
- } else {
- assertFalse(requested.containsKey(cb));
- requested.put(cb, req);
- }
- }
-
- @Override
- public void requestNetwork(NetworkRequest req, NetworkCallback cb) {
- fail("Should never be called.");
- }
-
- @Override
- public void requestNetwork(NetworkRequest req,
- int timeoutMs, int legacyType, Handler h, NetworkCallback cb) {
- assertFalse(allCallbacks.containsKey(cb));
- allCallbacks.put(cb, h);
- assertFalse(requested.containsKey(cb));
- requested.put(cb, req);
- assertFalse(legacyTypeMap.containsKey(cb));
- if (legacyType != ConnectivityManager.TYPE_NONE) {
- legacyTypeMap.put(cb, legacyType);
- }
- }
-
- @Override
- public void registerNetworkCallback(NetworkRequest req, NetworkCallback cb, Handler h) {
- assertFalse(allCallbacks.containsKey(cb));
- allCallbacks.put(cb, h);
- assertFalse(listening.containsKey(cb));
- listening.put(cb, req);
- }
-
- @Override
- public void registerNetworkCallback(NetworkRequest req, NetworkCallback cb) {
- fail("Should never be called.");
- }
-
- @Override
- public void registerDefaultNetworkCallback(NetworkCallback cb, Handler h) {
- fail("Should never be called.");
- }
-
- @Override
- public void registerDefaultNetworkCallback(NetworkCallback cb) {
- fail("Should never be called.");
- }
-
- @Override
- public void unregisterNetworkCallback(NetworkCallback cb) {
- if (trackingDefault.contains(cb)) {
- trackingDefault.remove(cb);
- } else if (listening.containsKey(cb)) {
- listening.remove(cb);
- } else if (requested.containsKey(cb)) {
- requested.remove(cb);
- legacyTypeMap.remove(cb);
- } else {
- fail("Unexpected callback removed");
- }
- allCallbacks.remove(cb);
-
- assertFalse(allCallbacks.containsKey(cb));
- assertFalse(trackingDefault.contains(cb));
- assertFalse(listening.containsKey(cb));
- assertFalse(requested.containsKey(cb));
- }
- }
-
- public static class TestNetworkAgent {
- public final TestConnectivityManager cm;
- public final Network networkId;
- public final int transportType;
- public final NetworkCapabilities networkCapabilities;
- public final LinkProperties linkProperties;
-
- public TestNetworkAgent(TestConnectivityManager cm, int transportType) {
- this.cm = cm;
- this.networkId = new Network(cm.getNetworkId());
- this.transportType = transportType;
- networkCapabilities = new NetworkCapabilities();
- networkCapabilities.addTransportType(transportType);
- networkCapabilities.addCapability(NET_CAPABILITY_INTERNET);
- linkProperties = new LinkProperties();
- }
-
- public void fakeConnect() {
- for (NetworkCallback cb : cm.listening.keySet()) {
- cb.onAvailable(networkId);
- cb.onCapabilitiesChanged(networkId, copy(networkCapabilities));
- cb.onLinkPropertiesChanged(networkId, copy(linkProperties));
- }
- }
-
- public void fakeDisconnect() {
- for (NetworkCallback cb : cm.listening.keySet()) {
- cb.onLost(networkId);
- }
- }
-
- public void sendLinkProperties() {
- for (NetworkCallback cb : cm.listening.keySet()) {
- cb.onLinkPropertiesChanged(networkId, copy(linkProperties));
- }
- }
-
- @Override
- public String toString() {
- return String.format("TestNetworkAgent: %s %s", networkId, networkCapabilities);
- }
- }
-
- public static class TestStateMachine extends StateMachine {
- public final ArrayList<Message> messages = new ArrayList<>();
- private final State mLoggingState = new LoggingState();
-
- class LoggingState extends State {
- @Override public void enter() {
- messages.clear();
- }
-
- @Override public void exit() {
- messages.clear();
- }
-
- @Override public boolean processMessage(Message msg) {
- messages.add(msg);
- return true;
- }
- }
-
- public TestStateMachine() {
- super("UpstreamNetworkMonitor.TestStateMachine");
- addState(mLoggingState);
- setInitialState(mLoggingState);
- super.start();
- }
- }
-
- static NetworkCapabilities copy(NetworkCapabilities nc) {
- return new NetworkCapabilities(nc);
- }
-
- static LinkProperties copy(LinkProperties lp) {
- return new LinkProperties(lp);
- }
-
- static void assertPrefixSet(Set<IpPrefix> prefixes, boolean expectation, String... expected) {
- final Set<String> expectedSet = new HashSet<>();
- Collections.addAll(expectedSet, expected);
- assertPrefixSet(prefixes, expectation, expectedSet);
- }
-
- static void assertPrefixSet(Set<IpPrefix> prefixes, boolean expectation, Set<String> expected) {
- for (String expectedPrefix : expected) {
- final String errStr = expectation ? "did not find" : "found";
- assertEquals(
- String.format("Failed expectation: %s prefix: %s", errStr, expectedPrefix),
- expectation, prefixes.contains(new IpPrefix(expectedPrefix)));
- }
- }
-}
diff --git a/services/backup/OWNERS b/services/backup/OWNERS
index 7c7e742..3c5268c 100644
--- a/services/backup/OWNERS
+++ b/services/backup/OWNERS
@@ -1,7 +1,6 @@
# Bug component: 656484
aabhinav@google.com
-alsutton@google.com
bryanmawhinney@google.com
jstemmer@google.com
nathch@google.com
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 31872fe..22423fe 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -65,7 +65,6 @@
import android.annotation.Nullable;
import android.app.AppOpsManager;
import android.app.BroadcastOptions;
-import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
@@ -1146,8 +1145,7 @@
dataConnectionStats.startMonitoring();
mKeepaliveTracker = new KeepaliveTracker(mContext, mHandler);
- mNotifier = new NetworkNotificationManager(mContext, mTelephonyManager,
- mContext.getSystemService(NotificationManager.class));
+ mNotifier = new NetworkNotificationManager(mContext, mTelephonyManager);
final int dailyLimit = Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.NETWORK_SWITCH_NOTIFICATION_DAILY_LIMIT,
@@ -6256,9 +6254,9 @@
final int newPermission = getNetworkPermission(newNc);
if (oldPermission != newPermission && nai.created && !nai.isVPN()) {
try {
- mNMS.setNetworkPermission(nai.network.netId, newPermission);
- } catch (RemoteException e) {
- loge("Exception in setNetworkPermission: " + e);
+ mNetd.networkSetPermissionForNetwork(nai.network.netId, newPermission);
+ } catch (RemoteException | ServiceSpecificException e) {
+ loge("Exception in networkSetPermissionForNetwork: " + e);
}
}
}
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index dea6c04..1c99465 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -2009,17 +2009,6 @@
}
@Override
- public void setNetworkPermission(int netId, int permission) {
- NetworkStack.checkNetworkStackPermission(mContext);
-
- try {
- mNetdService.networkSetPermissionForNetwork(netId, permission);
- } catch (RemoteException | ServiceSpecificException e) {
- throw new IllegalStateException(e);
- }
- }
-
- @Override
public void allowProtect(int uid) {
NetworkStack.checkNetworkStackPermission(mContext);
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 8cc5fea..1cdc95a 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -1604,10 +1604,12 @@
if (!checkNotifyPermission("notifyDisplayInfoChanged()")) {
return;
}
+ String str = "notifyDisplayInfoChanged: PhoneId=" + phoneId + " subId=" + subId
+ + " telephonyDisplayInfo=" + telephonyDisplayInfo;
if (VDBG) {
- log("notifyDisplayInfoChanged: PhoneId=" + phoneId
- + " subId=" + subId + " telephonyDisplayInfo=" + telephonyDisplayInfo);
+ log(str);
}
+ mLocalLog.log(str);
synchronized (mRecords) {
if (validatePhoneId(phoneId)) {
mTelephonyDisplayInfos[phoneId] = telephonyDisplayInfo;
@@ -2295,10 +2297,10 @@
pw.println("mOutgoingCallEmergencyNumber=" + mOutgoingCallEmergencyNumber[i]);
pw.println("mOutgoingSmsEmergencyNumber=" + mOutgoingSmsEmergencyNumber[i]);
pw.println("mBarringInfo=" + mBarringInfo.get(i));
+ pw.println("mTelephonyDisplayInfo=" + mTelephonyDisplayInfos[i]);
pw.decreaseIndent();
}
pw.println("mCarrierNetworkChangeState=" + mCarrierNetworkChangeState);
-
pw.println("mPhoneCapability=" + mPhoneCapability);
pw.println("mActiveDataSubId=" + mActiveDataSubId);
pw.println("mRadioPowerState=" + mRadioPowerState);
diff --git a/services/core/java/com/android/server/VcnManagementService.java b/services/core/java/com/android/server/VcnManagementService.java
new file mode 100644
index 0000000..db7e16c
--- /dev/null
+++ b/services/core/java/com/android/server/VcnManagementService.java
@@ -0,0 +1,103 @@
+/*
+ * 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.server;
+
+import static java.util.Objects.requireNonNull;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.net.vcn.IVcnManagementService;
+
+/**
+ * VcnManagementService manages Virtual Carrier Network profiles and lifecycles.
+ *
+ * <pre>The internal structure of the VCN Management subsystem is as follows:
+ *
+ * +------------------------+ 1:1 +--------------------------------+
+ * | VcnManagementService | ------------ Creates -------------> | TelephonySubscriptionManager |
+ * | | | |
+ * | Manages configs and | | Tracks subscriptions, carrier |
+ * | VcnInstance lifecycles | <--- Notifies of subscription & --- | privilege changes, caches maps |
+ * +------------------------+ carrier privilege changes +--------------------------------+
+ * | 1:N ^
+ * | |
+ * | +-------------------------------+
+ * +---------------+ |
+ * | |
+ * Creates when config present, |
+ * subscription group active, and |
+ * providing app is carrier privileged Notifies of safe
+ * | mode state changes
+ * v |
+ * +-----------------------------------------------------------------------+
+ * | VcnInstance |
+ * | |
+ * | Manages tunnel lifecycles based on fulfillable NetworkRequest(s) |
+ * | and overall safe-mode |
+ * +-----------------------------------------------------------------------+
+ * | 1:N ^
+ * Creates to fulfill |
+ * NetworkRequest(s), tears Notifies of VcnTunnel
+ * down when no longer needed teardown (e.g. Network reaped)
+ * | and safe-mode timer changes
+ * v |
+ * +-----------------------------------------------------------------------+
+ * | VcnTunnel |
+ * | |
+ * | Manages a single (IKEv2) tunnel session and NetworkAgent, |
+ * | handles mobility events, (IPsec) Tunnel setup and safe-mode timers |
+ * +-----------------------------------------------------------------------+
+ * | 1:1 ^
+ * | |
+ * Creates upon instantiation Notifies of changes in
+ * | selected underlying network
+ * | or its properties
+ * v |
+ * +-----------------------------------------------------------------------+
+ * | UnderlyingNetworkTracker |
+ * | |
+ * | Manages lifecycle of underlying physical networks, filing requests to |
+ * | bring them up, and releasing them as they become no longer necessary |
+ * +-----------------------------------------------------------------------+
+ * </pre>
+ *
+ * @hide
+ */
+public class VcnManagementService extends IVcnManagementService.Stub {
+ @NonNull private static final String TAG = VcnManagementService.class.getSimpleName();
+
+ public static final boolean VDBG = false; // STOPSHIP: if true
+
+ /* Binder context for this service */
+ @NonNull private final Context mContext;
+ @NonNull private final Dependencies mDeps;
+
+ private VcnManagementService(@NonNull Context context, @NonNull Dependencies deps) {
+ mContext = requireNonNull(context, "Missing context");
+ mDeps = requireNonNull(deps, "Missing dependencies");
+ }
+
+ // Package-visibility for SystemServer to create instances.
+ static VcnManagementService create(@NonNull Context context) {
+ return new VcnManagementService(context, new Dependencies());
+ }
+
+ private static class Dependencies {}
+
+ /** Notifies the VcnManagementService that external dependencies can be set up */
+ public void systemReady() {}
+}
diff --git a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
index 26356b4..3385393 100644
--- a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
+++ b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
@@ -21,6 +21,7 @@
import static android.net.NetworkCapabilities.TRANSPORT_VPN;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+import android.annotation.NonNull;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
@@ -75,16 +76,21 @@
private static final boolean DBG = true;
private static final boolean VDBG = false;
+ // The context is for the current user (system server)
private final Context mContext;
private final TelephonyManager mTelephonyManager;
+ // The notification manager is created from a context for User.ALL, so notifications
+ // will be sent to all users.
private final NotificationManager mNotificationManager;
// Tracks the types of notifications managed by this instance, from creation to cancellation.
private final SparseIntArray mNotificationTypeMap;
- public NetworkNotificationManager(Context c, TelephonyManager t, NotificationManager n) {
+ public NetworkNotificationManager(@NonNull final Context c, @NonNull final TelephonyManager t) {
mContext = c;
mTelephonyManager = t;
- mNotificationManager = n;
+ mNotificationManager =
+ (NotificationManager) c.createContextAsUser(UserHandle.ALL, 0 /* flags */)
+ .getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationTypeMap = new SparseIntArray();
}
@@ -282,7 +288,7 @@
mNotificationTypeMap.put(id, eventId);
try {
- mNotificationManager.notifyAsUser(tag, eventId, notification, UserHandle.ALL);
+ mNotificationManager.notify(tag, eventId, notification);
} catch (NullPointerException npe) {
Slog.d(TAG, "setNotificationVisible: visible notificationManager error", npe);
}
@@ -311,7 +317,7 @@
nameOf(eventId)));
}
try {
- mNotificationManager.cancelAsUser(tag, eventId, UserHandle.ALL);
+ mNotificationManager.cancel(tag, eventId);
} catch (NullPointerException npe) {
Slog.d(TAG, String.format(
"failed to clear notification tag=%s event=%s", tag, nameOf(eventId)), npe);
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index e3481a3..1a83272 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -199,8 +199,11 @@
// automated reconnection
private final Context mContext;
+ // The context is for specific user which is created from mUserId
+ private final Context mUserIdContext;
@VisibleForTesting final Dependencies mDeps;
private final NetworkInfo mNetworkInfo;
+ private int mLegacyState;
@VisibleForTesting protected String mPackage;
private int mOwnerUID;
private boolean mIsPackageTargetingAtLeastQ;
@@ -398,6 +401,7 @@
int userId, @NonNull KeyStore keyStore, SystemServices systemServices,
Ikev2SessionCreator ikev2SessionCreator) {
mContext = context;
+ mUserIdContext = context.createContextAsUser(UserHandle.of(userId), 0 /* flags */);
mDeps = deps;
mNetd = netService;
mUserId = userId;
@@ -415,6 +419,7 @@
Log.wtf(TAG, "Problem registering observer", e);
}
+ mLegacyState = LegacyVpnInfo.STATE_DISCONNECTED;
mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_VPN, 0 /* subtype */, NETWORKTYPE,
"" /* subtypeName */);
mNetworkCapabilities = new NetworkCapabilities();
@@ -440,6 +445,7 @@
@VisibleForTesting
protected void updateState(DetailedState detailedState, String reason) {
if (LOGD) Log.d(TAG, "setting state=" + detailedState + ", reason=" + reason);
+ mLegacyState = LegacyVpnInfo.stateFromNetworkInfo(detailedState);
mNetworkInfo.setDetailedState(detailedState, reason, null);
if (mNetworkAgent != null) {
mNetworkAgent.sendNetworkInfo(mNetworkInfo);
@@ -1243,6 +1249,7 @@
// behaves the same as when it uses the default network.
mNetworkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+ mLegacyState = LegacyVpnInfo.STATE_CONNECTING;
mNetworkInfo.setDetailedState(DetailedState.CONNECTING, null, null);
NetworkAgentConfig networkAgentConfig = new NetworkAgentConfig();
@@ -1921,9 +1928,10 @@
final UserHandle user = UserHandle.of(mUserId);
final long token = Binder.clearCallingIdentity();
try {
- final NotificationManager notificationManager = NotificationManager.from(mContext);
+ final NotificationManager notificationManager =
+ mUserIdContext.getSystemService(NotificationManager.class);
if (!visible) {
- notificationManager.cancelAsUser(TAG, SystemMessage.NOTE_VPN_DISCONNECTED, user);
+ notificationManager.cancel(TAG, SystemMessage.NOTE_VPN_DISCONNECTED);
return;
}
final Intent intent = new Intent();
@@ -1943,8 +1951,7 @@
.setVisibility(Notification.VISIBILITY_PUBLIC)
.setOngoing(true)
.setColor(mContext.getColor(R.color.system_notification_accent_color));
- notificationManager.notifyAsUser(TAG, SystemMessage.NOTE_VPN_DISCONNECTED,
- builder.build(), user);
+ notificationManager.notify(TAG, SystemMessage.NOTE_VPN_DISCONNECTED, builder.build());
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -2265,7 +2272,7 @@
final LegacyVpnInfo info = new LegacyVpnInfo();
info.key = mConfig.user;
- info.state = LegacyVpnInfo.stateFromNetworkInfo(mNetworkInfo);
+ info.state = mLegacyState;
if (mNetworkInfo.isConnected()) {
info.intent = mStatusIntent;
}
diff --git a/services/core/java/com/android/server/net/LockdownVpnTracker.java b/services/core/java/com/android/server/net/LockdownVpnTracker.java
index 3a262d6..06cebac 100644
--- a/services/core/java/com/android/server/net/LockdownVpnTracker.java
+++ b/services/core/java/com/android/server/net/LockdownVpnTracker.java
@@ -65,6 +65,7 @@
@NonNull private final Context mContext;
@NonNull private final ConnectivityService mConnService;
+ @NonNull private final NotificationManager mNotificationManager;
@NonNull private final Handler mHandler;
@NonNull private final Vpn mVpn;
@NonNull private final VpnProfile mProfile;
@@ -93,6 +94,7 @@
mHandler = Objects.requireNonNull(handler);
mVpn = Objects.requireNonNull(vpn);
mProfile = Objects.requireNonNull(profile);
+ mNotificationManager = mContext.getSystemService(NotificationManager.class);
final Intent configIntent = new Intent(ACTION_VPN_SETTINGS);
mConfigIntent = PendingIntent.getActivity(mContext, 0 /* requestCode */, configIntent,
@@ -266,11 +268,11 @@
.setColor(mContext.getColor(
com.android.internal.R.color.system_notification_accent_color));
- NotificationManager.from(mContext).notify(null, SystemMessage.NOTE_VPN_STATUS,
+ mNotificationManager.notify(null /* tag */, SystemMessage.NOTE_VPN_STATUS,
builder.build());
}
private void hideNotification() {
- NotificationManager.from(mContext).cancel(null, SystemMessage.NOTE_VPN_STATUS);
+ mNotificationManager.cancel(null, SystemMessage.NOTE_VPN_STATUS);
}
}
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index ffdcf7e..7d0457b 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -526,8 +526,9 @@
private final SparseBooleanArray mRestrictBackgroundAllowlistRevokedUids =
new SparseBooleanArray();
+ final Object mMeteredIfacesLock = new Object();
/** Set of ifaces that are metered. */
- @GuardedBy("mNetworkPoliciesSecondLock")
+ @GuardedBy("mMeteredIfacesLock")
private ArraySet<String> mMeteredIfaces = new ArraySet<>();
/** Set of over-limit templates that have been notified. */
@GuardedBy("mNetworkPoliciesSecondLock")
@@ -1980,13 +1981,15 @@
}
// Remove quota from any interfaces that are no longer metered.
- for (int i = mMeteredIfaces.size() - 1; i >= 0; i--) {
- final String iface = mMeteredIfaces.valueAt(i);
- if (!newMeteredIfaces.contains(iface)) {
- removeInterfaceQuotaAsync(iface);
+ synchronized (mMeteredIfacesLock) {
+ for (int i = mMeteredIfaces.size() - 1; i >= 0; i--) {
+ final String iface = mMeteredIfaces.valueAt(i);
+ if (!newMeteredIfaces.contains(iface)) {
+ removeInterfaceQuotaAsync(iface);
+ }
}
+ mMeteredIfaces = newMeteredIfaces;
}
- mMeteredIfaces = newMeteredIfaces;
final ContentResolver cr = mContext.getContentResolver();
final boolean quotaEnabled = Settings.Global.getInt(cr,
@@ -2038,7 +2041,10 @@
mSubscriptionOpportunisticQuota.put(subId, quotaBytes);
}
- final String[] meteredIfaces = mMeteredIfaces.toArray(new String[mMeteredIfaces.size()]);
+ final String[] meteredIfaces;
+ synchronized (mMeteredIfacesLock) {
+ meteredIfaces = mMeteredIfaces.toArray(new String[mMeteredIfaces.size()]);
+ }
mHandler.obtainMessage(MSG_METERED_IFACES_CHANGED, meteredIfaces).sendToTarget();
mHandler.obtainMessage(MSG_ADVISE_PERSIST_THRESHOLD, lowestRule).sendToTarget();
@@ -3460,7 +3466,10 @@
fout.print("Restrict background: "); fout.println(mRestrictBackground);
fout.print("Restrict power: "); fout.println(mRestrictPower);
fout.print("Device idle: "); fout.println(mDeviceIdleMode);
- fout.print("Metered ifaces: "); fout.println(mMeteredIfaces);
+ synchronized (mMeteredIfacesLock) {
+ fout.print("Metered ifaces: ");
+ fout.println(mMeteredIfaces);
+ }
fout.println();
fout.print("mRestrictBackgroundLowPowerMode: " + mRestrictBackgroundLowPowerMode);
@@ -4656,7 +4665,7 @@
}
case MSG_LIMIT_REACHED: {
final String iface = (String) msg.obj;
- synchronized (mNetworkPoliciesSecondLock) {
+ synchronized (mMeteredIfacesLock) {
// fast return if not needed.
if (!mMeteredIfaces.contains(iface)) {
return true;
@@ -5298,7 +5307,7 @@
isBackgroundRestricted = mRestrictBackground;
}
final boolean isNetworkMetered;
- synchronized (mNetworkPoliciesSecondLock) {
+ synchronized (mMeteredIfacesLock) {
isNetworkMetered = mMeteredIfaces.contains(ifname);
}
final boolean ret = isUidNetworkingBlockedInternal(uid, uidRules, isNetworkMetered,
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index cc8c751..ae693c7 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -1018,6 +1018,7 @@
IStorageManager storageManager = null;
NetworkManagementService networkManagement = null;
IpSecService ipSecService = null;
+ VcnManagementService vcnManagement = null;
NetworkStatsService networkStats = null;
NetworkPolicyManagerService networkPolicy = null;
IConnectivityManager connectivity = null;
@@ -1453,6 +1454,15 @@
}
t.traceEnd();
+ t.traceBegin("StartVcnManagementService");
+ try {
+ vcnManagement = VcnManagementService.create(context);
+ ServiceManager.addService(Context.VCN_MANAGEMENT_SERVICE, vcnManagement);
+ } catch (Throwable e) {
+ reportWtf("starting VCN Management Service", e);
+ }
+ t.traceEnd();
+
t.traceBegin("StartTextServicesManager");
mSystemServiceManager.startService(TextServicesManagerService.Lifecycle.class);
t.traceEnd();
@@ -2228,6 +2238,7 @@
final MediaRouterService mediaRouterF = mediaRouter;
final MmsServiceBroker mmsServiceF = mmsService;
final IpSecService ipSecServiceF = ipSecService;
+ final VcnManagementService vcnManagementF = vcnManagement;
final WindowManagerService windowManagerF = wm;
final ConnectivityManager connectivityF = (ConnectivityManager)
context.getSystemService(Context.CONNECTIVITY_SERVICE);
@@ -2316,6 +2327,15 @@
reportWtf("making IpSec Service ready", e);
}
t.traceEnd();
+ t.traceBegin("MakeVcnManagementServiceReady");
+ try {
+ if (vcnManagementF != null) {
+ vcnManagementF.systemReady();
+ }
+ } catch (Throwable e) {
+ reportWtf("making VcnManagementService ready", e);
+ }
+ t.traceEnd();
t.traceBegin("MakeNetworkStatsServiceReady");
try {
if (networkStatsF != null) {
diff --git a/services/net/Android.bp b/services/net/Android.bp
index afea1a0..72ad366 100644
--- a/services/net/Android.bp
+++ b/services/net/Android.bp
@@ -66,5 +66,8 @@
":framework-annotations",
"java/android/net/util/NetworkConstants.java",
],
- visibility: ["//frameworks/base/packages/Tethering"],
+ visibility: [
+ "//frameworks/base/packages/Tethering",
+ "//packages/modules/Connectivity/Tethering"
+ ],
}
diff --git a/telephony/api/system-current.txt b/telephony/api/system-current.txt
deleted file mode 100644
index 24eea0e..0000000
--- a/telephony/api/system-current.txt
+++ /dev/null
@@ -1,2053 +0,0 @@
-// Signature format: 2.0
-package android.telephony {
-
- public final class AccessNetworkConstants {
- field public static final int TRANSPORT_TYPE_INVALID = -1; // 0xffffffff
- }
-
- public static final class AccessNetworkConstants.NgranBands {
- method public static int getFrequencyRangeGroup(int);
- field public static final int FREQUENCY_RANGE_GROUP_1 = 1; // 0x1
- field public static final int FREQUENCY_RANGE_GROUP_2 = 2; // 0x2
- field public static final int FREQUENCY_RANGE_GROUP_UNKNOWN = 0; // 0x0
- }
-
- public final class BarringInfo implements android.os.Parcelable {
- ctor public BarringInfo();
- method @NonNull public android.telephony.BarringInfo createLocationInfoSanitizedCopy();
- }
-
- public final class CallAttributes implements android.os.Parcelable {
- ctor public CallAttributes(@NonNull android.telephony.PreciseCallState, int, @NonNull android.telephony.CallQuality);
- method public int describeContents();
- method @NonNull public android.telephony.CallQuality getCallQuality();
- method public int getNetworkType();
- method @NonNull public android.telephony.PreciseCallState getPreciseCallState();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CallAttributes> CREATOR;
- }
-
- public final class CallForwardingInfo implements android.os.Parcelable {
- ctor public CallForwardingInfo(boolean, int, @Nullable String, int);
- method public int describeContents();
- method @Nullable public String getNumber();
- method public int getReason();
- method public int getTimeoutSeconds();
- method public boolean isEnabled();
- field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CallForwardingInfo> CREATOR;
- field public static final int REASON_ALL = 4; // 0x4
- field public static final int REASON_ALL_CONDITIONAL = 5; // 0x5
- field public static final int REASON_BUSY = 1; // 0x1
- field public static final int REASON_NOT_REACHABLE = 3; // 0x3
- field public static final int REASON_NO_REPLY = 2; // 0x2
- field public static final int REASON_UNCONDITIONAL = 0; // 0x0
- }
-
- public final class CallQuality implements android.os.Parcelable {
- ctor public CallQuality(int, int, int, int, int, int, int, int, int, int, int);
- ctor public CallQuality(int, int, int, int, int, int, int, int, int, int, int, boolean, boolean, boolean);
- method public int describeContents();
- method public int getAverageRelativeJitter();
- method public int getAverageRoundTripTime();
- method public int getCallDuration();
- method public int getCodecType();
- method public int getDownlinkCallQualityLevel();
- method public int getMaxRelativeJitter();
- method public int getNumRtpPacketsNotReceived();
- method public int getNumRtpPacketsReceived();
- method public int getNumRtpPacketsTransmitted();
- method public int getNumRtpPacketsTransmittedLost();
- method public int getUplinkCallQualityLevel();
- method public boolean isIncomingSilenceDetectedAtCallSetup();
- method public boolean isOutgoingSilenceDetectedAtCallSetup();
- method public boolean isRtpInactivityDetected();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final int CALL_QUALITY_BAD = 4; // 0x4
- field public static final int CALL_QUALITY_EXCELLENT = 0; // 0x0
- field public static final int CALL_QUALITY_FAIR = 2; // 0x2
- field public static final int CALL_QUALITY_GOOD = 1; // 0x1
- field public static final int CALL_QUALITY_NOT_AVAILABLE = 5; // 0x5
- field public static final int CALL_QUALITY_POOR = 3; // 0x3
- field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CallQuality> CREATOR;
- }
-
- public class CarrierConfigManager {
- method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getDefaultCarrierServicePackageName();
- method @NonNull public static android.os.PersistableBundle getDefaultConfig();
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void overrideConfig(int, @Nullable android.os.PersistableBundle);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void updateConfigForPhoneId(int, String);
- field public static final String KEY_CARRIER_SETUP_APP_STRING = "carrier_setup_app_string";
- field public static final String KEY_SUPPORT_CDMA_1X_VOICE_CALLS_BOOL = "support_cdma_1x_voice_calls_bool";
- }
-
- public static final class CarrierConfigManager.Wifi {
- field public static final String KEY_HOTSPOT_MAX_CLIENT_COUNT = "wifi.hotspot_maximum_client_count";
- field public static final String KEY_PREFIX = "wifi.";
- }
-
- public final class CarrierRestrictionRules implements android.os.Parcelable {
- method @NonNull public java.util.List<java.lang.Boolean> areCarrierIdentifiersAllowed(@NonNull java.util.List<android.service.carrier.CarrierIdentifier>);
- method public int describeContents();
- method @NonNull public java.util.List<android.service.carrier.CarrierIdentifier> getAllowedCarriers();
- method public int getDefaultCarrierRestriction();
- method @NonNull public java.util.List<android.service.carrier.CarrierIdentifier> getExcludedCarriers();
- method public int getMultiSimPolicy();
- method public boolean isAllCarriersAllowed();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final int CARRIER_RESTRICTION_DEFAULT_ALLOWED = 1; // 0x1
- field public static final int CARRIER_RESTRICTION_DEFAULT_NOT_ALLOWED = 0; // 0x0
- field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CarrierRestrictionRules> CREATOR;
- field public static final int MULTISIM_POLICY_NONE = 0; // 0x0
- field public static final int MULTISIM_POLICY_ONE_VALID_SIM_MUST_BE_PRESENT = 1; // 0x1
- }
-
- public static final class CarrierRestrictionRules.Builder {
- ctor public CarrierRestrictionRules.Builder();
- method @NonNull public android.telephony.CarrierRestrictionRules build();
- method @NonNull public android.telephony.CarrierRestrictionRules.Builder setAllCarriersAllowed();
- method @NonNull public android.telephony.CarrierRestrictionRules.Builder setAllowedCarriers(@NonNull java.util.List<android.service.carrier.CarrierIdentifier>);
- method @NonNull public android.telephony.CarrierRestrictionRules.Builder setDefaultCarrierRestriction(int);
- method @NonNull public android.telephony.CarrierRestrictionRules.Builder setExcludedCarriers(@NonNull java.util.List<android.service.carrier.CarrierIdentifier>);
- method @NonNull public android.telephony.CarrierRestrictionRules.Builder setMultiSimPolicy(int);
- }
-
- public class CbGeoUtils {
- }
-
- public static class CbGeoUtils.Circle implements android.telephony.CbGeoUtils.Geometry {
- ctor public CbGeoUtils.Circle(@NonNull android.telephony.CbGeoUtils.LatLng, double);
- method public boolean contains(@NonNull android.telephony.CbGeoUtils.LatLng);
- method @NonNull public android.telephony.CbGeoUtils.LatLng getCenter();
- method public double getRadius();
- }
-
- public static interface CbGeoUtils.Geometry {
- method public boolean contains(@NonNull android.telephony.CbGeoUtils.LatLng);
- }
-
- public static class CbGeoUtils.LatLng {
- ctor public CbGeoUtils.LatLng(double, double);
- method public double distance(@NonNull android.telephony.CbGeoUtils.LatLng);
- method @NonNull public android.telephony.CbGeoUtils.LatLng subtract(@NonNull android.telephony.CbGeoUtils.LatLng);
- field public final double lat;
- field public final double lng;
- }
-
- public static class CbGeoUtils.Polygon implements android.telephony.CbGeoUtils.Geometry {
- ctor public CbGeoUtils.Polygon(@NonNull java.util.List<android.telephony.CbGeoUtils.LatLng>);
- method public boolean contains(@NonNull android.telephony.CbGeoUtils.LatLng);
- method @NonNull public java.util.List<android.telephony.CbGeoUtils.LatLng> getVertices();
- }
-
- public abstract class CellBroadcastService extends android.app.Service {
- ctor public CellBroadcastService();
- method @NonNull @WorkerThread public abstract CharSequence getCellBroadcastAreaInfo(int);
- method public android.os.IBinder onBind(@Nullable android.content.Intent);
- method public abstract void onCdmaCellBroadcastSms(int, @NonNull byte[], int);
- method public abstract void onCdmaScpMessage(int, @NonNull java.util.List<android.telephony.cdma.CdmaSmsCbProgramData>, @NonNull String, @NonNull java.util.function.Consumer<android.os.Bundle>);
- method public abstract void onGsmCellBroadcastSms(int, @NonNull byte[]);
- field public static final String CELL_BROADCAST_SERVICE_INTERFACE = "android.telephony.CellBroadcastService";
- }
-
- public abstract class CellIdentity implements android.os.Parcelable {
- method @NonNull public abstract android.telephony.CellLocation asCellLocation();
- method @NonNull public abstract android.telephony.CellIdentity sanitizeLocationInfo();
- }
-
- public final class CellIdentityCdma extends android.telephony.CellIdentity {
- method @NonNull public android.telephony.cdma.CdmaCellLocation asCellLocation();
- method @NonNull public android.telephony.CellIdentityCdma sanitizeLocationInfo();
- }
-
- public final class CellIdentityGsm extends android.telephony.CellIdentity {
- method @NonNull public android.telephony.gsm.GsmCellLocation asCellLocation();
- method @NonNull public android.telephony.CellIdentityGsm sanitizeLocationInfo();
- }
-
- public final class CellIdentityLte extends android.telephony.CellIdentity {
- method @NonNull public android.telephony.gsm.GsmCellLocation asCellLocation();
- method @NonNull public android.telephony.CellIdentityLte sanitizeLocationInfo();
- }
-
- public final class CellIdentityNr extends android.telephony.CellIdentity {
- method @NonNull public android.telephony.CellLocation asCellLocation();
- method @NonNull public android.telephony.CellIdentityNr sanitizeLocationInfo();
- }
-
- public final class CellIdentityTdscdma extends android.telephony.CellIdentity {
- method @NonNull public android.telephony.gsm.GsmCellLocation asCellLocation();
- method @NonNull public android.telephony.CellIdentityTdscdma sanitizeLocationInfo();
- }
-
- public final class CellIdentityWcdma extends android.telephony.CellIdentity {
- method @NonNull public android.telephony.gsm.GsmCellLocation asCellLocation();
- method @NonNull public android.telephony.CellIdentityWcdma sanitizeLocationInfo();
- }
-
- public final class DataFailCause {
- field @Deprecated public static final int VSNCP_APN_UNATHORIZED = 2238; // 0x8be
- }
-
- public final class DataSpecificRegistrationInfo implements android.os.Parcelable {
- method public int describeContents();
- method @NonNull public android.telephony.LteVopsSupportInfo getLteVopsSupportInfo();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.telephony.DataSpecificRegistrationInfo> CREATOR;
- }
-
- public final class ImsiEncryptionInfo implements android.os.Parcelable {
- method public int describeContents();
- method @Nullable public String getKeyIdentifier();
- method @Nullable public java.security.PublicKey getPublicKey();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ImsiEncryptionInfo> CREATOR;
- }
-
- public final class LteVopsSupportInfo implements android.os.Parcelable {
- ctor public LteVopsSupportInfo(int, int);
- method public int describeContents();
- method public int getEmcBearerSupport();
- method public int getVopsSupport();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.telephony.LteVopsSupportInfo> CREATOR;
- field public static final int LTE_STATUS_NOT_AVAILABLE = 1; // 0x1
- field public static final int LTE_STATUS_NOT_SUPPORTED = 3; // 0x3
- field public static final int LTE_STATUS_SUPPORTED = 2; // 0x2
- }
-
- public class MbmsDownloadSession implements java.lang.AutoCloseable {
- field public static final String MBMS_DOWNLOAD_SERVICE_ACTION = "android.telephony.action.EmbmsDownload";
- }
-
- public class MbmsGroupCallSession implements java.lang.AutoCloseable {
- field public static final String MBMS_GROUP_CALL_SERVICE_ACTION = "android.telephony.action.EmbmsGroupCall";
- }
-
- public class MbmsStreamingSession implements java.lang.AutoCloseable {
- field public static final String MBMS_STREAMING_SERVICE_ACTION = "android.telephony.action.EmbmsStreaming";
- }
-
- public final class NetworkRegistrationInfo implements android.os.Parcelable {
- method @Nullable public android.telephony.DataSpecificRegistrationInfo getDataSpecificInfo();
- method public int getRegistrationState();
- method public int getRejectCause();
- method public int getRoamingType();
- method public boolean isEmergencyEnabled();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final int REGISTRATION_STATE_DENIED = 3; // 0x3
- field public static final int REGISTRATION_STATE_HOME = 1; // 0x1
- field public static final int REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING = 0; // 0x0
- field public static final int REGISTRATION_STATE_NOT_REGISTERED_SEARCHING = 2; // 0x2
- field public static final int REGISTRATION_STATE_ROAMING = 5; // 0x5
- field public static final int REGISTRATION_STATE_UNKNOWN = 4; // 0x4
- }
-
- public static final class NetworkRegistrationInfo.Builder {
- ctor public NetworkRegistrationInfo.Builder();
- method @NonNull public android.telephony.NetworkRegistrationInfo build();
- method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setAccessNetworkTechnology(int);
- method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setAvailableServices(@NonNull java.util.List<java.lang.Integer>);
- method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setCellIdentity(@Nullable android.telephony.CellIdentity);
- method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setDomain(int);
- method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setEmergencyOnly(boolean);
- method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setRegisteredPlmn(@Nullable String);
- method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setRegistrationState(int);
- method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setRejectCause(int);
- method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setTransportType(int);
- }
-
- public abstract class NetworkService extends android.app.Service {
- ctor public NetworkService();
- method public android.os.IBinder onBind(android.content.Intent);
- method @Nullable public abstract android.telephony.NetworkService.NetworkServiceProvider onCreateNetworkServiceProvider(int);
- field public static final String SERVICE_INTERFACE = "android.telephony.NetworkService";
- }
-
- public abstract class NetworkService.NetworkServiceProvider implements java.lang.AutoCloseable {
- ctor public NetworkService.NetworkServiceProvider(int);
- method public abstract void close();
- method public final int getSlotIndex();
- method public final void notifyNetworkRegistrationInfoChanged();
- method public void requestNetworkRegistrationInfo(int, @NonNull android.telephony.NetworkServiceCallback);
- }
-
- public class NetworkServiceCallback {
- method public void onRequestNetworkRegistrationInfoComplete(int, @Nullable android.telephony.NetworkRegistrationInfo);
- field public static final int RESULT_ERROR_BUSY = 3; // 0x3
- field public static final int RESULT_ERROR_FAILED = 5; // 0x5
- field public static final int RESULT_ERROR_ILLEGAL_STATE = 4; // 0x4
- field public static final int RESULT_ERROR_INVALID_ARG = 2; // 0x2
- field public static final int RESULT_ERROR_UNSUPPORTED = 1; // 0x1
- field public static final int RESULT_SUCCESS = 0; // 0x0
- }
-
- public interface NumberVerificationCallback {
- method public default void onCallReceived(@NonNull String);
- method public default void onVerificationFailed(int);
- field public static final int REASON_CONCURRENT_REQUESTS = 4; // 0x4
- field public static final int REASON_IN_ECBM = 5; // 0x5
- field public static final int REASON_IN_EMERGENCY_CALL = 6; // 0x6
- field public static final int REASON_NETWORK_NOT_AVAILABLE = 2; // 0x2
- field public static final int REASON_TIMED_OUT = 1; // 0x1
- field public static final int REASON_TOO_MANY_CALLS = 3; // 0x3
- field public static final int REASON_UNSPECIFIED = 0; // 0x0
- }
-
- public final class PhoneNumberRange implements android.os.Parcelable {
- ctor public PhoneNumberRange(@NonNull String, @NonNull String, @NonNull String, @NonNull String);
- method public int describeContents();
- method public boolean matches(@NonNull String);
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.telephony.PhoneNumberRange> CREATOR;
- }
-
- public class PhoneNumberUtils {
- method @NonNull public static String getUsernameFromUriNumber(@NonNull String);
- method public static boolean isUriNumber(@Nullable String);
- method public static boolean isVoiceMailNumber(@NonNull android.content.Context, int, @Nullable String);
- }
-
- public final class PreciseCallState implements android.os.Parcelable {
- ctor public PreciseCallState(int, int, int, int, int);
- method public int describeContents();
- method public int getBackgroundCallState();
- method public int getForegroundCallState();
- method public int getRingingCallState();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.telephony.PreciseCallState> CREATOR;
- field public static final int PRECISE_CALL_STATE_ACTIVE = 1; // 0x1
- field public static final int PRECISE_CALL_STATE_ALERTING = 4; // 0x4
- field public static final int PRECISE_CALL_STATE_DIALING = 3; // 0x3
- field public static final int PRECISE_CALL_STATE_DISCONNECTED = 7; // 0x7
- field public static final int PRECISE_CALL_STATE_DISCONNECTING = 8; // 0x8
- field public static final int PRECISE_CALL_STATE_HOLDING = 2; // 0x2
- field public static final int PRECISE_CALL_STATE_IDLE = 0; // 0x0
- field public static final int PRECISE_CALL_STATE_INCOMING = 5; // 0x5
- field public static final int PRECISE_CALL_STATE_NOT_VALID = -1; // 0xffffffff
- field public static final int PRECISE_CALL_STATE_WAITING = 6; // 0x6
- }
-
- public final class PreciseDataConnectionState implements android.os.Parcelable {
- method @Deprecated @NonNull public String getDataConnectionApn();
- method @Deprecated public int getDataConnectionApnTypeBitMask();
- method @Deprecated public int getDataConnectionFailCause();
- method @Deprecated public int getDataConnectionState();
- method public int getId();
- }
-
- public final class PreciseDisconnectCause {
- field public static final int ACCESS_CLASS_BLOCKED = 260; // 0x104
- field public static final int ACCESS_INFORMATION_DISCARDED = 43; // 0x2b
- field public static final int ACM_LIMIT_EXCEEDED = 68; // 0x44
- field public static final int BEARER_CAPABILITY_NOT_AUTHORIZED = 57; // 0x39
- field public static final int BEARER_NOT_AVAIL = 58; // 0x3a
- field public static final int BEARER_SERVICE_NOT_IMPLEMENTED = 65; // 0x41
- field public static final int BUSY = 17; // 0x11
- field public static final int CALL_BARRED = 240; // 0xf0
- field public static final int CALL_REJECTED = 21; // 0x15
- field public static final int CDMA_ACCESS_BLOCKED = 1009; // 0x3f1
- field public static final int CDMA_ACCESS_FAILURE = 1006; // 0x3ee
- field public static final int CDMA_DROP = 1001; // 0x3e9
- field public static final int CDMA_INTERCEPT = 1002; // 0x3ea
- field public static final int CDMA_LOCKED_UNTIL_POWER_CYCLE = 1000; // 0x3e8
- field public static final int CDMA_NOT_EMERGENCY = 1008; // 0x3f0
- field public static final int CDMA_PREEMPTED = 1007; // 0x3ef
- field public static final int CDMA_REORDER = 1003; // 0x3eb
- field public static final int CDMA_RETRY_ORDER = 1005; // 0x3ed
- field public static final int CDMA_SO_REJECT = 1004; // 0x3ec
- field public static final int CHANNEL_NOT_AVAIL = 44; // 0x2c
- field public static final int CHANNEL_UNACCEPTABLE = 6; // 0x6
- field public static final int CONDITIONAL_IE_ERROR = 100; // 0x64
- field public static final int DESTINATION_OUT_OF_ORDER = 27; // 0x1b
- field public static final int ERROR_UNSPECIFIED = 65535; // 0xffff
- field public static final int FACILITY_REJECTED = 29; // 0x1d
- field public static final int FDN_BLOCKED = 241; // 0xf1
- field public static final int IMEI_NOT_ACCEPTED = 243; // 0xf3
- field public static final int IMSI_UNKNOWN_IN_VLR = 242; // 0xf2
- field public static final int INCOMING_CALLS_BARRED_WITHIN_CUG = 55; // 0x37
- field public static final int INCOMPATIBLE_DESTINATION = 88; // 0x58
- field public static final int INFORMATION_ELEMENT_NON_EXISTENT = 99; // 0x63
- field public static final int INTERWORKING_UNSPECIFIED = 127; // 0x7f
- field public static final int INVALID_MANDATORY_INFORMATION = 96; // 0x60
- field public static final int INVALID_NUMBER_FORMAT = 28; // 0x1c
- field public static final int INVALID_TRANSACTION_IDENTIFIER = 81; // 0x51
- field public static final int MESSAGE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE = 101; // 0x65
- field public static final int MESSAGE_TYPE_NON_IMPLEMENTED = 97; // 0x61
- field public static final int MESSAGE_TYPE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE = 98; // 0x62
- field public static final int NETWORK_DETACH = 261; // 0x105
- field public static final int NETWORK_OUT_OF_ORDER = 38; // 0x26
- field public static final int NETWORK_REJECT = 252; // 0xfc
- field public static final int NETWORK_RESP_TIMEOUT = 251; // 0xfb
- field public static final int NORMAL = 16; // 0x10
- field public static final int NORMAL_UNSPECIFIED = 31; // 0x1f
- field public static final int NOT_VALID = -1; // 0xffffffff
- field public static final int NO_ANSWER_FROM_USER = 19; // 0x13
- field public static final int NO_CIRCUIT_AVAIL = 34; // 0x22
- field public static final int NO_DISCONNECT_CAUSE_AVAILABLE = 0; // 0x0
- field public static final int NO_ROUTE_TO_DESTINATION = 3; // 0x3
- field public static final int NO_USER_RESPONDING = 18; // 0x12
- field public static final int NO_VALID_SIM = 249; // 0xf9
- field public static final int NUMBER_CHANGED = 22; // 0x16
- field public static final int OEM_CAUSE_1 = 61441; // 0xf001
- field public static final int OEM_CAUSE_10 = 61450; // 0xf00a
- field public static final int OEM_CAUSE_11 = 61451; // 0xf00b
- field public static final int OEM_CAUSE_12 = 61452; // 0xf00c
- field public static final int OEM_CAUSE_13 = 61453; // 0xf00d
- field public static final int OEM_CAUSE_14 = 61454; // 0xf00e
- field public static final int OEM_CAUSE_15 = 61455; // 0xf00f
- field public static final int OEM_CAUSE_2 = 61442; // 0xf002
- field public static final int OEM_CAUSE_3 = 61443; // 0xf003
- field public static final int OEM_CAUSE_4 = 61444; // 0xf004
- field public static final int OEM_CAUSE_5 = 61445; // 0xf005
- field public static final int OEM_CAUSE_6 = 61446; // 0xf006
- field public static final int OEM_CAUSE_7 = 61447; // 0xf007
- field public static final int OEM_CAUSE_8 = 61448; // 0xf008
- field public static final int OEM_CAUSE_9 = 61449; // 0xf009
- field public static final int ONLY_DIGITAL_INFORMATION_BEARER_AVAILABLE = 70; // 0x46
- field public static final int OPERATOR_DETERMINED_BARRING = 8; // 0x8
- field public static final int OUT_OF_SRV = 248; // 0xf8
- field public static final int PREEMPTION = 25; // 0x19
- field public static final int PROTOCOL_ERROR_UNSPECIFIED = 111; // 0x6f
- field public static final int QOS_NOT_AVAIL = 49; // 0x31
- field public static final int RADIO_ACCESS_FAILURE = 253; // 0xfd
- field public static final int RADIO_INTERNAL_ERROR = 250; // 0xfa
- field public static final int RADIO_LINK_FAILURE = 254; // 0xfe
- field public static final int RADIO_LINK_LOST = 255; // 0xff
- field public static final int RADIO_OFF = 247; // 0xf7
- field public static final int RADIO_RELEASE_ABNORMAL = 259; // 0x103
- field public static final int RADIO_RELEASE_NORMAL = 258; // 0x102
- field public static final int RADIO_SETUP_FAILURE = 257; // 0x101
- field public static final int RADIO_UPLINK_FAILURE = 256; // 0x100
- field public static final int RECOVERY_ON_TIMER_EXPIRED = 102; // 0x66
- field public static final int REQUESTED_FACILITY_NOT_IMPLEMENTED = 69; // 0x45
- field public static final int REQUESTED_FACILITY_NOT_SUBSCRIBED = 50; // 0x32
- field public static final int RESOURCES_UNAVAILABLE_OR_UNSPECIFIED = 47; // 0x2f
- field public static final int SEMANTICALLY_INCORRECT_MESSAGE = 95; // 0x5f
- field public static final int SERVICE_OPTION_NOT_AVAILABLE = 63; // 0x3f
- field public static final int SERVICE_OR_OPTION_NOT_IMPLEMENTED = 79; // 0x4f
- field public static final int STATUS_ENQUIRY = 30; // 0x1e
- field public static final int SWITCHING_CONGESTION = 42; // 0x2a
- field public static final int TEMPORARY_FAILURE = 41; // 0x29
- field public static final int UNOBTAINABLE_NUMBER = 1; // 0x1
- field public static final int USER_NOT_MEMBER_OF_CUG = 87; // 0x57
- }
-
- public class ServiceState implements android.os.Parcelable {
- method @Nullable public android.telephony.NetworkRegistrationInfo getNetworkRegistrationInfo(int, int);
- method @NonNull public java.util.List<android.telephony.NetworkRegistrationInfo> getNetworkRegistrationInfoListForDomain(int);
- method @NonNull public java.util.List<android.telephony.NetworkRegistrationInfo> getNetworkRegistrationInfoListForTransportType(int);
- field public static final int ROAMING_TYPE_DOMESTIC = 2; // 0x2
- field public static final int ROAMING_TYPE_INTERNATIONAL = 3; // 0x3
- field public static final int ROAMING_TYPE_NOT_ROAMING = 0; // 0x0
- field public static final int ROAMING_TYPE_UNKNOWN = 1; // 0x1
- }
-
- public final class SmsCbCmasInfo implements android.os.Parcelable {
- ctor public SmsCbCmasInfo(int, int, int, int, int, int);
- method public int describeContents();
- method public int getCategory();
- method public int getCertainty();
- method public int getMessageClass();
- method public int getResponseType();
- method public int getSeverity();
- method public int getUrgency();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final int CMAS_CATEGORY_CBRNE = 10; // 0xa
- field public static final int CMAS_CATEGORY_ENV = 7; // 0x7
- field public static final int CMAS_CATEGORY_FIRE = 5; // 0x5
- field public static final int CMAS_CATEGORY_GEO = 0; // 0x0
- field public static final int CMAS_CATEGORY_HEALTH = 6; // 0x6
- field public static final int CMAS_CATEGORY_INFRA = 9; // 0x9
- field public static final int CMAS_CATEGORY_MET = 1; // 0x1
- field public static final int CMAS_CATEGORY_OTHER = 11; // 0xb
- field public static final int CMAS_CATEGORY_RESCUE = 4; // 0x4
- field public static final int CMAS_CATEGORY_SAFETY = 2; // 0x2
- field public static final int CMAS_CATEGORY_SECURITY = 3; // 0x3
- field public static final int CMAS_CATEGORY_TRANSPORT = 8; // 0x8
- field public static final int CMAS_CATEGORY_UNKNOWN = -1; // 0xffffffff
- field public static final int CMAS_CERTAINTY_LIKELY = 1; // 0x1
- field public static final int CMAS_CERTAINTY_OBSERVED = 0; // 0x0
- field public static final int CMAS_CERTAINTY_UNKNOWN = -1; // 0xffffffff
- field public static final int CMAS_CLASS_CHILD_ABDUCTION_EMERGENCY = 3; // 0x3
- field public static final int CMAS_CLASS_CMAS_EXERCISE = 5; // 0x5
- field public static final int CMAS_CLASS_EXTREME_THREAT = 1; // 0x1
- field public static final int CMAS_CLASS_OPERATOR_DEFINED_USE = 6; // 0x6
- field public static final int CMAS_CLASS_PRESIDENTIAL_LEVEL_ALERT = 0; // 0x0
- field public static final int CMAS_CLASS_REQUIRED_MONTHLY_TEST = 4; // 0x4
- field public static final int CMAS_CLASS_SEVERE_THREAT = 2; // 0x2
- field public static final int CMAS_CLASS_UNKNOWN = -1; // 0xffffffff
- field public static final int CMAS_RESPONSE_TYPE_ASSESS = 6; // 0x6
- field public static final int CMAS_RESPONSE_TYPE_AVOID = 5; // 0x5
- field public static final int CMAS_RESPONSE_TYPE_EVACUATE = 1; // 0x1
- field public static final int CMAS_RESPONSE_TYPE_EXECUTE = 3; // 0x3
- field public static final int CMAS_RESPONSE_TYPE_MONITOR = 4; // 0x4
- field public static final int CMAS_RESPONSE_TYPE_NONE = 7; // 0x7
- field public static final int CMAS_RESPONSE_TYPE_PREPARE = 2; // 0x2
- field public static final int CMAS_RESPONSE_TYPE_SHELTER = 0; // 0x0
- field public static final int CMAS_RESPONSE_TYPE_UNKNOWN = -1; // 0xffffffff
- field public static final int CMAS_SEVERITY_EXTREME = 0; // 0x0
- field public static final int CMAS_SEVERITY_SEVERE = 1; // 0x1
- field public static final int CMAS_SEVERITY_UNKNOWN = -1; // 0xffffffff
- field public static final int CMAS_URGENCY_EXPECTED = 1; // 0x1
- field public static final int CMAS_URGENCY_IMMEDIATE = 0; // 0x0
- field public static final int CMAS_URGENCY_UNKNOWN = -1; // 0xffffffff
- field @NonNull public static final android.os.Parcelable.Creator<android.telephony.SmsCbCmasInfo> CREATOR;
- }
-
- public final class SmsCbEtwsInfo implements android.os.Parcelable {
- ctor public SmsCbEtwsInfo(int, boolean, boolean, boolean, @Nullable byte[]);
- method public int describeContents();
- method @Nullable public byte[] getPrimaryNotificationSignature();
- method public long getPrimaryNotificationTimestamp();
- method public int getWarningType();
- method public boolean isEmergencyUserAlert();
- method public boolean isPopupAlert();
- method public boolean isPrimary();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.telephony.SmsCbEtwsInfo> CREATOR;
- field public static final int ETWS_WARNING_TYPE_EARTHQUAKE = 0; // 0x0
- field public static final int ETWS_WARNING_TYPE_EARTHQUAKE_AND_TSUNAMI = 2; // 0x2
- field public static final int ETWS_WARNING_TYPE_OTHER_EMERGENCY = 4; // 0x4
- field public static final int ETWS_WARNING_TYPE_TEST_MESSAGE = 3; // 0x3
- field public static final int ETWS_WARNING_TYPE_TSUNAMI = 1; // 0x1
- field public static final int ETWS_WARNING_TYPE_UNKNOWN = -1; // 0xffffffff
- }
-
- public final class SmsCbLocation implements android.os.Parcelable {
- ctor public SmsCbLocation(@NonNull String, int, int);
- method public int describeContents();
- method public int getCid();
- method public int getLac();
- method @NonNull public String getPlmn();
- method public boolean isInLocationArea(@NonNull android.telephony.SmsCbLocation);
- method public boolean isInLocationArea(@Nullable String, int, int);
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.telephony.SmsCbLocation> CREATOR;
- }
-
- public final class SmsCbMessage implements android.os.Parcelable {
- ctor public SmsCbMessage(int, int, int, @NonNull android.telephony.SmsCbLocation, int, @Nullable String, int, @Nullable String, int, @Nullable android.telephony.SmsCbEtwsInfo, @Nullable android.telephony.SmsCbCmasInfo, int, @Nullable java.util.List<android.telephony.CbGeoUtils.Geometry>, long, int, int);
- method @NonNull public static android.telephony.SmsCbMessage createFromCursor(@NonNull android.database.Cursor);
- method public int describeContents();
- method @Nullable public android.telephony.SmsCbCmasInfo getCmasWarningInfo();
- method @NonNull public android.content.ContentValues getContentValues();
- method public int getDataCodingScheme();
- method @Nullable public android.telephony.SmsCbEtwsInfo getEtwsWarningInfo();
- method public int getGeographicalScope();
- method @NonNull public java.util.List<android.telephony.CbGeoUtils.Geometry> getGeometries();
- method @Nullable public String getLanguageCode();
- method @NonNull public android.telephony.SmsCbLocation getLocation();
- method public int getMaximumWaitingDuration();
- method @Nullable public String getMessageBody();
- method public int getMessageFormat();
- method public int getMessagePriority();
- method public long getReceivedTime();
- method public int getSerialNumber();
- method public int getServiceCategory();
- method public int getSlotIndex();
- method public int getSubscriptionId();
- method public boolean isCmasMessage();
- method public boolean isEmergencyMessage();
- method public boolean isEtwsMessage();
- method public boolean needGeoFencingCheck();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.telephony.SmsCbMessage> CREATOR;
- field public static final int GEOGRAPHICAL_SCOPE_CELL_WIDE = 3; // 0x3
- field public static final int GEOGRAPHICAL_SCOPE_CELL_WIDE_IMMEDIATE = 0; // 0x0
- field public static final int GEOGRAPHICAL_SCOPE_LOCATION_AREA_WIDE = 2; // 0x2
- field public static final int GEOGRAPHICAL_SCOPE_PLMN_WIDE = 1; // 0x1
- field public static final int MAXIMUM_WAIT_TIME_NOT_SET = 255; // 0xff
- field public static final int MESSAGE_FORMAT_3GPP = 1; // 0x1
- field public static final int MESSAGE_FORMAT_3GPP2 = 2; // 0x2
- field public static final int MESSAGE_PRIORITY_EMERGENCY = 3; // 0x3
- field public static final int MESSAGE_PRIORITY_INTERACTIVE = 1; // 0x1
- field public static final int MESSAGE_PRIORITY_NORMAL = 0; // 0x0
- field public static final int MESSAGE_PRIORITY_URGENT = 2; // 0x2
- }
-
- public final class SmsManager {
- method public boolean disableCellBroadcastRange(int, int, int);
- method public boolean enableCellBroadcastRange(int, int, int);
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getPremiumSmsConsent(@NonNull String);
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getSmsCapacityOnIcc();
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void sendMultipartTextMessageWithoutPersisting(String, String, java.util.List<java.lang.String>, java.util.List<android.app.PendingIntent>, java.util.List<android.app.PendingIntent>);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setPremiumSmsConsent(@NonNull String, int);
- field public static final int PREMIUM_SMS_CONSENT_ALWAYS_ALLOW = 3; // 0x3
- field public static final int PREMIUM_SMS_CONSENT_ASK_USER = 1; // 0x1
- field public static final int PREMIUM_SMS_CONSENT_NEVER_ALLOW = 2; // 0x2
- field public static final int PREMIUM_SMS_CONSENT_UNKNOWN = 0; // 0x0
- }
-
- public class SmsMessage {
- method @Nullable public static android.telephony.SmsMessage createFromNativeSmsSubmitPdu(@NonNull byte[], boolean);
- method @Nullable public static android.telephony.SmsMessage.SubmitPdu getSmsPdu(int, int, @Nullable String, @NonNull String, @NonNull String, long);
- method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public static byte[] getSubmitPduEncodedMessage(boolean, @NonNull String, @NonNull String, int, @IntRange(from=0) int, @IntRange(from=0) int, @IntRange(from=0, to=255) int, @IntRange(from=1, to=255) int, @IntRange(from=1, to=255) int);
- }
-
- public class SubscriptionInfo implements android.os.Parcelable {
- method public boolean areUiccApplicationsEnabled();
- method @Nullable public java.util.List<android.telephony.UiccAccessRule> getAccessRules();
- method public int getProfileClass();
- method public boolean isGroupDisabled();
- }
-
- public class SubscriptionManager {
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean canDisablePhysicalSubscription();
- method public boolean canManageSubscription(@NonNull android.telephony.SubscriptionInfo, @NonNull String);
- method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int[] getActiveSubscriptionIdList();
- method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.SubscriptionInfo getActiveSubscriptionInfoForIcc(@NonNull String);
- method public java.util.List<android.telephony.SubscriptionInfo> getAvailableSubscriptionInfoList();
- method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int[] getCompleteActiveSubscriptionIdList();
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getEnabledSubscriptionId(int);
- method @NonNull public static android.content.res.Resources getResourcesForSubId(@NonNull android.content.Context, int);
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isSubscriptionEnabled(int);
- method public void requestEmbeddedSubscriptionInfoListRefresh();
- method public void requestEmbeddedSubscriptionInfoListRefresh(int);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDefaultDataSubId(int);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDefaultSmsSubId(int);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDefaultVoiceSubscriptionId(int);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setPreferredDataSubscriptionId(int, boolean, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.Consumer<java.lang.Integer>);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setSubscriptionEnabled(int, boolean);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setUiccApplicationsEnabled(int, boolean);
- field @RequiresPermission(android.Manifest.permission.MANAGE_SUBSCRIPTION_PLANS) public static final String ACTION_SUBSCRIPTION_PLANS_CHANGED = "android.telephony.action.SUBSCRIPTION_PLANS_CHANGED";
- field @NonNull public static final android.net.Uri ADVANCED_CALLING_ENABLED_CONTENT_URI;
- field @Deprecated public static final int PROFILE_CLASS_DEFAULT;
- field public static final int PROFILE_CLASS_OPERATIONAL;
- field public static final int PROFILE_CLASS_PROVISIONING;
- field public static final int PROFILE_CLASS_TESTING;
- field public static final int PROFILE_CLASS_UNSET;
- field @NonNull public static final android.net.Uri VT_ENABLED_CONTENT_URI;
- field @NonNull public static final android.net.Uri WFC_ENABLED_CONTENT_URI;
- field @NonNull public static final android.net.Uri WFC_MODE_CONTENT_URI;
- field @NonNull public static final android.net.Uri WFC_ROAMING_ENABLED_CONTENT_URI;
- field @NonNull public static final android.net.Uri WFC_ROAMING_MODE_CONTENT_URI;
- }
-
- public final class TelephonyHistogram implements android.os.Parcelable {
- ctor public TelephonyHistogram(int, int, int);
- ctor public TelephonyHistogram(android.telephony.TelephonyHistogram);
- ctor public TelephonyHistogram(android.os.Parcel);
- method public void addTimeTaken(int);
- method public int describeContents();
- method public int getAverageTime();
- method public int getBucketCount();
- method public int[] getBucketCounters();
- method public int[] getBucketEndPoints();
- method public int getCategory();
- method public int getId();
- method public int getMaxTime();
- method public int getMinTime();
- method public int getSampleCount();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.telephony.TelephonyHistogram> CREATOR;
- field public static final int TELEPHONY_CATEGORY_RIL = 1; // 0x1
- }
-
- public class TelephonyManager {
- method @Deprecated @RequiresPermission(android.Manifest.permission.CALL_PHONE) public void call(String, String);
- method public int checkCarrierPrivilegesForPackage(String);
- method public int checkCarrierPrivilegesForPackageAnyPhone(String);
- method public void dial(String);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean disableDataConnectivity();
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean enableDataConnectivity();
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean enableModemForSlot(int, boolean);
- method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void enableVideoCalling(boolean);
- method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getAidForAppType(int);
- method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<android.service.carrier.CarrierIdentifier> getAllowedCarriers(int);
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getAllowedNetworkTypes();
- method @Nullable @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public android.content.ComponentName getAndUpdateDefaultRespondViaMessageApplication();
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getCallForwarding(int, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CallForwardingInfoCallback);
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getCallWaitingStatus(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
- method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int);
- method public java.util.List<java.lang.String> getCarrierPackageNamesForIntent(android.content.Intent);
- method public java.util.List<java.lang.String> getCarrierPackageNamesForIntentAndPhone(android.content.Intent, int);
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getCarrierPrivilegeStatus(int);
- method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<java.lang.String> getCarrierPrivilegedPackagesForAllActiveSubscriptions();
- method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.CarrierRestrictionRules getCarrierRestrictionRules();
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String getCdmaMdn();
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String getCdmaMdn(int);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String getCdmaMin();
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String getCdmaMin(int);
- method public String getCdmaPrlVersion();
- method public int getCurrentPhoneType();
- method public int getCurrentPhoneType(int);
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getDataActivationState();
- method @Deprecated public boolean getDataEnabled();
- method @Deprecated public boolean getDataEnabled(int);
- method @Nullable @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public android.content.ComponentName getDefaultRespondViaMessageApplication();
- method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getDeviceSoftwareVersion(int);
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean getEmergencyCallbackMode();
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getEmergencyNumberDbVersion();
- method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getIsimDomain();
- method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getIsimIst();
- method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.Map<java.lang.Integer,java.lang.Integer> getLogicalToPhysicalSlotMapping();
- method public int getMaxNumberOfSimultaneouslyActiveSims();
- method public static long getMaxNumberVerificationTimeoutMillis();
- method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String[] getMergedImsisFromGroup();
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getPreferredNetworkTypeBitmask();
- method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public int getRadioPowerState();
- method public int getSimApplicationState();
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getSimApplicationState(int);
- method public int getSimCardState();
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getSimCardState(int);
- method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.Locale getSimLocale();
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getSupportedRadioAccessFamily();
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public java.util.List<android.telephony.TelephonyHistogram> getTelephonyHistograms();
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.UiccSlotInfo[] getUiccSlotsInfo();
- method @Nullable public android.os.Bundle getVisualVoicemailSettings();
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getVoiceActivationState();
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean handlePinMmi(String);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean handlePinMmiForSubscriber(int, String);
- method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean iccCloseLogicalChannelBySlot(int, int);
- method @Nullable @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public android.telephony.IccOpenLogicalChannelResponse iccOpenLogicalChannelBySlot(int, @Nullable String, int);
- method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String iccTransmitApduBasicChannelBySlot(int, int, int, int, int, int, @Nullable String);
- method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String iccTransmitApduLogicalChannelBySlot(int, int, int, int, int, int, int, @Nullable String);
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isAnyRadioPoweredOn();
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isApnMetered(int);
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isApplicationOnUicc(int);
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isDataConnectionAllowed();
- method public boolean isDataConnectivityPossible();
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isDataEnabledForApn(int);
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isEmergencyAssistanceEnabled();
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public boolean isIccLockEnabled();
- method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isIdle();
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isLteCdmaEvdoGsmWcdmaEnabled();
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isMobileDataPolicyEnabled(int);
- method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isOffhook();
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isOpportunisticNetworkEnabled();
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isPotentialEmergencyNumber(@NonNull String);
- method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isRadioOn();
- method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isRinging();
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean isTetheringApnRequired();
- method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isVideoCallingEnabled();
- method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public boolean isVisualVoicemailEnabled(android.telecom.PhoneAccountHandle);
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean matchesCurrentSimOperator(@NonNull String, int, @Nullable String);
- method public boolean needsOtaServiceProvisioning();
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void notifyOtaEmergencyNumberDbInstalled();
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean rebootRadio();
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void reportDefaultNetworkStatus(boolean);
- method @RequiresPermission(allOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.MODIFY_PHONE_STATE}) public void requestCellInfoUpdate(@NonNull android.os.WorkSource, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CellInfoCallback);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void requestNumberVerification(@NonNull android.telephony.PhoneNumberRange, long, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.NumberVerificationCallback);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void resetAllCarrierActions();
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void resetCarrierKeysForImsiEncryption();
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void resetIms(int);
- method @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public void resetOtaEmergencyNumberDbFilePath();
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean resetRadioConfig();
- method @RequiresPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL) public void resetSettings();
- method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setAllowedCarriers(int, java.util.List<android.service.carrier.CarrierIdentifier>);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setAllowedNetworkTypes(long);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCarrierDataEnabled(boolean);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCallForwarding(@NonNull android.telephony.CallForwardingInfo, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.Consumer<java.lang.Integer>);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCallWaitingEnabled(boolean, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.Consumer<java.lang.Integer>);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setCarrierRestrictionRules(@NonNull android.telephony.CarrierRestrictionRules);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataActivationState(int);
- method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataEnabled(int, boolean);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataRoamingEnabled(boolean);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setMobileDataPolicyEnabledStatus(int, boolean);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setMultiSimCarrierRestriction(boolean);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setOpportunisticNetworkState(boolean);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setPreferredNetworkTypeBitmask(long);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setRadio(boolean);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setRadioEnabled(boolean);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setRadioPower(boolean);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSimPowerState(int);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSimPowerStateForSlot(int, int);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSystemSelectionChannels(@NonNull java.util.List<android.telephony.RadioAccessSpecifier>, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSystemSelectionChannels(@NonNull java.util.List<android.telephony.RadioAccessSpecifier>);
- method @Deprecated public void setVisualVoicemailEnabled(android.telecom.PhoneAccountHandle, boolean);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoiceActivationState(int);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void shutdownAllRadios();
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean supplyPin(String);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int[] supplyPinReportResult(String);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean supplyPuk(String, String);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int[] supplyPukReportResult(String, String);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean switchSlots(int[]);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void toggleRadioOnOff();
- method @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public void updateOtaEmergencyNumberDbFilePath(@NonNull android.os.ParcelFileDescriptor);
- method public void updateServiceLocation();
- field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final String ACTION_ANOMALY_REPORTED = "android.telephony.action.ANOMALY_REPORTED";
- field public static final String ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED = "android.intent.action.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED";
- field public static final String ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED = "android.intent.action.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED";
- field public static final String ACTION_EMERGENCY_ASSISTANCE = "android.telephony.action.EMERGENCY_ASSISTANCE";
- field public static final String ACTION_EMERGENCY_CALLBACK_MODE_CHANGED = "android.intent.action.EMERGENCY_CALLBACK_MODE_CHANGED";
- field public static final String ACTION_EMERGENCY_CALL_STATE_CHANGED = "android.intent.action.EMERGENCY_CALL_STATE_CHANGED";
- field public static final String ACTION_REQUEST_OMADM_CONFIGURATION_UPDATE = "com.android.omadm.service.CONFIGURATION_UPDATE";
- field public static final String ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS = "android.telephony.action.SHOW_NOTICE_ECM_BLOCK_OTHERS";
- field public static final String ACTION_SIM_APPLICATION_STATE_CHANGED = "android.telephony.action.SIM_APPLICATION_STATE_CHANGED";
- field public static final String ACTION_SIM_CARD_STATE_CHANGED = "android.telephony.action.SIM_CARD_STATE_CHANGED";
- field public static final String ACTION_SIM_SLOT_STATUS_CHANGED = "android.telephony.action.SIM_SLOT_STATUS_CHANGED";
- field public static final int CALL_WAITING_STATUS_DISABLED = 2; // 0x2
- field public static final int CALL_WAITING_STATUS_ENABLED = 1; // 0x1
- field public static final int CALL_WAITING_STATUS_NOT_SUPPORTED = 4; // 0x4
- field public static final int CALL_WAITING_STATUS_UNKNOWN_ERROR = 3; // 0x3
- field public static final int CARRIER_PRIVILEGE_STATUS_ERROR_LOADING_RULES = -2; // 0xfffffffe
- field public static final int CARRIER_PRIVILEGE_STATUS_HAS_ACCESS = 1; // 0x1
- field public static final int CARRIER_PRIVILEGE_STATUS_NO_ACCESS = 0; // 0x0
- field public static final int CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED = -1; // 0xffffffff
- field public static final String EXTRA_ANOMALY_DESCRIPTION = "android.telephony.extra.ANOMALY_DESCRIPTION";
- field public static final String EXTRA_ANOMALY_ID = "android.telephony.extra.ANOMALY_ID";
- field public static final String EXTRA_PHONE_IN_ECM_STATE = "android.telephony.extra.PHONE_IN_ECM_STATE";
- field public static final String EXTRA_PHONE_IN_EMERGENCY_CALL = "android.telephony.extra.PHONE_IN_EMERGENCY_CALL";
- field public static final String EXTRA_SIM_STATE = "android.telephony.extra.SIM_STATE";
- field public static final String EXTRA_VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL = "android.telephony.extra.VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL";
- field public static final String EXTRA_VOICEMAIL_SCRAMBLED_PIN_STRING = "android.telephony.extra.VOICEMAIL_SCRAMBLED_PIN_STRING";
- field public static final int INVALID_EMERGENCY_NUMBER_DB_VERSION = -1; // 0xffffffff
- field public static final int KEY_TYPE_EPDG = 1; // 0x1
- field public static final int KEY_TYPE_WLAN = 2; // 0x2
- field public static final int MOBILE_DATA_POLICY_DATA_ON_NON_DEFAULT_DURING_VOICE_CALL = 1; // 0x1
- field public static final int MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED = 2; // 0x2
- field public static final long NETWORK_TYPE_BITMASK_1xRTT = 64L; // 0x40L
- field public static final long NETWORK_TYPE_BITMASK_CDMA = 8L; // 0x8L
- field public static final long NETWORK_TYPE_BITMASK_EDGE = 2L; // 0x2L
- field public static final long NETWORK_TYPE_BITMASK_EHRPD = 8192L; // 0x2000L
- field public static final long NETWORK_TYPE_BITMASK_EVDO_0 = 16L; // 0x10L
- field public static final long NETWORK_TYPE_BITMASK_EVDO_A = 32L; // 0x20L
- field public static final long NETWORK_TYPE_BITMASK_EVDO_B = 2048L; // 0x800L
- field public static final long NETWORK_TYPE_BITMASK_GPRS = 1L; // 0x1L
- field public static final long NETWORK_TYPE_BITMASK_GSM = 32768L; // 0x8000L
- field public static final long NETWORK_TYPE_BITMASK_HSDPA = 128L; // 0x80L
- field public static final long NETWORK_TYPE_BITMASK_HSPA = 512L; // 0x200L
- field public static final long NETWORK_TYPE_BITMASK_HSPAP = 16384L; // 0x4000L
- field public static final long NETWORK_TYPE_BITMASK_HSUPA = 256L; // 0x100L
- field public static final long NETWORK_TYPE_BITMASK_IWLAN = 131072L; // 0x20000L
- field public static final long NETWORK_TYPE_BITMASK_LTE = 4096L; // 0x1000L
- field public static final long NETWORK_TYPE_BITMASK_LTE_CA = 262144L; // 0x40000L
- field public static final long NETWORK_TYPE_BITMASK_NR = 524288L; // 0x80000L
- field public static final long NETWORK_TYPE_BITMASK_TD_SCDMA = 65536L; // 0x10000L
- field public static final long NETWORK_TYPE_BITMASK_UMTS = 4L; // 0x4L
- field public static final long NETWORK_TYPE_BITMASK_UNKNOWN = 0L; // 0x0L
- field public static final int RADIO_POWER_OFF = 0; // 0x0
- field public static final int RADIO_POWER_ON = 1; // 0x1
- field public static final int RADIO_POWER_UNAVAILABLE = 2; // 0x2
- field public static final int SET_CARRIER_RESTRICTION_ERROR = 2; // 0x2
- field public static final int SET_CARRIER_RESTRICTION_NOT_SUPPORTED = 1; // 0x1
- field public static final int SET_CARRIER_RESTRICTION_SUCCESS = 0; // 0x0
- field public static final int SIM_ACTIVATION_STATE_ACTIVATED = 2; // 0x2
- field public static final int SIM_ACTIVATION_STATE_ACTIVATING = 1; // 0x1
- field public static final int SIM_ACTIVATION_STATE_DEACTIVATED = 3; // 0x3
- field public static final int SIM_ACTIVATION_STATE_RESTRICTED = 4; // 0x4
- field public static final int SIM_ACTIVATION_STATE_UNKNOWN = 0; // 0x0
- field public static final int SIM_STATE_LOADED = 10; // 0xa
- field public static final int SIM_STATE_PRESENT = 11; // 0xb
- field public static final int SRVCC_STATE_HANDOVER_CANCELED = 3; // 0x3
- field public static final int SRVCC_STATE_HANDOVER_COMPLETED = 1; // 0x1
- field public static final int SRVCC_STATE_HANDOVER_FAILED = 2; // 0x2
- field public static final int SRVCC_STATE_HANDOVER_NONE = -1; // 0xffffffff
- field public static final int SRVCC_STATE_HANDOVER_STARTED = 0; // 0x0
- }
-
- public static interface TelephonyManager.CallForwardingInfoCallback {
- method public void onCallForwardingInfoAvailable(@NonNull android.telephony.CallForwardingInfo);
- method public void onError(int);
- field public static final int RESULT_ERROR_FDN_CHECK_FAILURE = 2; // 0x2
- field public static final int RESULT_ERROR_NOT_SUPPORTED = 3; // 0x3
- field public static final int RESULT_ERROR_UNKNOWN = 1; // 0x1
- field public static final int RESULT_SUCCESS = 0; // 0x0
- }
-
- public final class UiccAccessRule implements android.os.Parcelable {
- ctor public UiccAccessRule(byte[], @Nullable String, long);
- method public int describeContents();
- method public int getCarrierPrivilegeStatus(android.content.pm.PackageInfo);
- method public int getCarrierPrivilegeStatus(android.content.pm.Signature, String);
- method public String getCertificateHexString();
- method @Nullable public String getPackageName();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.telephony.UiccAccessRule> CREATOR;
- }
-
- public class UiccSlotInfo implements android.os.Parcelable {
- ctor @Deprecated public UiccSlotInfo(boolean, boolean, String, int, int, boolean);
- method public int describeContents();
- method public String getCardId();
- method public int getCardStateInfo();
- method public boolean getIsActive();
- method public boolean getIsEuicc();
- method public boolean getIsExtendedApduSupported();
- method public int getLogicalSlotIdx();
- method public boolean isRemovable();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final int CARD_STATE_INFO_ABSENT = 1; // 0x1
- field public static final int CARD_STATE_INFO_ERROR = 3; // 0x3
- field public static final int CARD_STATE_INFO_PRESENT = 2; // 0x2
- field public static final int CARD_STATE_INFO_RESTRICTED = 4; // 0x4
- field @NonNull public static final android.os.Parcelable.Creator<android.telephony.UiccSlotInfo> CREATOR;
- }
-
- public abstract class VisualVoicemailService extends android.app.Service {
- method public static final void sendVisualVoicemailSms(android.content.Context, android.telecom.PhoneAccountHandle, String, short, String, android.app.PendingIntent);
- method public static final void setSmsFilterSettings(android.content.Context, android.telecom.PhoneAccountHandle, android.telephony.VisualVoicemailSmsFilterSettings);
- }
-
-}
-
-package android.telephony.cdma {
-
- public final class CdmaSmsCbProgramData implements android.os.Parcelable {
- method public int describeContents();
- method public int getCategory();
- method public int getOperation();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final int CATEGORY_CMAS_CHILD_ABDUCTION_EMERGENCY = 4099; // 0x1003
- field public static final int CATEGORY_CMAS_EXTREME_THREAT = 4097; // 0x1001
- field public static final int CATEGORY_CMAS_LAST_RESERVED_VALUE = 4351; // 0x10ff
- field public static final int CATEGORY_CMAS_PRESIDENTIAL_LEVEL_ALERT = 4096; // 0x1000
- field public static final int CATEGORY_CMAS_SEVERE_THREAT = 4098; // 0x1002
- field public static final int CATEGORY_CMAS_TEST_MESSAGE = 4100; // 0x1004
- field @NonNull public static final android.os.Parcelable.Creator<android.telephony.cdma.CdmaSmsCbProgramData> CREATOR;
- field public static final int OPERATION_ADD_CATEGORY = 1; // 0x1
- field public static final int OPERATION_CLEAR_CATEGORIES = 2; // 0x2
- field public static final int OPERATION_DELETE_CATEGORY = 0; // 0x0
- }
-
-}
-
-package android.telephony.data {
-
- public final class DataCallResponse implements android.os.Parcelable {
- method public int describeContents();
- method @NonNull public java.util.List<android.net.LinkAddress> getAddresses();
- method public int getCause();
- method @NonNull public java.util.List<java.net.InetAddress> getDnsAddresses();
- method @NonNull public java.util.List<java.net.InetAddress> getGatewayAddresses();
- method public int getHandoverFailureMode();
- method public int getId();
- method @NonNull public String getInterfaceName();
- method public int getLinkStatus();
- method @Deprecated public int getMtu();
- method public int getMtuV4();
- method public int getMtuV6();
- method @NonNull public java.util.List<java.net.InetAddress> getPcscfAddresses();
- method public int getProtocolType();
- method public int getSuggestedRetryTime();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.telephony.data.DataCallResponse> CREATOR;
- field public static final int HANDOVER_FAILURE_MODE_DO_FALLBACK = 1; // 0x1
- field public static final int HANDOVER_FAILURE_MODE_LEGACY = 0; // 0x0
- field public static final int HANDOVER_FAILURE_MODE_NO_FALLBACK_RETRY_HANDOVER = 2; // 0x2
- field public static final int HANDOVER_FAILURE_MODE_NO_FALLBACK_RETRY_SETUP_NORMAL = 3; // 0x3
- field public static final int HANDOVER_FAILURE_MODE_UNKNOWN = -1; // 0xffffffff
- field public static final int LINK_STATUS_ACTIVE = 2; // 0x2
- field public static final int LINK_STATUS_DORMANT = 1; // 0x1
- field public static final int LINK_STATUS_INACTIVE = 0; // 0x0
- field public static final int LINK_STATUS_UNKNOWN = -1; // 0xffffffff
- }
-
- public static final class DataCallResponse.Builder {
- ctor public DataCallResponse.Builder();
- method @NonNull public android.telephony.data.DataCallResponse build();
- method @NonNull public android.telephony.data.DataCallResponse.Builder setAddresses(@NonNull java.util.List<android.net.LinkAddress>);
- method @NonNull public android.telephony.data.DataCallResponse.Builder setCause(int);
- method @NonNull public android.telephony.data.DataCallResponse.Builder setDnsAddresses(@NonNull java.util.List<java.net.InetAddress>);
- method @NonNull public android.telephony.data.DataCallResponse.Builder setGatewayAddresses(@NonNull java.util.List<java.net.InetAddress>);
- method @NonNull public android.telephony.data.DataCallResponse.Builder setHandoverFailureMode(int);
- method @NonNull public android.telephony.data.DataCallResponse.Builder setId(int);
- method @NonNull public android.telephony.data.DataCallResponse.Builder setInterfaceName(@NonNull String);
- method @NonNull public android.telephony.data.DataCallResponse.Builder setLinkStatus(int);
- method @Deprecated @NonNull public android.telephony.data.DataCallResponse.Builder setMtu(int);
- method @NonNull public android.telephony.data.DataCallResponse.Builder setMtuV4(int);
- method @NonNull public android.telephony.data.DataCallResponse.Builder setMtuV6(int);
- method @NonNull public android.telephony.data.DataCallResponse.Builder setPcscfAddresses(@NonNull java.util.List<java.net.InetAddress>);
- method @NonNull public android.telephony.data.DataCallResponse.Builder setProtocolType(int);
- method @NonNull public android.telephony.data.DataCallResponse.Builder setSuggestedRetryTime(int);
- }
-
- public final class DataProfile implements android.os.Parcelable {
- method public int describeContents();
- method @NonNull public String getApn();
- method public int getAuthType();
- method public int getBearerBitmask();
- method @Deprecated public int getMtu();
- method public int getMtuV4();
- method public int getMtuV6();
- method @Nullable public String getPassword();
- method public int getProfileId();
- method public int getProtocolType();
- method public int getRoamingProtocolType();
- method public int getSupportedApnTypesBitmask();
- method public int getType();
- method @Nullable public String getUserName();
- method public boolean isEnabled();
- method public boolean isPersistent();
- method public boolean isPreferred();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.telephony.data.DataProfile> CREATOR;
- field public static final int TYPE_3GPP = 1; // 0x1
- field public static final int TYPE_3GPP2 = 2; // 0x2
- field public static final int TYPE_COMMON = 0; // 0x0
- }
-
- public static final class DataProfile.Builder {
- ctor public DataProfile.Builder();
- method @NonNull public android.telephony.data.DataProfile build();
- method @NonNull public android.telephony.data.DataProfile.Builder enable(boolean);
- method @NonNull public android.telephony.data.DataProfile.Builder setApn(@NonNull String);
- method @NonNull public android.telephony.data.DataProfile.Builder setAuthType(int);
- method @NonNull public android.telephony.data.DataProfile.Builder setBearerBitmask(int);
- method @Deprecated @NonNull public android.telephony.data.DataProfile.Builder setMtu(int);
- method @NonNull public android.telephony.data.DataProfile.Builder setMtuV4(int);
- method @NonNull public android.telephony.data.DataProfile.Builder setMtuV6(int);
- method @NonNull public android.telephony.data.DataProfile.Builder setPassword(@NonNull String);
- method @NonNull public android.telephony.data.DataProfile.Builder setPersistent(boolean);
- method @NonNull public android.telephony.data.DataProfile.Builder setPreferred(boolean);
- method @NonNull public android.telephony.data.DataProfile.Builder setProfileId(int);
- method @NonNull public android.telephony.data.DataProfile.Builder setProtocolType(int);
- method @NonNull public android.telephony.data.DataProfile.Builder setRoamingProtocolType(int);
- method @NonNull public android.telephony.data.DataProfile.Builder setSupportedApnTypesBitmask(int);
- method @NonNull public android.telephony.data.DataProfile.Builder setType(int);
- method @NonNull public android.telephony.data.DataProfile.Builder setUserName(@NonNull String);
- }
-
- public abstract class DataService extends android.app.Service {
- ctor public DataService();
- method public android.os.IBinder onBind(android.content.Intent);
- method @Nullable public abstract android.telephony.data.DataService.DataServiceProvider onCreateDataServiceProvider(int);
- field public static final int REQUEST_REASON_HANDOVER = 3; // 0x3
- field public static final int REQUEST_REASON_NORMAL = 1; // 0x1
- field public static final int REQUEST_REASON_SHUTDOWN = 2; // 0x2
- field public static final int REQUEST_REASON_UNKNOWN = 0; // 0x0
- field public static final String SERVICE_INTERFACE = "android.telephony.data.DataService";
- }
-
- public abstract class DataService.DataServiceProvider implements java.lang.AutoCloseable {
- ctor public DataService.DataServiceProvider(int);
- method public abstract void close();
- method public void deactivateDataCall(int, int, @Nullable android.telephony.data.DataServiceCallback);
- method public final int getSlotIndex();
- method public final void notifyDataCallListChanged(java.util.List<android.telephony.data.DataCallResponse>);
- method public void requestDataCallList(@NonNull android.telephony.data.DataServiceCallback);
- method public void setDataProfile(@NonNull java.util.List<android.telephony.data.DataProfile>, boolean, @NonNull android.telephony.data.DataServiceCallback);
- method public void setInitialAttachApn(@NonNull android.telephony.data.DataProfile, boolean, @NonNull android.telephony.data.DataServiceCallback);
- method public void setupDataCall(int, @NonNull android.telephony.data.DataProfile, boolean, boolean, int, @Nullable android.net.LinkProperties, @NonNull android.telephony.data.DataServiceCallback);
- }
-
- public class DataServiceCallback {
- method public void onDataCallListChanged(@NonNull java.util.List<android.telephony.data.DataCallResponse>);
- method public void onDeactivateDataCallComplete(int);
- method public void onRequestDataCallListComplete(int, @NonNull java.util.List<android.telephony.data.DataCallResponse>);
- method public void onSetDataProfileComplete(int);
- method public void onSetInitialAttachApnComplete(int);
- method public void onSetupDataCallComplete(int, @Nullable android.telephony.data.DataCallResponse);
- field public static final int RESULT_ERROR_BUSY = 3; // 0x3
- field public static final int RESULT_ERROR_ILLEGAL_STATE = 4; // 0x4
- field public static final int RESULT_ERROR_INVALID_ARG = 2; // 0x2
- field public static final int RESULT_ERROR_UNSUPPORTED = 1; // 0x1
- field public static final int RESULT_SUCCESS = 0; // 0x0
- }
-
- public abstract class QualifiedNetworksService extends android.app.Service {
- ctor public QualifiedNetworksService();
- method @NonNull public abstract android.telephony.data.QualifiedNetworksService.NetworkAvailabilityProvider onCreateNetworkAvailabilityProvider(int);
- field public static final String QUALIFIED_NETWORKS_SERVICE_INTERFACE = "android.telephony.data.QualifiedNetworksService";
- }
-
- public abstract class QualifiedNetworksService.NetworkAvailabilityProvider implements java.lang.AutoCloseable {
- ctor public QualifiedNetworksService.NetworkAvailabilityProvider(int);
- method public abstract void close();
- method public final int getSlotIndex();
- method public final void updateQualifiedNetworkTypes(int, @NonNull java.util.List<java.lang.Integer>);
- }
-
-}
-
-package android.telephony.euicc {
-
- public final class DownloadableSubscription implements android.os.Parcelable {
- method public java.util.List<android.telephony.UiccAccessRule> getAccessRules();
- method @Nullable public String getCarrierName();
- }
-
- public static final class DownloadableSubscription.Builder {
- ctor public DownloadableSubscription.Builder();
- ctor public DownloadableSubscription.Builder(android.telephony.euicc.DownloadableSubscription);
- method public android.telephony.euicc.DownloadableSubscription build();
- method public android.telephony.euicc.DownloadableSubscription.Builder setAccessRules(java.util.List<android.telephony.UiccAccessRule>);
- method public android.telephony.euicc.DownloadableSubscription.Builder setCarrierName(String);
- method public android.telephony.euicc.DownloadableSubscription.Builder setConfirmationCode(String);
- method public android.telephony.euicc.DownloadableSubscription.Builder setEncodedActivationCode(String);
- }
-
- public class EuiccCardManager {
- method public void authenticateServer(String, String, byte[], byte[], byte[], byte[], java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<byte[]>);
- method public void cancelSession(String, byte[], @android.telephony.euicc.EuiccCardManager.CancelReason int, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<byte[]>);
- method public void deleteProfile(String, String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.Void>);
- method public void disableProfile(String, String, boolean, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.Void>);
- method public void listNotifications(String, @android.telephony.euicc.EuiccNotification.Event int, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<android.telephony.euicc.EuiccNotification[]>);
- method public void loadBoundProfilePackage(String, byte[], java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<byte[]>);
- method public void prepareDownload(String, @Nullable byte[], byte[], byte[], byte[], java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<byte[]>);
- method public void removeNotificationFromList(String, int, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.Void>);
- method public void requestAllProfiles(String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<android.service.euicc.EuiccProfileInfo[]>);
- method public void requestDefaultSmdpAddress(String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.String>);
- method public void requestEuiccChallenge(String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<byte[]>);
- method public void requestEuiccInfo1(String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<byte[]>);
- method public void requestEuiccInfo2(String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<byte[]>);
- method public void requestProfile(String, String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<android.service.euicc.EuiccProfileInfo>);
- method public void requestRulesAuthTable(String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<android.telephony.euicc.EuiccRulesAuthTable>);
- method public void requestSmdsAddress(String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.String>);
- method public void resetMemory(String, @android.telephony.euicc.EuiccCardManager.ResetOption int, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.Void>);
- method public void retrieveNotification(String, int, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<android.telephony.euicc.EuiccNotification>);
- method public void retrieveNotificationList(String, @android.telephony.euicc.EuiccNotification.Event int, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<android.telephony.euicc.EuiccNotification[]>);
- method public void setDefaultSmdpAddress(String, String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.Void>);
- method public void setNickname(String, String, String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.Void>);
- method public void switchToProfile(String, String, boolean, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<android.service.euicc.EuiccProfileInfo>);
- field public static final int CANCEL_REASON_END_USER_REJECTED = 0; // 0x0
- field public static final int CANCEL_REASON_POSTPONED = 1; // 0x1
- field public static final int CANCEL_REASON_PPR_NOT_ALLOWED = 3; // 0x3
- field public static final int CANCEL_REASON_TIMEOUT = 2; // 0x2
- field public static final int RESET_OPTION_DELETE_FIELD_LOADED_TEST_PROFILES = 2; // 0x2
- field public static final int RESET_OPTION_DELETE_OPERATIONAL_PROFILES = 1; // 0x1
- field public static final int RESET_OPTION_RESET_DEFAULT_SMDP_ADDRESS = 4; // 0x4
- field public static final int RESULT_CALLER_NOT_ALLOWED = -3; // 0xfffffffd
- field public static final int RESULT_EUICC_NOT_FOUND = -2; // 0xfffffffe
- field public static final int RESULT_OK = 0; // 0x0
- field public static final int RESULT_UNKNOWN_ERROR = -1; // 0xffffffff
- }
-
- @IntDef(prefix={"CANCEL_REASON_"}, value={android.telephony.euicc.EuiccCardManager.CANCEL_REASON_END_USER_REJECTED, android.telephony.euicc.EuiccCardManager.CANCEL_REASON_POSTPONED, android.telephony.euicc.EuiccCardManager.CANCEL_REASON_TIMEOUT, android.telephony.euicc.EuiccCardManager.CANCEL_REASON_PPR_NOT_ALLOWED}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface EuiccCardManager.CancelReason {
- }
-
- @IntDef(flag=true, prefix={"RESET_OPTION_"}, value={android.telephony.euicc.EuiccCardManager.RESET_OPTION_DELETE_OPERATIONAL_PROFILES, android.telephony.euicc.EuiccCardManager.RESET_OPTION_DELETE_FIELD_LOADED_TEST_PROFILES, android.telephony.euicc.EuiccCardManager.RESET_OPTION_RESET_DEFAULT_SMDP_ADDRESS}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface EuiccCardManager.ResetOption {
- }
-
- public static interface EuiccCardManager.ResultCallback<T> {
- method public void onComplete(int, T);
- }
-
- public class EuiccManager {
- method @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public void continueOperation(android.content.Intent, android.os.Bundle);
- method @Deprecated @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public void eraseSubscriptions(@NonNull android.app.PendingIntent);
- method @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public void eraseSubscriptions(@android.telephony.euicc.EuiccCardManager.ResetOption int, @NonNull android.app.PendingIntent);
- method @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public void getDefaultDownloadableSubscriptionList(android.app.PendingIntent);
- method @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public void getDownloadableSubscriptionMetadata(android.telephony.euicc.DownloadableSubscription, android.app.PendingIntent);
- method @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public int getOtaStatus();
- method @NonNull @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public java.util.List<java.lang.String> getSupportedCountries();
- method @NonNull @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public java.util.List<java.lang.String> getUnsupportedCountries();
- method @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public boolean isSupportedCountry(@NonNull String);
- method @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public void setSupportedCountries(@NonNull java.util.List<java.lang.String>);
- method @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public void setUnsupportedCountries(@NonNull java.util.List<java.lang.String>);
- field public static final String ACTION_DELETE_SUBSCRIPTION_PRIVILEGED = "android.telephony.euicc.action.DELETE_SUBSCRIPTION_PRIVILEGED";
- field @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public static final String ACTION_OTA_STATUS_CHANGED = "android.telephony.euicc.action.OTA_STATUS_CHANGED";
- field public static final String ACTION_PROVISION_EMBEDDED_SUBSCRIPTION = "android.telephony.euicc.action.PROVISION_EMBEDDED_SUBSCRIPTION";
- field public static final String ACTION_RENAME_SUBSCRIPTION_PRIVILEGED = "android.telephony.euicc.action.RENAME_SUBSCRIPTION_PRIVILEGED";
- field public static final String ACTION_TOGGLE_SUBSCRIPTION_PRIVILEGED = "android.telephony.euicc.action.TOGGLE_SUBSCRIPTION_PRIVILEGED";
- field public static final int EUICC_ACTIVATION_TYPE_ACCOUNT_REQUIRED = 4; // 0x4
- field public static final int EUICC_ACTIVATION_TYPE_BACKUP = 2; // 0x2
- field public static final int EUICC_ACTIVATION_TYPE_DEFAULT = 1; // 0x1
- field public static final int EUICC_ACTIVATION_TYPE_TRANSFER = 3; // 0x3
- field public static final int EUICC_OTA_FAILED = 2; // 0x2
- field public static final int EUICC_OTA_IN_PROGRESS = 1; // 0x1
- field public static final int EUICC_OTA_NOT_NEEDED = 4; // 0x4
- field public static final int EUICC_OTA_STATUS_UNAVAILABLE = 5; // 0x5
- field public static final int EUICC_OTA_SUCCEEDED = 3; // 0x3
- field public static final String EXTRA_ACTIVATION_TYPE = "android.telephony.euicc.extra.ACTIVATION_TYPE";
- field public static final String EXTRA_EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTIONS = "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTIONS";
- field public static final String EXTRA_ENABLE_SUBSCRIPTION = "android.telephony.euicc.extra.ENABLE_SUBSCRIPTION";
- field public static final String EXTRA_FORCE_PROVISION = "android.telephony.euicc.extra.FORCE_PROVISION";
- field public static final String EXTRA_FROM_SUBSCRIPTION_ID = "android.telephony.euicc.extra.FROM_SUBSCRIPTION_ID";
- field public static final String EXTRA_PHYSICAL_SLOT_ID = "android.telephony.euicc.extra.PHYSICAL_SLOT_ID";
- field public static final String EXTRA_SUBSCRIPTION_ID = "android.telephony.euicc.extra.SUBSCRIPTION_ID";
- field public static final String EXTRA_SUBSCRIPTION_NICKNAME = "android.telephony.euicc.extra.SUBSCRIPTION_NICKNAME";
- }
-
- @IntDef(prefix={"EUICC_OTA_"}, value={android.telephony.euicc.EuiccManager.EUICC_OTA_IN_PROGRESS, android.telephony.euicc.EuiccManager.EUICC_OTA_FAILED, android.telephony.euicc.EuiccManager.EUICC_OTA_SUCCEEDED, android.telephony.euicc.EuiccManager.EUICC_OTA_NOT_NEEDED, android.telephony.euicc.EuiccManager.EUICC_OTA_STATUS_UNAVAILABLE}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface EuiccManager.OtaStatus {
- }
-
- public final class EuiccNotification implements android.os.Parcelable {
- ctor public EuiccNotification(int, String, @android.telephony.euicc.EuiccNotification.Event int, @Nullable byte[]);
- method public int describeContents();
- method @Nullable public byte[] getData();
- method @android.telephony.euicc.EuiccNotification.Event public int getEvent();
- method public int getSeq();
- method public String getTargetAddr();
- method public void writeToParcel(android.os.Parcel, int);
- field @android.telephony.euicc.EuiccNotification.Event public static final int ALL_EVENTS = 15; // 0xf
- field @NonNull public static final android.os.Parcelable.Creator<android.telephony.euicc.EuiccNotification> CREATOR;
- field public static final int EVENT_DELETE = 8; // 0x8
- field public static final int EVENT_DISABLE = 4; // 0x4
- field public static final int EVENT_ENABLE = 2; // 0x2
- field public static final int EVENT_INSTALL = 1; // 0x1
- }
-
- @IntDef(flag=true, prefix={"EVENT_"}, value={android.telephony.euicc.EuiccNotification.EVENT_INSTALL, android.telephony.euicc.EuiccNotification.EVENT_ENABLE, android.telephony.euicc.EuiccNotification.EVENT_DISABLE, android.telephony.euicc.EuiccNotification.EVENT_DELETE}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface EuiccNotification.Event {
- }
-
- public final class EuiccRulesAuthTable implements android.os.Parcelable {
- method public int describeContents();
- method public int findIndex(@android.service.euicc.EuiccProfileInfo.PolicyRule int, android.service.carrier.CarrierIdentifier);
- method public boolean hasPolicyRuleFlag(int, @android.telephony.euicc.EuiccRulesAuthTable.PolicyRuleFlag int);
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.telephony.euicc.EuiccRulesAuthTable> CREATOR;
- field public static final int POLICY_RULE_FLAG_CONSENT_REQUIRED = 1; // 0x1
- }
-
- public static final class EuiccRulesAuthTable.Builder {
- ctor public EuiccRulesAuthTable.Builder(int);
- method public android.telephony.euicc.EuiccRulesAuthTable.Builder add(int, java.util.List<android.service.carrier.CarrierIdentifier>, int);
- method public android.telephony.euicc.EuiccRulesAuthTable build();
- }
-
- @IntDef(flag=true, prefix={"POLICY_RULE_FLAG_"}, value={android.telephony.euicc.EuiccRulesAuthTable.POLICY_RULE_FLAG_CONSENT_REQUIRED}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface EuiccRulesAuthTable.PolicyRuleFlag {
- }
-
-}
-
-package android.telephony.ims {
-
- public final class ImsCallForwardInfo implements android.os.Parcelable {
- ctor public ImsCallForwardInfo(int, int, int, int, @NonNull String, int);
- method public int describeContents();
- method public int getCondition();
- method public String getNumber();
- method public int getServiceClass();
- method public int getStatus();
- method public int getTimeSeconds();
- method public int getToA();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final int CDIV_CF_REASON_ALL = 4; // 0x4
- field public static final int CDIV_CF_REASON_ALL_CONDITIONAL = 5; // 0x5
- field public static final int CDIV_CF_REASON_BUSY = 1; // 0x1
- field public static final int CDIV_CF_REASON_NOT_LOGGED_IN = 6; // 0x6
- field public static final int CDIV_CF_REASON_NOT_REACHABLE = 3; // 0x3
- field public static final int CDIV_CF_REASON_NO_REPLY = 2; // 0x2
- field public static final int CDIV_CF_REASON_UNCONDITIONAL = 0; // 0x0
- field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsCallForwardInfo> CREATOR;
- field public static final int STATUS_ACTIVE = 1; // 0x1
- field public static final int STATUS_NOT_ACTIVE = 0; // 0x0
- field public static final int TYPE_OF_ADDRESS_INTERNATIONAL = 145; // 0x91
- field public static final int TYPE_OF_ADDRESS_UNKNOWN = 129; // 0x81
- }
-
- public final class ImsCallProfile implements android.os.Parcelable {
- ctor public ImsCallProfile();
- ctor public ImsCallProfile(int, int);
- ctor public ImsCallProfile(int, int, android.os.Bundle, android.telephony.ims.ImsStreamMediaProfile);
- method public int describeContents();
- method public String getCallExtra(String);
- method public String getCallExtra(String, String);
- method public boolean getCallExtraBoolean(String);
- method public boolean getCallExtraBoolean(String, boolean);
- method public int getCallExtraInt(String);
- method public int getCallExtraInt(String, int);
- method public android.os.Bundle getCallExtras();
- method public int getCallType();
- method public static int getCallTypeFromVideoState(int);
- method public int getCallerNumberVerificationStatus();
- method public int getEmergencyCallRouting();
- method public int getEmergencyServiceCategories();
- method @NonNull public java.util.List<java.lang.String> getEmergencyUrns();
- method public android.telephony.ims.ImsStreamMediaProfile getMediaProfile();
- method @NonNull public android.os.Bundle getProprietaryCallExtras();
- method public int getRestrictCause();
- method public int getServiceType();
- method public static int getVideoStateFromCallType(int);
- method public static int getVideoStateFromImsCallProfile(android.telephony.ims.ImsCallProfile);
- method public boolean hasKnownUserIntentEmergency();
- method public boolean isEmergencyCallTesting();
- method public boolean isVideoCall();
- method public boolean isVideoPaused();
- method public static int presentationToOir(int);
- method public void setCallExtra(String, String);
- method public void setCallExtraBoolean(String, boolean);
- method public void setCallExtraInt(String, int);
- method public void setCallRestrictCause(int);
- method public void setCallerNumberVerificationStatus(int);
- method public void setEmergencyCallRouting(int);
- method public void setEmergencyCallTesting(boolean);
- method public void setEmergencyServiceCategories(int);
- method public void setEmergencyUrns(@NonNull java.util.List<java.lang.String>);
- method public void setHasKnownUserIntentEmergency(boolean);
- method public void updateCallExtras(android.telephony.ims.ImsCallProfile);
- method public void updateCallType(android.telephony.ims.ImsCallProfile);
- method public void updateMediaProfile(android.telephony.ims.ImsCallProfile);
- method public void writeToParcel(android.os.Parcel, int);
- field public static final int CALL_RESTRICT_CAUSE_DISABLED = 2; // 0x2
- field public static final int CALL_RESTRICT_CAUSE_HD = 3; // 0x3
- field public static final int CALL_RESTRICT_CAUSE_NONE = 0; // 0x0
- field public static final int CALL_RESTRICT_CAUSE_RAT = 1; // 0x1
- field public static final int CALL_TYPE_VIDEO_N_VOICE = 3; // 0x3
- field public static final int CALL_TYPE_VOICE = 2; // 0x2
- field public static final int CALL_TYPE_VOICE_N_VIDEO = 1; // 0x1
- field public static final int CALL_TYPE_VS = 8; // 0x8
- field public static final int CALL_TYPE_VS_RX = 10; // 0xa
- field public static final int CALL_TYPE_VS_TX = 9; // 0x9
- field public static final int CALL_TYPE_VT = 4; // 0x4
- field public static final int CALL_TYPE_VT_NODIR = 7; // 0x7
- field public static final int CALL_TYPE_VT_RX = 6; // 0x6
- field public static final int CALL_TYPE_VT_TX = 5; // 0x5
- field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsCallProfile> CREATOR;
- field public static final int DIALSTRING_NORMAL = 0; // 0x0
- field public static final int DIALSTRING_SS_CONF = 1; // 0x1
- field public static final int DIALSTRING_USSD = 2; // 0x2
- field public static final String EXTRA_ADDITIONAL_CALL_INFO = "AdditionalCallInfo";
- field public static final String EXTRA_ADDITIONAL_SIP_INVITE_FIELDS = "android.telephony.ims.extra.ADDITIONAL_SIP_INVITE_FIELDS";
- field public static final String EXTRA_CALL_DISCONNECT_CAUSE = "android.telephony.ims.extra.CALL_DISCONNECT_CAUSE";
- field public static final String EXTRA_CALL_NETWORK_TYPE = "android.telephony.ims.extra.CALL_NETWORK_TYPE";
- field @Deprecated public static final String EXTRA_CALL_RAT_TYPE = "CallRadioTech";
- field public static final String EXTRA_CHILD_NUMBER = "ChildNum";
- field public static final String EXTRA_CNA = "cna";
- field public static final String EXTRA_CNAP = "cnap";
- field public static final String EXTRA_CODEC = "Codec";
- field public static final String EXTRA_DIALSTRING = "dialstring";
- field public static final String EXTRA_DISPLAY_TEXT = "DisplayText";
- field public static final String EXTRA_EMERGENCY_CALL = "e_call";
- field public static final String EXTRA_FORWARDED_NUMBER = "android.telephony.ims.extra.FORWARDED_NUMBER";
- field public static final String EXTRA_IS_CALL_PULL = "CallPull";
- field public static final String EXTRA_OI = "oi";
- field public static final String EXTRA_OIR = "oir";
- field public static final String EXTRA_REMOTE_URI = "remote_uri";
- field public static final String EXTRA_USSD = "ussd";
- field public static final int OIR_DEFAULT = 0; // 0x0
- field public static final int OIR_PRESENTATION_NOT_RESTRICTED = 2; // 0x2
- field public static final int OIR_PRESENTATION_PAYPHONE = 4; // 0x4
- field public static final int OIR_PRESENTATION_RESTRICTED = 1; // 0x1
- field public static final int OIR_PRESENTATION_UNKNOWN = 3; // 0x3
- field public static final int SERVICE_TYPE_EMERGENCY = 2; // 0x2
- field public static final int SERVICE_TYPE_NONE = 0; // 0x0
- field public static final int SERVICE_TYPE_NORMAL = 1; // 0x1
- field public static final int VERIFICATION_STATUS_FAILED = 2; // 0x2
- field public static final int VERIFICATION_STATUS_NOT_VERIFIED = 0; // 0x0
- field public static final int VERIFICATION_STATUS_PASSED = 1; // 0x1
- }
-
- public class ImsCallSessionListener {
- method public void callQualityChanged(@NonNull android.telephony.CallQuality);
- method public void callSessionConferenceExtendFailed(android.telephony.ims.ImsReasonInfo);
- method public void callSessionConferenceExtendReceived(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile);
- method public void callSessionConferenceExtended(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile);
- method public void callSessionConferenceStateUpdated(android.telephony.ims.ImsConferenceState);
- method @Deprecated public void callSessionHandover(int, int, android.telephony.ims.ImsReasonInfo);
- method @Deprecated public void callSessionHandoverFailed(int, int, android.telephony.ims.ImsReasonInfo);
- method public void callSessionHeld(android.telephony.ims.ImsCallProfile);
- method public void callSessionHoldFailed(android.telephony.ims.ImsReasonInfo);
- method public void callSessionHoldReceived(android.telephony.ims.ImsCallProfile);
- method public void callSessionInitiated(android.telephony.ims.ImsCallProfile);
- method public void callSessionInitiatedFailed(android.telephony.ims.ImsReasonInfo);
- method public void callSessionInviteParticipantsRequestDelivered();
- method public void callSessionInviteParticipantsRequestFailed(android.telephony.ims.ImsReasonInfo);
- method @Deprecated public void callSessionMayHandover(int, int);
- method public void callSessionMergeComplete(android.telephony.ims.stub.ImsCallSessionImplBase);
- method public void callSessionMergeFailed(android.telephony.ims.ImsReasonInfo);
- method public void callSessionMergeStarted(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile);
- method public void callSessionMultipartyStateChanged(boolean);
- method public void callSessionProgressing(android.telephony.ims.ImsStreamMediaProfile);
- method public void callSessionRemoveParticipantsRequestDelivered();
- method public void callSessionRemoveParticipantsRequestFailed(android.telephony.ims.ImsReasonInfo);
- method public void callSessionResumeFailed(android.telephony.ims.ImsReasonInfo);
- method public void callSessionResumeReceived(android.telephony.ims.ImsCallProfile);
- method public void callSessionResumed(android.telephony.ims.ImsCallProfile);
- method public void callSessionRttAudioIndicatorChanged(@NonNull android.telephony.ims.ImsStreamMediaProfile);
- method public void callSessionRttMessageReceived(String);
- method public void callSessionRttModifyRequestReceived(android.telephony.ims.ImsCallProfile);
- method public void callSessionRttModifyResponseReceived(int);
- method public void callSessionSuppServiceReceived(android.telephony.ims.ImsSuppServiceNotification);
- method public void callSessionTerminated(android.telephony.ims.ImsReasonInfo);
- method public void callSessionTtyModeReceived(int);
- method public void callSessionUpdateFailed(android.telephony.ims.ImsReasonInfo);
- method public void callSessionUpdateReceived(android.telephony.ims.ImsCallProfile);
- method public void callSessionUpdated(android.telephony.ims.ImsCallProfile);
- method public void callSessionUssdMessageReceived(int, String);
- method public void onHandover(int, int, @Nullable android.telephony.ims.ImsReasonInfo);
- method public void onHandoverFailed(int, int, @NonNull android.telephony.ims.ImsReasonInfo);
- method public void onMayHandover(int, int);
- }
-
- public final class ImsConferenceState implements android.os.Parcelable {
- method public int describeContents();
- method public static int getConnectionStateForStatus(String);
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsConferenceState> CREATOR;
- field public static final String DISPLAY_TEXT = "display-text";
- field public static final String ENDPOINT = "endpoint";
- field public static final String SIP_STATUS_CODE = "sipstatuscode";
- field public static final String STATUS = "status";
- field public static final String STATUS_ALERTING = "alerting";
- field public static final String STATUS_CONNECTED = "connected";
- field public static final String STATUS_CONNECT_FAIL = "connect-fail";
- field public static final String STATUS_DIALING_IN = "dialing-in";
- field public static final String STATUS_DIALING_OUT = "dialing-out";
- field public static final String STATUS_DISCONNECTED = "disconnected";
- field public static final String STATUS_DISCONNECTING = "disconnecting";
- field public static final String STATUS_MUTED_VIA_FOCUS = "muted-via-focus";
- field public static final String STATUS_ON_HOLD = "on-hold";
- field public static final String STATUS_PENDING = "pending";
- field public static final String STATUS_SEND_ONLY = "sendonly";
- field public static final String STATUS_SEND_RECV = "sendrecv";
- field public static final String USER = "user";
- field public final java.util.HashMap<java.lang.String,android.os.Bundle> mParticipants;
- }
-
- public final class ImsException extends java.lang.Exception {
- ctor public ImsException(@Nullable String);
- ctor public ImsException(@Nullable String, int);
- ctor public ImsException(@Nullable String, int, @Nullable Throwable);
- }
-
- public final class ImsExternalCallState implements android.os.Parcelable {
- ctor public ImsExternalCallState(@NonNull String, @NonNull android.net.Uri, @Nullable android.net.Uri, boolean, int, int, boolean);
- method public int describeContents();
- method @NonNull public android.net.Uri getAddress();
- method public int getCallId();
- method public int getCallState();
- method public int getCallType();
- method @Nullable public android.net.Uri getLocalAddress();
- method public boolean isCallHeld();
- method public boolean isCallPullable();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final int CALL_STATE_CONFIRMED = 1; // 0x1
- field public static final int CALL_STATE_TERMINATED = 2; // 0x2
- field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsExternalCallState> CREATOR;
- }
-
- public class ImsManager {
- method @NonNull public android.telephony.ims.SipDelegateManager getSipDelegateManager(int);
- }
-
- public class ImsMmTelManager implements android.telephony.ims.RegistrationManager {
- method @Deprecated @NonNull @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public static android.telephony.ims.ImsMmTelManager createForSubscriptionId(int);
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getFeatureState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>) throws android.telephony.ims.ImsException;
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getRegistrationState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getVoWiFiRoamingModeSetting();
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isAvailable(int, int);
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isCapable(int, int);
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void isSupported(int, int, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>) throws android.telephony.ims.ImsException;
- method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerImsRegistrationCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ImsMmTelManager.RegistrationCallback) throws android.telephony.ims.ImsException;
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setAdvancedCallingSettingEnabled(boolean);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setRttCapabilitySetting(boolean);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiModeSetting(int);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiNonPersistent(boolean, int);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiRoamingModeSetting(int);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiRoamingSettingEnabled(boolean);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiSettingEnabled(boolean);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVtSettingEnabled(boolean);
- method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterImsRegistrationCallback(@NonNull android.telephony.ims.ImsMmTelManager.RegistrationCallback);
- }
-
- @Deprecated public static class ImsMmTelManager.RegistrationCallback extends android.telephony.ims.RegistrationManager.RegistrationCallback {
- ctor @Deprecated public ImsMmTelManager.RegistrationCallback();
- }
-
- public final class ImsReasonInfo implements android.os.Parcelable {
- field public static final String EXTRA_MSG_SERVICE_NOT_AUTHORIZED = "Forbidden. Not Authorized for Service";
- }
-
- public class ImsService extends android.app.Service {
- ctor public ImsService();
- method public android.telephony.ims.feature.MmTelFeature createMmTelFeature(int);
- method public android.telephony.ims.feature.RcsFeature createRcsFeature(int);
- method public void disableIms(int);
- method public void enableIms(int);
- method public android.telephony.ims.stub.ImsConfigImplBase getConfig(int);
- method public long getImsServiceCapabilities();
- method public android.telephony.ims.stub.ImsRegistrationImplBase getRegistration(int);
- method @Nullable public android.telephony.ims.stub.SipTransportImplBase getSipTransport(int);
- method public final void onUpdateSupportedImsFeatures(android.telephony.ims.stub.ImsFeatureConfiguration) throws android.os.RemoteException;
- method public android.telephony.ims.stub.ImsFeatureConfiguration querySupportedImsFeatures();
- method public void readyForFeatureCreation();
- field public static final long CAPABILITY_SIP_DELEGATE_CREATION = 2L; // 0x2L
- }
-
- public final class ImsSsData implements android.os.Parcelable {
- ctor public ImsSsData(int, int, int, int, int);
- method public int describeContents();
- method @Nullable public java.util.List<android.telephony.ims.ImsCallForwardInfo> getCallForwardInfo();
- method public int getRequestType();
- method public int getResult();
- method public int getServiceClass();
- method public int getServiceType();
- method @NonNull public java.util.List<android.telephony.ims.ImsSsInfo> getSuppServiceInfo();
- method public int getTeleserviceType();
- method public boolean isTypeBarring();
- method public boolean isTypeCf();
- method public boolean isTypeClip();
- method public boolean isTypeClir();
- method public boolean isTypeColp();
- method public boolean isTypeColr();
- method public boolean isTypeCw();
- method public boolean isTypeIcb();
- method public boolean isTypeInterrogation();
- method public boolean isTypeUnConditional();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsSsData> CREATOR;
- field public static final int RESULT_SUCCESS = 0; // 0x0
- field public static final int SERVICE_CLASS_DATA = 2; // 0x2
- field public static final int SERVICE_CLASS_DATA_CIRCUIT_ASYNC = 32; // 0x20
- field public static final int SERVICE_CLASS_DATA_CIRCUIT_SYNC = 16; // 0x10
- field public static final int SERVICE_CLASS_DATA_PACKET_ACCESS = 64; // 0x40
- field public static final int SERVICE_CLASS_DATA_PAD = 128; // 0x80
- field public static final int SERVICE_CLASS_FAX = 4; // 0x4
- field public static final int SERVICE_CLASS_NONE = 0; // 0x0
- field public static final int SERVICE_CLASS_SMS = 8; // 0x8
- field public static final int SERVICE_CLASS_VOICE = 1; // 0x1
- field public static final int SS_ACTIVATION = 0; // 0x0
- field public static final int SS_ALL_BARRING = 18; // 0x12
- field public static final int SS_ALL_DATA_TELESERVICES = 3; // 0x3
- field public static final int SS_ALL_TELESERVICES_EXCEPT_SMS = 5; // 0x5
- field public static final int SS_ALL_TELESEVICES = 1; // 0x1
- field public static final int SS_ALL_TELE_AND_BEARER_SERVICES = 0; // 0x0
- field public static final int SS_BAIC = 16; // 0x10
- field public static final int SS_BAIC_ROAMING = 17; // 0x11
- field public static final int SS_BAOC = 13; // 0xd
- field public static final int SS_BAOIC = 14; // 0xe
- field public static final int SS_BAOIC_EXC_HOME = 15; // 0xf
- field public static final int SS_CFU = 0; // 0x0
- field public static final int SS_CFUT = 6; // 0x6
- field public static final int SS_CF_ALL = 4; // 0x4
- field public static final int SS_CF_ALL_CONDITIONAL = 5; // 0x5
- field public static final int SS_CF_BUSY = 1; // 0x1
- field public static final int SS_CF_NOT_REACHABLE = 3; // 0x3
- field public static final int SS_CF_NO_REPLY = 2; // 0x2
- field public static final int SS_CLIP = 7; // 0x7
- field public static final int SS_CLIR = 8; // 0x8
- field public static final int SS_CNAP = 11; // 0xb
- field public static final int SS_COLP = 9; // 0x9
- field public static final int SS_COLR = 10; // 0xa
- field public static final int SS_DEACTIVATION = 1; // 0x1
- field public static final int SS_ERASURE = 4; // 0x4
- field public static final int SS_INCOMING_BARRING = 20; // 0x14
- field public static final int SS_INCOMING_BARRING_ANONYMOUS = 22; // 0x16
- field public static final int SS_INCOMING_BARRING_DN = 21; // 0x15
- field public static final int SS_INTERROGATION = 2; // 0x2
- field public static final int SS_OUTGOING_BARRING = 19; // 0x13
- field public static final int SS_REGISTRATION = 3; // 0x3
- field public static final int SS_SMS_SERVICES = 4; // 0x4
- field public static final int SS_TELEPHONY = 2; // 0x2
- field public static final int SS_WAIT = 12; // 0xc
- }
-
- public static final class ImsSsData.Builder {
- ctor public ImsSsData.Builder(int, int, int, int, int);
- method @NonNull public android.telephony.ims.ImsSsData build();
- method @NonNull public android.telephony.ims.ImsSsData.Builder setCallForwardingInfo(@NonNull java.util.List<android.telephony.ims.ImsCallForwardInfo>);
- method @NonNull public android.telephony.ims.ImsSsData.Builder setSuppServiceInfo(@NonNull java.util.List<android.telephony.ims.ImsSsInfo>);
- }
-
- public final class ImsSsInfo implements android.os.Parcelable {
- ctor @Deprecated public ImsSsInfo(int, @Nullable String);
- method public int describeContents();
- method public int getClirInterrogationStatus();
- method public int getClirOutgoingState();
- method @Deprecated public String getIcbNum();
- method @Nullable public String getIncomingCommunicationBarringNumber();
- method public int getProvisionStatus();
- method public int getStatus();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final int CLIR_OUTGOING_DEFAULT = 0; // 0x0
- field public static final int CLIR_OUTGOING_INVOCATION = 1; // 0x1
- field public static final int CLIR_OUTGOING_SUPPRESSION = 2; // 0x2
- field public static final int CLIR_STATUS_NOT_PROVISIONED = 0; // 0x0
- field public static final int CLIR_STATUS_PROVISIONED_PERMANENT = 1; // 0x1
- field public static final int CLIR_STATUS_TEMPORARILY_ALLOWED = 4; // 0x4
- field public static final int CLIR_STATUS_TEMPORARILY_RESTRICTED = 3; // 0x3
- field public static final int CLIR_STATUS_UNKNOWN = 2; // 0x2
- field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsSsInfo> CREATOR;
- field public static final int DISABLED = 0; // 0x0
- field public static final int ENABLED = 1; // 0x1
- field public static final int NOT_REGISTERED = -1; // 0xffffffff
- field public static final int SERVICE_NOT_PROVISIONED = 0; // 0x0
- field public static final int SERVICE_PROVISIONED = 1; // 0x1
- field public static final int SERVICE_PROVISIONING_UNKNOWN = -1; // 0xffffffff
- }
-
- public static final class ImsSsInfo.Builder {
- ctor public ImsSsInfo.Builder(int);
- method @NonNull public android.telephony.ims.ImsSsInfo build();
- method @NonNull public android.telephony.ims.ImsSsInfo.Builder setClirInterrogationStatus(int);
- method @NonNull public android.telephony.ims.ImsSsInfo.Builder setClirOutgoingState(int);
- method @NonNull public android.telephony.ims.ImsSsInfo.Builder setIncomingCommunicationBarringNumber(@NonNull String);
- method @NonNull public android.telephony.ims.ImsSsInfo.Builder setProvisionStatus(int);
- }
-
- public final class ImsStreamMediaProfile implements android.os.Parcelable {
- ctor public ImsStreamMediaProfile(int, int, int, int, int);
- method public void copyFrom(android.telephony.ims.ImsStreamMediaProfile);
- method public int describeContents();
- method public int getAudioDirection();
- method public int getAudioQuality();
- method public int getRttMode();
- method public int getVideoDirection();
- method public int getVideoQuality();
- method public boolean isReceivingRttAudio();
- method public boolean isRttCall();
- method public void setReceivingRttAudio(boolean);
- method public void setRttMode(int);
- method public void writeToParcel(android.os.Parcel, int);
- field public static final int AUDIO_QUALITY_AMR = 1; // 0x1
- field public static final int AUDIO_QUALITY_AMR_WB = 2; // 0x2
- field public static final int AUDIO_QUALITY_EVRC = 4; // 0x4
- field public static final int AUDIO_QUALITY_EVRC_B = 5; // 0x5
- field public static final int AUDIO_QUALITY_EVRC_NW = 7; // 0x7
- field public static final int AUDIO_QUALITY_EVRC_WB = 6; // 0x6
- field public static final int AUDIO_QUALITY_EVS_FB = 20; // 0x14
- field public static final int AUDIO_QUALITY_EVS_NB = 17; // 0x11
- field public static final int AUDIO_QUALITY_EVS_SWB = 19; // 0x13
- field public static final int AUDIO_QUALITY_EVS_WB = 18; // 0x12
- field public static final int AUDIO_QUALITY_G711A = 13; // 0xd
- field public static final int AUDIO_QUALITY_G711AB = 15; // 0xf
- field public static final int AUDIO_QUALITY_G711U = 11; // 0xb
- field public static final int AUDIO_QUALITY_G722 = 14; // 0xe
- field public static final int AUDIO_QUALITY_G723 = 12; // 0xc
- field public static final int AUDIO_QUALITY_G729 = 16; // 0x10
- field public static final int AUDIO_QUALITY_GSM_EFR = 8; // 0x8
- field public static final int AUDIO_QUALITY_GSM_FR = 9; // 0x9
- field public static final int AUDIO_QUALITY_GSM_HR = 10; // 0xa
- field public static final int AUDIO_QUALITY_NONE = 0; // 0x0
- field public static final int AUDIO_QUALITY_QCELP13K = 3; // 0x3
- field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsStreamMediaProfile> CREATOR;
- field public static final int DIRECTION_INACTIVE = 0; // 0x0
- field public static final int DIRECTION_INVALID = -1; // 0xffffffff
- field public static final int DIRECTION_RECEIVE = 1; // 0x1
- field public static final int DIRECTION_SEND = 2; // 0x2
- field public static final int DIRECTION_SEND_RECEIVE = 3; // 0x3
- field public static final int RTT_MODE_DISABLED = 0; // 0x0
- field public static final int RTT_MODE_FULL = 1; // 0x1
- field public static final int VIDEO_QUALITY_NONE = 0; // 0x0
- field public static final int VIDEO_QUALITY_QCIF = 1; // 0x1
- field public static final int VIDEO_QUALITY_QVGA_LANDSCAPE = 2; // 0x2
- field public static final int VIDEO_QUALITY_QVGA_PORTRAIT = 4; // 0x4
- field public static final int VIDEO_QUALITY_VGA_LANDSCAPE = 8; // 0x8
- field public static final int VIDEO_QUALITY_VGA_PORTRAIT = 16; // 0x10
- }
-
- public final class ImsSuppServiceNotification implements android.os.Parcelable {
- ctor public ImsSuppServiceNotification(int, int, int, int, String, String[]);
- method public int describeContents();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsSuppServiceNotification> CREATOR;
- field public final int code;
- field public final String[] history;
- field public final int index;
- field public final int notificationType;
- field public final String number;
- field public final int type;
- }
-
- public class ImsUtListener {
- method public void onLineIdentificationSupplementaryServiceResponse(int, @NonNull android.telephony.ims.ImsSsInfo);
- method public void onSupplementaryServiceIndication(android.telephony.ims.ImsSsData);
- method public void onUtConfigurationCallBarringQueried(int, android.telephony.ims.ImsSsInfo[]);
- method public void onUtConfigurationCallForwardQueried(int, android.telephony.ims.ImsCallForwardInfo[]);
- method public void onUtConfigurationCallWaitingQueried(int, android.telephony.ims.ImsSsInfo[]);
- method @Deprecated public void onUtConfigurationQueried(int, android.os.Bundle);
- method public void onUtConfigurationQueryFailed(int, android.telephony.ims.ImsReasonInfo);
- method public void onUtConfigurationUpdateFailed(int, android.telephony.ims.ImsReasonInfo);
- method public void onUtConfigurationUpdated(int);
- field @Deprecated public static final String BUNDLE_KEY_CLIR = "queryClir";
- field @Deprecated public static final String BUNDLE_KEY_SSINFO = "imsSsInfo";
- }
-
- public abstract class ImsVideoCallProvider {
- ctor public ImsVideoCallProvider();
- method public void changeCallDataUsage(long);
- method public void changeCameraCapabilities(android.telecom.VideoProfile.CameraCapabilities);
- method public void changePeerDimensions(int, int);
- method public void changeVideoQuality(int);
- method public void handleCallSessionEvent(int);
- method public abstract void onRequestCallDataUsage();
- method public abstract void onRequestCameraCapabilities();
- method public abstract void onSendSessionModifyRequest(android.telecom.VideoProfile, android.telecom.VideoProfile);
- method public abstract void onSendSessionModifyResponse(android.telecom.VideoProfile);
- method public abstract void onSetCamera(String);
- method public void onSetCamera(String, int);
- method public abstract void onSetDeviceOrientation(int);
- method public abstract void onSetDisplaySurface(android.view.Surface);
- method public abstract void onSetPauseImage(android.net.Uri);
- method public abstract void onSetPreviewSurface(android.view.Surface);
- method public abstract void onSetZoom(float);
- method public void receiveSessionModifyRequest(android.telecom.VideoProfile);
- method public void receiveSessionModifyResponse(int, android.telecom.VideoProfile, android.telecom.VideoProfile);
- }
-
- public class ProvisioningManager {
- method @NonNull public static android.telephony.ims.ProvisioningManager createForSubscriptionId(int);
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public int getProvisioningIntValue(int);
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public boolean getProvisioningStatusForCapability(int, int);
- method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public String getProvisioningStringValue(int);
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public boolean getRcsProvisioningStatusForCapability(int);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void notifyRcsAutoConfigurationReceived(@NonNull byte[], boolean);
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerProvisioningChangedCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ProvisioningManager.Callback) throws android.telephony.ims.ImsException;
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public int setProvisioningIntValue(int, int);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setProvisioningStatusForCapability(int, int, boolean);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public int setProvisioningStringValue(int, @NonNull String);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setRcsProvisioningStatusForCapability(int, boolean);
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterProvisioningChangedCallback(@NonNull android.telephony.ims.ProvisioningManager.Callback);
- field public static final int KEY_VOICE_OVER_WIFI_ENTITLEMENT_ID = 67; // 0x43
- field public static final int KEY_VOICE_OVER_WIFI_MODE_OVERRIDE = 27; // 0x1b
- field public static final int KEY_VOICE_OVER_WIFI_ROAMING_ENABLED_OVERRIDE = 26; // 0x1a
- field public static final int PROVISIONING_VALUE_DISABLED = 0; // 0x0
- field public static final int PROVISIONING_VALUE_ENABLED = 1; // 0x1
- field public static final String STRING_QUERY_RESULT_ERROR_GENERIC = "STRING_QUERY_RESULT_ERROR_GENERIC";
- field public static final String STRING_QUERY_RESULT_ERROR_NOT_READY = "STRING_QUERY_RESULT_ERROR_NOT_READY";
- }
-
- public static class ProvisioningManager.Callback {
- ctor public ProvisioningManager.Callback();
- method public void onProvisioningIntChanged(int, int);
- method public void onProvisioningStringChanged(int, @NonNull String);
- }
-
- public class RcsUceAdapter {
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setUceSettingEnabled(boolean) throws android.telephony.ims.ImsException;
- }
-
- public class SipDelegateManager {
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isSupported() throws android.telephony.ims.ImsException;
- }
-
-}
-
-package android.telephony.ims.feature {
-
- public final class CapabilityChangeRequest implements android.os.Parcelable {
- method public void addCapabilitiesToDisableForTech(int, int);
- method public void addCapabilitiesToEnableForTech(int, int);
- method public int describeContents();
- method public java.util.List<android.telephony.ims.feature.CapabilityChangeRequest.CapabilityPair> getCapabilitiesToDisable();
- method public java.util.List<android.telephony.ims.feature.CapabilityChangeRequest.CapabilityPair> getCapabilitiesToEnable();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.feature.CapabilityChangeRequest> CREATOR;
- }
-
- public static class CapabilityChangeRequest.CapabilityPair {
- ctor public CapabilityChangeRequest.CapabilityPair(int, int);
- method public int getCapability();
- method public int getRadioTech();
- }
-
- public abstract class ImsFeature {
- ctor public ImsFeature();
- method public abstract void changeEnabledCapabilities(android.telephony.ims.feature.CapabilityChangeRequest, android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy);
- method public int getFeatureState();
- method public final int getSlotIndex();
- method public abstract void onFeatureReady();
- method public abstract void onFeatureRemoved();
- method public final void setFeatureState(int);
- field public static final int CAPABILITY_ERROR_GENERIC = -1; // 0xffffffff
- field public static final int CAPABILITY_SUCCESS = 0; // 0x0
- field public static final int FEATURE_EMERGENCY_MMTEL = 0; // 0x0
- field public static final int FEATURE_MMTEL = 1; // 0x1
- field public static final int FEATURE_RCS = 2; // 0x2
- field public static final int STATE_INITIALIZING = 1; // 0x1
- field public static final int STATE_READY = 2; // 0x2
- field public static final int STATE_UNAVAILABLE = 0; // 0x0
- }
-
- @Deprecated public static class ImsFeature.Capabilities {
- field @Deprecated protected int mCapabilities;
- }
-
- protected static class ImsFeature.CapabilityCallbackProxy {
- method public void onChangeCapabilityConfigurationError(int, int, int);
- }
-
- public class MmTelFeature extends android.telephony.ims.feature.ImsFeature {
- ctor public MmTelFeature();
- method public void changeEnabledCapabilities(@NonNull android.telephony.ims.feature.CapabilityChangeRequest, @NonNull android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy);
- method @Nullable public android.telephony.ims.ImsCallProfile createCallProfile(int, int);
- method @Nullable public android.telephony.ims.stub.ImsCallSessionImplBase createCallSession(@NonNull android.telephony.ims.ImsCallProfile);
- method @NonNull public android.telephony.ims.stub.ImsEcbmImplBase getEcbm();
- method @NonNull public android.telephony.ims.stub.ImsMultiEndpointImplBase getMultiEndpoint();
- method @NonNull public android.telephony.ims.stub.ImsSmsImplBase getSmsImplementation();
- method @NonNull public android.telephony.ims.stub.ImsUtImplBase getUt();
- method public final void notifyCapabilitiesStatusChanged(@NonNull android.telephony.ims.feature.MmTelFeature.MmTelCapabilities);
- method public final void notifyIncomingCall(@NonNull android.telephony.ims.stub.ImsCallSessionImplBase, @NonNull android.os.Bundle);
- method public final void notifyRejectedCall(@NonNull android.telephony.ims.ImsCallProfile, @NonNull android.telephony.ims.ImsReasonInfo);
- method public final void notifyVoiceMessageCountUpdate(int);
- method public void onFeatureReady();
- method public void onFeatureRemoved();
- method public boolean queryCapabilityConfiguration(int, int);
- method @NonNull public final android.telephony.ims.feature.MmTelFeature.MmTelCapabilities queryCapabilityStatus();
- method public void setUiTtyMode(int, @Nullable android.os.Message);
- method public int shouldProcessCall(@NonNull String[]);
- field public static final String EXTRA_IS_UNKNOWN_CALL = "android.telephony.ims.feature.extra.IS_UNKNOWN_CALL";
- field public static final String EXTRA_IS_USSD = "android.telephony.ims.feature.extra.IS_USSD";
- field public static final int PROCESS_CALL_CSFB = 1; // 0x1
- field public static final int PROCESS_CALL_IMS = 0; // 0x0
- }
-
- public static class MmTelFeature.MmTelCapabilities extends android.telephony.ims.feature.ImsFeature.Capabilities {
- ctor public MmTelFeature.MmTelCapabilities();
- ctor @Deprecated public MmTelFeature.MmTelCapabilities(android.telephony.ims.feature.ImsFeature.Capabilities);
- ctor public MmTelFeature.MmTelCapabilities(int);
- method public final void addCapabilities(int);
- method public final void removeCapabilities(int);
- }
-
- public class RcsFeature extends android.telephony.ims.feature.ImsFeature {
- ctor public RcsFeature();
- method public void changeEnabledCapabilities(@NonNull android.telephony.ims.feature.CapabilityChangeRequest, @NonNull android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy);
- method public void onFeatureReady();
- method public void onFeatureRemoved();
- }
-
-}
-
-package android.telephony.ims.stub {
-
- public class ImsCallSessionImplBase implements java.lang.AutoCloseable {
- ctor public ImsCallSessionImplBase();
- method public void accept(int, android.telephony.ims.ImsStreamMediaProfile);
- method public void close();
- method public void deflect(String);
- method public void extendToConference(String[]);
- method public String getCallId();
- method public android.telephony.ims.ImsCallProfile getCallProfile();
- method public android.telephony.ims.ImsVideoCallProvider getImsVideoCallProvider();
- method public android.telephony.ims.ImsCallProfile getLocalCallProfile();
- method public String getProperty(String);
- method public android.telephony.ims.ImsCallProfile getRemoteCallProfile();
- method public int getState();
- method public void hold(android.telephony.ims.ImsStreamMediaProfile);
- method public void inviteParticipants(String[]);
- method public boolean isInCall();
- method public boolean isMultiparty();
- method public void merge();
- method public void reject(int);
- method public void removeParticipants(String[]);
- method public void resume(android.telephony.ims.ImsStreamMediaProfile);
- method public void sendDtmf(char, android.os.Message);
- method public void sendRttMessage(String);
- method public void sendRttModifyRequest(android.telephony.ims.ImsCallProfile);
- method public void sendRttModifyResponse(boolean);
- method public void sendUssd(String);
- method public void setListener(android.telephony.ims.ImsCallSessionListener);
- method public void setMute(boolean);
- method public void start(String, android.telephony.ims.ImsCallProfile);
- method public void startConference(String[], android.telephony.ims.ImsCallProfile);
- method public void startDtmf(char);
- method public void stopDtmf();
- method public void terminate(int);
- method public void update(int, android.telephony.ims.ImsStreamMediaProfile);
- field public static final int USSD_MODE_NOTIFY = 0; // 0x0
- field public static final int USSD_MODE_REQUEST = 1; // 0x1
- }
-
- public static class ImsCallSessionImplBase.State {
- method public static String toString(int);
- field public static final int ESTABLISHED = 4; // 0x4
- field public static final int ESTABLISHING = 3; // 0x3
- field public static final int IDLE = 0; // 0x0
- field public static final int INITIATED = 1; // 0x1
- field public static final int INVALID = -1; // 0xffffffff
- field public static final int NEGOTIATING = 2; // 0x2
- field public static final int REESTABLISHING = 6; // 0x6
- field public static final int RENEGOTIATING = 5; // 0x5
- field public static final int TERMINATED = 8; // 0x8
- field public static final int TERMINATING = 7; // 0x7
- }
-
- public class ImsConfigImplBase {
- ctor public ImsConfigImplBase();
- method public int getConfigInt(int);
- method public String getConfigString(int);
- method public final void notifyProvisionedValueChanged(int, int);
- method public final void notifyProvisionedValueChanged(int, String);
- method public void notifyRcsAutoConfigurationReceived(@NonNull byte[], boolean);
- method public int setConfig(int, int);
- method public int setConfig(int, String);
- field public static final int CONFIG_RESULT_FAILED = 1; // 0x1
- field public static final int CONFIG_RESULT_SUCCESS = 0; // 0x0
- field public static final int CONFIG_RESULT_UNKNOWN = -1; // 0xffffffff
- }
-
- public class ImsEcbmImplBase {
- ctor public ImsEcbmImplBase();
- method public final void enteredEcbm();
- method public void exitEmergencyCallbackMode();
- method public final void exitedEcbm();
- }
-
- public final class ImsFeatureConfiguration implements android.os.Parcelable {
- method public int describeContents();
- method public java.util.Set<android.telephony.ims.stub.ImsFeatureConfiguration.FeatureSlotPair> getServiceFeatures();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.stub.ImsFeatureConfiguration> CREATOR;
- }
-
- public static class ImsFeatureConfiguration.Builder {
- ctor public ImsFeatureConfiguration.Builder();
- method public android.telephony.ims.stub.ImsFeatureConfiguration.Builder addFeature(int, int);
- method public android.telephony.ims.stub.ImsFeatureConfiguration build();
- }
-
- public static final class ImsFeatureConfiguration.FeatureSlotPair {
- ctor public ImsFeatureConfiguration.FeatureSlotPair(int, int);
- field public final int featureType;
- field public final int slotId;
- }
-
- public class ImsMultiEndpointImplBase {
- ctor public ImsMultiEndpointImplBase();
- method public final void onImsExternalCallStateUpdate(java.util.List<android.telephony.ims.ImsExternalCallState>);
- method public void requestImsExternalCallStateInfo();
- }
-
- public class ImsRegistrationImplBase {
- ctor public ImsRegistrationImplBase();
- method public final void onDeregistered(android.telephony.ims.ImsReasonInfo);
- method public final void onRegistered(int);
- method public final void onRegistering(int);
- method public final void onSubscriberAssociatedUriChanged(android.net.Uri[]);
- method public final void onTechnologyChangeFailed(int, android.telephony.ims.ImsReasonInfo);
- field public static final int REGISTRATION_TECH_IWLAN = 1; // 0x1
- field public static final int REGISTRATION_TECH_LTE = 0; // 0x0
- field public static final int REGISTRATION_TECH_NONE = -1; // 0xffffffff
- }
-
- public class ImsSmsImplBase {
- ctor public ImsSmsImplBase();
- method public void acknowledgeSms(int, @IntRange(from=0, to=65535) int, int);
- method public void acknowledgeSmsReport(int, @IntRange(from=0, to=65535) int, int);
- method public String getSmsFormat();
- method public void onReady();
- method @Deprecated public final void onSendSmsResult(int, @IntRange(from=0, to=65535) int, int, int) throws java.lang.RuntimeException;
- method public final void onSendSmsResultError(int, @IntRange(from=0, to=65535) int, int, int, int) throws java.lang.RuntimeException;
- method public final void onSendSmsResultSuccess(int, @IntRange(from=0, to=65535) int) throws java.lang.RuntimeException;
- method public final void onSmsReceived(int, String, byte[]) throws java.lang.RuntimeException;
- method @Deprecated public final void onSmsStatusReportReceived(int, @IntRange(from=0, to=65535) int, String, byte[]) throws java.lang.RuntimeException;
- method public final void onSmsStatusReportReceived(int, String, byte[]) throws java.lang.RuntimeException;
- method public void sendSms(int, @IntRange(from=0, to=65535) int, String, String, boolean, byte[]);
- field public static final int DELIVER_STATUS_ERROR_GENERIC = 2; // 0x2
- field public static final int DELIVER_STATUS_ERROR_NO_MEMORY = 3; // 0x3
- field public static final int DELIVER_STATUS_ERROR_REQUEST_NOT_SUPPORTED = 4; // 0x4
- field public static final int DELIVER_STATUS_OK = 1; // 0x1
- field public static final int RESULT_NO_NETWORK_ERROR = -1; // 0xffffffff
- field public static final int SEND_STATUS_ERROR = 2; // 0x2
- field public static final int SEND_STATUS_ERROR_FALLBACK = 4; // 0x4
- field public static final int SEND_STATUS_ERROR_RETRY = 3; // 0x3
- field public static final int SEND_STATUS_OK = 1; // 0x1
- field public static final int STATUS_REPORT_STATUS_ERROR = 2; // 0x2
- field public static final int STATUS_REPORT_STATUS_OK = 1; // 0x1
- }
-
- public class ImsUtImplBase {
- ctor public ImsUtImplBase();
- method public void close();
- method public int queryCallBarring(int);
- method public int queryCallBarringForServiceClass(int, int);
- method public int queryCallForward(int, String);
- method public int queryCallWaiting();
- method public int queryClip();
- method public int queryClir();
- method public int queryColp();
- method public int queryColr();
- method public void setListener(android.telephony.ims.ImsUtListener);
- method public int transact(android.os.Bundle);
- method public int updateCallBarring(int, int, String[]);
- method public int updateCallBarringForServiceClass(int, int, String[], int);
- method public int updateCallForward(int, int, String, int, int);
- method public int updateCallWaiting(boolean, int);
- method public int updateClip(boolean);
- method public int updateClir(int);
- method public int updateColp(boolean);
- method public int updateColr(int);
- }
-
- public class SipTransportImplBase {
- ctor public SipTransportImplBase(@NonNull java.util.concurrent.Executor);
- }
-
-}
-
-package android.telephony.mbms {
-
- public static class DownloadRequest.Builder {
- method public android.telephony.mbms.DownloadRequest.Builder setServiceId(String);
- }
-
- public final class FileInfo implements android.os.Parcelable {
- ctor public FileInfo(android.net.Uri, String);
- }
-
- public final class FileServiceInfo extends android.telephony.mbms.ServiceInfo implements android.os.Parcelable {
- ctor public FileServiceInfo(java.util.Map<java.util.Locale,java.lang.String>, String, java.util.List<java.util.Locale>, String, java.util.Date, java.util.Date, java.util.List<android.telephony.mbms.FileInfo>);
- }
-
- public class MbmsDownloadReceiver extends android.content.BroadcastReceiver {
- field public static final int RESULT_APP_NOTIFICATION_ERROR = 6; // 0x6
- field public static final int RESULT_BAD_TEMP_FILE_ROOT = 3; // 0x3
- field public static final int RESULT_DOWNLOAD_FINALIZATION_ERROR = 4; // 0x4
- field public static final int RESULT_INVALID_ACTION = 1; // 0x1
- field public static final int RESULT_MALFORMED_INTENT = 2; // 0x2
- field public static final int RESULT_OK = 0; // 0x0
- field public static final int RESULT_TEMP_FILE_GENERATION_ERROR = 5; // 0x5
- }
-
- public final class StreamingServiceInfo extends android.telephony.mbms.ServiceInfo implements android.os.Parcelable {
- ctor public StreamingServiceInfo(java.util.Map<java.util.Locale,java.lang.String>, String, java.util.List<java.util.Locale>, String, java.util.Date, java.util.Date);
- }
-
- public final class UriPathPair implements android.os.Parcelable {
- method public int describeContents();
- method public android.net.Uri getContentUri();
- method public android.net.Uri getFilePathUri();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.telephony.mbms.UriPathPair> CREATOR;
- }
-
-}
-
-package android.telephony.mbms.vendor {
-
- public class MbmsDownloadServiceBase extends android.os.Binder implements android.os.IInterface {
- ctor public MbmsDownloadServiceBase();
- method public int addProgressListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadProgressListener) throws android.os.RemoteException;
- method public int addStatusListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadStatusListener) throws android.os.RemoteException;
- method public android.os.IBinder asBinder();
- method public int cancelDownload(android.telephony.mbms.DownloadRequest) throws android.os.RemoteException;
- method public void dispose(int) throws android.os.RemoteException;
- method public int download(android.telephony.mbms.DownloadRequest) throws android.os.RemoteException;
- method public int initialize(int, android.telephony.mbms.MbmsDownloadSessionCallback) throws android.os.RemoteException;
- method @NonNull public java.util.List<android.telephony.mbms.DownloadRequest> listPendingDownloads(int) throws android.os.RemoteException;
- method public void onAppCallbackDied(int, int);
- method public boolean onTransact(int, android.os.Parcel, android.os.Parcel, int) throws android.os.RemoteException;
- method public int removeProgressListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadProgressListener) throws android.os.RemoteException;
- method public int removeStatusListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadStatusListener) throws android.os.RemoteException;
- method public int requestDownloadState(android.telephony.mbms.DownloadRequest, android.telephony.mbms.FileInfo) throws android.os.RemoteException;
- method public int requestUpdateFileServices(int, java.util.List<java.lang.String>) throws android.os.RemoteException;
- method public int resetDownloadKnowledge(android.telephony.mbms.DownloadRequest) throws android.os.RemoteException;
- method public int setTempFileRootDirectory(int, String) throws android.os.RemoteException;
- }
-
- public class MbmsGroupCallServiceBase extends android.app.Service {
- ctor public MbmsGroupCallServiceBase();
- method public void dispose(int) throws android.os.RemoteException;
- method public int initialize(@NonNull android.telephony.mbms.MbmsGroupCallSessionCallback, int) throws android.os.RemoteException;
- method public void onAppCallbackDied(int, int);
- method public android.os.IBinder onBind(android.content.Intent);
- method public int startGroupCall(int, long, @NonNull java.util.List<java.lang.Integer>, @NonNull java.util.List<java.lang.Integer>, @NonNull android.telephony.mbms.GroupCallCallback);
- method public void stopGroupCall(int, long);
- method public void updateGroupCall(int, long, @NonNull java.util.List<java.lang.Integer>, @NonNull java.util.List<java.lang.Integer>);
- }
-
- public class MbmsStreamingServiceBase extends android.os.Binder implements android.os.IInterface {
- ctor public MbmsStreamingServiceBase();
- method public android.os.IBinder asBinder();
- method public void dispose(int) throws android.os.RemoteException;
- method @Nullable public android.net.Uri getPlaybackUri(int, String) throws android.os.RemoteException;
- method public int initialize(android.telephony.mbms.MbmsStreamingSessionCallback, int) throws android.os.RemoteException;
- method public void onAppCallbackDied(int, int);
- method public boolean onTransact(int, android.os.Parcel, android.os.Parcel, int) throws android.os.RemoteException;
- method public int requestUpdateStreamingServices(int, java.util.List<java.lang.String>) throws android.os.RemoteException;
- method public int startStreaming(int, String, android.telephony.mbms.StreamingServiceCallback) throws android.os.RemoteException;
- method public void stopStreaming(int, String) throws android.os.RemoteException;
- }
-
- public class VendorUtils {
- ctor public VendorUtils();
- method public static android.content.ComponentName getAppReceiverFromPackageName(android.content.Context, String);
- field public static final String ACTION_CLEANUP = "android.telephony.mbms.action.CLEANUP";
- field public static final String ACTION_DOWNLOAD_RESULT_INTERNAL = "android.telephony.mbms.action.DOWNLOAD_RESULT_INTERNAL";
- field public static final String ACTION_FILE_DESCRIPTOR_REQUEST = "android.telephony.mbms.action.FILE_DESCRIPTOR_REQUEST";
- field public static final String EXTRA_FD_COUNT = "android.telephony.mbms.extra.FD_COUNT";
- field public static final String EXTRA_FINAL_URI = "android.telephony.mbms.extra.FINAL_URI";
- field public static final String EXTRA_FREE_URI_LIST = "android.telephony.mbms.extra.FREE_URI_LIST";
- field public static final String EXTRA_PAUSED_LIST = "android.telephony.mbms.extra.PAUSED_LIST";
- field public static final String EXTRA_PAUSED_URI_LIST = "android.telephony.mbms.extra.PAUSED_URI_LIST";
- field public static final String EXTRA_SERVICE_ID = "android.telephony.mbms.extra.SERVICE_ID";
- field public static final String EXTRA_TEMP_FILES_IN_USE = "android.telephony.mbms.extra.TEMP_FILES_IN_USE";
- field public static final String EXTRA_TEMP_FILE_ROOT = "android.telephony.mbms.extra.TEMP_FILE_ROOT";
- field public static final String EXTRA_TEMP_LIST = "android.telephony.mbms.extra.TEMP_LIST";
- }
-
-}
-
diff --git a/telephony/api/system-removed.txt b/telephony/api/system-removed.txt
deleted file mode 100644
index ae46075..0000000
--- a/telephony/api/system-removed.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-// Signature format: 2.0
-package android.telephony {
-
- public class TelephonyManager {
- method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void answerRingingCall();
- method @Deprecated @RequiresPermission(android.Manifest.permission.CALL_PHONE) public boolean endCall();
- method @Deprecated public void silenceRinger();
- }
-
-}
-
-package android.telephony.data {
-
- public final class DataCallResponse implements android.os.Parcelable {
- ctor public DataCallResponse(int, int, int, int, int, @Nullable String, @Nullable java.util.List<android.net.LinkAddress>, @Nullable java.util.List<java.net.InetAddress>, @Nullable java.util.List<java.net.InetAddress>, @Nullable java.util.List<java.net.InetAddress>, int);
- }
-
-}
-
diff --git a/telephony/common/com/android/internal/telephony/CarrierAppUtils.java b/telephony/common/com/android/internal/telephony/CarrierAppUtils.java
index e57b030..7aecfdd 100644
--- a/telephony/common/com/android/internal/telephony/CarrierAppUtils.java
+++ b/telephony/common/com/android/internal/telephony/CarrierAppUtils.java
@@ -124,11 +124,7 @@
}
private static boolean isUpdatedSystemApp(ApplicationInfo ai) {
- if ((ai.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
- return true;
- }
-
- return false;
+ return (ai.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0;
}
/**
diff --git a/telephony/framework-telephony-jarjar-rules.txt b/telephony/framework-telephony-jarjar-rules.txt
deleted file mode 100644
index 212eba1..0000000
--- a/telephony/framework-telephony-jarjar-rules.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-rule android.telephony.Annotation* android.telephony.framework.Annotation@1
-rule android.util.RecurrenceRule* android.telephony.RecurrenceRule@1
-rule com.android.i18n.phonenumbers.** com.android.telephony.framework.phonenumbers.@1
-rule com.android.internal.os.SomeArgs* android.telephony.SomeArgs@1
-rule com.android.internal.util.BitwiseInputStream* android.telephony.BitwiseInputStream@1
-rule com.android.internal.util.BitwiseOutputStream* android.telephony.BitwiseOutputStream@1
-rule com.android.internal.util.Preconditions* android.telephony.Preconditions@1
-rule com.android.internal.util.IndentingPrintWriter* android.telephony.IndentingPrintWriter@1
-rule com.android.internal.util.HexDump* android.telephony.HexDump@1
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 23d450b..56c2500 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -2802,7 +2802,11 @@
/** Current network is LTE_CA {@hide} */
@UnsupportedAppUsage
public static final int NETWORK_TYPE_LTE_CA = TelephonyProtoEnums.NETWORK_TYPE_LTE_CA; // = 19.
- /** Current network is NR(New Radio) 5G. */
+ /**
+ * Current network is NR (New Radio) 5G.
+ * This will only be returned for 5G SA.
+ * For 5G NSA, the network type will be {@link #NETWORK_TYPE_LTE}.
+ */
public static final int NETWORK_TYPE_NR = TelephonyProtoEnums.NETWORK_TYPE_NR; // 20.
private static final @NetworkType int[] NETWORK_TYPES = {
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 3705aaa..3a46291 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -251,6 +251,7 @@
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.AdditionalAnswers;
import org.mockito.ArgumentCaptor;
import org.mockito.InOrder;
import org.mockito.Mock;
@@ -452,6 +453,13 @@
}
@Override
+ public Context createContextAsUser(UserHandle user, int flags) {
+ final Context asUser = mock(Context.class, AdditionalAnswers.delegatesTo(this));
+ doReturn(user).when(asUser).getUser();
+ return asUser;
+ }
+
+ @Override
public ContentResolver getContentResolver() {
return mContentResolver;
}
@@ -4992,22 +5000,22 @@
// simulate that situation and check if ConnectivityService could filter that case.
mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
waitForIdle();
- verify(mNotificationManager, timeout(TIMEOUT_MS).times(1)).notifyAsUser(anyString(),
- eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), any(), eq(UserHandle.ALL));
+ verify(mNotificationManager, timeout(TIMEOUT_MS).times(1)).notify(anyString(),
+ eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), any());
// If private DNS resolution successful, the PRIVATE_DNS_BROKEN notification shouldn't be
// shown.
mWiFiNetworkAgent.setNetworkValid(true /* isStrictMode */);
mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
waitForIdle();
- verify(mNotificationManager, timeout(TIMEOUT_MS).times(1)).cancelAsUser(anyString(),
- eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), eq(UserHandle.ALL));
+ verify(mNotificationManager, timeout(TIMEOUT_MS).times(1)).cancel(anyString(),
+ eq(NotificationType.PRIVATE_DNS_BROKEN.eventId));
// If private DNS resolution failed again, the PRIVATE_DNS_BROKEN notification should be
// shown again.
mWiFiNetworkAgent.setNetworkInvalid(true /* isStrictMode */);
mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
waitForIdle();
- verify(mNotificationManager, timeout(TIMEOUT_MS).times(2)).notifyAsUser(anyString(),
- eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), any(), eq(UserHandle.ALL));
+ verify(mNotificationManager, timeout(TIMEOUT_MS).times(2)).notify(anyString(),
+ eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), any());
}
@Test
diff --git a/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java b/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java
index 47db5d4..b47be97 100644
--- a/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java
+++ b/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java
@@ -22,6 +22,7 @@
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
@@ -36,6 +37,7 @@
import android.content.res.Resources;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
+import android.os.UserHandle;
import android.telephony.TelephonyManager;
import androidx.test.filters.SmallTest;
@@ -47,6 +49,7 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.AdditionalAnswers;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -104,17 +107,22 @@
when(mCtx.getResources()).thenReturn(mResources);
when(mCtx.getPackageManager()).thenReturn(mPm);
when(mCtx.getApplicationInfo()).thenReturn(new ApplicationInfo());
+ final Context asUserCtx = mock(Context.class, AdditionalAnswers.delegatesTo(mCtx));
+ doReturn(UserHandle.ALL).when(asUserCtx).getUser();
+ when(mCtx.createContextAsUser(eq(UserHandle.ALL), anyInt())).thenReturn(asUserCtx);
+ when(mCtx.getSystemService(eq(Context.NOTIFICATION_SERVICE)))
+ .thenReturn(mNotificationManager);
when(mNetworkInfo.getExtraInfo()).thenReturn("extra");
when(mResources.getColor(anyInt(), any())).thenReturn(0xFF607D8B);
- mManager = new NetworkNotificationManager(mCtx, mTelephonyManager, mNotificationManager);
+ mManager = new NetworkNotificationManager(mCtx, mTelephonyManager);
}
private void verifyTitleByNetwork(final int id, final NetworkAgentInfo nai, final int title) {
final String tag = NetworkNotificationManager.tagFor(id);
mManager.showNotification(id, PRIVATE_DNS_BROKEN, nai, null, null, true);
verify(mNotificationManager, times(1))
- .notifyAsUser(eq(tag), eq(PRIVATE_DNS_BROKEN.eventId), any(), any());
+ .notify(eq(tag), eq(PRIVATE_DNS_BROKEN.eventId), any());
final int transportType = NetworkNotificationManager.approximateTransportType(nai);
if (transportType == NetworkCapabilities.TRANSPORT_WIFI) {
verify(mResources, times(1)).getString(title, eq(any()));
@@ -164,8 +172,8 @@
final int id = ids.get(i);
final int eventId = types.get(i).eventId;
final String tag = NetworkNotificationManager.tagFor(id);
- verify(mNotificationManager, times(1)).notifyAsUser(eq(tag), eq(eventId), any(), any());
- verify(mNotificationManager, times(1)).cancelAsUser(eq(tag), eq(eventId), any());
+ verify(mNotificationManager, times(1)).notify(eq(tag), eq(eventId), any());
+ verify(mNotificationManager, times(1)).cancel(eq(tag), eq(eventId));
}
}
@@ -174,13 +182,13 @@
mManager.showNotification(100, NO_INTERNET, mCellNai, mWifiNai, null, false);
mManager.showNotification(101, LOST_INTERNET, mCellNai, mWifiNai, null, false);
- verify(mNotificationManager, never()).notifyAsUser(any(), anyInt(), any(), any());
+ verify(mNotificationManager, never()).notify(any(), anyInt(), any());
mManager.showNotification(102, NO_INTERNET, mWifiNai, mCellNai, null, false);
final int eventId = NO_INTERNET.eventId;
final String tag = NetworkNotificationManager.tagFor(102);
- verify(mNotificationManager, times(1)).notifyAsUser(eq(tag), eq(eventId), any(), any());
+ verify(mNotificationManager, times(1)).notify(eq(tag), eq(eventId), any());
}
@Test
@@ -191,7 +199,7 @@
mManager.showNotification(103, LOST_INTERNET, mWifiNai, mCellNai, null, false);
mManager.showNotification(104, NETWORK_SWITCH, mWifiNai, mCellNai, null, false);
- verify(mNotificationManager, never()).notifyAsUser(any(), anyInt(), any(), any());
+ verify(mNotificationManager, never()).notify(any(), anyInt(), any());
}
@Test
@@ -201,19 +209,16 @@
// Show first NO_INTERNET
mManager.showNotification(id, NO_INTERNET, mWifiNai, mCellNai, null, false);
- verify(mNotificationManager, times(1))
- .notifyAsUser(eq(tag), eq(NO_INTERNET.eventId), any(), any());
+ verify(mNotificationManager, times(1)).notify(eq(tag), eq(NO_INTERNET.eventId), any());
// Captive portal detection triggers SIGN_IN a bit later, clearing the previous NO_INTERNET
mManager.showNotification(id, SIGN_IN, mWifiNai, mCellNai, null, false);
- verify(mNotificationManager, times(1))
- .cancelAsUser(eq(tag), eq(NO_INTERNET.eventId), any());
- verify(mNotificationManager, times(1))
- .notifyAsUser(eq(tag), eq(SIGN_IN.eventId), any(), any());
+ verify(mNotificationManager, times(1)).cancel(eq(tag), eq(NO_INTERNET.eventId));
+ verify(mNotificationManager, times(1)).notify(eq(tag), eq(SIGN_IN.eventId), any());
// Network disconnects
mManager.clearNotification(id);
- verify(mNotificationManager, times(1)).cancelAsUser(eq(tag), eq(SIGN_IN.eventId), any());
+ verify(mNotificationManager, times(1)).cancel(eq(tag), eq(SIGN_IN.eventId));
}
@Test
@@ -223,18 +228,17 @@
// Show first SIGN_IN
mManager.showNotification(id, SIGN_IN, mWifiNai, mCellNai, null, false);
- verify(mNotificationManager, times(1))
- .notifyAsUser(eq(tag), eq(SIGN_IN.eventId), any(), any());
+ verify(mNotificationManager, times(1)).notify(eq(tag), eq(SIGN_IN.eventId), any());
reset(mNotificationManager);
// NO_INTERNET arrives after, but is ignored.
mManager.showNotification(id, NO_INTERNET, mWifiNai, mCellNai, null, false);
- verify(mNotificationManager, never()).cancelAsUser(any(), anyInt(), any());
- verify(mNotificationManager, never()).notifyAsUser(any(), anyInt(), any(), any());
+ verify(mNotificationManager, never()).cancel(any(), anyInt());
+ verify(mNotificationManager, never()).notify(any(), anyInt(), any());
// Network disconnects
mManager.clearNotification(id);
- verify(mNotificationManager, times(1)).cancelAsUser(eq(tag), eq(SIGN_IN.eventId), any());
+ verify(mNotificationManager, times(1)).cancel(eq(tag), eq(SIGN_IN.eventId));
}
@Test
@@ -246,24 +250,20 @@
// to previous type or not. If they are equal then clear the notification; if they are not
// equal then return.
mManager.showNotification(id, NO_INTERNET, mWifiNai, mCellNai, null, false);
- verify(mNotificationManager, times(1))
- .notifyAsUser(eq(tag), eq(NO_INTERNET.eventId), any(), any());
+ verify(mNotificationManager, times(1)).notify(eq(tag), eq(NO_INTERNET.eventId), any());
// Previous notification is NO_INTERNET and given type is NO_INTERNET too. The notification
// should be cleared.
mManager.clearNotification(id, NO_INTERNET);
- verify(mNotificationManager, times(1))
- .cancelAsUser(eq(tag), eq(NO_INTERNET.eventId), any());
+ verify(mNotificationManager, times(1)).cancel(eq(tag), eq(NO_INTERNET.eventId));
// SIGN_IN is popped-up.
mManager.showNotification(id, SIGN_IN, mWifiNai, mCellNai, null, false);
- verify(mNotificationManager, times(1))
- .notifyAsUser(eq(tag), eq(SIGN_IN.eventId), any(), any());
+ verify(mNotificationManager, times(1)).notify(eq(tag), eq(SIGN_IN.eventId), any());
// The notification type is not matching previous one, PARTIAL_CONNECTIVITY won't be
// cleared.
mManager.clearNotification(id, PARTIAL_CONNECTIVITY);
- verify(mNotificationManager, never())
- .cancelAsUser(eq(tag), eq(PARTIAL_CONNECTIVITY.eventId), any());
+ verify(mNotificationManager, never()).cancel(eq(tag), eq(PARTIAL_CONNECTIVITY.eventId));
}
}
diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java
index daa2627..2fa0914 100644
--- a/tests/net/java/com/android/server/connectivity/VpnTest.java
+++ b/tests/net/java/com/android/server/connectivity/VpnTest.java
@@ -45,6 +45,7 @@
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -106,6 +107,7 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.AdditionalAnswers;
import org.mockito.Answers;
import org.mockito.ArgumentCaptor;
import org.mockito.InOrder;
@@ -215,6 +217,8 @@
when(mContext.getOpPackageName()).thenReturn(TEST_VPN_PKG);
when(mContext.getSystemService(eq(Context.USER_SERVICE))).thenReturn(mUserManager);
when(mContext.getSystemService(eq(Context.APP_OPS_SERVICE))).thenReturn(mAppOps);
+ when(mContext.getSystemServiceName(NotificationManager.class))
+ .thenReturn(Context.NOTIFICATION_SERVICE);
when(mContext.getSystemService(eq(Context.NOTIFICATION_SERVICE)))
.thenReturn(mNotificationManager);
when(mContext.getSystemService(eq(Context.CONNECTIVITY_SERVICE)))
@@ -594,26 +598,23 @@
// Don't show a notification for regular disconnected states.
vpn.updateState(DetailedState.DISCONNECTED, TAG);
- order.verify(mNotificationManager, atLeastOnce())
- .cancelAsUser(anyString(), anyInt(), eq(userHandle));
+ order.verify(mNotificationManager, atLeastOnce()).cancel(anyString(), anyInt());
// Start showing a notification for disconnected once always-on.
vpn.setAlwaysOnPackage(PKGS[0], false, null, mKeyStore);
- order.verify(mNotificationManager)
- .notifyAsUser(anyString(), anyInt(), any(), eq(userHandle));
+ order.verify(mNotificationManager).notify(anyString(), anyInt(), any());
// Stop showing the notification once connected.
vpn.updateState(DetailedState.CONNECTED, TAG);
- order.verify(mNotificationManager).cancelAsUser(anyString(), anyInt(), eq(userHandle));
+ order.verify(mNotificationManager).cancel(anyString(), anyInt());
// Show the notification if we disconnect again.
vpn.updateState(DetailedState.DISCONNECTED, TAG);
- order.verify(mNotificationManager)
- .notifyAsUser(anyString(), anyInt(), any(), eq(userHandle));
+ order.verify(mNotificationManager).notify(anyString(), anyInt(), any());
// Notification should be cleared after unsetting always-on package.
vpn.setAlwaysOnPackage(null, false, null, mKeyStore);
- order.verify(mNotificationManager).cancelAsUser(anyString(), anyInt(), eq(userHandle));
+ order.verify(mNotificationManager).cancel(anyString(), anyInt());
}
@Test
@@ -1272,6 +1273,10 @@
* Mock some methods of vpn object.
*/
private Vpn createVpn(@UserIdInt int userId) {
+ final Context asUserContext = mock(Context.class, AdditionalAnswers.delegatesTo(mContext));
+ doReturn(UserHandle.of(userId)).when(asUserContext).getUser();
+ when(mContext.createContextAsUser(eq(UserHandle.of(userId)), anyInt()))
+ .thenReturn(asUserContext);
return new Vpn(Looper.myLooper(), mContext, new TestDeps(), mNetService,
userId, mKeyStore, mSystemServices, mIkev2SessionCreator);
}