Make TetheringManager to system API

Also deprecated tethering APIs in ConnectivityManager.
Will have follow up change to remove @hide tethering function in
ConnectivityManager.

Bug: 145093446
Bug: 148038547
Test: -build, flash, boot
      -atest TetheringTests

Change-Id: Ia432057bf9056727c4a0ca97d160a49274d33581
Merged-In: Ia432057bf9056727c4a0ca97d160a49274d33581
This commit is contained in:
markchien
2020-01-21 13:11:06 +08:00
committed by Lorenzo Colitti
parent cdf60baad8
commit 249752d8a3
9 changed files with 401 additions and 72 deletions

View File

@@ -36,6 +36,7 @@ java_library {
sdk_version: "system_current", sdk_version: "system_current",
srcs: [ srcs: [
"src/android/net/TetheringManager.java", "src/android/net/TetheringManager.java",
"src/android/net/TetheringConstants.java",
":framework-tethering-annotations", ":framework-tethering-annotations",
], ],
static_libs: [ static_libs: [
@@ -63,9 +64,11 @@ filegroup {
name: "framework-tethering-srcs", name: "framework-tethering-srcs",
srcs: [ srcs: [
"src/android/net/TetheringManager.java", "src/android/net/TetheringManager.java",
"src/android/net/TetheringConstants.java",
"src/android/net/IIntResultListener.aidl", "src/android/net/IIntResultListener.aidl",
"src/android/net/ITetheringEventCallback.aidl", "src/android/net/ITetheringEventCallback.aidl",
"src/android/net/ITetheringConnector.aidl", "src/android/net/ITetheringConnector.aidl",
"src/android/net/TetheringCallbackStartedParcel.aidl",
"src/android/net/TetheringConfigurationParcel.aidl", "src/android/net/TetheringConfigurationParcel.aidl",
"src/android/net/TetherStatesParcel.aidl", "src/android/net/TetherStatesParcel.aidl",
], ],

View File

@@ -18,6 +18,7 @@ package android.net;
import android.net.Network; import android.net.Network;
import android.net.TetheringConfigurationParcel; import android.net.TetheringConfigurationParcel;
import android.net.TetheringCallbackStartedParcel;
import android.net.TetherStatesParcel; import android.net.TetherStatesParcel;
/** /**
@@ -26,8 +27,8 @@ import android.net.TetherStatesParcel;
*/ */
oneway interface ITetheringEventCallback oneway interface ITetheringEventCallback
{ {
void onCallbackStarted(in Network network, in TetheringConfigurationParcel config, /** Called immediately after the callbacks are registered */
in TetherStatesParcel states); void onCallbackStarted(in TetheringCallbackStartedParcel parcel);
void onCallbackStopped(int errorCode); void onCallbackStopped(int errorCode);
void onUpstreamChanged(in Network network); void onUpstreamChanged(in Network network);
void onConfigurationChanged(in TetheringConfigurationParcel config); void onConfigurationChanged(in TetheringConfigurationParcel config);

View File

@@ -0,0 +1,32 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT 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;
/**
* Initial information reported by tethering upon callback registration.
* @hide
*/
parcelable TetheringCallbackStartedParcel {
boolean tetheringSupported;
Network upstreamNetwork;
TetheringConfigurationParcel config;
TetherStatesParcel states;
}

View File

@@ -0,0 +1,66 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT 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.os.ResultReceiver;
/**
* Collections of constants for internal tethering usage.
*
* <p>These hidden constants are not in TetheringManager as they are not part of the API stubs
* generated for TetheringManager, which prevents the tethering module from linking them at
* build time.
* TODO: investigate changing the tethering build rules so that Tethering can reference hidden
* symbols from framework-tethering even when they are in a non-hidden class.
* @hide
*/
public class TetheringConstants {
/**
* Extra used for communicating with the TetherService. Includes the type of tethering to
* enable if any.
*
* {@hide}
*/
public static final String EXTRA_ADD_TETHER_TYPE = "extraAddTetherType";
/**
* Extra used for communicating with the TetherService. Includes the type of tethering for
* which to cancel provisioning.
*
* {@hide}
*/
public static final String EXTRA_REM_TETHER_TYPE = "extraRemTetherType";
/**
* Extra used for communicating with the TetherService. True to schedule a recheck of tether
* provisioning.
*
* {@hide}
*/
public static final String EXTRA_SET_ALARM = "extraSetAlarm";
/**
* Tells the TetherService to run a provision check now.
*
* {@hide}
*/
public static final String EXTRA_RUN_PROVISION = "extraRunProvision";
/**
* Extra used for communicating with the TetherService. Contains the {@link ResultReceiver}
* which will receive provisioning results. Can be left empty.
*
* {@hide}
*/
public static final String EXTRA_PROVISION_CALLBACK = "extraProvisionCallback";
}

View File

@@ -16,8 +16,12 @@
package android.net; package android.net;
import android.annotation.NonNull; import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.content.Context; import android.content.Context;
import android.net.ConnectivityManager.OnTetheringEventCallback; import android.os.Bundle;
import android.os.ConditionVariable; import android.os.ConditionVariable;
import android.os.IBinder; import android.os.IBinder;
import android.os.RemoteException; import android.os.RemoteException;
@@ -25,6 +29,11 @@ import android.os.ResultReceiver;
import android.util.ArrayMap; import android.util.ArrayMap;
import android.util.Log; import android.util.Log;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
/** /**
@@ -34,7 +43,8 @@ import java.util.concurrent.Executor;
* *
* @hide * @hide
*/ */
// TODO: make it @SystemApi @SystemApi
@TestApi
public class TetheringManager { public class TetheringManager {
private static final String TAG = TetheringManager.class.getSimpleName(); private static final String TAG = TetheringManager.class.getSimpleName();
private static final int DEFAULT_TIMEOUT_MS = 60_000; private static final int DEFAULT_TIMEOUT_MS = 60_000;
@@ -44,7 +54,7 @@ public class TetheringManager {
private final ITetheringConnector mConnector; private final ITetheringConnector mConnector;
private final TetheringCallbackInternal mCallback; private final TetheringCallbackInternal mCallback;
private final Context mContext; private final Context mContext;
private final ArrayMap<OnTetheringEventCallback, ITetheringEventCallback> private final ArrayMap<TetheringEventCallback, ITetheringEventCallback>
mTetheringEventCallbacks = new ArrayMap<>(); mTetheringEventCallbacks = new ArrayMap<>();
private TetheringConfigurationParcel mTetheringConfiguration; private TetheringConfigurationParcel mTetheringConfiguration;
@@ -72,7 +82,7 @@ public class TetheringManager {
* gives a String[] listing all the interfaces currently in local-only * gives a String[] listing all the interfaces currently in local-only
* mode (ie, has DHCPv4+IPv6-ULA support and no packet forwarding) * mode (ie, has DHCPv4+IPv6-ULA support and no packet forwarding)
*/ */
public static final String EXTRA_ACTIVE_LOCAL_ONLY = "localOnlyArray"; public static final String EXTRA_ACTIVE_LOCAL_ONLY = "android.net.extra.ACTIVE_LOCAL_ONLY";
/** /**
* gives a String[] listing all the interfaces currently tethered * gives a String[] listing all the interfaces currently tethered
@@ -118,35 +128,6 @@ public class TetheringManager {
*/ */
public static final int TETHERING_WIFI_P2P = 3; public static final int TETHERING_WIFI_P2P = 3;
/**
* Extra used for communicating with the TetherService. Includes the type of tethering to
* enable if any.
*/
public static final String EXTRA_ADD_TETHER_TYPE = "extraAddTetherType";
/**
* Extra used for communicating with the TetherService. Includes the type of tethering for
* which to cancel provisioning.
*/
public static final String EXTRA_REM_TETHER_TYPE = "extraRemTetherType";
/**
* Extra used for communicating with the TetherService. True to schedule a recheck of tether
* provisioning.
*/
public static final String EXTRA_SET_ALARM = "extraSetAlarm";
/**
* Tells the TetherService to run a provision check now.
*/
public static final String EXTRA_RUN_PROVISION = "extraRunProvision";
/**
* Extra used for communicating with the TetherService. Contains the {@link ResultReceiver}
* which will receive provisioning results. Can be left empty.
*/
public static final String EXTRA_PROVISION_CALLBACK = "extraProvisionCallback";
public static final int TETHER_ERROR_NO_ERROR = 0; public static final int TETHER_ERROR_NO_ERROR = 0;
public static final int TETHER_ERROR_UNKNOWN_IFACE = 1; public static final int TETHER_ERROR_UNKNOWN_IFACE = 1;
public static final int TETHER_ERROR_SERVICE_UNAVAIL = 2; public static final int TETHER_ERROR_SERVICE_UNAVAIL = 2;
@@ -160,12 +141,14 @@ public class TetheringManager {
public static final int TETHER_ERROR_IFACE_CFG_ERROR = 10; public static final int TETHER_ERROR_IFACE_CFG_ERROR = 10;
public static final int TETHER_ERROR_PROVISION_FAILED = 11; public static final int TETHER_ERROR_PROVISION_FAILED = 11;
public static final int TETHER_ERROR_DHCPSERVER_ERROR = 12; public static final int TETHER_ERROR_DHCPSERVER_ERROR = 12;
public static final int TETHER_ERROR_ENTITLEMENT_UNKONWN = 13; public static final int TETHER_ERROR_ENTITLEMENT_UNKNOWN = 13;
public static final int TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION = 14; public static final int TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION = 14;
public static final int TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION = 15; public static final int TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION = 15;
/** /**
* Create a TetheringManager object for interacting with the tethering service. * Create a TetheringManager object for interacting with the tethering service.
*
* {@hide}
*/ */
public TetheringManager(@NonNull final Context context, @NonNull final IBinder service) { public TetheringManager(@NonNull final Context context, @NonNull final IBinder service) {
mContext = context; mContext = context;
@@ -229,10 +212,9 @@ public class TetheringManager {
private final ConditionVariable mWaitForCallback = new ConditionVariable(); private final ConditionVariable mWaitForCallback = new ConditionVariable();
@Override @Override
public void onCallbackStarted(Network network, TetheringConfigurationParcel config, public void onCallbackStarted(TetheringCallbackStartedParcel parcel) {
TetherStatesParcel states) { mTetheringConfiguration = parcel.config;
mTetheringConfiguration = config; mTetherStatesParcel = parcel.states;
mTetherStatesParcel = states;
mWaitForCallback.open(); mWaitForCallback.open();
} }
@@ -275,6 +257,8 @@ public class TetheringManager {
* *
* @param iface the interface name to tether. * @param iface the interface name to tether.
* @return error a {@code TETHER_ERROR} value indicating success or failure type * @return error a {@code TETHER_ERROR} value indicating success or failure type
*
* {@hide}
*/ */
@Deprecated @Deprecated
public int tether(@NonNull final String iface) { public int tether(@NonNull final String iface) {
@@ -296,6 +280,8 @@ public class TetheringManager {
* *
* @deprecated The only usages is PanService. It uses this for legacy reasons * @deprecated The only usages is PanService. It uses this for legacy reasons
* and will migrate away as soon as possible. * and will migrate away as soon as possible.
*
* {@hide}
*/ */
@Deprecated @Deprecated
public int untether(@NonNull final String iface) { public int untether(@NonNull final String iface) {
@@ -320,6 +306,8 @@ public class TetheringManager {
* #startTethering or #stopTethering which encapsulate proper entitlement logic. If the API is * #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 * used and an entitlement check is needed, downstream USB tethering will be enabled but will
* not have any upstream. * not have any upstream.
*
* {@hide}
*/ */
@Deprecated @Deprecated
public int setUsbTethering(final boolean enable) { public int setUsbTethering(final boolean enable) {
@@ -340,7 +328,7 @@ public class TetheringManager {
/** /**
* Starts tethering and runs tether provisioning for the given type if needed. If provisioning * Starts tethering and runs tether provisioning for the given type if needed. If provisioning
* fails, stopTethering will be called automatically. * fails, stopTethering will be called automatically.
* * @hide
*/ */
// TODO: improve the usage of ResultReceiver, b/145096122 // TODO: improve the usage of ResultReceiver, b/145096122
public void startTethering(final int type, @NonNull final ResultReceiver receiver, public void startTethering(final int type, @NonNull final ResultReceiver receiver,
@@ -374,12 +362,64 @@ public class TetheringManager {
}); });
} }
/**
* Callback for use with {@link #getLatestTetheringEntitlementResult} to find out whether
* entitlement succeeded.
*/
public interface OnTetheringEntitlementResultListener {
/**
* Called to notify entitlement result.
*
* @param resultCode an int value of entitlement result. It may be one of
* {@link #TETHER_ERROR_NO_ERROR},
* {@link #TETHER_ERROR_PROVISION_FAILED}, or
* {@link #TETHER_ERROR_ENTITLEMENT_UNKNOWN}.
*/
void onTetheringEntitlementResult(int resultCode);
}
/** /**
* Request the latest value of the tethering entitlement check. * Request the latest value of the tethering entitlement check.
* *
* Note: Allow privileged apps who have TETHER_PRIVILEGED permission to access. If it turns * <p>This method will only return the latest entitlement result if it is available. If no
* out some such apps are observed to abuse this API, change to per-UID limits on this API * cached entitlement result is available, and {@code showEntitlementUi} is false,
* if it's really needed. * {@link #TETHER_ERROR_ENTITLEMENT_UNKNOWN} will be returned. If {@code showEntitlementUi} is
* true, entitlement will be run.
*
* @param type the downstream type of tethering. Must be one of {@code #TETHERING_*} constants.
* @param showEntitlementUi a boolean indicating whether to run UI-based entitlement check.
* @param executor the executor on which callback will be invoked.
* @param listener an {@link OnTetheringEntitlementResultListener} which will be called to
* notify the caller of the result of entitlement check. The listener may be called zero
* or one time.
*/
@RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
public void requestLatestTetheringEntitlementResult(int type, boolean showEntitlementUi,
@NonNull Executor executor,
@NonNull final OnTetheringEntitlementResultListener listener) {
if (listener == null) {
throw new IllegalArgumentException(
"OnTetheringEntitlementResultListener cannot be null.");
}
ResultReceiver wrappedListener = new ResultReceiver(null /* handler */) {
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
executor.execute(() -> {
listener.onTetheringEntitlementResult(resultCode);
});
}
};
requestLatestTetheringEntitlementResult(type, wrappedListener,
showEntitlementUi);
}
/**
* Helper function of #requestLatestTetheringEntitlementResult to remain backwards compatible
* with ConnectivityManager#getLatestTetheringEntitlementResult
*
* {@hide}
*/ */
// TODO: improve the usage of ResultReceiver, b/145096122 // TODO: improve the usage of ResultReceiver, b/145096122
public void requestLatestTetheringEntitlementResult(final int type, public void requestLatestTetheringEntitlementResult(final int type,
@@ -395,10 +435,127 @@ public class TetheringManager {
} }
} }
/**
* Callback for use with {@link registerTetheringEventCallback} to find out tethering
* upstream status.
*/
public abstract static class TetheringEventCallback {
/**
* Called when tethering supported status changed.
*
* <p>This will be called immediately after the callback is registered, and may be called
* multiple times later upon changes.
*
* <p>Tethering may be disabled via system properties, device configuration, or device
* policy restrictions.
*
* @param supported The new supported status
*/
public void onTetheringSupported(boolean supported) {}
/**
* Called when tethering upstream changed.
*
* <p>This will be called immediately after the callback is registered, and may be called
* multiple times later upon changes.
*
* @param network the {@link Network} of tethering upstream. Null means tethering doesn't
* have any upstream.
*/
public void onUpstreamChanged(@Nullable Network network) {}
/**
* Called when there was a change in tethering interface regular expressions.
*
* <p>This will be called immediately after the callback is registered, and may be called
* multiple times later upon changes.
* @param reg The new regular expressions.
* @deprecated Referencing interfaces by regular expressions is a deprecated mechanism.
*/
@Deprecated
public void onTetherableInterfaceRegexpsChanged(@NonNull TetheringInterfaceRegexps reg) {}
/**
* Called when there was a change in the list of tetherable interfaces.
*
* <p>This will be called immediately after the callback is registered, and may be called
* multiple times later upon changes.
* @param interfaces The list of tetherable interfaces.
*/
public void onTetherableInterfacesChanged(@NonNull List<String> interfaces) {}
/**
* Called when there was a change in the list of tethered interfaces.
*
* <p>This will be called immediately after the callback is registered, and may be called
* multiple times later upon changes.
* @param interfaces The list of tethered interfaces.
*/
public void onTetheredInterfacesChanged(@NonNull List<String> interfaces) {}
/**
* Called when an error occurred configuring tethering.
*
* <p>This will be called immediately after the callback is registered if the latest status
* on the interface is an error, and may be called multiple times later upon changes.
* @param ifName Name of the interface.
* @param error One of {@code TetheringManager#TETHER_ERROR_*}.
*/
public void onError(@NonNull String ifName, int error) {}
}
/**
* Regular expressions used to identify tethering interfaces.
* @deprecated Referencing interfaces by regular expressions is a deprecated mechanism.
*/
@Deprecated
public static class TetheringInterfaceRegexps {
private final String[] mTetherableBluetoothRegexs;
private final String[] mTetherableUsbRegexs;
private final String[] mTetherableWifiRegexs;
public TetheringInterfaceRegexps(@NonNull String[] tetherableBluetoothRegexs,
@NonNull String[] tetherableUsbRegexs, @NonNull String[] tetherableWifiRegexs) {
mTetherableBluetoothRegexs = tetherableBluetoothRegexs.clone();
mTetherableUsbRegexs = tetherableUsbRegexs.clone();
mTetherableWifiRegexs = tetherableWifiRegexs.clone();
}
@NonNull
public List<String> getTetherableBluetoothRegexs() {
return Collections.unmodifiableList(Arrays.asList(mTetherableBluetoothRegexs));
}
@NonNull
public List<String> getTetherableUsbRegexs() {
return Collections.unmodifiableList(Arrays.asList(mTetherableUsbRegexs));
}
@NonNull
public List<String> getTetherableWifiRegexs() {
return Collections.unmodifiableList(Arrays.asList(mTetherableWifiRegexs));
}
@Override
public int hashCode() {
return Objects.hash(mTetherableBluetoothRegexs, mTetherableUsbRegexs,
mTetherableWifiRegexs);
}
@Override
public boolean equals(@Nullable Object obj) {
if (!(obj instanceof TetheringInterfaceRegexps)) return false;
final TetheringInterfaceRegexps other = (TetheringInterfaceRegexps) obj;
return Arrays.equals(mTetherableBluetoothRegexs, other.mTetherableBluetoothRegexs)
&& Arrays.equals(mTetherableUsbRegexs, other.mTetherableUsbRegexs)
&& Arrays.equals(mTetherableWifiRegexs, other.mTetherableWifiRegexs);
}
}
/** /**
* Start listening to tethering change events. Any new added callback will receive the last * Start listening to tethering change events. Any new added callback will receive the last
* tethering status right away. If callback is registered, * tethering status right away. If callback is registered,
* {@link OnTetheringEventCallback#onUpstreamChanged} will immediately be called. If tethering * {@link TetheringEventCallback#onUpstreamChanged} will immediately be called. If tethering
* has no upstream or disabled, the argument of callback will be null. The same callback object * has no upstream or disabled, the argument of callback will be null. The same callback object
* cannot be registered twice. * cannot be registered twice.
* *
@@ -406,15 +563,20 @@ public class TetheringManager {
* @param callback the callback to be called when tethering has change events. * @param callback the callback to be called when tethering has change events.
*/ */
public void registerTetheringEventCallback(@NonNull Executor executor, public void registerTetheringEventCallback(@NonNull Executor executor,
@NonNull OnTetheringEventCallback callback) { @NonNull TetheringEventCallback callback) {
final String callerPkg = mContext.getOpPackageName(); final String callerPkg = mContext.getOpPackageName();
Log.i(TAG, "registerTetheringEventCallback caller:" + callerPkg); Log.i(TAG, "registerTetheringEventCallback caller:" + callerPkg);
synchronized (mTetheringEventCallbacks) { synchronized (mTetheringEventCallbacks) {
if (!mTetheringEventCallbacks.containsKey(callback)) { if (mTetheringEventCallbacks.containsKey(callback)) {
throw new IllegalArgumentException("callback was already registered."); throw new IllegalArgumentException("callback was already registered.");
} }
final ITetheringEventCallback remoteCallback = new ITetheringEventCallback.Stub() { final ITetheringEventCallback remoteCallback = new ITetheringEventCallback.Stub() {
// Only accessed with a lock on this object
private final HashMap<String, Integer> mErrorStates = new HashMap<>();
private String[] mLastTetherableInterfaces = null;
private String[] mLastTetheredInterfaces = null;
@Override @Override
public void onUpstreamChanged(Network network) throws RemoteException { public void onUpstreamChanged(Network network) throws RemoteException {
executor.execute(() -> { executor.execute(() -> {
@@ -422,11 +584,45 @@ public class TetheringManager {
}); });
} }
private synchronized void sendErrorCallbacks(final TetherStatesParcel newStates) {
for (int i = 0; i < newStates.erroredIfaceList.length; i++) {
final String iface = newStates.erroredIfaceList[i];
final Integer lastError = mErrorStates.get(iface);
final int newError = newStates.lastErrorList[i];
if (newError != TETHER_ERROR_NO_ERROR
&& !Objects.equals(lastError, newError)) {
callback.onError(iface, newError);
}
mErrorStates.put(iface, newError);
}
}
private synchronized void maybeSendTetherableIfacesChangedCallback(
final TetherStatesParcel newStates) {
if (Arrays.equals(mLastTetherableInterfaces, newStates.availableList)) return;
mLastTetherableInterfaces = newStates.availableList.clone();
callback.onTetherableInterfacesChanged(
Collections.unmodifiableList(Arrays.asList(mLastTetherableInterfaces)));
}
private synchronized void maybeSendTetheredIfacesChangedCallback(
final TetherStatesParcel newStates) {
if (Arrays.equals(mLastTetheredInterfaces, newStates.tetheredList)) return;
mLastTetheredInterfaces = newStates.tetheredList.clone();
callback.onTetheredInterfacesChanged(
Collections.unmodifiableList(Arrays.asList(mLastTetheredInterfaces)));
}
// Called immediately after the callbacks are registered.
@Override @Override
public void onCallbackStarted(Network network, TetheringConfigurationParcel config, public void onCallbackStarted(TetheringCallbackStartedParcel parcel) {
TetherStatesParcel states) {
executor.execute(() -> { executor.execute(() -> {
callback.onUpstreamChanged(network); callback.onTetheringSupported(parcel.tetheringSupported);
callback.onUpstreamChanged(parcel.upstreamNetwork);
sendErrorCallbacks(parcel.states);
sendRegexpsChanged(parcel.config);
maybeSendTetherableIfacesChangedCallback(parcel.states);
maybeSendTetheredIfacesChangedCallback(parcel.states);
}); });
} }
@@ -437,11 +633,26 @@ public class TetheringManager {
}); });
} }
@Override private void sendRegexpsChanged(TetheringConfigurationParcel parcel) {
public void onConfigurationChanged(TetheringConfigurationParcel config) { } callback.onTetherableInterfaceRegexpsChanged(new TetheringInterfaceRegexps(
parcel.tetherableBluetoothRegexs,
parcel.tetherableUsbRegexs,
parcel.tetherableWifiRegexs));
}
@Override @Override
public void onTetherStatesChanged(TetherStatesParcel states) { } public void onConfigurationChanged(TetheringConfigurationParcel config) {
executor.execute(() -> sendRegexpsChanged(config));
}
@Override
public void onTetherStatesChanged(TetherStatesParcel states) {
executor.execute(() -> {
sendErrorCallbacks(states);
maybeSendTetherableIfacesChangedCallback(states);
maybeSendTetheredIfacesChangedCallback(states);
});
}
}; };
try { try {
mConnector.registerTetheringEventCallback(remoteCallback, callerPkg); mConnector.registerTetheringEventCallback(remoteCallback, callerPkg);
@@ -458,7 +669,7 @@ public class TetheringManager {
* *
* @param callback previously registered callback. * @param callback previously registered callback.
*/ */
public void unregisterTetheringEventCallback(@NonNull final OnTetheringEventCallback callback) { public void unregisterTetheringEventCallback(@NonNull final TetheringEventCallback callback) {
final String callerPkg = mContext.getOpPackageName(); final String callerPkg = mContext.getOpPackageName();
Log.i(TAG, "unregisterTetheringEventCallback caller:" + callerPkg); Log.i(TAG, "unregisterTetheringEventCallback caller:" + callerPkg);
@@ -482,6 +693,7 @@ public class TetheringManager {
* @param iface The name of the interface of interest * @param iface The name of the interface of interest
* @return error The error code of the last error tethering or untethering the named * @return error The error code of the last error tethering or untethering the named
* interface * interface
* @hide
*/ */
public int getLastTetherError(@NonNull final String iface) { public int getLastTetherError(@NonNull final String iface) {
mCallback.waitForStarted(); mCallback.waitForStarted();
@@ -503,6 +715,7 @@ public class TetheringManager {
* *
* @return an array of 0 or more regular expression Strings defining * @return an array of 0 or more regular expression Strings defining
* what interfaces are considered tetherable usb interfaces. * what interfaces are considered tetherable usb interfaces.
* @hide
*/ */
public @NonNull String[] getTetherableUsbRegexs() { public @NonNull String[] getTetherableUsbRegexs() {
mCallback.waitForStarted(); mCallback.waitForStarted();
@@ -516,6 +729,7 @@ public class TetheringManager {
* *
* @return an array of 0 or more regular expression Strings defining * @return an array of 0 or more regular expression Strings defining
* what interfaces are considered tetherable wifi interfaces. * what interfaces are considered tetherable wifi interfaces.
* @hide
*/ */
public @NonNull String[] getTetherableWifiRegexs() { public @NonNull String[] getTetherableWifiRegexs() {
mCallback.waitForStarted(); mCallback.waitForStarted();
@@ -529,6 +743,7 @@ public class TetheringManager {
* *
* @return an array of 0 or more regular expression Strings defining * @return an array of 0 or more regular expression Strings defining
* what interfaces are considered tetherable bluetooth interfaces. * what interfaces are considered tetherable bluetooth interfaces.
* @hide
*/ */
public @NonNull String[] getTetherableBluetoothRegexs() { public @NonNull String[] getTetherableBluetoothRegexs() {
mCallback.waitForStarted(); mCallback.waitForStarted();
@@ -540,6 +755,7 @@ public class TetheringManager {
* device configuration and current interface existence. * device configuration and current interface existence.
* *
* @return an array of 0 or more Strings of tetherable interface names. * @return an array of 0 or more Strings of tetherable interface names.
* @hide
*/ */
public @NonNull String[] getTetherableIfaces() { public @NonNull String[] getTetherableIfaces() {
mCallback.waitForStarted(); mCallback.waitForStarted();
@@ -552,6 +768,7 @@ public class TetheringManager {
* Get the set of tethered interfaces. * Get the set of tethered interfaces.
* *
* @return an array of 0 or more String of currently tethered interface names. * @return an array of 0 or more String of currently tethered interface names.
* @hide
*/ */
public @NonNull String[] getTetheredIfaces() { public @NonNull String[] getTetheredIfaces() {
mCallback.waitForStarted(); mCallback.waitForStarted();
@@ -570,6 +787,7 @@ public class TetheringManager {
* *
* @return an array of 0 or more String indicating the interface names * @return an array of 0 or more String indicating the interface names
* which failed to tether. * which failed to tether.
* @hide
*/ */
public @NonNull String[] getTetheringErroredIfaces() { public @NonNull String[] getTetheringErroredIfaces() {
mCallback.waitForStarted(); mCallback.waitForStarted();
@@ -582,6 +800,7 @@ public class TetheringManager {
* Get the set of tethered dhcp ranges. * Get the set of tethered dhcp ranges.
* *
* @deprecated This API just return the default value which is not used in DhcpServer. * @deprecated This API just return the default value which is not used in DhcpServer.
* @hide
*/ */
@Deprecated @Deprecated
public @NonNull String[] getTetheredDhcpRanges() { public @NonNull String[] getTetheredDhcpRanges() {
@@ -595,6 +814,7 @@ public class TetheringManager {
* due to device configuration. * due to device configuration.
* *
* @return a boolean - {@code true} indicating Tethering is supported. * @return a boolean - {@code true} indicating Tethering is supported.
* @hide
*/ */
public boolean isTetheringSupported() { public boolean isTetheringSupported() {
final String callerPkg = mContext.getOpPackageName(); final String callerPkg = mContext.getOpPackageName();

View File

@@ -16,14 +16,14 @@
package com.android.server.connectivity.tethering; package com.android.server.connectivity.tethering;
import static android.net.TetheringManager.EXTRA_ADD_TETHER_TYPE; import static android.net.TetheringConstants.EXTRA_ADD_TETHER_TYPE;
import static android.net.TetheringManager.EXTRA_PROVISION_CALLBACK; import static android.net.TetheringConstants.EXTRA_PROVISION_CALLBACK;
import static android.net.TetheringManager.EXTRA_RUN_PROVISION; import static android.net.TetheringConstants.EXTRA_RUN_PROVISION;
import static android.net.TetheringManager.TETHERING_BLUETOOTH; import static android.net.TetheringManager.TETHERING_BLUETOOTH;
import static android.net.TetheringManager.TETHERING_INVALID; import static android.net.TetheringManager.TETHERING_INVALID;
import static android.net.TetheringManager.TETHERING_USB; import static android.net.TetheringManager.TETHERING_USB;
import static android.net.TetheringManager.TETHERING_WIFI; import static android.net.TetheringManager.TETHERING_WIFI;
import static android.net.TetheringManager.TETHER_ERROR_ENTITLEMENT_UNKONWN; import static android.net.TetheringManager.TETHER_ERROR_ENTITLEMENT_UNKNOWN;
import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR; import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
import static android.net.TetheringManager.TETHER_ERROR_PROVISION_FAILED; import static android.net.TetheringManager.TETHER_ERROR_PROVISION_FAILED;
@@ -577,7 +577,7 @@ public class EntitlementManager {
private static String errorString(int value) { private static String errorString(int value) {
switch (value) { switch (value) {
case TETHER_ERROR_ENTITLEMENT_UNKONWN: return "TETHER_ERROR_ENTITLEMENT_UNKONWN"; case TETHER_ERROR_ENTITLEMENT_UNKNOWN: return "TETHER_ERROR_ENTITLEMENT_UNKONWN";
case TETHER_ERROR_NO_ERROR: return "TETHER_ERROR_NO_ERROR"; case TETHER_ERROR_NO_ERROR: return "TETHER_ERROR_NO_ERROR";
case TETHER_ERROR_PROVISION_FAILED: return "TETHER_ERROR_PROVISION_FAILED"; case TETHER_ERROR_PROVISION_FAILED: return "TETHER_ERROR_PROVISION_FAILED";
default: default:
@@ -657,7 +657,7 @@ public class EntitlementManager {
} }
final int cacheValue = mEntitlementCacheValue.get( final int cacheValue = mEntitlementCacheValue.get(
downstream, TETHER_ERROR_ENTITLEMENT_UNKONWN); downstream, TETHER_ERROR_ENTITLEMENT_UNKNOWN);
if (cacheValue == TETHER_ERROR_NO_ERROR || !showEntitlementUi) { if (cacheValue == TETHER_ERROR_NO_ERROR || !showEntitlementUi) {
receiver.send(cacheValue, null); receiver.send(cacheValue, null);
} else { } else {

View File

@@ -74,6 +74,7 @@ import android.net.LinkProperties;
import android.net.Network; import android.net.Network;
import android.net.NetworkInfo; import android.net.NetworkInfo;
import android.net.TetherStatesParcel; import android.net.TetherStatesParcel;
import android.net.TetheringCallbackStartedParcel;
import android.net.TetheringConfigurationParcel; import android.net.TetheringConfigurationParcel;
import android.net.ip.IpServer; import android.net.ip.IpServer;
import android.net.shared.NetdUtils; import android.net.shared.NetdUtils;
@@ -951,6 +952,7 @@ public class Tethering {
mWrapper.showTetheredNotification( mWrapper.showTetheredNotification(
R.drawable.stat_sys_tether_general, false); R.drawable.stat_sys_tether_general, false);
mWrapper.untetherAll(); mWrapper.untetherAll();
// TODO(b/148139325): send tetheringSupported on restriction change
} }
} }
} }
@@ -1844,9 +1846,13 @@ public class Tethering {
void registerTetheringEventCallback(ITetheringEventCallback callback) { void registerTetheringEventCallback(ITetheringEventCallback callback) {
mHandler.post(() -> { mHandler.post(() -> {
mTetheringEventCallbacks.register(callback); mTetheringEventCallbacks.register(callback);
final TetheringCallbackStartedParcel parcel = new TetheringCallbackStartedParcel();
parcel.tetheringSupported = mDeps.isTetheringSupported();
parcel.upstreamNetwork = mTetherUpstream;
parcel.config = mConfig.toStableParcelable();
parcel.states = mTetherStatesParcel;
try { try {
callback.onCallbackStarted(mTetherUpstream, mConfig.toStableParcelable(), callback.onCallbackStarted(parcel);
mTetherStatesParcel);
} catch (RemoteException e) { } catch (RemoteException e) {
// Not really very much to do here. // Not really very much to do here.
} }
@@ -1881,6 +1887,7 @@ public class Tethering {
for (int i = 0; i < length; i++) { for (int i = 0; i < length; i++) {
try { try {
mTetheringEventCallbacks.getBroadcastItem(i).onConfigurationChanged(config); mTetheringEventCallbacks.getBroadcastItem(i).onConfigurationChanged(config);
// TODO(b/148139325): send tetheringSupported on configuration change
} catch (RemoteException e) { } catch (RemoteException e) {
// Not really very much to do here. // Not really very much to do here.
} }

View File

@@ -19,7 +19,7 @@ package com.android.server.connectivity.tethering;
import static android.net.TetheringManager.TETHERING_BLUETOOTH; import static android.net.TetheringManager.TETHERING_BLUETOOTH;
import static android.net.TetheringManager.TETHERING_USB; import static android.net.TetheringManager.TETHERING_USB;
import static android.net.TetheringManager.TETHERING_WIFI; import static android.net.TetheringManager.TETHERING_WIFI;
import static android.net.TetheringManager.TETHER_ERROR_ENTITLEMENT_UNKONWN; import static android.net.TetheringManager.TETHER_ERROR_ENTITLEMENT_UNKNOWN;
import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR; import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
import static android.net.TetheringManager.TETHER_ERROR_PROVISION_FAILED; import static android.net.TetheringManager.TETHER_ERROR_PROVISION_FAILED;
import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY; import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY;
@@ -110,7 +110,7 @@ public final class EntitlementManagerTest {
} }
public class WrappedEntitlementManager extends EntitlementManager { public class WrappedEntitlementManager extends EntitlementManager {
public int fakeEntitlementResult = TETHER_ERROR_ENTITLEMENT_UNKONWN; public int fakeEntitlementResult = TETHER_ERROR_ENTITLEMENT_UNKNOWN;
public int uiProvisionCount = 0; public int uiProvisionCount = 0;
public int silentProvisionCount = 0; public int silentProvisionCount = 0;
@@ -120,7 +120,7 @@ public final class EntitlementManagerTest {
} }
public void reset() { public void reset() {
fakeEntitlementResult = TETHER_ERROR_ENTITLEMENT_UNKONWN; fakeEntitlementResult = TETHER_ERROR_ENTITLEMENT_UNKNOWN;
uiProvisionCount = 0; uiProvisionCount = 0;
silentProvisionCount = 0; silentProvisionCount = 0;
} }
@@ -274,7 +274,7 @@ public final class EntitlementManagerTest {
receiver = new ResultReceiver(null) { receiver = new ResultReceiver(null) {
@Override @Override
protected void onReceiveResult(int resultCode, Bundle resultData) { protected void onReceiveResult(int resultCode, Bundle resultData) {
assertEquals(TETHER_ERROR_ENTITLEMENT_UNKONWN, resultCode); assertEquals(TETHER_ERROR_ENTITLEMENT_UNKNOWN, resultCode);
mCallbacklatch.countDown(); mCallbacklatch.countDown();
} }
}; };
@@ -343,7 +343,7 @@ public final class EntitlementManagerTest {
receiver = new ResultReceiver(null) { receiver = new ResultReceiver(null) {
@Override @Override
protected void onReceiveResult(int resultCode, Bundle resultData) { protected void onReceiveResult(int resultCode, Bundle resultData) {
assertEquals(TETHER_ERROR_ENTITLEMENT_UNKONWN, resultCode); assertEquals(TETHER_ERROR_ENTITLEMENT_UNKNOWN, resultCode);
mCallbacklatch.countDown(); mCallbacklatch.countDown();
} }
}; };

View File

@@ -86,6 +86,7 @@ import android.net.NetworkCapabilities;
import android.net.NetworkRequest; import android.net.NetworkRequest;
import android.net.RouteInfo; import android.net.RouteInfo;
import android.net.TetherStatesParcel; import android.net.TetherStatesParcel;
import android.net.TetheringCallbackStartedParcel;
import android.net.TetheringConfigurationParcel; import android.net.TetheringConfigurationParcel;
import android.net.dhcp.DhcpServerCallbacks; import android.net.dhcp.DhcpServerCallbacks;
import android.net.dhcp.DhcpServingParamsParcel; import android.net.dhcp.DhcpServingParamsParcel;
@@ -1113,11 +1114,10 @@ public class TetheringTest {
} }
@Override @Override
public void onCallbackStarted(Network network, TetheringConfigurationParcel config, public void onCallbackStarted(TetheringCallbackStartedParcel parcel) {
TetherStatesParcel states) { mActualUpstreams.add(parcel.upstreamNetwork);
mActualUpstreams.add(network); mTetheringConfigs.add(parcel.config);
mTetheringConfigs.add(config); mTetherStates.add(parcel.states);
mTetherStates.add(states);
} }
@Override @Override