diff options
35 files changed, 1503 insertions, 364 deletions
diff --git a/core/java/android/os/ResultReceiver.aidl b/core/java/android/os/ResultReceiver.aidl index 28ce6d5f15b0..1ea6b43043d6 100644 --- a/core/java/android/os/ResultReceiver.aidl +++ b/core/java/android/os/ResultReceiver.aidl @@ -17,4 +17,4 @@ package android.os; -parcelable ResultReceiver; +@JavaOnlyStableParcelable parcelable ResultReceiver; diff --git a/packages/Tethering/Android.bp b/packages/Tethering/Android.bp index cd51f5f90c34..7e8721d3cc70 100644 --- a/packages/Tethering/Android.bp +++ b/packages/Tethering/Android.bp @@ -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", - ], -} diff --git a/packages/Tethering/AndroidManifest.xml b/packages/Tethering/AndroidManifest.xml index eb51593e4538..1430ed00aa91 100644 --- a/packages/Tethering/AndroidManifest.xml +++ b/packages/Tethering/AndroidManifest.xml @@ -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> diff --git a/packages/Tethering/AndroidManifest_InProcess.xml b/packages/Tethering/AndroidManifest_InProcess.xml new file mode 100644 index 000000000000..28d405c3133a --- /dev/null +++ b/packages/Tethering/AndroidManifest_InProcess.xml @@ -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> diff --git a/packages/Tethering/common/TetheringLib/Android.bp b/packages/Tethering/common/TetheringLib/Android.bp index 5b01b1e038c3..adc5a723a960 100644 --- a/packages/Tethering/common/TetheringLib/Android.bp +++ b/packages/Tethering/common/TetheringLib/Android.bp @@ -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"], +} diff --git a/packages/Tethering/common/TetheringLib/src/android/net/ITetherInternalCallback.aidl b/packages/Tethering/common/TetheringLib/src/android/net/ITetherInternalCallback.aidl new file mode 100644 index 000000000000..abb00e819f50 --- /dev/null +++ b/packages/Tethering/common/TetheringLib/src/android/net/ITetherInternalCallback.aidl @@ -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); +} diff --git a/packages/Tethering/common/TetheringLib/src/android/net/ITetheringConnector.aidl b/packages/Tethering/common/TetheringLib/src/android/net/ITetheringConnector.aidl index 443481e33f8d..bfe502fbeb11 100644 --- a/packages/Tethering/common/TetheringLib/src/android/net/ITetheringConnector.aidl +++ b/packages/Tethering/common/TetheringLib/src/android/net/ITetheringConnector.aidl @@ -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); } diff --git a/packages/Tethering/common/TetheringLib/src/android/net/TetherStatesParcel.aidl b/packages/Tethering/common/TetheringLib/src/android/net/TetherStatesParcel.aidl new file mode 100644 index 000000000000..3d842b337428 --- /dev/null +++ b/packages/Tethering/common/TetheringLib/src/android/net/TetherStatesParcel.aidl @@ -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; +} diff --git a/packages/Tethering/common/TetheringLib/src/android/net/TetheringConfigurationParcel.aidl b/packages/Tethering/common/TetheringLib/src/android/net/TetheringConfigurationParcel.aidl new file mode 100644 index 000000000000..fdf0d16057b3 --- /dev/null +++ b/packages/Tethering/common/TetheringLib/src/android/net/TetheringConfigurationParcel.aidl @@ -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; +} diff --git a/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java b/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java new file mode 100644 index 000000000000..9e8726edf0e1 --- /dev/null +++ b/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java @@ -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(); + } +} diff --git a/packages/Tethering/jni/com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp b/packages/Tethering/jni/com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp index 3eaf48845a2f..663154a49048 100644 --- a/packages/Tethering/jni/com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp +++ b/packages/Tethering/jni/com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp @@ -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 diff --git a/packages/Tethering/src/android/net/util/BaseNetdUnsolicitedEventListener.java b/packages/Tethering/src/android/net/util/BaseNetdUnsolicitedEventListener.java new file mode 100644 index 000000000000..3218c0b387bb --- /dev/null +++ b/packages/Tethering/src/android/net/util/BaseNetdUnsolicitedEventListener.java @@ -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; + } +} diff --git a/services/net/java/android/net/util/VersionedBroadcastListener.java b/packages/Tethering/src/android/net/util/VersionedBroadcastListener.java index 107c40495f9e..e2804abd752b 100644 --- a/services/net/java/android/net/util/VersionedBroadcastListener.java +++ b/packages/Tethering/src/android/net/util/VersionedBroadcastListener.java @@ -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; diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/EntitlementManager.java b/packages/Tethering/src/com/android/server/connectivity/tethering/EntitlementManager.java index 6b0f1de7ce85..ba5d08dce4ca 100644 --- a/packages/Tethering/src/com/android/server/connectivity/tethering/EntitlementManager.java +++ b/packages/Tethering/src/com/android/server/connectivity/tethering/EntitlementManager.java @@ -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); diff --git a/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringCoordinator.java b/packages/Tethering/src/com/android/server/connectivity/tethering/IPv6TetheringCoordinator.java index 81863439c017..edfe3cad9039 100644 --- a/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringCoordinator.java +++ b/packages/Tethering/src/com/android/server/connectivity/tethering/IPv6TetheringCoordinator.java @@ -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) { diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/OffloadHardwareInterface.java b/packages/Tethering/src/com/android/server/connectivity/tethering/OffloadHardwareInterface.java index 01339a4a2c33..00a677338b1b 100644 --- a/packages/Tethering/src/com/android/server/connectivity/tethering/OffloadHardwareInterface.java +++ b/packages/Tethering/src/com/android/server/connectivity/tethering/OffloadHardwareInterface.java @@ -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. */ diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java index acedc3635730..058fb4fe98ca 100644 --- a/services/core/java/com/android/server/connectivity/Tethering.java +++ b/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java @@ -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) { + // Don't need to synchronized mTetherInternalCallback because all the usage of this variable + // should run at the same thread. + if (mTetherInternalCallback == null) return; + + try { + mTetherInternalCallback.onUpstreamChanged(network); + } catch (RemoteException e) { + // Not really very much to do here. + } } - private void reportUpstreamChanged(Network network) { - final int length = mTetheringEventCallbacks.beginBroadcast(); + private void reportConfigurationChanged(TetheringConfigurationParcel config) { + 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.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. } } - @Override - public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { + 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); diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringConfiguration.java b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringConfiguration.java index ca9b1681bacc..0ab4d634e84d 100644 --- a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringConfiguration.java +++ b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringConfiguration.java @@ -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; + } } diff --git a/services/core/java/com/android/server/connectivity/tethering/TetheringDependencies.java b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringDependencies.java index 4ad7ac4bead0..0ba84127d8da 100644 --- a/services/core/java/com/android/server/connectivity/tethering/TetheringDependencies.java +++ b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringDependencies.java @@ -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; + } } diff --git a/services/core/java/com/android/server/connectivity/tethering/TetheringInterfaceUtils.java b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringInterfaceUtils.java index 0ef3805ff7c0..0ef3805ff7c0 100644 --- a/services/core/java/com/android/server/connectivity/tethering/TetheringInterfaceUtils.java +++ b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringInterfaceUtils.java diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java new file mode 100644 index 000000000000..456f2f7f27f5 --- /dev/null +++ b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java @@ -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; + } +} diff --git a/packages/Tethering/tests/unit/Android.bp b/packages/Tethering/tests/unit/Android.bp index 363be18a73bc..5b018df21aaf 100644 --- a/packages/Tethering/tests/unit/Android.bp +++ b/packages/Tethering/tests/unit/Android.bp @@ -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", - ], -} diff --git a/tests/net/java/android/net/util/VersionedBroadcastListenerTest.java b/packages/Tethering/tests/unit/src/android/net/util/VersionedBroadcastListenerTest.java index 0d27d5bf0a11..5a9b6e380ea9 100644 --- a/tests/net/java/android/net/util/VersionedBroadcastListenerTest.java +++ b/packages/Tethering/tests/unit/src/android/net/util/VersionedBroadcastListenerTest.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(); } diff --git a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/EntitlementManagerTest.java b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/EntitlementManagerTest.java index 5217e26a40ef..99cf9e90d912 100644 --- a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/EntitlementManagerTest.java +++ b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/EntitlementManagerTest.java @@ -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); diff --git a/tests/net/java/com/android/server/connectivity/TetheringTest.java b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java index 9e5717b4bd64..4f6f61bf95d6 100644 --- a/tests/net/java/com/android/server/connectivity/TetheringTest.java +++ b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java @@ -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)); diff --git a/services/core/Android.bp b/services/core/Android.bp index 4900781d6df5..4e75e006e111 100644 --- a/services/core/Android.bp +++ b/services/core/Android.bp @@ -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", - ], -} diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index bb7406a56772..652dd40297b9 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.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. diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 08c94267e969..e473c96980b6 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -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; diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp index 7b3fbb97da56..2b1c07ba40b1 100644 --- a/services/core/jni/Android.bp +++ b/services/core/jni/Android.bp @@ -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", diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp index efffa6ca735b..692c9d25baa9 100644 --- a/services/core/jni/onload.cpp +++ b/services/core/jni/onload.cpp @@ -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); diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 78f572d32fd5..2a2fff2886ed 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -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; @@ -2185,6 +2186,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) { diff --git a/services/net/Android.bp b/services/net/Android.bp index 45430eab9bf4..2dabdb7d47de 100644 --- a/services/net/Android.bp +++ b/services/net/Android.bp @@ -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", diff --git a/tests/net/Android.bp b/tests/net/Android.bp index 10f27e243c8c..b2f384ac8360 100644 --- a/tests/net/Android.bp +++ b/tests/net/Android.bp @@ -45,7 +45,6 @@ android_test { name: "FrameworksNetTests", defaults: ["FrameworksNetTests-jni-defaults"], srcs: [ - ":tethering-tests-src", "java/**/*.java", "java/**/*.kt", ], diff --git a/tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt b/tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt index 334b26d82129..25028fb3ca0e 100644 --- a/tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt +++ b/tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.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() diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 7ea9bcf36f91..2a09f647a46b 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -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()); |