[Tether07] Migrate Tethering into module am: 0df2ebc43d
am: 6b828d2915
Change-Id: I6e71b418b7303d37144532ab056c21ccbefcb554
This commit is contained in:
@@ -17,4 +17,4 @@
|
||||
|
||||
package android.os;
|
||||
|
||||
parcelable ResultReceiver;
|
||||
@JavaOnlyStableParcelable parcelable ResultReceiver;
|
||||
|
||||
@@ -22,13 +22,12 @@ java_defaults {
|
||||
":framework-tethering-shared-srcs",
|
||||
":net-module-utils-srcs",
|
||||
":services-tethering-shared-srcs",
|
||||
":servicescore-tethering-src",
|
||||
],
|
||||
static_libs: [
|
||||
"androidx.annotation_annotation",
|
||||
"netd_aidl_interface-java",
|
||||
"netd_aidl_interface-unstable-java",
|
||||
"netlink-client",
|
||||
"networkstack-aidl-interfaces-java",
|
||||
"networkstack-aidl-interfaces-unstable-java",
|
||||
"android.hardware.tetheroffload.control-V1.0-java",
|
||||
"tethering-client",
|
||||
],
|
||||
@@ -96,7 +95,16 @@ java_defaults {
|
||||
}
|
||||
|
||||
// Non-updatable tethering running in the system server process for devices not using the module
|
||||
// TODO: build in-process tethering APK here.
|
||||
android_app {
|
||||
name: "InProcessTethering",
|
||||
defaults: ["TetheringAppDefaults"],
|
||||
static_libs: ["TetheringApiCurrentLib"],
|
||||
certificate: "platform",
|
||||
manifest: "AndroidManifest_InProcess.xml",
|
||||
// InProcessTethering is a replacement for Tethering
|
||||
overrides: ["Tethering"],
|
||||
// TODO: use PlatformNetworkPermissionConfig.
|
||||
}
|
||||
|
||||
// Updatable tethering packaged as an application
|
||||
android_app {
|
||||
@@ -109,36 +117,3 @@ android_app {
|
||||
// The permission configuration *must* be included to ensure security of the device
|
||||
required: ["NetworkPermissionConfig"],
|
||||
}
|
||||
|
||||
// This group will be removed when tethering migration is done.
|
||||
filegroup {
|
||||
name: "tethering-servicescore-srcs",
|
||||
srcs: [
|
||||
"src/com/android/server/connectivity/tethering/EntitlementManager.java",
|
||||
"src/com/android/server/connectivity/tethering/OffloadController.java",
|
||||
"src/com/android/server/connectivity/tethering/OffloadHardwareInterface.java",
|
||||
"src/com/android/server/connectivity/tethering/TetheringConfiguration.java",
|
||||
"src/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java",
|
||||
],
|
||||
}
|
||||
|
||||
// This group will be removed when tethering migration is done.
|
||||
filegroup {
|
||||
name: "tethering-servicesnet-srcs",
|
||||
srcs: [
|
||||
"src/android/net/dhcp/DhcpServerCallbacks.java",
|
||||
"src/android/net/dhcp/DhcpServingParamsParcelExt.java",
|
||||
"src/android/net/ip/IpServer.java",
|
||||
"src/android/net/ip/RouterAdvertisementDaemon.java",
|
||||
"src/android/net/util/InterfaceSet.java",
|
||||
"src/android/net/util/PrefixUtils.java",
|
||||
],
|
||||
}
|
||||
|
||||
// This group would be removed when tethering migration is done.
|
||||
filegroup {
|
||||
name: "tethering-jni-srcs",
|
||||
srcs: [
|
||||
"jni/com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp",
|
||||
],
|
||||
}
|
||||
|
||||
@@ -25,5 +25,11 @@
|
||||
android:process="com.android.networkstack.process"
|
||||
android:extractNativeLibs="false"
|
||||
android:persistent="true">
|
||||
<service android:name="com.android.server.connectivity.tethering.TetheringService"
|
||||
android:permission="android.permission.MAINLINE_NETWORK_STACK">
|
||||
<intent-filter>
|
||||
<action android:name="android.net.ITetheringConnector"/>
|
||||
</intent-filter>
|
||||
</service>
|
||||
</application>
|
||||
</manifest>
|
||||
|
||||
35
packages/Tethering/AndroidManifest_InProcess.xml
Normal file
35
packages/Tethering/AndroidManifest_InProcess.xml
Normal file
@@ -0,0 +1,35 @@
|
||||
<?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.inprocess"
|
||||
android:sharedUserId="android.uid.system"
|
||||
android:process="system">
|
||||
<uses-sdk android:minSdkVersion="29" android:targetSdkVersion="29" />
|
||||
<application>
|
||||
<!-- TODO: Using MAINLINE_NETWORK_STACK instead of NETWORK_STACK when tethering run in the
|
||||
same process with networkstack -->
|
||||
<service android:name="com.android.server.connectivity.tethering.TetheringService"
|
||||
android:process="system"
|
||||
android:permission="android.permission.NETWORK_STACK">
|
||||
<intent-filter>
|
||||
<action android:name="android.net.ITetheringConnector.InProcess"/>
|
||||
</intent-filter>
|
||||
</service>
|
||||
</application>
|
||||
</manifest>
|
||||
@@ -18,8 +18,12 @@
|
||||
aidl_interface {
|
||||
name: "tethering-aidl-interfaces",
|
||||
local_include_dir: "src",
|
||||
include_dirs: ["frameworks/base/core/java"], // For framework parcelables.
|
||||
srcs: [
|
||||
"src/android/net/ITetherInternalCallback.aidl",
|
||||
"src/android/net/ITetheringConnector.aidl",
|
||||
"src/android/net/TetheringConfigurationParcel.aidl",
|
||||
"src/android/net/TetherStatesParcel.aidl",
|
||||
],
|
||||
backend: {
|
||||
ndk: {
|
||||
@@ -33,8 +37,15 @@ aidl_interface {
|
||||
|
||||
java_library {
|
||||
name: "tethering-client",
|
||||
platform_apis: true,
|
||||
sdk_version: "system_current",
|
||||
static_libs: [
|
||||
"tethering-aidl-interfaces-java",
|
||||
],
|
||||
}
|
||||
|
||||
// This is temporary file group which would be removed after TetheringManager is built
|
||||
// into tethering-client. Will be done by aosp/1156906.
|
||||
filegroup {
|
||||
name: "tethering-manager",
|
||||
srcs: ["src/android/net/TetheringManager.java"],
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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.TetheringConfigurationParcel;
|
||||
import android.net.TetherStatesParcel;
|
||||
|
||||
/**
|
||||
* Callback class for receiving tethering changed events
|
||||
* @hide
|
||||
*/
|
||||
oneway interface ITetherInternalCallback
|
||||
{
|
||||
void onUpstreamChanged(in Network network);
|
||||
void onConfigurationChanged(in TetheringConfigurationParcel config);
|
||||
void onTetherStatesChanged(in TetherStatesParcel states);
|
||||
void onCallbackCreated(in Network network, in TetheringConfigurationParcel config,
|
||||
in TetherStatesParcel states);
|
||||
}
|
||||
@@ -15,6 +15,23 @@
|
||||
*/
|
||||
package android.net;
|
||||
|
||||
import android.net.ITetherInternalCallback;
|
||||
import android.os.ResultReceiver;
|
||||
|
||||
/** @hide */
|
||||
oneway interface ITetheringConnector {
|
||||
void tether(String iface);
|
||||
|
||||
void untether(String iface);
|
||||
|
||||
void setUsbTethering(boolean enable);
|
||||
|
||||
void startTethering(int type, in ResultReceiver receiver, boolean showProvisioningUi);
|
||||
|
||||
void stopTethering(int type);
|
||||
|
||||
void requestLatestTetheringEntitlementResult(int type, in ResultReceiver receiver,
|
||||
boolean showEntitlementUi);
|
||||
|
||||
void registerTetherInternalCallback(ITetherInternalCallback callback);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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 a 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;
|
||||
}
|
||||
@@ -0,0 +1,507 @@
|
||||
/*
|
||||
* 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.Manifest.permission.NETWORK_STACK;
|
||||
import static android.net.ConnectivityManager.TETHER_ERROR_NO_ERROR;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.net.util.SharedLog;
|
||||
import android.os.ConditionVariable;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteCallbackList;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ResultReceiver;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
/**
|
||||
* Service used to communicate with the tethering, which is running in a separate module.
|
||||
* @hide
|
||||
*/
|
||||
public class TetheringManager {
|
||||
private static final String TAG = TetheringManager.class.getSimpleName();
|
||||
|
||||
private static TetheringManager sInstance;
|
||||
|
||||
@Nullable
|
||||
private ITetheringConnector mConnector;
|
||||
private TetherInternalCallback mCallback;
|
||||
private Network mTetherUpstream;
|
||||
private TetheringConfigurationParcel mTetheringConfiguration;
|
||||
private TetherStatesParcel mTetherStatesParcel;
|
||||
|
||||
private final RemoteCallbackList<ITetheringEventCallback> mTetheringEventCallbacks =
|
||||
new RemoteCallbackList<>();
|
||||
@GuardedBy("mLog")
|
||||
private final SharedLog mLog = new SharedLog(TAG);
|
||||
|
||||
private TetheringManager() { }
|
||||
|
||||
/**
|
||||
* Get the TetheringManager singleton instance.
|
||||
*/
|
||||
public static synchronized TetheringManager getInstance() {
|
||||
if (sInstance == null) {
|
||||
sInstance = new TetheringManager();
|
||||
}
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
private class TetheringConnection implements
|
||||
ConnectivityModuleConnector.ModuleServiceCallback {
|
||||
@Override
|
||||
public void onModuleServiceConnected(@NonNull IBinder service) {
|
||||
logi("Tethering service connected");
|
||||
registerTetheringService(service);
|
||||
}
|
||||
}
|
||||
|
||||
private void registerTetheringService(@NonNull IBinder service) {
|
||||
final ITetheringConnector connector = ITetheringConnector.Stub.asInterface(service);
|
||||
|
||||
log("Tethering service registered");
|
||||
|
||||
// Currently TetheringManager instance is only used by ConnectivityService and mConnector
|
||||
// only expect to assign once when system server start and bind tethering service.
|
||||
// STOPSHIP: Change mConnector to final before TetheringManager put into boot classpath.
|
||||
mConnector = connector;
|
||||
mCallback = new TetherInternalCallback();
|
||||
try {
|
||||
mConnector.registerTetherInternalCallback(mCallback);
|
||||
} catch (RemoteException e) {
|
||||
e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
private class TetherInternalCallback extends ITetherInternalCallback.Stub {
|
||||
private final ConditionVariable mWaitForCallback = new ConditionVariable(false);
|
||||
private static final int EVENT_CALLBACK_TIMEOUT_MS = 60_000;
|
||||
|
||||
@Override
|
||||
public void onUpstreamChanged(Network network) {
|
||||
mTetherUpstream = network;
|
||||
reportUpstreamChanged(network);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigurationChanged(TetheringConfigurationParcel config) {
|
||||
mTetheringConfiguration = config;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTetherStatesChanged(TetherStatesParcel states) {
|
||||
mTetherStatesParcel = states;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCallbackCreated(Network network, TetheringConfigurationParcel config,
|
||||
TetherStatesParcel states) {
|
||||
mTetherUpstream = network;
|
||||
mTetheringConfiguration = config;
|
||||
mTetherStatesParcel = states;
|
||||
mWaitForCallback.open();
|
||||
}
|
||||
|
||||
boolean awaitCallbackCreation() {
|
||||
return mWaitForCallback.block(EVENT_CALLBACK_TIMEOUT_MS);
|
||||
}
|
||||
}
|
||||
|
||||
private void reportUpstreamChanged(Network network) {
|
||||
final int length = mTetheringEventCallbacks.beginBroadcast();
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the tethering service. Should be called only once on device startup.
|
||||
*
|
||||
* <p>This method will start the tethering service either in the network stack process,
|
||||
* or inside the system server on devices that do not support the tethering module.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
public void start() {
|
||||
// Using MAINLINE_NETWORK_STACK permission after cutting off the dpendency of system server.
|
||||
ConnectivityModuleConnector.getInstance().startModuleService(
|
||||
ITetheringConnector.class.getName(), NETWORK_STACK,
|
||||
new TetheringConnection());
|
||||
log("Tethering service start requested");
|
||||
}
|
||||
|
||||
/**
|
||||
* 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. Note: return value do not have any meaning. It is better to use
|
||||
* #getTetherableIfaces() to ensure corresponding interface is available for
|
||||
* tethering before calling #tether().
|
||||
*
|
||||
* TODO: Deprecate this API. The only usages should be in PanService and Wifi P2P which
|
||||
* need direct access.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
public int tether(@NonNull String iface) {
|
||||
try {
|
||||
mConnector.tether(iface);
|
||||
} catch (RemoteException e) {
|
||||
e.rethrowFromSystemServer();
|
||||
}
|
||||
return TETHER_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop tethering the named interface.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
public int untether(@NonNull String iface) {
|
||||
try {
|
||||
mConnector.untether(iface);
|
||||
} catch (RemoteException e) {
|
||||
e.rethrowFromSystemServer();
|
||||
}
|
||||
return TETHER_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to both alter the mode of USB and Tethering of USB. WARNING: 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.
|
||||
*
|
||||
* @Deprecated
|
||||
* {@hide}
|
||||
*/
|
||||
public int setUsbTethering(boolean enable) {
|
||||
try {
|
||||
mConnector.setUsbTethering(enable);
|
||||
} catch (RemoteException e) {
|
||||
e.rethrowFromSystemServer();
|
||||
}
|
||||
return TETHER_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts tethering and runs tether provisioning for the given type if needed. If provisioning
|
||||
* fails, stopTethering will be called automatically.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
// TODO: improve the usage of ResultReceiver, b/145096122
|
||||
public void startTethering(int type, @NonNull ResultReceiver receiver,
|
||||
boolean showProvisioningUi) {
|
||||
try {
|
||||
mConnector.startTethering(type, receiver, showProvisioningUi);
|
||||
} catch (RemoteException e) {
|
||||
e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops tethering for the given type. Also cancels any provisioning rechecks for that type if
|
||||
* applicable.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
public void stopTethering(int type) {
|
||||
try {
|
||||
mConnector.stopTethering(type);
|
||||
} catch (RemoteException e) {
|
||||
e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Request the latest value of the tethering entitlement check.
|
||||
*
|
||||
* Note: Allow privileged apps who have TETHER_PRIVILEGED permission to access. If it turns
|
||||
* out some such apps are observed to abuse this API, change to per-UID limits on this API
|
||||
* if it's really needed.
|
||||
*/
|
||||
// TODO: improve the usage of ResultReceiver, b/145096122
|
||||
public void requestLatestTetheringEntitlementResult(int type, @NonNull ResultReceiver receiver,
|
||||
boolean showEntitlementUi) {
|
||||
try {
|
||||
mConnector.requestLatestTetheringEntitlementResult(type, receiver, showEntitlementUi);
|
||||
} catch (RemoteException e) {
|
||||
e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register tethering event callback.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
public void registerTetheringEventCallback(@NonNull ITetheringEventCallback callback) {
|
||||
mTetheringEventCallbacks.register(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister tethering event callback.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
public void unregisterTetheringEventCallback(@NonNull ITetheringEventCallback callback) {
|
||||
mTetheringEventCallbacks.unregister(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a more detailed error code after a Tethering or Untethering
|
||||
* request asynchronously failed.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
public int getLastTetherError(@NonNull String iface) {
|
||||
if (!mCallback.awaitCallbackCreation()) {
|
||||
throw new NullPointerException("callback was not ready yet");
|
||||
}
|
||||
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.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
public @NonNull String[] getTetherableUsbRegexs() {
|
||||
if (!mCallback.awaitCallbackCreation()) {
|
||||
throw new NullPointerException("callback was not ready yet");
|
||||
}
|
||||
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.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
public @NonNull String[] getTetherableWifiRegexs() {
|
||||
if (!mCallback.awaitCallbackCreation()) {
|
||||
throw new NullPointerException("callback was not ready yet");
|
||||
}
|
||||
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.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
public @NonNull String[] getTetherableBluetoothRegexs() {
|
||||
if (!mCallback.awaitCallbackCreation()) {
|
||||
throw new NullPointerException("callback was not ready yet");
|
||||
}
|
||||
return mTetheringConfiguration.tetherableBluetoothRegexs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the set of tetherable, available interfaces. This list is limited by
|
||||
* device configuration and current interface existence.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
public @NonNull String[] getTetherableIfaces() {
|
||||
if (!mCallback.awaitCallbackCreation()) {
|
||||
throw new NullPointerException("callback was not ready yet");
|
||||
}
|
||||
if (mTetherStatesParcel == null) return new String[0];
|
||||
return mTetherStatesParcel.availableList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the set of tethered interfaces.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
public @NonNull String[] getTetheredIfaces() {
|
||||
if (!mCallback.awaitCallbackCreation()) {
|
||||
throw new NullPointerException("callback was not ready yet");
|
||||
}
|
||||
if (mTetherStatesParcel == null) return new String[0];
|
||||
return mTetherStatesParcel.tetheredList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the set of interface names which attempted to tether but
|
||||
* failed.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
public @NonNull String[] getTetheringErroredIfaces() {
|
||||
if (!mCallback.awaitCallbackCreation()) {
|
||||
throw new NullPointerException("callback was not ready yet");
|
||||
}
|
||||
if (mTetherStatesParcel == null) return new String[0];
|
||||
return mTetherStatesParcel.erroredIfaceList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the set of tethered dhcp ranges.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
public @NonNull String[] getTetheredDhcpRanges() {
|
||||
if (!mCallback.awaitCallbackCreation()) {
|
||||
throw new NullPointerException("callback was not ready yet");
|
||||
}
|
||||
return mTetheringConfiguration.legacyDhcpRanges;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the device allows for tethering.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
public boolean hasTetherableConfiguration() {
|
||||
if (!mCallback.awaitCallbackCreation()) {
|
||||
throw new NullPointerException("callback was not ready yet");
|
||||
}
|
||||
final boolean hasDownstreamConfiguration =
|
||||
(mTetheringConfiguration.tetherableUsbRegexs.length != 0)
|
||||
|| (mTetheringConfiguration.tetherableWifiRegexs.length != 0)
|
||||
|| (mTetheringConfiguration.tetherableBluetoothRegexs.length != 0);
|
||||
final boolean hasUpstreamConfiguration =
|
||||
(mTetheringConfiguration.preferredUpstreamIfaceTypes.length != 0)
|
||||
|| mTetheringConfiguration.chooseUpstreamAutomatically;
|
||||
|
||||
return hasDownstreamConfiguration && hasUpstreamConfiguration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Log a message in the local log.
|
||||
*/
|
||||
private void log(@NonNull String message) {
|
||||
synchronized (mLog) {
|
||||
mLog.log(message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Log a condition that should never happen.
|
||||
*/
|
||||
private void logWtf(@NonNull String message, @Nullable Throwable e) {
|
||||
Slog.wtf(TAG, message);
|
||||
synchronized (mLog) {
|
||||
mLog.e(message, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Log a ERROR level message in the local and system logs.
|
||||
*/
|
||||
private void loge(@NonNull String message, @Nullable Throwable e) {
|
||||
synchronized (mLog) {
|
||||
mLog.e(message, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Log a INFO level message in the local and system logs.
|
||||
*/
|
||||
private void logi(@NonNull String message) {
|
||||
synchronized (mLog) {
|
||||
mLog.i(message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump TetheringManager logs to the specified {@link PrintWriter}.
|
||||
*/
|
||||
public void dump(@NonNull PrintWriter pw) {
|
||||
// dump is thread-safe on SharedLog
|
||||
mLog.dump(null, pw, null);
|
||||
|
||||
pw.print("subId: ");
|
||||
pw.println(mTetheringConfiguration.subId);
|
||||
|
||||
dumpStringArray(pw, "tetherableUsbRegexs",
|
||||
mTetheringConfiguration.tetherableUsbRegexs);
|
||||
dumpStringArray(pw, "tetherableWifiRegexs",
|
||||
mTetheringConfiguration.tetherableWifiRegexs);
|
||||
dumpStringArray(pw, "tetherableBluetoothRegexs",
|
||||
mTetheringConfiguration.tetherableBluetoothRegexs);
|
||||
|
||||
pw.print("isDunRequired: ");
|
||||
pw.println(mTetheringConfiguration.isDunRequired);
|
||||
|
||||
pw.print("chooseUpstreamAutomatically: ");
|
||||
pw.println(mTetheringConfiguration.chooseUpstreamAutomatically);
|
||||
|
||||
dumpStringArray(pw, "legacyDhcpRanges", mTetheringConfiguration.legacyDhcpRanges);
|
||||
dumpStringArray(pw, "defaultIPv4DNS", mTetheringConfiguration.defaultIPv4DNS);
|
||||
|
||||
dumpStringArray(pw, "provisioningApp", mTetheringConfiguration.provisioningApp);
|
||||
pw.print("provisioningAppNoUi: ");
|
||||
pw.println(mTetheringConfiguration.provisioningAppNoUi);
|
||||
|
||||
pw.print("enableLegacyDhcpServer: ");
|
||||
pw.println(mTetheringConfiguration.enableLegacyDhcpServer);
|
||||
|
||||
pw.println();
|
||||
}
|
||||
|
||||
private static void dumpStringArray(@NonNull PrintWriter pw, @NonNull String label,
|
||||
@Nullable 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();
|
||||
}
|
||||
}
|
||||
@@ -145,4 +145,18 @@ int register_android_server_connectivity_tethering_OffloadHardwareInterface(JNIE
|
||||
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) {
|
||||
ALOGE("ERROR: GetEnv failed");
|
||||
return JNI_ERR;
|
||||
}
|
||||
|
||||
if (register_android_server_connectivity_tethering_OffloadHardwareInterface(env) < 0) {
|
||||
return JNI_ERR;
|
||||
}
|
||||
|
||||
return JNI_VERSION_1_6;
|
||||
}
|
||||
|
||||
}; // namespace android
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
@@ -39,10 +39,6 @@ import java.util.function.Consumer;
|
||||
public class VersionedBroadcastListener {
|
||||
private static final boolean DBG = false;
|
||||
|
||||
public interface IntentCallback {
|
||||
public void run(Intent intent);
|
||||
}
|
||||
|
||||
private final String mTag;
|
||||
private final Context mContext;
|
||||
private final Handler mHandler;
|
||||
@@ -61,6 +57,7 @@ public class VersionedBroadcastListener {
|
||||
mGenerationNumber = new AtomicInteger(0);
|
||||
}
|
||||
|
||||
/** Start listening to intent broadcast. */
|
||||
public void startListening() {
|
||||
if (DBG) Log.d(mTag, "startListening");
|
||||
if (mReceiver != null) return;
|
||||
@@ -69,6 +66,7 @@ public class VersionedBroadcastListener {
|
||||
mContext.registerReceiver(mReceiver, mFilter, null, mHandler);
|
||||
}
|
||||
|
||||
/** Stop listening to intent broadcast. */
|
||||
public void stopListening() {
|
||||
if (DBG) Log.d(mTag, "stopListening");
|
||||
if (mReceiver == null) return;
|
||||
@@ -85,8 +83,7 @@ public class VersionedBroadcastListener {
|
||||
// Used to verify this receiver is still current.
|
||||
public final int generationNumber;
|
||||
|
||||
public Receiver(
|
||||
String tag, AtomicInteger atomicGenerationNumber, Consumer<Intent> callback) {
|
||||
Receiver(String tag, AtomicInteger atomicGenerationNumber, Consumer<Intent> callback) {
|
||||
this.tag = tag;
|
||||
this.atomicGenerationNumber = atomicGenerationNumber;
|
||||
this.callback = callback;
|
||||
@@ -98,8 +95,8 @@ public class VersionedBroadcastListener {
|
||||
final int currentGenerationNumber = atomicGenerationNumber.get();
|
||||
|
||||
if (DBG) {
|
||||
Log.d(tag, "receiver generationNumber=" + generationNumber +
|
||||
", current generationNumber=" + currentGenerationNumber);
|
||||
Log.d(tag, "receiver generationNumber=" + generationNumber
|
||||
+ ", current generationNumber=" + currentGenerationNumber);
|
||||
}
|
||||
if (generationNumber != currentGenerationNumber) return;
|
||||
|
||||
@@ -47,6 +47,7 @@ import android.os.Parcel;
|
||||
import android.os.PersistableBundle;
|
||||
import android.os.ResultReceiver;
|
||||
import android.os.SystemClock;
|
||||
import android.os.SystemProperties;
|
||||
import android.os.UserHandle;
|
||||
import android.provider.Settings;
|
||||
import android.telephony.CarrierConfigManager;
|
||||
@@ -55,7 +56,6 @@ import android.util.SparseIntArray;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.util.StateMachine;
|
||||
import com.android.server.connectivity.MockableSystemProperties;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
|
||||
@@ -94,7 +94,6 @@ public class EntitlementManager {
|
||||
private final ArraySet<Integer> mCurrentTethers;
|
||||
private final Context mContext;
|
||||
private final int mPermissionChangeMessageCode;
|
||||
private final MockableSystemProperties mSystemProperties;
|
||||
private final SharedLog mLog;
|
||||
private final SparseIntArray mEntitlementCacheValue;
|
||||
private final EntitlementHandler mHandler;
|
||||
@@ -110,12 +109,12 @@ public class EntitlementManager {
|
||||
private TetheringConfigurationFetcher mFetcher;
|
||||
|
||||
public EntitlementManager(Context ctx, StateMachine tetherMasterSM, SharedLog log,
|
||||
int permissionChangeMessageCode, MockableSystemProperties systemProperties) {
|
||||
int permissionChangeMessageCode) {
|
||||
|
||||
mContext = ctx;
|
||||
mLog = log.forSubComponent(TAG);
|
||||
mCurrentTethers = new ArraySet<Integer>();
|
||||
mCellularPermitted = new SparseIntArray();
|
||||
mSystemProperties = systemProperties;
|
||||
mEntitlementCacheValue = new SparseIntArray();
|
||||
mTetherMasterSM = tetherMasterSM;
|
||||
mPermissionChangeMessageCode = permissionChangeMessageCode;
|
||||
@@ -287,7 +286,7 @@ public class EntitlementManager {
|
||||
*/
|
||||
@VisibleForTesting
|
||||
protected boolean isTetherProvisioningRequired(final TetheringConfiguration config) {
|
||||
if (mSystemProperties.getBoolean(DISABLE_PROVISIONING_SYSPROP_KEY, false)
|
||||
if (SystemProperties.getBoolean(DISABLE_PROVISIONING_SYSPROP_KEY, false)
|
||||
|| config.provisioningApp.length == 0) {
|
||||
return false;
|
||||
}
|
||||
@@ -526,8 +525,8 @@ public class EntitlementManager {
|
||||
handleMaybeRunProvisioning(config);
|
||||
break;
|
||||
case EVENT_GET_ENTITLEMENT_VALUE:
|
||||
handleGetLatestTetheringEntitlementValue(msg.arg1, (ResultReceiver) msg.obj,
|
||||
toBool(msg.arg2));
|
||||
handleRequestLatestTetheringEntitlementValue(msg.arg1,
|
||||
(ResultReceiver) msg.obj, toBool(msg.arg2));
|
||||
break;
|
||||
default:
|
||||
mLog.log("Unknown event: " + msg.what);
|
||||
@@ -651,15 +650,15 @@ public class EntitlementManager {
|
||||
}
|
||||
|
||||
/** Get the last value of the tethering entitlement check. */
|
||||
public void getLatestTetheringEntitlementResult(int downstream, ResultReceiver receiver,
|
||||
public void requestLatestTetheringEntitlementResult(int downstream, ResultReceiver receiver,
|
||||
boolean showEntitlementUi) {
|
||||
mHandler.sendMessage(mHandler.obtainMessage(EVENT_GET_ENTITLEMENT_VALUE,
|
||||
downstream, encodeBool(showEntitlementUi), receiver));
|
||||
|
||||
}
|
||||
|
||||
private void handleGetLatestTetheringEntitlementValue(int downstream, ResultReceiver receiver,
|
||||
boolean showEntitlementUi) {
|
||||
private void handleRequestLatestTetheringEntitlementValue(int downstream,
|
||||
ResultReceiver receiver, boolean showEntitlementUi) {
|
||||
final TetheringConfiguration config = mFetcher.fetchTetheringConfiguration();
|
||||
if (!isTetherProvisioningRequired(config)) {
|
||||
receiver.send(TETHER_ERROR_NO_ERROR, null);
|
||||
|
||||
@@ -82,6 +82,7 @@ public class IPv6TetheringCoordinator {
|
||||
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
|
||||
@@ -97,6 +98,7 @@ public class IPv6TetheringCoordinator {
|
||||
}
|
||||
}
|
||||
|
||||
/** Remove downstream from ipv6 tethering candidate list. */
|
||||
public void removeActiveDownstream(IpServer downstream) {
|
||||
stopIPv6TetheringOn(downstream);
|
||||
if (mActiveDownstreams.remove(findDownstream(downstream))) {
|
||||
@@ -112,6 +114,11 @@ public class IPv6TetheringCoordinator {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Call when upstream NetworkState may be changed.
|
||||
* If upstream has ipv6 for tethering, update this new NetworkState
|
||||
* to IpServer. Otherwise stop ipv6 tethering on downstream interfaces.
|
||||
*/
|
||||
public void updateUpstreamNetworkState(NetworkState ns) {
|
||||
if (VDBG) {
|
||||
Log.d(TAG, "updateUpstreamNetworkState: " + toDebugString(ns));
|
||||
@@ -122,8 +129,8 @@ public class IPv6TetheringCoordinator {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mUpstreamNetworkState != null &&
|
||||
!ns.network.equals(mUpstreamNetworkState.network)) {
|
||||
if (mUpstreamNetworkState != null
|
||||
&& !ns.network.equals(mUpstreamNetworkState.network)) {
|
||||
stopIPv6TetheringOnAllInterfaces();
|
||||
}
|
||||
|
||||
@@ -221,8 +228,8 @@ public class IPv6TetheringCoordinator {
|
||||
|
||||
for (RouteInfo routeInfo : lp.getRoutes()) {
|
||||
final IpPrefix destination = routeInfo.getDestination();
|
||||
if ((destination.getAddress() instanceof Inet6Address) &&
|
||||
(destination.getPrefixLength() <= 64)) {
|
||||
if ((destination.getAddress() instanceof Inet6Address)
|
||||
&& (destination.getPrefixLength() <= 64)) {
|
||||
v6only.addRoute(routeInfo);
|
||||
}
|
||||
}
|
||||
@@ -242,12 +249,12 @@ public class IPv6TetheringCoordinator {
|
||||
// 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();
|
||||
return (ip instanceof Inet6Address)
|
||||
&& !ip.isAnyLocalAddress()
|
||||
&& !ip.isLoopbackAddress()
|
||||
&& !ip.isLinkLocalAddress()
|
||||
&& !ip.isSiteLocalAddress()
|
||||
&& !ip.isMulticastAddress();
|
||||
}
|
||||
|
||||
private static LinkProperties getUniqueLocalConfig(byte[] ulp, short subnetId) {
|
||||
@@ -107,6 +107,8 @@ public class OffloadHardwareInterface {
|
||||
public OffloadHardwareInterface(Handler h, SharedLog log) {
|
||||
mHandler = h;
|
||||
mLog = log.forSubComponent(TAG);
|
||||
|
||||
System.loadLibrary("tetheroffloadjni");
|
||||
}
|
||||
|
||||
/** Get default value indicating whether offload is supported. */
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.connectivity;
|
||||
package com.android.server.connectivity.tethering;
|
||||
|
||||
import static android.hardware.usb.UsbManager.USB_CONFIGURED;
|
||||
import static android.hardware.usb.UsbManager.USB_CONNECTED;
|
||||
@@ -47,8 +47,6 @@ 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.server.ConnectivityService.SHORT_ARG;
|
||||
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
@@ -62,9 +60,10 @@ import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.res.Resources;
|
||||
import android.hardware.usb.UsbManager;
|
||||
import android.net.INetd;
|
||||
import android.net.INetworkPolicyManager;
|
||||
import android.net.INetworkStatsService;
|
||||
import android.net.ITetheringEventCallback;
|
||||
import android.net.ITetherInternalCallback;
|
||||
import android.net.IpPrefix;
|
||||
import android.net.LinkAddress;
|
||||
import android.net.LinkProperties;
|
||||
@@ -72,7 +71,10 @@ import android.net.Network;
|
||||
import android.net.NetworkInfo;
|
||||
import android.net.NetworkState;
|
||||
import android.net.NetworkUtils;
|
||||
import android.net.TetherStatesParcel;
|
||||
import android.net.TetheringConfigurationParcel;
|
||||
import android.net.ip.IpServer;
|
||||
import android.net.util.BaseNetdUnsolicitedEventListener;
|
||||
import android.net.util.InterfaceSet;
|
||||
import android.net.util.PrefixUtils;
|
||||
import android.net.util.SharedLog;
|
||||
@@ -87,7 +89,6 @@ import android.os.Handler;
|
||||
import android.os.INetworkManagementService;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.os.RemoteCallbackList;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ResultReceiver;
|
||||
import android.os.UserHandle;
|
||||
@@ -111,14 +112,6 @@ import com.android.internal.util.Protocol;
|
||||
import com.android.internal.util.State;
|
||||
import com.android.internal.util.StateMachine;
|
||||
import com.android.server.LocalServices;
|
||||
import com.android.server.connectivity.tethering.EntitlementManager;
|
||||
import com.android.server.connectivity.tethering.IPv6TetheringCoordinator;
|
||||
import com.android.server.connectivity.tethering.OffloadController;
|
||||
import com.android.server.connectivity.tethering.TetheringConfiguration;
|
||||
import com.android.server.connectivity.tethering.TetheringDependencies;
|
||||
import com.android.server.connectivity.tethering.TetheringInterfaceUtils;
|
||||
import com.android.server.connectivity.tethering.UpstreamNetworkMonitor;
|
||||
import com.android.server.net.BaseNetworkObserver;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.PrintWriter;
|
||||
@@ -127,32 +120,32 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*
|
||||
* 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 extends BaseNetworkObserver {
|
||||
public class Tethering {
|
||||
|
||||
private final static String TAG = Tethering.class.getSimpleName();
|
||||
private final static boolean DBG = false;
|
||||
private final static boolean VDBG = false;
|
||||
private static final String TAG = Tethering.class.getSimpleName();
|
||||
private static final boolean DBG = false;
|
||||
private static final boolean VDBG = false;
|
||||
|
||||
private static final Class[] messageClasses = {
|
||||
private static final Class[] sMessageClasses = {
|
||||
Tethering.class, TetherMasterSM.class, IpServer.class
|
||||
};
|
||||
private static final SparseArray<String> sMagicDecoderRing =
|
||||
MessageUtils.findMessageNames(messageClasses);
|
||||
MessageUtils.findMessageNames(sMessageClasses);
|
||||
|
||||
private static class TetherState {
|
||||
public final IpServer ipServer;
|
||||
public int lastState;
|
||||
public int lastError;
|
||||
|
||||
public TetherState(IpServer ipServer) {
|
||||
TetherState(IpServer ipServer) {
|
||||
this.ipServer = ipServer;
|
||||
// Assume all state machines start out available and with no errors.
|
||||
lastState = IpServer.STATE_AVAILABLE;
|
||||
@@ -177,6 +170,7 @@ public class Tethering extends BaseNetworkObserver {
|
||||
private final Context mContext;
|
||||
private final ArrayMap<String, TetherState> mTetherStates;
|
||||
private final BroadcastReceiver mStateReceiver;
|
||||
// Stopship: replace mNMService before production.
|
||||
private final INetworkManagementService mNMService;
|
||||
private final INetworkStatsService mStatsService;
|
||||
private final INetworkPolicyManager mPolicyManager;
|
||||
@@ -191,10 +185,12 @@ public class Tethering extends BaseNetworkObserver {
|
||||
private final TetheringDependencies mDeps;
|
||||
private final EntitlementManager mEntitlementMgr;
|
||||
private final Handler mHandler;
|
||||
private final RemoteCallbackList<ITetheringEventCallback> mTetheringEventCallbacks =
|
||||
new RemoteCallbackList<>();
|
||||
private final PhoneStateListener mPhoneStateListener;
|
||||
private final INetd mNetd;
|
||||
private final NetdCallback mNetdCallback;
|
||||
private int mActiveDataSubId = INVALID_SUBSCRIPTION_ID;
|
||||
// All the usage of mTetherInternalCallback should run in the same thread.
|
||||
private ITetherInternalCallback mTetherInternalCallback = null;
|
||||
|
||||
private volatile TetheringConfiguration mConfig;
|
||||
private InterfaceSet mCurrentUpstreamIfaceSet;
|
||||
@@ -205,18 +201,17 @@ public class Tethering extends BaseNetworkObserver {
|
||||
// True iff. WiFi tethering should be started when soft AP is ready.
|
||||
private boolean mWifiTetherRequested;
|
||||
private Network mTetherUpstream;
|
||||
private TetherStatesParcel mTetherStatesParcel;
|
||||
|
||||
public Tethering(Context context, INetworkManagementService nmService,
|
||||
INetworkStatsService statsService, INetworkPolicyManager policyManager,
|
||||
Looper looper, MockableSystemProperties systemProperties,
|
||||
TetheringDependencies deps) {
|
||||
mLog.mark("constructed");
|
||||
mContext = context;
|
||||
mNMService = nmService;
|
||||
mStatsService = statsService;
|
||||
mPolicyManager = policyManager;
|
||||
mLooper = looper;
|
||||
public Tethering(TetheringDependencies deps) {
|
||||
mLog.mark("Tethering.constructed");
|
||||
mDeps = deps;
|
||||
mContext = mDeps.getContext();
|
||||
mNMService = mDeps.getINetworkManagementService();
|
||||
mStatsService = mDeps.getINetworkStatsService();
|
||||
mPolicyManager = mDeps.getINetworkPolicyManager();
|
||||
mNetd = mDeps.getINetd(mContext);
|
||||
mLooper = mDeps.getTetheringLooper();
|
||||
|
||||
mPublicSync = new Object();
|
||||
|
||||
@@ -239,7 +234,7 @@ public class Tethering extends BaseNetworkObserver {
|
||||
// EntitlementManager will send EVENT_UPSTREAM_PERMISSION_CHANGED when cellular upstream
|
||||
// permission is changed according to entitlement check result.
|
||||
mEntitlementMgr = mDeps.getEntitlementManager(mContext, mTetherMasterSM, mLog,
|
||||
TetherMasterSM.EVENT_UPSTREAM_PERMISSION_CHANGED, systemProperties);
|
||||
TetherMasterSM.EVENT_UPSTREAM_PERMISSION_CHANGED);
|
||||
mEntitlementMgr.setOnUiEntitlementFailedListener((int downstream) -> {
|
||||
mLog.log("OBSERVED UiEnitlementFailed");
|
||||
stopTethering(downstream);
|
||||
@@ -278,10 +273,18 @@ public class Tethering extends BaseNetworkObserver {
|
||||
|
||||
mStateReceiver = new StateReceiver();
|
||||
|
||||
mNetdCallback = new NetdCallback();
|
||||
try {
|
||||
mNetd.registerUnsolicitedEventListener(mNetdCallback);
|
||||
} catch (RemoteException e) {
|
||||
mLog.e("Unable to register netd UnsolicitedEventListener");
|
||||
}
|
||||
|
||||
// Load tethering configuration.
|
||||
updateConfiguration();
|
||||
|
||||
startStateMachineUpdaters(mHandler);
|
||||
startTrackDefaultNetwork();
|
||||
}
|
||||
|
||||
private void startStateMachineUpdaters(Handler handler) {
|
||||
@@ -318,6 +321,7 @@ public class Tethering extends BaseNetworkObserver {
|
||||
private void updateConfiguration() {
|
||||
mConfig = mDeps.generateTetheringConfiguration(mContext, mLog, mActiveDataSubId);
|
||||
mUpstreamNetworkMonitor.updateMobileRequiresDun(mConfig.isDunRequired);
|
||||
reportConfigurationChanged(mConfig.toStableParcelable());
|
||||
}
|
||||
|
||||
private void maybeDunSettingChanged() {
|
||||
@@ -327,10 +331,31 @@ public class Tethering extends BaseNetworkObserver {
|
||||
updateConfiguration();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void interfaceStatusChanged(String iface, boolean up) {
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
void interfaceStatusChanged(String iface, boolean up) {
|
||||
// Never called directly: only called from interfaceLinkStateChanged.
|
||||
// See NetlinkHandler.cpp:71.
|
||||
// See NetlinkHandler.cpp: notifyInterfaceChanged.
|
||||
if (VDBG) Log.d(TAG, "interfaceStatusChanged " + iface + ", " + up);
|
||||
synchronized (mPublicSync) {
|
||||
if (up) {
|
||||
@@ -349,8 +374,7 @@ public class Tethering extends BaseNetworkObserver {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void interfaceLinkStateChanged(String iface, boolean up) {
|
||||
void interfaceLinkStateChanged(String iface, boolean up) {
|
||||
interfaceStatusChanged(iface, up);
|
||||
}
|
||||
|
||||
@@ -369,28 +393,27 @@ public class Tethering extends BaseNetworkObserver {
|
||||
return TETHERING_INVALID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void interfaceAdded(String iface) {
|
||||
void interfaceAdded(String iface) {
|
||||
if (VDBG) Log.d(TAG, "interfaceAdded " + iface);
|
||||
synchronized (mPublicSync) {
|
||||
maybeTrackNewInterfaceLocked(iface);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void interfaceRemoved(String iface) {
|
||||
|
||||
void interfaceRemoved(String iface) {
|
||||
if (VDBG) Log.d(TAG, "interfaceRemoved " + iface);
|
||||
synchronized (mPublicSync) {
|
||||
stopTrackingInterfaceLocked(iface);
|
||||
}
|
||||
}
|
||||
|
||||
public void startTethering(int type, ResultReceiver receiver, boolean showProvisioningUi) {
|
||||
void startTethering(int type, ResultReceiver receiver, boolean showProvisioningUi) {
|
||||
mEntitlementMgr.startProvisioningIfNeeded(type, showProvisioningUi);
|
||||
enableTetheringInternal(type, true /* enabled */, receiver);
|
||||
}
|
||||
|
||||
public void stopTethering(int type) {
|
||||
void stopTethering(int type) {
|
||||
enableTetheringInternal(type, false /* disabled */, null);
|
||||
mEntitlementMgr.stopProvisioningIfNeeded(type);
|
||||
}
|
||||
@@ -434,8 +457,8 @@ public class Tethering extends BaseNetworkObserver {
|
||||
mLog.e("setWifiTethering: failed to get WifiManager!");
|
||||
return TETHER_ERROR_SERVICE_UNAVAIL;
|
||||
}
|
||||
if ((enable && mgr.startSoftAp(null /* use existing wifi config */)) ||
|
||||
(!enable && mgr.stopSoftAp())) {
|
||||
if ((enable && mgr.startSoftAp(null /* use existing wifi config */))
|
||||
|| (!enable && mgr.stopSoftAp())) {
|
||||
mWifiTetherRequested = enable;
|
||||
return TETHER_ERROR_NO_ERROR;
|
||||
}
|
||||
@@ -450,8 +473,8 @@ public class Tethering extends BaseNetworkObserver {
|
||||
private void setBluetoothTethering(final boolean enable, final ResultReceiver receiver) {
|
||||
final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
|
||||
if (adapter == null || !adapter.isEnabled()) {
|
||||
Log.w(TAG, "Tried to enable bluetooth tethering with null or disabled adapter. null: " +
|
||||
(adapter == null));
|
||||
Log.w(TAG, "Tried to enable bluetooth tethering with null or disabled adapter. null: "
|
||||
+ (adapter == null));
|
||||
sendTetherResult(receiver, TETHER_ERROR_SERVICE_UNAVAIL);
|
||||
return;
|
||||
}
|
||||
@@ -487,7 +510,7 @@ public class Tethering extends BaseNetworkObserver {
|
||||
}, BluetoothProfile.PAN);
|
||||
}
|
||||
|
||||
public int tether(String iface) {
|
||||
int tether(String iface) {
|
||||
return tether(iface, IpServer.STATE_TETHERED);
|
||||
}
|
||||
|
||||
@@ -515,7 +538,7 @@ public class Tethering extends BaseNetworkObserver {
|
||||
}
|
||||
}
|
||||
|
||||
public int untether(String iface) {
|
||||
int untether(String iface) {
|
||||
if (DBG) Log.d(TAG, "Untethering " + iface);
|
||||
synchronized (mPublicSync) {
|
||||
TetherState tetherState = mTetherStates.get(iface);
|
||||
@@ -532,19 +555,19 @@ public class Tethering extends BaseNetworkObserver {
|
||||
}
|
||||
}
|
||||
|
||||
public void untetherAll() {
|
||||
void untetherAll() {
|
||||
stopTethering(TETHERING_WIFI);
|
||||
stopTethering(TETHERING_WIFI_P2P);
|
||||
stopTethering(TETHERING_USB);
|
||||
stopTethering(TETHERING_BLUETOOTH);
|
||||
}
|
||||
|
||||
public int getLastTetherError(String iface) {
|
||||
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");
|
||||
Log.e(TAG, "Tried to getLastTetherError on an unknown iface :" + iface
|
||||
+ ", ignoring");
|
||||
return TETHER_ERROR_UNKNOWN_IFACE;
|
||||
}
|
||||
return tetherState.lastError;
|
||||
@@ -559,12 +582,14 @@ public class Tethering extends BaseNetworkObserver {
|
||||
final ArrayList<String> tetherList = new ArrayList<>();
|
||||
final ArrayList<String> localOnlyList = new ArrayList<>();
|
||||
final ArrayList<String> erroredList = new ArrayList<>();
|
||||
final ArrayList<Integer> lastErrorList = new ArrayList<>();
|
||||
|
||||
boolean wifiTethered = false;
|
||||
boolean usbTethered = false;
|
||||
boolean bluetoothTethered = false;
|
||||
|
||||
final TetheringConfiguration cfg = mConfig;
|
||||
final TetherStatesParcel mTetherStatesParcel = new TetherStatesParcel();
|
||||
|
||||
synchronized (mPublicSync) {
|
||||
for (int i = 0; i < mTetherStates.size(); i++) {
|
||||
@@ -572,6 +597,7 @@ public class Tethering extends BaseNetworkObserver {
|
||||
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) {
|
||||
@@ -588,9 +614,21 @@ public class Tethering extends BaseNetworkObserver {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 |
|
||||
Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
|
||||
bcast.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
|
||||
| Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
|
||||
bcast.putStringArrayListExtra(EXTRA_AVAILABLE_TETHER, availableList);
|
||||
bcast.putStringArrayListExtra(EXTRA_ACTIVE_LOCAL_ONLY, localOnlyList);
|
||||
bcast.putStringArrayListExtra(EXTRA_ACTIVE_TETHER, tetherList);
|
||||
@@ -638,16 +676,16 @@ public class Tethering extends BaseNetworkObserver {
|
||||
}
|
||||
int icon = 0;
|
||||
switch(id) {
|
||||
case SystemMessage.NOTE_TETHER_USB:
|
||||
icon = com.android.internal.R.drawable.stat_sys_tether_usb;
|
||||
break;
|
||||
case SystemMessage.NOTE_TETHER_BLUETOOTH:
|
||||
icon = com.android.internal.R.drawable.stat_sys_tether_bluetooth;
|
||||
break;
|
||||
case SystemMessage.NOTE_TETHER_GENERAL:
|
||||
default:
|
||||
icon = com.android.internal.R.drawable.stat_sys_tether_general;
|
||||
break;
|
||||
case SystemMessage.NOTE_TETHER_USB:
|
||||
icon = com.android.internal.R.drawable.stat_sys_tether_usb;
|
||||
break;
|
||||
case SystemMessage.NOTE_TETHER_BLUETOOTH:
|
||||
icon = com.android.internal.R.drawable.stat_sys_tether_bluetooth;
|
||||
break;
|
||||
case SystemMessage.NOTE_TETHER_GENERAL:
|
||||
default:
|
||||
icon = com.android.internal.R.drawable.stat_sys_tether_general;
|
||||
break;
|
||||
}
|
||||
|
||||
if (mLastNotificationId != 0) {
|
||||
@@ -701,7 +739,7 @@ public class Tethering extends BaseNetworkObserver {
|
||||
@VisibleForTesting
|
||||
protected void clearTetheredNotification() {
|
||||
NotificationManager notificationManager =
|
||||
(NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
(NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
if (notificationManager != null && mLastNotificationId != 0) {
|
||||
notificationManager.cancelAsUser(null, mLastNotificationId,
|
||||
UserHandle.ALL);
|
||||
@@ -732,8 +770,8 @@ public class Tethering extends BaseNetworkObserver {
|
||||
private void handleConnectivityAction(Intent intent) {
|
||||
final NetworkInfo networkInfo =
|
||||
(NetworkInfo) intent.getParcelableExtra(EXTRA_NETWORK_INFO);
|
||||
if (networkInfo == null ||
|
||||
networkInfo.getDetailedState() == NetworkInfo.DetailedState.FAILED) {
|
||||
if (networkInfo == null
|
||||
|| networkInfo.getDetailedState() == NetworkInfo.DetailedState.FAILED) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -888,8 +926,8 @@ public class Tethering extends BaseNetworkObserver {
|
||||
}
|
||||
}
|
||||
|
||||
mLog.log("Error disabling Wi-Fi IP serving; " +
|
||||
(TextUtils.isEmpty(ifname) ? "no interface name specified"
|
||||
mLog.log("Error disabling Wi-Fi IP serving; "
|
||||
+ (TextUtils.isEmpty(ifname) ? "no interface name specified"
|
||||
: "specified interface: " + ifname));
|
||||
}
|
||||
|
||||
@@ -928,8 +966,8 @@ public class Tethering extends BaseNetworkObserver {
|
||||
changeInterfaceState(ifname, ipServingMode);
|
||||
} else {
|
||||
mLog.e(String.format(
|
||||
"Cannot enable IP serving in mode %s on missing interface name",
|
||||
ipServingMode));
|
||||
"Cannot enable IP serving in mode %s on missing interface name",
|
||||
ipServingMode));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -989,11 +1027,11 @@ public class Tethering extends BaseNetworkObserver {
|
||||
}
|
||||
}
|
||||
|
||||
public TetheringConfiguration getTetheringConfiguration() {
|
||||
TetheringConfiguration getTetheringConfiguration() {
|
||||
return mConfig;
|
||||
}
|
||||
|
||||
public boolean hasTetherableConfiguration() {
|
||||
boolean hasTetherableConfiguration() {
|
||||
final TetheringConfiguration cfg = mConfig;
|
||||
final boolean hasDownstreamConfiguration =
|
||||
(cfg.tetherableUsbRegexs.length != 0)
|
||||
@@ -1007,19 +1045,19 @@ public class Tethering extends BaseNetworkObserver {
|
||||
|
||||
// TODO - update callers to use getTetheringConfiguration(),
|
||||
// which has only final members.
|
||||
public String[] getTetherableUsbRegexs() {
|
||||
String[] getTetherableUsbRegexs() {
|
||||
return copy(mConfig.tetherableUsbRegexs);
|
||||
}
|
||||
|
||||
public String[] getTetherableWifiRegexs() {
|
||||
String[] getTetherableWifiRegexs() {
|
||||
return copy(mConfig.tetherableWifiRegexs);
|
||||
}
|
||||
|
||||
public String[] getTetherableBluetoothRegexs() {
|
||||
String[] getTetherableBluetoothRegexs() {
|
||||
return copy(mConfig.tetherableBluetoothRegexs);
|
||||
}
|
||||
|
||||
public int setUsbTethering(boolean enable) {
|
||||
int setUsbTethering(boolean enable) {
|
||||
if (VDBG) Log.d(TAG, "setUsbTethering(" + enable + ")");
|
||||
UsbManager usbManager = (UsbManager) mContext.getSystemService(Context.USB_SERVICE);
|
||||
if (usbManager == null) {
|
||||
@@ -1035,7 +1073,7 @@ public class Tethering extends BaseNetworkObserver {
|
||||
}
|
||||
|
||||
// TODO review API - figure out how to delete these entirely.
|
||||
public String[] getTetheredIfaces() {
|
||||
String[] getTetheredIfaces() {
|
||||
ArrayList<String> list = new ArrayList<String>();
|
||||
synchronized (mPublicSync) {
|
||||
for (int i = 0; i < mTetherStates.size(); i++) {
|
||||
@@ -1048,7 +1086,7 @@ public class Tethering extends BaseNetworkObserver {
|
||||
return list.toArray(new String[list.size()]);
|
||||
}
|
||||
|
||||
public String[] getTetherableIfaces() {
|
||||
String[] getTetherableIfaces() {
|
||||
ArrayList<String> list = new ArrayList<String>();
|
||||
synchronized (mPublicSync) {
|
||||
for (int i = 0; i < mTetherStates.size(); i++) {
|
||||
@@ -1061,13 +1099,13 @@ public class Tethering extends BaseNetworkObserver {
|
||||
return list.toArray(new String[list.size()]);
|
||||
}
|
||||
|
||||
public String[] getTetheredDhcpRanges() {
|
||||
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;
|
||||
}
|
||||
|
||||
public String[] getErroredIfaces() {
|
||||
String[] getErroredIfaces() {
|
||||
ArrayList<String> list = new ArrayList<String>();
|
||||
synchronized (mPublicSync) {
|
||||
for (int i = 0; i < mTetherStates.size(); i++) {
|
||||
@@ -1518,8 +1556,8 @@ public class Tethering extends BaseNetworkObserver {
|
||||
}
|
||||
|
||||
if (DBG) {
|
||||
Log.d(TAG, "TetherModeAlive still has " + mNotifyList.size() +
|
||||
" live requests:");
|
||||
Log.d(TAG, "TetherModeAlive still has " + mNotifyList.size()
|
||||
+ " live requests:");
|
||||
for (IpServer o : mNotifyList) {
|
||||
Log.d(TAG, " " + o);
|
||||
}
|
||||
@@ -1588,7 +1626,7 @@ public class Tethering extends BaseNetworkObserver {
|
||||
transitionTo(mInitialState);
|
||||
break;
|
||||
default:
|
||||
retValue = false;
|
||||
retValue = false;
|
||||
}
|
||||
return retValue;
|
||||
}
|
||||
@@ -1625,7 +1663,7 @@ public class Tethering extends BaseNetworkObserver {
|
||||
notify(IpServer.CMD_START_TETHERING_ERROR);
|
||||
try {
|
||||
mNMService.setIpForwardingEnabled(false);
|
||||
} catch (Exception e) {}
|
||||
} catch (Exception e) { }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1636,7 +1674,7 @@ public class Tethering extends BaseNetworkObserver {
|
||||
notify(IpServer.CMD_STOP_TETHERING_ERROR);
|
||||
try {
|
||||
mNMService.setIpForwardingEnabled(false);
|
||||
} catch (Exception e) {}
|
||||
} catch (Exception e) { }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1647,10 +1685,10 @@ public class Tethering extends BaseNetworkObserver {
|
||||
notify(IpServer.CMD_SET_DNS_FORWARDERS_ERROR);
|
||||
try {
|
||||
mNMService.stopTethering();
|
||||
} catch (Exception e) {}
|
||||
} catch (Exception e) { }
|
||||
try {
|
||||
mNMService.setIpForwardingEnabled(false);
|
||||
} catch (Exception e) {}
|
||||
} catch (Exception e) { }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1731,55 +1769,66 @@ public class Tethering extends BaseNetworkObserver {
|
||||
}
|
||||
}
|
||||
|
||||
public void systemReady() {
|
||||
private void startTrackDefaultNetwork() {
|
||||
mUpstreamNetworkMonitor.startTrackDefaultNetwork(mDeps.getDefaultNetworkRequest(),
|
||||
mEntitlementMgr);
|
||||
}
|
||||
|
||||
/** Get the latest value of the tethering entitlement check. */
|
||||
public void getLatestTetheringEntitlementResult(int type, ResultReceiver receiver,
|
||||
void requestLatestTetheringEntitlementResult(int type, ResultReceiver receiver,
|
||||
boolean showEntitlementUi) {
|
||||
if (receiver != null) {
|
||||
mEntitlementMgr.getLatestTetheringEntitlementResult(type, receiver, showEntitlementUi);
|
||||
mEntitlementMgr.requestLatestTetheringEntitlementResult(type, receiver,
|
||||
showEntitlementUi);
|
||||
}
|
||||
}
|
||||
|
||||
/** Register tethering event callback */
|
||||
public void registerTetheringEventCallback(ITetheringEventCallback callback) {
|
||||
void registerTetherInternalCallback(ITetherInternalCallback callback) {
|
||||
mHandler.post(() -> {
|
||||
mTetherInternalCallback = callback;
|
||||
try {
|
||||
callback.onUpstreamChanged(mTetherUpstream);
|
||||
mTetherInternalCallback.onCallbackCreated(mTetherUpstream,
|
||||
mConfig.toStableParcelable(), mTetherStatesParcel);
|
||||
} catch (RemoteException e) {
|
||||
// Not really very much to do here.
|
||||
}
|
||||
mTetheringEventCallbacks.register(callback);
|
||||
});
|
||||
}
|
||||
|
||||
/** Unregister tethering event callback */
|
||||
public void unregisterTetheringEventCallback(ITetheringEventCallback callback) {
|
||||
mHandler.post(() -> {
|
||||
mTetheringEventCallbacks.unregister(callback);
|
||||
});
|
||||
}
|
||||
|
||||
private void reportUpstreamChanged(Network network) {
|
||||
final int length = mTetheringEventCallbacks.beginBroadcast();
|
||||
// Don't need to synchronized mTetherInternalCallback because all the usage of this variable
|
||||
// should run at the same thread.
|
||||
if (mTetherInternalCallback == null) return;
|
||||
|
||||
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();
|
||||
mTetherInternalCallback.onUpstreamChanged(network);
|
||||
} catch (RemoteException e) {
|
||||
// Not really very much to do here.
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
|
||||
private void reportConfigurationChanged(TetheringConfigurationParcel config) {
|
||||
if (mTetherInternalCallback == null) return;
|
||||
|
||||
try {
|
||||
mTetherInternalCallback.onConfigurationChanged(config);
|
||||
} catch (RemoteException e) {
|
||||
// Not really very much to do here.
|
||||
}
|
||||
}
|
||||
|
||||
private void reportTetherStateChanged(TetherStatesParcel states) {
|
||||
if (mTetherInternalCallback == null) return;
|
||||
|
||||
try {
|
||||
mTetherInternalCallback.onTetherStatesChanged(states);
|
||||
} catch (RemoteException e) {
|
||||
// Not really very much to do here.
|
||||
}
|
||||
}
|
||||
|
||||
void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
|
||||
// Binder.java closes the resource for us.
|
||||
@SuppressWarnings("resource")
|
||||
final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
|
||||
@@ -1838,7 +1887,7 @@ public class Tethering extends BaseNetworkObserver {
|
||||
|
||||
pw.println("Log:");
|
||||
pw.increaseIndent();
|
||||
if (argsContain(args, SHORT_ARG)) {
|
||||
if (argsContain(args, "--short")) {
|
||||
pw.println("<log removed for brevity>");
|
||||
} else {
|
||||
mLog.dump(fd, pw, args);
|
||||
@@ -38,6 +38,7 @@ import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.TetheringConfigurationParcel;
|
||||
import android.net.util.SharedLog;
|
||||
import android.provider.Settings;
|
||||
import android.telephony.SubscriptionManager;
|
||||
@@ -384,4 +385,32 @@ public class TetheringConfiguration {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert this TetheringConfiguration to a TetheringConfigurationParcel.
|
||||
*/
|
||||
public TetheringConfigurationParcel toStableParcelable() {
|
||||
final TetheringConfigurationParcel parcel = new TetheringConfigurationParcel();
|
||||
parcel.subId = subId;
|
||||
parcel.tetherableUsbRegexs = tetherableUsbRegexs;
|
||||
parcel.tetherableWifiRegexs = tetherableWifiRegexs;
|
||||
parcel.tetherableBluetoothRegexs = tetherableBluetoothRegexs;
|
||||
parcel.isDunRequired = isDunRequired;
|
||||
parcel.chooseUpstreamAutomatically = chooseUpstreamAutomatically;
|
||||
|
||||
int[] preferredTypes = new int[preferredUpstreamIfaceTypes.size()];
|
||||
int index = 0;
|
||||
for (Integer type : preferredUpstreamIfaceTypes) {
|
||||
preferredTypes[index++] = type;
|
||||
}
|
||||
parcel.preferredUpstreamIfaceTypes = preferredTypes;
|
||||
|
||||
parcel.legacyDhcpRanges = legacyDhcpRanges;
|
||||
parcel.defaultIPv4DNS = defaultIPv4DNS;
|
||||
parcel.enableLegacyDhcpServer = enableLegacyDhcpServer;
|
||||
parcel.provisioningApp = provisioningApp;
|
||||
parcel.provisioningAppNoUi = provisioningAppNoUi;
|
||||
parcel.provisioningCheckPeriod = provisioningCheckPeriod;
|
||||
return parcel;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,13 +17,19 @@
|
||||
package com.android.server.connectivity.tethering;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.INetd;
|
||||
import android.net.INetworkPolicyManager;
|
||||
import android.net.INetworkStatsService;
|
||||
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.INetworkManagementService;
|
||||
import android.os.Looper;
|
||||
import android.os.ServiceManager;
|
||||
|
||||
import com.android.internal.util.StateMachine;
|
||||
import com.android.server.connectivity.MockableSystemProperties;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
@@ -82,8 +88,8 @@ public class TetheringDependencies {
|
||||
* Get a reference to the EntitlementManager to be used by tethering.
|
||||
*/
|
||||
public EntitlementManager getEntitlementManager(Context ctx, StateMachine target,
|
||||
SharedLog log, int what, MockableSystemProperties systemProperties) {
|
||||
return new EntitlementManager(ctx, target, log, what, systemProperties);
|
||||
SharedLog log, int what) {
|
||||
return new EntitlementManager(ctx, target, log, what);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -93,4 +99,53 @@ public class TetheringDependencies {
|
||||
int subId) {
|
||||
return new TetheringConfiguration(ctx, log, subId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a reference to INetworkManagementService to registerTetheringStatsProvider from
|
||||
* OffloadController. Note: This should be removed soon by Usage refactor work in R
|
||||
* development cycle.
|
||||
*/
|
||||
public INetworkManagementService getINetworkManagementService() {
|
||||
return INetworkManagementService.Stub.asInterface(
|
||||
ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a reference to INetworkStatsService to force update tethering usage.
|
||||
* Note: This should be removed in R development cycle.
|
||||
*/
|
||||
public INetworkStatsService getINetworkStatsService() {
|
||||
return INetworkStatsService.Stub.asInterface(
|
||||
ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a reference to INetworkPolicyManager to be used by tethering.
|
||||
*/
|
||||
public INetworkPolicyManager getINetworkPolicyManager() {
|
||||
return INetworkPolicyManager.Stub.asInterface(
|
||||
ServiceManager.getService(Context.NETWORK_POLICY_SERVICE));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 tethering thread looper.
|
||||
*/
|
||||
public Looper getTetheringLooper() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Context of TetheringSerice.
|
||||
*/
|
||||
public Context getContext() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
* 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.server.connectivity.tethering;
|
||||
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.ITetherInternalCallback;
|
||||
import android.net.ITetheringConnector;
|
||||
import android.net.NetworkRequest;
|
||||
import android.net.util.SharedLog;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
import android.os.ResultReceiver;
|
||||
import android.os.SystemProperties;
|
||||
import android.provider.Settings;
|
||||
|
||||
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 final SharedLog mLog = new SharedLog(TAG);
|
||||
private TetheringConnector mConnector;
|
||||
private Context mContext;
|
||||
private TetheringDependencies mDeps;
|
||||
private Tethering mTethering;
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
mLog.mark("onCreate");
|
||||
mDeps = getTetheringDependencies();
|
||||
mContext = mDeps.getContext();
|
||||
mTethering = makeTethering(mDeps);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a reference to Tethering object.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
public Tethering makeTethering(TetheringDependencies deps) {
|
||||
return new Tethering(deps);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a binder connector for the system server to communicate with the tethering.
|
||||
*/
|
||||
private synchronized IBinder makeConnector() {
|
||||
if (mConnector == null) {
|
||||
mConnector = new TetheringConnector(mTethering);
|
||||
}
|
||||
return mConnector;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
mLog.mark("onBind");
|
||||
return makeConnector();
|
||||
}
|
||||
|
||||
private static class TetheringConnector extends ITetheringConnector.Stub {
|
||||
private final Tethering mService;
|
||||
|
||||
TetheringConnector(Tethering tether) {
|
||||
mService = tether;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tether(String iface) {
|
||||
mService.tether(iface);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void untether(String iface) {
|
||||
mService.untether(iface);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUsbTethering(boolean enable) {
|
||||
mService.setUsbTethering(enable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startTethering(int type, ResultReceiver receiver, boolean showProvisioningUi) {
|
||||
mService.startTethering(type, receiver, showProvisioningUi);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopTethering(int type) {
|
||||
mService.stopTethering(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requestLatestTetheringEntitlementResult(int type, ResultReceiver receiver,
|
||||
boolean showEntitlementUi) {
|
||||
mService.requestLatestTetheringEntitlementResult(type, receiver, showEntitlementUi);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerTetherInternalCallback(ITetherInternalCallback callback) {
|
||||
mService.registerTetherInternalCallback(callback);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter writer,
|
||||
@Nullable String[] args) {
|
||||
mTethering.dump(fd, writer, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* An injection method for testing.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
public TetheringDependencies getTetheringDependencies() {
|
||||
if (mDeps == null) {
|
||||
mDeps = new TetheringDependencies() {
|
||||
@Override
|
||||
public NetworkRequest getDefaultNetworkRequest() {
|
||||
ConnectivityManager cm = (ConnectivityManager) mContext.getSystemService(
|
||||
Context.CONNECTIVITY_SERVICE);
|
||||
return cm.getDefaultRequest();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Looper getTetheringLooper() {
|
||||
final HandlerThread tetherThread = new HandlerThread("android.tethering");
|
||||
tetherThread.start();
|
||||
return tetherThread.getLooper();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTetheringSupported() {
|
||||
int defaultVal =
|
||||
SystemProperties.get("ro.tether.denied").equals("true") ? 0 : 1;
|
||||
boolean tetherSupported = Settings.Global.getInt(mContext.getContentResolver(),
|
||||
Settings.Global.TETHER_SUPPORTED, defaultVal) != 0;
|
||||
return tetherSupported;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Context getContext() {
|
||||
return TetheringService.this;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return mDeps;
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,6 @@ android_test {
|
||||
name: "TetheringTests",
|
||||
certificate: "platform",
|
||||
srcs: [
|
||||
":servicescore-tethering-src",
|
||||
"src/**/*.java",
|
||||
],
|
||||
test_suites: ["device-tests"],
|
||||
@@ -41,17 +40,3 @@ android_test {
|
||||
"libstaticjvmtiagent",
|
||||
],
|
||||
}
|
||||
|
||||
// This group would be removed when tethering migration is done.
|
||||
filegroup {
|
||||
name: "tethering-tests-src",
|
||||
srcs: [
|
||||
"src/com/android/server/connectivity/tethering/EntitlementManagerTest.java",
|
||||
"src/com/android/server/connectivity/tethering/OffloadControllerTest.java",
|
||||
"src/com/android/server/connectivity/tethering/TetheringConfigurationTest.java",
|
||||
"src/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java",
|
||||
"src/android/net/dhcp/DhcpServingParamsParcelExtTest.java",
|
||||
"src/android/net/ip/IpServerTest.java",
|
||||
"src/android/net/util/InterfaceSetTest.java",
|
||||
],
|
||||
}
|
||||
|
||||
@@ -51,7 +51,9 @@ public class VersionedBroadcastListenerTest {
|
||||
private VersionedBroadcastListener mListener;
|
||||
private int mCallbackCount;
|
||||
|
||||
private void doCallback() { mCallbackCount++; }
|
||||
private void doCallback() {
|
||||
mCallbackCount++;
|
||||
}
|
||||
|
||||
private class MockContext extends BroadcastInterceptingContext {
|
||||
MockContext(Context base) {
|
||||
@@ -96,7 +98,7 @@ public class VersionedBroadcastListenerTest {
|
||||
mListener.startListening();
|
||||
for (int i = 0; i < 5; i++) {
|
||||
sendBroadcast();
|
||||
assertEquals(i+1, mCallbackCount);
|
||||
assertEquals(i + 1, mCallbackCount);
|
||||
}
|
||||
mListener.stopListening();
|
||||
}
|
||||
@@ -24,6 +24,9 @@ import static android.net.ConnectivityManager.TETHER_ERROR_NO_ERROR;
|
||||
import static android.net.ConnectivityManager.TETHER_ERROR_PROVISION_FAILED;
|
||||
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;
|
||||
@@ -44,6 +47,7 @@ import android.os.Bundle;
|
||||
import android.os.Message;
|
||||
import android.os.PersistableBundle;
|
||||
import android.os.ResultReceiver;
|
||||
import android.os.SystemProperties;
|
||||
import android.os.test.TestLooper;
|
||||
import android.provider.Settings;
|
||||
import android.telephony.CarrierConfigManager;
|
||||
@@ -57,7 +61,6 @@ import com.android.internal.util.State;
|
||||
import com.android.internal.util.StateMachine;
|
||||
import com.android.internal.util.test.BroadcastInterceptingContext;
|
||||
import com.android.internal.util.test.FakeSettingsProvider;
|
||||
import com.android.server.connectivity.MockableSystemProperties;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
@@ -65,6 +68,8 @@ import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.mockito.MockitoSession;
|
||||
import org.mockito.quality.Strictness;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
@@ -80,7 +85,6 @@ public final class EntitlementManagerTest {
|
||||
|
||||
@Mock private CarrierConfigManager mCarrierConfigManager;
|
||||
@Mock private Context mContext;
|
||||
@Mock private MockableSystemProperties mSystemProperties;
|
||||
@Mock private Resources mResources;
|
||||
@Mock private SharedLog mLog;
|
||||
@Mock private EntitlementManager.OnUiEntitlementFailedListener mEntitlementFailedListener;
|
||||
@@ -95,6 +99,7 @@ public final class EntitlementManagerTest {
|
||||
private TestStateMachine mSM;
|
||||
private WrappedEntitlementManager mEnMgr;
|
||||
private TetheringConfiguration mConfig;
|
||||
private MockitoSession mMockingSession;
|
||||
|
||||
private class MockContext extends BroadcastInterceptingContext {
|
||||
MockContext(Context base) {
|
||||
@@ -118,8 +123,8 @@ public final class EntitlementManagerTest {
|
||||
public int silentProvisionCount = 0;
|
||||
|
||||
public WrappedEntitlementManager(Context ctx, StateMachine target,
|
||||
SharedLog log, int what, MockableSystemProperties systemProperties) {
|
||||
super(ctx, target, log, what, systemProperties);
|
||||
SharedLog log, int what) {
|
||||
super(ctx, target, log, what);
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
@@ -144,6 +149,15 @@ public final class EntitlementManagerTest {
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mMockingSession = mockitoSession()
|
||||
.initMocks(this)
|
||||
.spyStatic(SystemProperties.class)
|
||||
.strictness(Strictness.WARN)
|
||||
.startMocking();
|
||||
// Don't disable tethering provisioning unless requested.
|
||||
doReturn(false).when(
|
||||
() -> SystemProperties.getBoolean(
|
||||
eq(EntitlementManager.DISABLE_PROVISIONING_SYSPROP_KEY), anyBoolean()));
|
||||
|
||||
when(mResources.getStringArray(R.array.config_tether_dhcp_range))
|
||||
.thenReturn(new String[0]);
|
||||
@@ -161,8 +175,7 @@ public final class EntitlementManagerTest {
|
||||
mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
|
||||
mMockContext = new MockContext(mContext);
|
||||
mSM = new TestStateMachine();
|
||||
mEnMgr = new WrappedEntitlementManager(mMockContext, mSM, mLog, EVENT_EM_UPDATE,
|
||||
mSystemProperties);
|
||||
mEnMgr = new WrappedEntitlementManager(mMockContext, mSM, mLog, EVENT_EM_UPDATE);
|
||||
mEnMgr.setOnUiEntitlementFailedListener(mEntitlementFailedListener);
|
||||
mConfig = new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
|
||||
mEnMgr.setTetheringConfigurationFetcher(() -> {
|
||||
@@ -176,6 +189,7 @@ public final class EntitlementManagerTest {
|
||||
mSM.quit();
|
||||
mSM = null;
|
||||
}
|
||||
mMockingSession.finishMocking();
|
||||
}
|
||||
|
||||
private void setupForRequiredProvisioning() {
|
||||
@@ -184,9 +198,6 @@ public final class EntitlementManagerTest {
|
||||
.thenReturn(PROVISIONING_APP_NAME);
|
||||
when(mResources.getString(R.string.config_mobile_hotspot_provision_app_no_ui))
|
||||
.thenReturn(PROVISIONING_NO_UI_APP_NAME);
|
||||
// Don't disable tethering provisioning unless requested.
|
||||
when(mSystemProperties.getBoolean(eq(EntitlementManager.DISABLE_PROVISIONING_SYSPROP_KEY),
|
||||
anyBoolean())).thenReturn(false);
|
||||
// Act like the CarrierConfigManager is present and ready unless told otherwise.
|
||||
when(mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE))
|
||||
.thenReturn(mCarrierConfigManager);
|
||||
@@ -244,7 +255,7 @@ public final class EntitlementManagerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetLastEntitlementCacheValue() throws Exception {
|
||||
public void testRequestLastEntitlementCacheValue() throws Exception {
|
||||
final CountDownLatch mCallbacklatch = new CountDownLatch(1);
|
||||
// 1. Entitlement check is not required.
|
||||
mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR;
|
||||
@@ -255,7 +266,7 @@ public final class EntitlementManagerTest {
|
||||
mCallbacklatch.countDown();
|
||||
}
|
||||
};
|
||||
mEnMgr.getLatestTetheringEntitlementResult(TETHERING_WIFI, receiver, true);
|
||||
mEnMgr.requestLatestTetheringEntitlementResult(TETHERING_WIFI, receiver, true);
|
||||
mLooper.dispatchAll();
|
||||
callbackTimeoutHelper(mCallbacklatch);
|
||||
assertEquals(0, mEnMgr.uiProvisionCount);
|
||||
@@ -270,7 +281,7 @@ public final class EntitlementManagerTest {
|
||||
mCallbacklatch.countDown();
|
||||
}
|
||||
};
|
||||
mEnMgr.getLatestTetheringEntitlementResult(TETHERING_WIFI, receiver, false);
|
||||
mEnMgr.requestLatestTetheringEntitlementResult(TETHERING_WIFI, receiver, false);
|
||||
mLooper.dispatchAll();
|
||||
callbackTimeoutHelper(mCallbacklatch);
|
||||
assertEquals(0, mEnMgr.uiProvisionCount);
|
||||
@@ -284,7 +295,7 @@ public final class EntitlementManagerTest {
|
||||
mCallbacklatch.countDown();
|
||||
}
|
||||
};
|
||||
mEnMgr.getLatestTetheringEntitlementResult(TETHERING_WIFI, receiver, true);
|
||||
mEnMgr.requestLatestTetheringEntitlementResult(TETHERING_WIFI, receiver, true);
|
||||
mLooper.dispatchAll();
|
||||
callbackTimeoutHelper(mCallbacklatch);
|
||||
assertEquals(1, mEnMgr.uiProvisionCount);
|
||||
@@ -298,7 +309,7 @@ public final class EntitlementManagerTest {
|
||||
mCallbacklatch.countDown();
|
||||
}
|
||||
};
|
||||
mEnMgr.getLatestTetheringEntitlementResult(TETHERING_WIFI, receiver, false);
|
||||
mEnMgr.requestLatestTetheringEntitlementResult(TETHERING_WIFI, receiver, false);
|
||||
mLooper.dispatchAll();
|
||||
callbackTimeoutHelper(mCallbacklatch);
|
||||
assertEquals(0, mEnMgr.uiProvisionCount);
|
||||
@@ -312,7 +323,7 @@ public final class EntitlementManagerTest {
|
||||
mCallbacklatch.countDown();
|
||||
}
|
||||
};
|
||||
mEnMgr.getLatestTetheringEntitlementResult(TETHERING_WIFI, receiver, true);
|
||||
mEnMgr.requestLatestTetheringEntitlementResult(TETHERING_WIFI, receiver, true);
|
||||
mLooper.dispatchAll();
|
||||
callbackTimeoutHelper(mCallbacklatch);
|
||||
assertEquals(1, mEnMgr.uiProvisionCount);
|
||||
@@ -326,7 +337,7 @@ public final class EntitlementManagerTest {
|
||||
mCallbacklatch.countDown();
|
||||
}
|
||||
};
|
||||
mEnMgr.getLatestTetheringEntitlementResult(TETHERING_WIFI, receiver, true);
|
||||
mEnMgr.requestLatestTetheringEntitlementResult(TETHERING_WIFI, receiver, true);
|
||||
mLooper.dispatchAll();
|
||||
callbackTimeoutHelper(mCallbacklatch);
|
||||
assertEquals(0, mEnMgr.uiProvisionCount);
|
||||
@@ -339,7 +350,7 @@ public final class EntitlementManagerTest {
|
||||
mCallbacklatch.countDown();
|
||||
}
|
||||
};
|
||||
mEnMgr.getLatestTetheringEntitlementResult(TETHERING_USB, receiver, false);
|
||||
mEnMgr.requestLatestTetheringEntitlementResult(TETHERING_USB, receiver, false);
|
||||
mLooper.dispatchAll();
|
||||
callbackTimeoutHelper(mCallbacklatch);
|
||||
assertEquals(0, mEnMgr.uiProvisionCount);
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.connectivity;
|
||||
package com.android.server.connectivity.tethering;
|
||||
|
||||
import static android.hardware.usb.UsbManager.USB_CONFIGURED;
|
||||
import static android.hardware.usb.UsbManager.USB_CONNECTED;
|
||||
@@ -39,7 +39,9 @@ import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLED;
|
||||
import static android.provider.Settings.Global.TETHER_ENABLE_LEGACY_DHCP_SERVER;
|
||||
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
|
||||
|
||||
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;
|
||||
@@ -70,7 +72,7 @@ import android.hardware.usb.UsbManager;
|
||||
import android.net.INetd;
|
||||
import android.net.INetworkPolicyManager;
|
||||
import android.net.INetworkStatsService;
|
||||
import android.net.ITetheringEventCallback;
|
||||
import android.net.ITetherInternalCallback;
|
||||
import android.net.InterfaceConfiguration;
|
||||
import android.net.IpPrefix;
|
||||
import android.net.LinkAddress;
|
||||
@@ -82,6 +84,8 @@ import android.net.NetworkInfo;
|
||||
import android.net.NetworkState;
|
||||
import android.net.NetworkUtils;
|
||||
import android.net.RouteInfo;
|
||||
import android.net.TetherStatesParcel;
|
||||
import android.net.TetheringConfigurationParcel;
|
||||
import android.net.dhcp.DhcpServerCallbacks;
|
||||
import android.net.dhcp.DhcpServingParamsParcel;
|
||||
import android.net.dhcp.IDhcpServer;
|
||||
@@ -98,6 +102,7 @@ import android.net.wifi.p2p.WifiP2pManager;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.INetworkManagementService;
|
||||
import android.os.Looper;
|
||||
import android.os.PersistableBundle;
|
||||
import android.os.RemoteException;
|
||||
import android.os.UserHandle;
|
||||
@@ -109,6 +114,7 @@ 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;
|
||||
|
||||
@@ -116,11 +122,6 @@ 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.server.connectivity.tethering.IPv6TetheringCoordinator;
|
||||
import com.android.server.connectivity.tethering.OffloadHardwareInterface;
|
||||
import com.android.server.connectivity.tethering.TetheringConfiguration;
|
||||
import com.android.server.connectivity.tethering.TetheringDependencies;
|
||||
import com.android.server.connectivity.tethering.UpstreamNetworkMonitor;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
@@ -154,7 +155,6 @@ public class TetheringTest {
|
||||
@Mock private INetworkManagementService mNMService;
|
||||
@Mock private INetworkStatsService mStatsService;
|
||||
@Mock private INetworkPolicyManager mPolicyManager;
|
||||
@Mock private MockableSystemProperties mSystemProperties;
|
||||
@Mock private OffloadHardwareInterface mOffloadHardwareInterface;
|
||||
@Mock private Resources mResources;
|
||||
@Mock private TelephonyManager mTelephonyManager;
|
||||
@@ -184,22 +184,30 @@ public class TetheringTest {
|
||||
private Tethering mTethering;
|
||||
private PhoneStateListener mPhoneStateListener;
|
||||
|
||||
private class MockContext extends BroadcastInterceptingContext {
|
||||
MockContext(Context base) {
|
||||
private class TestContext extends BroadcastInterceptingContext {
|
||||
TestContext(Context base) {
|
||||
super(base);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApplicationInfo getApplicationInfo() { return mApplicationInfo; }
|
||||
public ApplicationInfo getApplicationInfo() {
|
||||
return mApplicationInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContentResolver getContentResolver() { return mContentResolver; }
|
||||
public ContentResolver getContentResolver() {
|
||||
return mContentResolver;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPackageName() { return "TetheringTest"; }
|
||||
public String getPackageName() {
|
||||
return "TetheringTest";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Resources getResources() { return mResources; }
|
||||
public Resources getResources() {
|
||||
return mResources;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getSystemService(String name) {
|
||||
@@ -266,14 +274,14 @@ public class TetheringTest {
|
||||
}
|
||||
|
||||
public class MockTetheringDependencies extends TetheringDependencies {
|
||||
StateMachine upstreamNetworkMonitorMasterSM;
|
||||
ArrayList<IpServer> ipv6CoordinatorNotifyList;
|
||||
int isTetheringSupportedCalls;
|
||||
StateMachine mUpstreamNetworkMonitorMasterSM;
|
||||
ArrayList<IpServer> mIpv6CoordinatorNotifyList;
|
||||
int mIsTetheringSupportedCalls;
|
||||
|
||||
public void reset() {
|
||||
upstreamNetworkMonitorMasterSM = null;
|
||||
ipv6CoordinatorNotifyList = null;
|
||||
isTetheringSupportedCalls = 0;
|
||||
mUpstreamNetworkMonitorMasterSM = null;
|
||||
mIpv6CoordinatorNotifyList = null;
|
||||
mIsTetheringSupportedCalls = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -284,14 +292,14 @@ public class TetheringTest {
|
||||
@Override
|
||||
public UpstreamNetworkMonitor getUpstreamNetworkMonitor(Context ctx,
|
||||
StateMachine target, SharedLog log, int what) {
|
||||
upstreamNetworkMonitorMasterSM = target;
|
||||
mUpstreamNetworkMonitorMasterSM = target;
|
||||
return mUpstreamNetworkMonitor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPv6TetheringCoordinator getIPv6TetheringCoordinator(
|
||||
ArrayList<IpServer> notifyList, SharedLog log) {
|
||||
ipv6CoordinatorNotifyList = notifyList;
|
||||
mIpv6CoordinatorNotifyList = notifyList;
|
||||
return mIPv6TetheringCoordinator;
|
||||
}
|
||||
|
||||
@@ -302,7 +310,7 @@ public class TetheringTest {
|
||||
|
||||
@Override
|
||||
public boolean isTetheringSupported() {
|
||||
isTetheringSupportedCalls++;
|
||||
mIsTetheringSupportedCalls++;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -311,6 +319,36 @@ public class TetheringTest {
|
||||
int subId) {
|
||||
return new MockTetheringConfiguration(ctx, log, subId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public INetworkManagementService getINetworkManagementService() {
|
||||
return mNMService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public INetworkStatsService getINetworkStatsService() {
|
||||
return mStatsService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public INetworkPolicyManager getINetworkPolicyManager() {
|
||||
return mPolicyManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public INetd getINetd(Context context) {
|
||||
return mNetd;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Looper getTetheringLooper() {
|
||||
return mLooper.getLooper();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Context getContext() {
|
||||
return mServiceContext;
|
||||
}
|
||||
}
|
||||
|
||||
private static NetworkState buildMobileUpstreamState(boolean withIPv4, boolean withIPv6,
|
||||
@@ -345,7 +383,7 @@ public class TetheringTest {
|
||||
|
||||
|
||||
final NetworkCapabilities capabilities = new NetworkCapabilities()
|
||||
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);;
|
||||
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
|
||||
return new NetworkState(info, prop, capabilities, new Network(100), null, "netid");
|
||||
}
|
||||
|
||||
@@ -390,7 +428,7 @@ public class TetheringTest {
|
||||
when(mRouterAdvertisementDaemon.start())
|
||||
.thenReturn(true);
|
||||
|
||||
mServiceContext = new MockContext(mContext);
|
||||
mServiceContext = new TestContext(mContext);
|
||||
mContentResolver = new MockContentResolver(mServiceContext);
|
||||
mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
|
||||
Settings.Global.putInt(mContentResolver, TETHER_ENABLE_LEGACY_DHCP_SERVER, 0);
|
||||
@@ -403,9 +441,9 @@ public class TetheringTest {
|
||||
};
|
||||
mServiceContext.registerReceiver(mBroadcastReceiver,
|
||||
new IntentFilter(ACTION_TETHER_STATE_CHANGED));
|
||||
mTetheringDependencies.reset();
|
||||
mTethering = makeTethering();
|
||||
verify(mNMService).registerTetheringStatsProvider(any(), anyString());
|
||||
verify(mNetd).registerUnsolicitedEventListener(any());
|
||||
final ArgumentCaptor<PhoneStateListener> phoneListenerCaptor =
|
||||
ArgumentCaptor.forClass(PhoneStateListener.class);
|
||||
verify(mTelephonyManager).listen(phoneListenerCaptor.capture(),
|
||||
@@ -414,9 +452,8 @@ public class TetheringTest {
|
||||
}
|
||||
|
||||
private Tethering makeTethering() {
|
||||
return new Tethering(mServiceContext, mNMService, mStatsService, mPolicyManager,
|
||||
mLooper.getLooper(), mSystemProperties,
|
||||
mTetheringDependencies);
|
||||
mTetheringDependencies.reset();
|
||||
return new Tethering(mTetheringDependencies);
|
||||
}
|
||||
|
||||
@After
|
||||
@@ -507,7 +544,7 @@ public class TetheringTest {
|
||||
// it creates a IpServer and sends out a broadcast indicating that the
|
||||
// interface is "available".
|
||||
if (emulateInterfaceStatusChanged) {
|
||||
assertEquals(1, mTetheringDependencies.isTetheringSupportedCalls);
|
||||
assertEquals(1, mTetheringDependencies.mIsTetheringSupportedCalls);
|
||||
verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
|
||||
verify(mWifiManager).updateInterfaceIpState(
|
||||
TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_UNSPECIFIED);
|
||||
@@ -584,7 +621,7 @@ public class TetheringTest {
|
||||
verify(mUpstreamNetworkMonitor, times(1)).startObserveAllNetworks();
|
||||
// This will be called twice, one is on entering IpServer.STATE_AVAILABLE,
|
||||
// and another one is on IpServer.STATE_TETHERED/IpServer.STATE_LOCAL_ONLY.
|
||||
assertEquals(2, mTetheringDependencies.isTetheringSupportedCalls);
|
||||
assertEquals(2, mTetheringDependencies.mIsTetheringSupportedCalls);
|
||||
|
||||
// Emulate externally-visible WifiManager effects, when hotspot mode
|
||||
// is being torn down.
|
||||
@@ -617,8 +654,7 @@ public class TetheringTest {
|
||||
argThat(sm -> sm.linkProperties().getInterfaceName().equals(TEST_USB_IFNAME)),
|
||||
eq(IpServer.STATE_TETHERED));
|
||||
|
||||
for (IpServer ipSrv :
|
||||
mTetheringDependencies.ipv6CoordinatorNotifyList) {
|
||||
for (IpServer ipSrv : mTetheringDependencies.mIpv6CoordinatorNotifyList) {
|
||||
NetworkState ipv6OnlyState = buildMobileUpstreamState(false, true, false);
|
||||
ipSrv.sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, 0, 0,
|
||||
upstreamState.linkProperties.isIpv6Provisioned()
|
||||
@@ -650,7 +686,7 @@ public class TetheringTest {
|
||||
@Test
|
||||
public void workingMobileUsbTethering_IPv4LegacyDhcp() {
|
||||
Settings.Global.putInt(mContentResolver, TETHER_ENABLE_LEGACY_DHCP_SERVER, 1);
|
||||
mTethering = makeTethering();
|
||||
sendConfigurationChanged();
|
||||
final NetworkState upstreamState = buildMobileIPv4UpstreamState();
|
||||
runUsbTethering(upstreamState);
|
||||
sendIPv6TetherUpdates(upstreamState);
|
||||
@@ -719,7 +755,7 @@ public class TetheringTest {
|
||||
.thenReturn(upstreamState);
|
||||
|
||||
// Upstream LinkProperties changed: UpstreamNetworkMonitor sends EVENT_ON_LINKPROPERTIES.
|
||||
mTetheringDependencies.upstreamNetworkMonitorMasterSM.sendMessage(
|
||||
mTetheringDependencies.mUpstreamNetworkMonitorMasterSM.sendMessage(
|
||||
Tethering.TetherMasterSM.EVENT_UPSTREAM_CALLBACK,
|
||||
UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES,
|
||||
0,
|
||||
@@ -784,7 +820,7 @@ public class TetheringTest {
|
||||
sendWifiApStateChanged(WIFI_AP_STATE_ENABLED);
|
||||
mLooper.dispatchAll();
|
||||
|
||||
assertEquals(1, mTetheringDependencies.isTetheringSupportedCalls);
|
||||
assertEquals(1, mTetheringDependencies.mIsTetheringSupportedCalls);
|
||||
verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
|
||||
verify(mWifiManager).updateInterfaceIpState(
|
||||
TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_UNSPECIFIED);
|
||||
@@ -828,7 +864,7 @@ public class TetheringTest {
|
||||
verify(mUpstreamNetworkMonitor, times(1)).registerMobileNetworkRequest();
|
||||
// This will be called twice, one is on entering IpServer.STATE_AVAILABLE,
|
||||
// and another one is on IpServer.STATE_TETHERED/IpServer.STATE_LOCAL_ONLY.
|
||||
assertEquals(2, mTetheringDependencies.isTetheringSupportedCalls);
|
||||
assertEquals(2, mTetheringDependencies.mIsTetheringSupportedCalls);
|
||||
|
||||
/////
|
||||
// We do not currently emulate any upstream being found.
|
||||
@@ -901,7 +937,7 @@ public class TetheringTest {
|
||||
TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_TETHERED);
|
||||
// There are 3 state change event:
|
||||
// AVAILABLE -> STATE_TETHERED -> STATE_AVAILABLE.
|
||||
assertEquals(3, mTetheringDependencies.isTetheringSupportedCalls);
|
||||
assertEquals(3, mTetheringDependencies.mIsTetheringSupportedCalls);
|
||||
verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
|
||||
// This is called, but will throw.
|
||||
verify(mNMService, times(1)).setIpForwardingEnabled(true);
|
||||
@@ -919,8 +955,8 @@ public class TetheringTest {
|
||||
}
|
||||
|
||||
private void userRestrictionsListenerBehaviour(
|
||||
boolean currentDisallow, boolean nextDisallow, String[] activeTetheringIfacesList,
|
||||
int expectedInteractionsWithShowNotification) throws Exception {
|
||||
boolean currentDisallow, boolean nextDisallow, String[] activeTetheringIfacesList,
|
||||
int expectedInteractionsWithShowNotification) throws Exception {
|
||||
final int userId = 0;
|
||||
final Bundle currRestrictions = new Bundle();
|
||||
final Bundle newRestrictions = new Bundle();
|
||||
@@ -1001,17 +1037,49 @@ public class TetheringTest {
|
||||
expectedInteractionsWithShowNotification);
|
||||
}
|
||||
|
||||
private class TestTetheringEventCallback extends ITetheringEventCallback.Stub {
|
||||
private class TestTetherInternalCallback extends ITetherInternalCallback.Stub {
|
||||
private final ArrayList<Network> mActualUpstreams = new ArrayList<>();
|
||||
private final ArrayList<TetheringConfigurationParcel> mTetheringConfigs =
|
||||
new ArrayList<>();
|
||||
private final ArrayList<TetherStatesParcel> mTetherStates = 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);
|
||||
}
|
||||
assertNoCallback();
|
||||
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 TetherStatesParcel pollTetherStatesChanged() {
|
||||
assertStateChangeCallback();
|
||||
return mTetherStates.remove(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1019,48 +1087,93 @@ public class TetheringTest {
|
||||
mActualUpstreams.add(network);
|
||||
}
|
||||
|
||||
public void assertNoCallback() {
|
||||
@Override
|
||||
public void onConfigurationChanged(TetheringConfigurationParcel config) {
|
||||
mTetheringConfigs.add(config);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTetherStatesChanged(TetherStatesParcel states) {
|
||||
mTetherStates.add(states);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCallbackCreated(Network network, TetheringConfigurationParcel config,
|
||||
TetherStatesParcel states) {
|
||||
mActualUpstreams.add(network);
|
||||
mTetheringConfigs.add(config);
|
||||
mTetherStates.add(states);
|
||||
}
|
||||
|
||||
public void assertNoUpstreamChangeCallback() {
|
||||
assertTrue(mActualUpstreams.isEmpty());
|
||||
}
|
||||
|
||||
public void assertNoConfigChangeCallback() {
|
||||
assertTrue(mTetheringConfigs.isEmpty());
|
||||
}
|
||||
|
||||
public void assertStateChangeCallback() {
|
||||
assertFalse(mTetherStates.isEmpty());
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegisterTetheringEventCallback() throws Exception {
|
||||
TestTetheringEventCallback callback1 = new TestTetheringEventCallback();
|
||||
TestTetheringEventCallback callback2 = new TestTetheringEventCallback();
|
||||
public void testRegisterTetherInternalCallback() throws Exception {
|
||||
TestTetherInternalCallback callback = new TestTetherInternalCallback();
|
||||
|
||||
// 1. Register one callback and run usb tethering.
|
||||
mTethering.registerTetheringEventCallback(callback1);
|
||||
// 1. Register one callback before running any tethering.
|
||||
mTethering.registerTetherInternalCallback(callback);
|
||||
mLooper.dispatchAll();
|
||||
callback1.expectUpstreamChanged(new Network[] {null});
|
||||
callback.expectUpstreamChanged(new Network[] {null});
|
||||
callback.expectConfigurationChanged(
|
||||
mTethering.getTetheringConfiguration().toStableParcelable());
|
||||
TetherStatesParcel tetherState = callback.pollTetherStatesChanged();
|
||||
assertEquals(tetherState, null);
|
||||
// 2. Enable wifi tethering
|
||||
NetworkState upstreamState = buildMobileDualStackUpstreamState();
|
||||
runUsbTethering(upstreamState);
|
||||
callback1.expectUpstreamChanged(upstreamState.network);
|
||||
// 2. Register second callback.
|
||||
mTethering.registerTetheringEventCallback(callback2);
|
||||
mLooper.dispatchAll();
|
||||
callback2.expectUpstreamChanged(upstreamState.network);
|
||||
// 3. Disable usb tethering.
|
||||
mTethering.stopTethering(TETHERING_USB);
|
||||
mLooper.dispatchAll();
|
||||
sendUsbBroadcast(false, false, false);
|
||||
mLooper.dispatchAll();
|
||||
callback1.expectUpstreamChanged(new Network[] {null});
|
||||
callback2.expectUpstreamChanged(new Network[] {null});
|
||||
// 4. Unregister first callback and run hotspot.
|
||||
mTethering.unregisterTetheringEventCallback(callback1);
|
||||
mLooper.dispatchAll();
|
||||
when(mUpstreamNetworkMonitor.getCurrentPreferredUpstream()).thenReturn(upstreamState);
|
||||
when(mUpstreamNetworkMonitor.selectPreferredUpstreamType(any()))
|
||||
.thenReturn(upstreamState);
|
||||
when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true);
|
||||
mTethering.startTethering(TETHERING_WIFI, null, false);
|
||||
mLooper.dispatchAll();
|
||||
mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
|
||||
mLooper.dispatchAll();
|
||||
tetherState = callback.pollTetherStatesChanged();
|
||||
assertArrayEquals(tetherState.availableList, new String[] {TEST_WLAN_IFNAME});
|
||||
|
||||
mTethering.startTethering(TETHERING_WIFI, null, false);
|
||||
sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_TETHERED);
|
||||
mLooper.dispatchAll();
|
||||
callback1.assertNoCallback();
|
||||
callback2.expectUpstreamChanged(upstreamState.network);
|
||||
tetherState = callback.pollTetherStatesChanged();
|
||||
assertArrayEquals(tetherState.tetheredList, new String[] {TEST_WLAN_IFNAME});
|
||||
callback.expectUpstreamChanged(upstreamState.network);
|
||||
|
||||
// 3. Disable wifi tethering.
|
||||
mTethering.stopTethering(TETHERING_WIFI);
|
||||
sendWifiApStateChanged(WifiManager.WIFI_AP_STATE_DISABLED);
|
||||
mLooper.dispatchAll();
|
||||
tetherState = callback.pollTetherStatesChanged();
|
||||
assertArrayEquals(tetherState.availableList, new String[] {TEST_WLAN_IFNAME});
|
||||
mLooper.dispatchAll();
|
||||
callback.expectUpstreamChanged(new Network[] {null});
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1091,7 +1204,7 @@ public class TetheringTest {
|
||||
verify(mUpstreamNetworkMonitor, times(1)).startObserveAllNetworks();
|
||||
// This will be called twice, one is on entering IpServer.STATE_AVAILABLE,
|
||||
// and another one is on IpServer.STATE_TETHERED/IpServer.STATE_LOCAL_ONLY.
|
||||
assertEquals(2, mTetheringDependencies.isTetheringSupportedCalls);
|
||||
assertEquals(2, mTetheringDependencies.mIsTetheringSupportedCalls);
|
||||
|
||||
assertEquals(TETHER_ERROR_NO_ERROR, mTethering.getLastTetherError(TEST_P2P_IFNAME));
|
||||
|
||||
@@ -20,7 +20,6 @@ java_library_static {
|
||||
":vold_aidl",
|
||||
":gsiservice_aidl",
|
||||
":platform-compat-config",
|
||||
":tethering-servicescore-srcs",
|
||||
"java/com/android/server/EventLogTags.logtags",
|
||||
"java/com/android/server/am/EventLogTags.logtags",
|
||||
"java/com/android/server/policy/EventLogTags.logtags",
|
||||
@@ -81,11 +80,3 @@ prebuilt_etc {
|
||||
name: "gps_debug.conf",
|
||||
src: "java/com/android/server/location/gps_debug.conf",
|
||||
}
|
||||
|
||||
// TODO: this should be removed after tethering migration done.
|
||||
filegroup {
|
||||
name: "servicescore-tethering-src",
|
||||
srcs: [
|
||||
"java/com/android/server/connectivity/MockableSystemProperties.java",
|
||||
],
|
||||
}
|
||||
|
||||
@@ -108,6 +108,7 @@ import android.net.PrivateDnsConfigParcel;
|
||||
import android.net.ProxyInfo;
|
||||
import android.net.RouteInfo;
|
||||
import android.net.SocketKeepalive;
|
||||
import android.net.TetheringManager;
|
||||
import android.net.UidRange;
|
||||
import android.net.Uri;
|
||||
import android.net.VpnService;
|
||||
@@ -187,9 +188,7 @@ import com.android.server.connectivity.NetworkNotificationManager;
|
||||
import com.android.server.connectivity.NetworkNotificationManager.NotificationType;
|
||||
import com.android.server.connectivity.PermissionMonitor;
|
||||
import com.android.server.connectivity.ProxyTracker;
|
||||
import com.android.server.connectivity.Tethering;
|
||||
import com.android.server.connectivity.Vpn;
|
||||
import com.android.server.connectivity.tethering.TetheringDependencies;
|
||||
import com.android.server.net.BaseNetdEventCallback;
|
||||
import com.android.server.net.BaseNetworkObserver;
|
||||
import com.android.server.net.LockdownVpnTracker;
|
||||
@@ -233,7 +232,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
|
||||
private static final String DIAG_ARG = "--diag";
|
||||
public static final String SHORT_ARG = "--short";
|
||||
private static final String TETHERING_ARG = "tethering";
|
||||
private static final String NETWORK_ARG = "networks";
|
||||
private static final String REQUEST_ARG = "requests";
|
||||
|
||||
@@ -280,7 +278,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
|
||||
private MockableSystemProperties mSystemProperties;
|
||||
|
||||
private Tethering mTethering;
|
||||
private TetheringManager mTetheringManager;
|
||||
|
||||
@VisibleForTesting
|
||||
protected final PermissionMonitor mPermissionMonitor;
|
||||
@@ -869,15 +867,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Tethering
|
||||
* Get a reference to the TetheringManager.
|
||||
*/
|
||||
public Tethering makeTethering(@NonNull Context context,
|
||||
@NonNull INetworkManagementService nms,
|
||||
@NonNull INetworkStatsService statsService,
|
||||
@NonNull INetworkPolicyManager policyManager,
|
||||
@NonNull TetheringDependencies tetheringDeps) {
|
||||
return new Tethering(context, nms, statsService, policyManager,
|
||||
IoThread.get().getLooper(), getSystemProperties(), tetheringDeps);
|
||||
public TetheringManager getTetheringManager() {
|
||||
return TetheringManager.getInstance();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1075,8 +1068,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
|
||||
mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
|
||||
|
||||
mTethering = deps.makeTethering(mContext, mNMS, mStatsService, mPolicyManager,
|
||||
makeTetheringDependencies());
|
||||
mTetheringManager = mDeps.getTetheringManager();
|
||||
|
||||
mPermissionMonitor = new PermissionMonitor(mContext, mNetd);
|
||||
|
||||
@@ -1111,7 +1103,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
mHandler);
|
||||
|
||||
try {
|
||||
mNMS.registerObserver(mTethering);
|
||||
mNMS.registerObserver(mDataActivityObserver);
|
||||
} catch (RemoteException e) {
|
||||
loge("Error registering observer :" + e);
|
||||
@@ -1145,19 +1136,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
registerPrivateDnsSettingsCallbacks();
|
||||
}
|
||||
|
||||
private TetheringDependencies makeTetheringDependencies() {
|
||||
return new TetheringDependencies() {
|
||||
@Override
|
||||
public boolean isTetheringSupported() {
|
||||
return ConnectivityService.this.isTetheringSupported();
|
||||
}
|
||||
@Override
|
||||
public NetworkRequest getDefaultNetworkRequest() {
|
||||
return mDefaultRequest;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static NetworkCapabilities createDefaultNetworkCapabilitiesForUid(int uid) {
|
||||
final NetworkCapabilities netCap = new NetworkCapabilities();
|
||||
netCap.addCapability(NET_CAPABILITY_INTERNET);
|
||||
@@ -1909,7 +1887,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
// TODO: relocate this specific callback in Tethering.
|
||||
if (restrictBackground) {
|
||||
log("onRestrictBackgroundChanged(true): disabling tethering");
|
||||
mTethering.untetherAll();
|
||||
mTetheringManager.stopTethering(ConnectivityManager.TETHERING_WIFI);
|
||||
mTetheringManager.stopTethering(ConnectivityManager.TETHERING_USB);
|
||||
mTetheringManager.stopTethering(ConnectivityManager.TETHERING_BLUETOOTH);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -2193,7 +2173,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
mPermissionMonitor.startMonitoring();
|
||||
mProxyTracker.loadGlobalProxy();
|
||||
registerNetdEventCallback();
|
||||
mTethering.systemReady();
|
||||
|
||||
synchronized (this) {
|
||||
mSystemReady = true;
|
||||
@@ -2405,9 +2384,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
if (ArrayUtils.contains(args, DIAG_ARG)) {
|
||||
dumpNetworkDiagnostics(pw);
|
||||
return;
|
||||
} else if (ArrayUtils.contains(args, TETHERING_ARG)) {
|
||||
mTethering.dump(fd, pw, args);
|
||||
return;
|
||||
} else if (ArrayUtils.contains(args, NETWORK_ARG)) {
|
||||
dumpNetworks(pw);
|
||||
return;
|
||||
@@ -2469,10 +2445,13 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
mLegacyTypeTracker.dump(pw);
|
||||
|
||||
pw.println();
|
||||
mTethering.dump(fd, pw, args);
|
||||
mKeepaliveTracker.dump(pw);
|
||||
|
||||
pw.println();
|
||||
mKeepaliveTracker.dump(pw);
|
||||
pw.println("TetheringManager logs:");
|
||||
pw.increaseIndent();
|
||||
TetheringManager.getInstance().dump(pw);
|
||||
pw.decreaseIndent();
|
||||
|
||||
pw.println();
|
||||
dumpAvoidBadWifiSettings(pw);
|
||||
@@ -4004,7 +3983,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
public int tether(String iface, String callerPkg) {
|
||||
ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
|
||||
if (isTetheringSupported()) {
|
||||
return mTethering.tether(iface);
|
||||
return mTetheringManager.tether(iface);
|
||||
} else {
|
||||
return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
|
||||
}
|
||||
@@ -4016,7 +3995,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
|
||||
|
||||
if (isTetheringSupported()) {
|
||||
return mTethering.untether(iface);
|
||||
return mTetheringManager.untether(iface);
|
||||
} else {
|
||||
return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
|
||||
}
|
||||
@@ -4028,7 +4007,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
enforceTetherAccessPermission();
|
||||
|
||||
if (isTetheringSupported()) {
|
||||
return mTethering.getLastTetherError(iface);
|
||||
return mTetheringManager.getLastTetherError(iface);
|
||||
} else {
|
||||
return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
|
||||
}
|
||||
@@ -4039,7 +4018,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
public String[] getTetherableUsbRegexs() {
|
||||
enforceTetherAccessPermission();
|
||||
if (isTetheringSupported()) {
|
||||
return mTethering.getTetherableUsbRegexs();
|
||||
return mTetheringManager.getTetherableUsbRegexs();
|
||||
} else {
|
||||
return new String[0];
|
||||
}
|
||||
@@ -4049,7 +4028,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
public String[] getTetherableWifiRegexs() {
|
||||
enforceTetherAccessPermission();
|
||||
if (isTetheringSupported()) {
|
||||
return mTethering.getTetherableWifiRegexs();
|
||||
return mTetheringManager.getTetherableWifiRegexs();
|
||||
} else {
|
||||
return new String[0];
|
||||
}
|
||||
@@ -4059,7 +4038,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
public String[] getTetherableBluetoothRegexs() {
|
||||
enforceTetherAccessPermission();
|
||||
if (isTetheringSupported()) {
|
||||
return mTethering.getTetherableBluetoothRegexs();
|
||||
return mTetheringManager.getTetherableBluetoothRegexs();
|
||||
} else {
|
||||
return new String[0];
|
||||
}
|
||||
@@ -4069,7 +4048,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
public int setUsbTethering(boolean enable, String callerPkg) {
|
||||
ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
|
||||
if (isTetheringSupported()) {
|
||||
return mTethering.setUsbTethering(enable);
|
||||
return mTetheringManager.setUsbTethering(enable);
|
||||
} else {
|
||||
return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
|
||||
}
|
||||
@@ -4080,25 +4059,25 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
@Override
|
||||
public String[] getTetherableIfaces() {
|
||||
enforceTetherAccessPermission();
|
||||
return mTethering.getTetherableIfaces();
|
||||
return mTetheringManager.getTetherableIfaces();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getTetheredIfaces() {
|
||||
enforceTetherAccessPermission();
|
||||
return mTethering.getTetheredIfaces();
|
||||
return mTetheringManager.getTetheredIfaces();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getTetheringErroredIfaces() {
|
||||
enforceTetherAccessPermission();
|
||||
return mTethering.getErroredIfaces();
|
||||
return mTetheringManager.getTetheringErroredIfaces();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getTetheredDhcpRanges() {
|
||||
enforceConnectivityInternalPermission();
|
||||
return mTethering.getTetheredDhcpRanges();
|
||||
return mTetheringManager.getTetheredDhcpRanges();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -4126,7 +4105,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
Binder.restoreCallingIdentity(token);
|
||||
}
|
||||
|
||||
return tetherEnabledInSettings && adminUser && mTethering.hasTetherableConfiguration();
|
||||
return tetherEnabledInSettings && adminUser
|
||||
&& mTetheringManager.hasTetherableConfiguration();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -4137,13 +4117,13 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
receiver.send(ConnectivityManager.TETHER_ERROR_UNSUPPORTED, null);
|
||||
return;
|
||||
}
|
||||
mTethering.startTethering(type, receiver, showProvisioningUi);
|
||||
mTetheringManager.startTethering(type, receiver, showProvisioningUi);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopTethering(int type, String callerPkg) {
|
||||
ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
|
||||
mTethering.stopTethering(type);
|
||||
mTetheringManager.stopTethering(type);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -4157,7 +4137,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
public void getLatestTetheringEntitlementResult(int type, ResultReceiver receiver,
|
||||
boolean showEntitlementUi, String callerPkg) {
|
||||
ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
|
||||
mTethering.getLatestTetheringEntitlementResult(type, receiver, showEntitlementUi);
|
||||
mTetheringManager.requestLatestTetheringEntitlementResult(
|
||||
type, receiver, showEntitlementUi);
|
||||
}
|
||||
|
||||
/** Register tethering event callback. */
|
||||
@@ -4165,7 +4146,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
public void registerTetheringEventCallback(ITetheringEventCallback callback,
|
||||
String callerPkg) {
|
||||
ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
|
||||
mTethering.registerTetheringEventCallback(callback);
|
||||
mTetheringManager.registerTetheringEventCallback(callback);
|
||||
}
|
||||
|
||||
/** Unregister tethering event callback. */
|
||||
@@ -4173,7 +4154,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
public void unregisterTetheringEventCallback(ITetheringEventCallback callback,
|
||||
String callerPkg) {
|
||||
ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
|
||||
mTethering.unregisterTetheringEventCallback(callback);
|
||||
mTetheringManager.unregisterTetheringEventCallback(callback);
|
||||
}
|
||||
|
||||
// Called when we lose the default network and have no replacement yet.
|
||||
|
||||
@@ -138,7 +138,6 @@ import com.android.internal.util.FileRotator;
|
||||
import com.android.internal.util.IndentingPrintWriter;
|
||||
import com.android.server.EventLogTags;
|
||||
import com.android.server.LocalServices;
|
||||
import com.android.server.connectivity.Tethering;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileDescriptor;
|
||||
|
||||
@@ -53,7 +53,6 @@ cc_library_static {
|
||||
"com_android_server_am_LowMemDetector.cpp",
|
||||
"onload.cpp",
|
||||
":lib_networkStatsFactory_native",
|
||||
":tethering-jni-srcs",
|
||||
],
|
||||
|
||||
include_dirs: [
|
||||
@@ -122,7 +121,6 @@ cc_defaults {
|
||||
"android.hardware.power@1.0",
|
||||
"android.hardware.power@1.1",
|
||||
"android.hardware.power.stats@1.0",
|
||||
"android.hardware.tetheroffload.config@1.0",
|
||||
"android.hardware.thermal@1.0",
|
||||
"android.hardware.tv.cec@1.0",
|
||||
"android.hardware.tv.input@1.0",
|
||||
|
||||
@@ -40,7 +40,6 @@ int register_android_server_vr_VrManagerService(JNIEnv* env);
|
||||
int register_android_server_VibratorService(JNIEnv* env);
|
||||
int register_android_server_location_GnssLocationProvider(JNIEnv* env);
|
||||
int register_android_server_connectivity_Vpn(JNIEnv* env);
|
||||
int register_android_server_connectivity_tethering_OffloadHardwareInterface(JNIEnv*);
|
||||
int register_android_server_TestNetworkService(JNIEnv* env);
|
||||
int register_android_server_devicepolicy_CryptoTestHelper(JNIEnv*);
|
||||
int register_android_server_hdmi_HdmiCecController(JNIEnv* env);
|
||||
@@ -88,7 +87,6 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
|
||||
register_android_server_SystemServer(env);
|
||||
register_android_server_location_GnssLocationProvider(env);
|
||||
register_android_server_connectivity_Vpn(env);
|
||||
register_android_server_connectivity_tethering_OffloadHardwareInterface(env);
|
||||
register_android_server_TestNetworkService(env);
|
||||
register_android_server_devicepolicy_CryptoTestHelper(env);
|
||||
register_android_server_ConsumerIrService(env);
|
||||
|
||||
@@ -42,6 +42,7 @@ import android.hardware.display.DisplayManagerInternal;
|
||||
import android.net.ConnectivityModuleConnector;
|
||||
import android.net.Network;
|
||||
import android.net.NetworkStackClient;
|
||||
import android.net.TetheringManager;
|
||||
import android.os.BaseBundle;
|
||||
import android.os.Binder;
|
||||
import android.os.Build;
|
||||
@@ -2187,6 +2188,15 @@ public final class SystemServer {
|
||||
}
|
||||
traceEnd();
|
||||
|
||||
traceBeginAndSlog("StartTethering");
|
||||
try {
|
||||
// Tethering must start after ConnectivityService and NetworkStack.
|
||||
TetheringManager.getInstance().start();
|
||||
} catch (Throwable e) {
|
||||
reportWtf("starting Tethering", e);
|
||||
}
|
||||
traceEnd();
|
||||
|
||||
traceBeginAndSlog("MakeLocationServiceReady");
|
||||
try {
|
||||
if (locationF != null) {
|
||||
|
||||
@@ -2,8 +2,8 @@ java_library_static {
|
||||
name: "services.net",
|
||||
srcs: [
|
||||
":net-module-utils-srcs",
|
||||
":tethering-servicesnet-srcs",
|
||||
"java/**/*.java",
|
||||
":tethering-manager",
|
||||
],
|
||||
static_libs: [
|
||||
"dnsresolver_aidl_interface-V2-java",
|
||||
|
||||
@@ -45,7 +45,6 @@ android_test {
|
||||
name: "FrameworksNetTests",
|
||||
defaults: ["FrameworksNetTests-jni-defaults"],
|
||||
srcs: [
|
||||
":tethering-tests-src",
|
||||
"java/**/*.java",
|
||||
"java/**/*.kt",
|
||||
],
|
||||
|
||||
@@ -32,6 +32,7 @@ import android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET
|
||||
import android.net.NetworkCapabilities.TRANSPORT_CELLULAR
|
||||
import android.net.NetworkRequest
|
||||
import android.net.TestNetworkStackClient
|
||||
import android.net.TetheringManager
|
||||
import android.net.metrics.IpConnectivityLog
|
||||
import android.os.ConditionVariable
|
||||
import android.os.IBinder
|
||||
@@ -48,7 +49,6 @@ import com.android.server.connectivity.DefaultNetworkMetrics
|
||||
import com.android.server.connectivity.IpConnectivityMetrics
|
||||
import com.android.server.connectivity.MockableSystemProperties
|
||||
import com.android.server.connectivity.ProxyTracker
|
||||
import com.android.server.connectivity.Tethering
|
||||
import com.android.server.net.NetworkPolicyManagerInternal
|
||||
import com.android.testutils.TestableNetworkCallback
|
||||
import org.junit.After
|
||||
@@ -169,8 +169,7 @@ class ConnectivityServiceIntegrationTest {
|
||||
val deps = spy(ConnectivityService.Dependencies())
|
||||
doReturn(networkStackClient).`when`(deps).networkStack
|
||||
doReturn(metricsLogger).`when`(deps).metricsLogger
|
||||
doReturn(mock(Tethering::class.java)).`when`(deps).makeTethering(
|
||||
any(), any(), any(), any(), any())
|
||||
doReturn(mock(TetheringManager::class.java)).`when`(deps).getTetheringManager()
|
||||
doReturn(mock(ProxyTracker::class.java)).`when`(deps).makeProxyTracker(any(), any())
|
||||
doReturn(mock(MockableSystemProperties::class.java)).`when`(deps).systemProperties
|
||||
doReturn(TestNetIdManager()).`when`(deps).makeNetIdManager()
|
||||
|
||||
@@ -163,6 +163,7 @@ import android.net.ProxyInfo;
|
||||
import android.net.ResolverParamsParcel;
|
||||
import android.net.RouteInfo;
|
||||
import android.net.SocketKeepalive;
|
||||
import android.net.TetheringManager;
|
||||
import android.net.UidRange;
|
||||
import android.net.metrics.IpConnectivityLog;
|
||||
import android.net.shared.NetworkMonitorUtils;
|
||||
@@ -210,7 +211,6 @@ import com.android.server.connectivity.MockableSystemProperties;
|
||||
import com.android.server.connectivity.Nat464Xlat;
|
||||
import com.android.server.connectivity.NetworkNotificationManager.NotificationType;
|
||||
import com.android.server.connectivity.ProxyTracker;
|
||||
import com.android.server.connectivity.Tethering;
|
||||
import com.android.server.connectivity.Vpn;
|
||||
import com.android.server.net.NetworkPinner;
|
||||
import com.android.server.net.NetworkPolicyManagerInternal;
|
||||
@@ -1130,7 +1130,7 @@ public class ConnectivityServiceTest {
|
||||
doReturn(new TestNetIdManager()).when(deps).makeNetIdManager();
|
||||
doReturn(mNetworkStack).when(deps).getNetworkStack();
|
||||
doReturn(systemProperties).when(deps).getSystemProperties();
|
||||
doReturn(mock(Tethering.class)).when(deps).makeTethering(any(), any(), any(), any(), any());
|
||||
doReturn(mock(TetheringManager.class)).when(deps).getTetheringManager();
|
||||
doReturn(mock(ProxyTracker.class)).when(deps).makeProxyTracker(any(), any());
|
||||
doReturn(mMetricsService).when(deps).getMetricsLogger();
|
||||
doReturn(true).when(deps).queryUserAccess(anyInt(), anyInt());
|
||||
|
||||
Reference in New Issue
Block a user