Merge "[Tether13] Move TetheringManager into framework"
am: 2410d67357
Change-Id: I05c79a1cf07e7679ea2a2c9221e541fb1c9a5a23
This commit is contained in:
18
Android.bp
18
Android.bp
@@ -266,6 +266,7 @@ filegroup {
|
|||||||
name: "framework-updatable-sources",
|
name: "framework-updatable-sources",
|
||||||
srcs: [
|
srcs: [
|
||||||
":framework-sdkext-sources",
|
":framework-sdkext-sources",
|
||||||
|
":framework-tethering-srcs",
|
||||||
":updatable-media-srcs",
|
":updatable-media-srcs",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -370,6 +371,7 @@ java_defaults {
|
|||||||
"ext",
|
"ext",
|
||||||
"unsupportedappusage",
|
"unsupportedappusage",
|
||||||
"updatable_media_stubs",
|
"updatable_media_stubs",
|
||||||
|
"framework-tethering",
|
||||||
],
|
],
|
||||||
|
|
||||||
jarjar_rules: ":framework-jarjar-rules",
|
jarjar_rules: ":framework-jarjar-rules",
|
||||||
@@ -605,10 +607,26 @@ filegroup {
|
|||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// keep these files in sync with the package/Tethering/jarjar-rules.txt for the tethering module.
|
||||||
filegroup {
|
filegroup {
|
||||||
name: "framework-tethering-shared-srcs",
|
name: "framework-tethering-shared-srcs",
|
||||||
srcs: [
|
srcs: [
|
||||||
"core/java/android/util/LocalLog.java",
|
"core/java/android/util/LocalLog.java",
|
||||||
|
"core/java/com/android/internal/util/BitUtils.java",
|
||||||
|
"core/java/com/android/internal/util/IndentingPrintWriter.java",
|
||||||
|
"core/java/com/android/internal/util/IState.java",
|
||||||
|
"core/java/com/android/internal/util/MessageUtils.java",
|
||||||
|
"core/java/com/android/internal/util/Preconditions.java",
|
||||||
|
"core/java/com/android/internal/util/State.java",
|
||||||
|
"core/java/com/android/internal/util/StateMachine.java",
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
filegroup {
|
||||||
|
name: "framework-tethering-annotations",
|
||||||
|
srcs: [
|
||||||
|
"core/java/android/annotation/NonNull.java",
|
||||||
|
"core/java/android/annotation/SystemApi.java",
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
// Build ext.jar
|
// Build ext.jar
|
||||||
|
|||||||
@@ -1554,6 +1554,7 @@ package android.content {
|
|||||||
field public static final String SYSTEM_UPDATE_SERVICE = "system_update";
|
field public static final String SYSTEM_UPDATE_SERVICE = "system_update";
|
||||||
field public static final String TELEPHONY_IMS_SERVICE = "telephony_ims";
|
field public static final String TELEPHONY_IMS_SERVICE = "telephony_ims";
|
||||||
field public static final String TELEPHONY_REGISTRY_SERVICE = "telephony_registry";
|
field public static final String TELEPHONY_REGISTRY_SERVICE = "telephony_registry";
|
||||||
|
field public static final String TETHERING_SERVICE = "tethering";
|
||||||
field public static final String VR_SERVICE = "vrmanager";
|
field public static final String VR_SERVICE = "vrmanager";
|
||||||
field @Deprecated public static final String WIFI_RTT_SERVICE = "rttmanager";
|
field @Deprecated public static final String WIFI_RTT_SERVICE = "rttmanager";
|
||||||
field public static final String WIFI_SCANNING_SERVICE = "wifiscanner";
|
field public static final String WIFI_SCANNING_SERVICE = "wifiscanner";
|
||||||
@@ -6644,6 +6645,7 @@ package android.provider {
|
|||||||
field public static final String INSTALL_CARRIER_APP_NOTIFICATION_SLEEP_MILLIS = "install_carrier_app_notification_sleep_millis";
|
field public static final String INSTALL_CARRIER_APP_NOTIFICATION_SLEEP_MILLIS = "install_carrier_app_notification_sleep_millis";
|
||||||
field public static final String OTA_DISABLE_AUTOMATIC_UPDATE = "ota_disable_automatic_update";
|
field public static final String OTA_DISABLE_AUTOMATIC_UPDATE = "ota_disable_automatic_update";
|
||||||
field public static final String REQUIRE_PASSWORD_TO_DECRYPT = "require_password_to_decrypt";
|
field public static final String REQUIRE_PASSWORD_TO_DECRYPT = "require_password_to_decrypt";
|
||||||
|
field public static final String TETHER_SUPPORTED = "tether_supported";
|
||||||
field public static final String THEATER_MODE_ON = "theater_mode_on";
|
field public static final String THEATER_MODE_ON = "theater_mode_on";
|
||||||
field public static final String WEBVIEW_MULTIPROCESS = "webview_multiprocess";
|
field public static final String WEBVIEW_MULTIPROCESS = "webview_multiprocess";
|
||||||
field public static final String WIFI_BADGING_THRESHOLDS = "wifi_badging_thresholds";
|
field public static final String WIFI_BADGING_THRESHOLDS = "wifi_badging_thresholds";
|
||||||
|
|||||||
@@ -111,6 +111,7 @@ import android.net.NetworkPolicyManager;
|
|||||||
import android.net.NetworkScoreManager;
|
import android.net.NetworkScoreManager;
|
||||||
import android.net.NetworkWatchlistManager;
|
import android.net.NetworkWatchlistManager;
|
||||||
import android.net.TestNetworkManager;
|
import android.net.TestNetworkManager;
|
||||||
|
import android.net.TetheringManager;
|
||||||
import android.net.lowpan.ILowpanManager;
|
import android.net.lowpan.ILowpanManager;
|
||||||
import android.net.lowpan.LowpanManager;
|
import android.net.lowpan.LowpanManager;
|
||||||
import android.net.nsd.INsdManager;
|
import android.net.nsd.INsdManager;
|
||||||
@@ -340,6 +341,17 @@ final class SystemServiceRegistry {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
registerService(Context.TETHERING_SERVICE, TetheringManager.class,
|
||||||
|
new CachedServiceFetcher<TetheringManager>() {
|
||||||
|
@Override
|
||||||
|
public TetheringManager createService(ContextImpl ctx) throws ServiceNotFoundException {
|
||||||
|
IBinder b = ServiceManager.getService(Context.TETHERING_SERVICE);
|
||||||
|
if (b == null) return null;
|
||||||
|
|
||||||
|
return new TetheringManager(ctx, b);
|
||||||
|
}});
|
||||||
|
|
||||||
|
|
||||||
registerService(Context.IPSEC_SERVICE, IpSecManager.class,
|
registerService(Context.IPSEC_SERVICE, IpSecManager.class,
|
||||||
new CachedServiceFetcher<IpSecManager>() {
|
new CachedServiceFetcher<IpSecManager>() {
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -3857,6 +3857,15 @@ public abstract class Context {
|
|||||||
*/
|
*/
|
||||||
public static final String NETWORK_STACK_SERVICE = "network_stack";
|
public static final String NETWORK_STACK_SERVICE = "network_stack";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use with {@link android.os.ServiceManager.getService()} to retrieve a
|
||||||
|
* {@link ITetheringConnector} IBinder for communicating with the tethering service
|
||||||
|
* @hide
|
||||||
|
* @see TetheringClient
|
||||||
|
*/
|
||||||
|
@SystemApi
|
||||||
|
public static final String TETHERING_SERVICE = "tethering";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use with {@link #getSystemService(String)} to retrieve a
|
* Use with {@link #getSystemService(String)} to retrieve a
|
||||||
* {@link android.net.IpSecManager} for encrypting Sockets or Networks with
|
* {@link android.net.IpSecManager} for encrypting Sockets or Networks with
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ import android.os.RemoteException;
|
|||||||
import android.os.ResultReceiver;
|
import android.os.ResultReceiver;
|
||||||
import android.os.ServiceManager;
|
import android.os.ServiceManager;
|
||||||
import android.os.ServiceSpecificException;
|
import android.os.ServiceSpecificException;
|
||||||
|
import android.os.SystemClock;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
import android.telephony.SubscriptionManager;
|
import android.telephony.SubscriptionManager;
|
||||||
import android.telephony.TelephonyManager;
|
import android.telephony.TelephonyManager;
|
||||||
@@ -57,7 +58,6 @@ import android.util.ArrayMap;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.SparseIntArray;
|
import android.util.SparseIntArray;
|
||||||
|
|
||||||
import com.android.internal.annotations.GuardedBy;
|
|
||||||
import com.android.internal.util.Preconditions;
|
import com.android.internal.util.Preconditions;
|
||||||
import com.android.internal.util.Protocol;
|
import com.android.internal.util.Protocol;
|
||||||
|
|
||||||
@@ -802,6 +802,7 @@ public class ConnectivityManager {
|
|||||||
|
|
||||||
private INetworkManagementService mNMService;
|
private INetworkManagementService mNMService;
|
||||||
private INetworkPolicyManager mNPManager;
|
private INetworkPolicyManager mNPManager;
|
||||||
|
private TetheringManager mTetheringManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests if a given integer represents a valid network type.
|
* Tests if a given integer represents a valid network type.
|
||||||
@@ -2340,6 +2341,28 @@ public class ConnectivityManager {
|
|||||||
return getInstanceOrNull();
|
return getInstanceOrNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final int TETHERING_TIMEOUT_MS = 60_000;
|
||||||
|
private final Object mTetheringLock = new Object();
|
||||||
|
|
||||||
|
private TetheringManager getTetheringManager() {
|
||||||
|
synchronized (mTetheringLock) {
|
||||||
|
if (mTetheringManager != null) {
|
||||||
|
return mTetheringManager;
|
||||||
|
}
|
||||||
|
final long before = System.currentTimeMillis();
|
||||||
|
while ((mTetheringManager = (TetheringManager) mContext.getSystemService(
|
||||||
|
Context.TETHERING_SERVICE)) == null) {
|
||||||
|
if (System.currentTimeMillis() - before > TETHERING_TIMEOUT_MS) {
|
||||||
|
Log.e(TAG, "Timeout waiting tethering service not ready yet");
|
||||||
|
throw new IllegalStateException("No tethering service yet");
|
||||||
|
}
|
||||||
|
SystemClock.sleep(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
return mTetheringManager;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the set of tetherable, available interfaces. This list is limited by
|
* Get the set of tetherable, available interfaces. This list is limited by
|
||||||
* device configuration and current interface existence.
|
* device configuration and current interface existence.
|
||||||
@@ -2351,11 +2374,7 @@ public class ConnectivityManager {
|
|||||||
@RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
|
@RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
|
||||||
@UnsupportedAppUsage
|
@UnsupportedAppUsage
|
||||||
public String[] getTetherableIfaces() {
|
public String[] getTetherableIfaces() {
|
||||||
try {
|
return getTetheringManager().getTetherableIfaces();
|
||||||
return mService.getTetherableIfaces();
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
throw e.rethrowFromSystemServer();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2368,11 +2387,7 @@ public class ConnectivityManager {
|
|||||||
@RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
|
@RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
|
||||||
@UnsupportedAppUsage
|
@UnsupportedAppUsage
|
||||||
public String[] getTetheredIfaces() {
|
public String[] getTetheredIfaces() {
|
||||||
try {
|
return getTetheringManager().getTetheredIfaces();
|
||||||
return mService.getTetheredIfaces();
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
throw e.rethrowFromSystemServer();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2391,11 +2406,7 @@ public class ConnectivityManager {
|
|||||||
@RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
|
@RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
|
||||||
@UnsupportedAppUsage
|
@UnsupportedAppUsage
|
||||||
public String[] getTetheringErroredIfaces() {
|
public String[] getTetheringErroredIfaces() {
|
||||||
try {
|
return getTetheringManager().getTetheringErroredIfaces();
|
||||||
return mService.getTetheringErroredIfaces();
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
throw e.rethrowFromSystemServer();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2406,11 +2417,7 @@ public class ConnectivityManager {
|
|||||||
*/
|
*/
|
||||||
@RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
|
@RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
|
||||||
public String[] getTetheredDhcpRanges() {
|
public String[] getTetheredDhcpRanges() {
|
||||||
try {
|
return getTetheringManager().getTetheredDhcpRanges();
|
||||||
return mService.getTetheredDhcpRanges();
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
throw e.rethrowFromSystemServer();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2439,13 +2446,7 @@ public class ConnectivityManager {
|
|||||||
*/
|
*/
|
||||||
@UnsupportedAppUsage
|
@UnsupportedAppUsage
|
||||||
public int tether(String iface) {
|
public int tether(String iface) {
|
||||||
try {
|
return getTetheringManager().tether(iface);
|
||||||
String pkgName = mContext.getOpPackageName();
|
|
||||||
Log.i(TAG, "tether caller:" + pkgName);
|
|
||||||
return mService.tether(iface, pkgName);
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
throw e.rethrowFromSystemServer();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2468,13 +2469,7 @@ public class ConnectivityManager {
|
|||||||
*/
|
*/
|
||||||
@UnsupportedAppUsage
|
@UnsupportedAppUsage
|
||||||
public int untether(String iface) {
|
public int untether(String iface) {
|
||||||
try {
|
return getTetheringManager().untether(iface);
|
||||||
String pkgName = mContext.getOpPackageName();
|
|
||||||
Log.i(TAG, "untether caller:" + pkgName);
|
|
||||||
return mService.untether(iface, pkgName);
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
throw e.rethrowFromSystemServer();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2499,16 +2494,7 @@ public class ConnectivityManager {
|
|||||||
@RequiresPermission(anyOf = {android.Manifest.permission.TETHER_PRIVILEGED,
|
@RequiresPermission(anyOf = {android.Manifest.permission.TETHER_PRIVILEGED,
|
||||||
android.Manifest.permission.WRITE_SETTINGS})
|
android.Manifest.permission.WRITE_SETTINGS})
|
||||||
public boolean isTetheringSupported() {
|
public boolean isTetheringSupported() {
|
||||||
String pkgName = mContext.getOpPackageName();
|
return getTetheringManager().isTetheringSupported();
|
||||||
try {
|
|
||||||
return mService.isTetheringSupported(pkgName);
|
|
||||||
} catch (SecurityException e) {
|
|
||||||
// This API is not available to this caller, but for backward-compatibility
|
|
||||||
// this will just return false instead of throwing.
|
|
||||||
return false;
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
throw e.rethrowFromSystemServer();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2577,14 +2563,7 @@ public class ConnectivityManager {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
getTetheringManager().startTethering(type, wrappedCallback, showProvisioningUi);
|
||||||
String pkgName = mContext.getOpPackageName();
|
|
||||||
Log.i(TAG, "startTethering caller:" + pkgName);
|
|
||||||
mService.startTethering(type, wrappedCallback, showProvisioningUi, pkgName);
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
Log.e(TAG, "Exception trying to start tethering.", e);
|
|
||||||
wrappedCallback.send(TETHER_ERROR_SERVICE_UNAVAIL, null);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2600,13 +2579,7 @@ public class ConnectivityManager {
|
|||||||
@SystemApi
|
@SystemApi
|
||||||
@RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
|
@RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
|
||||||
public void stopTethering(int type) {
|
public void stopTethering(int type) {
|
||||||
try {
|
getTetheringManager().stopTethering(type);
|
||||||
String pkgName = mContext.getOpPackageName();
|
|
||||||
Log.i(TAG, "stopTethering caller:" + pkgName);
|
|
||||||
mService.stopTethering(type, pkgName);
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
throw e.rethrowFromSystemServer();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2628,10 +2601,6 @@ public class ConnectivityManager {
|
|||||||
public void onUpstreamChanged(@Nullable Network network) {}
|
public void onUpstreamChanged(@Nullable Network network) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
@GuardedBy("mTetheringEventCallbacks")
|
|
||||||
private final ArrayMap<OnTetheringEventCallback, ITetheringEventCallback>
|
|
||||||
mTetheringEventCallbacks = new ArrayMap<>();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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 when tethering has no upstream or
|
* tethering status right away. If callback is registered when tethering has no upstream or
|
||||||
@@ -2649,27 +2618,7 @@ public class ConnectivityManager {
|
|||||||
@NonNull final OnTetheringEventCallback callback) {
|
@NonNull final OnTetheringEventCallback callback) {
|
||||||
Preconditions.checkNotNull(callback, "OnTetheringEventCallback cannot be null.");
|
Preconditions.checkNotNull(callback, "OnTetheringEventCallback cannot be null.");
|
||||||
|
|
||||||
synchronized (mTetheringEventCallbacks) {
|
getTetheringManager().registerTetheringEventCallback(executor, callback);
|
||||||
Preconditions.checkArgument(!mTetheringEventCallbacks.containsKey(callback),
|
|
||||||
"callback was already registered.");
|
|
||||||
ITetheringEventCallback remoteCallback = new ITetheringEventCallback.Stub() {
|
|
||||||
@Override
|
|
||||||
public void onUpstreamChanged(Network network) throws RemoteException {
|
|
||||||
Binder.withCleanCallingIdentity(() ->
|
|
||||||
executor.execute(() -> {
|
|
||||||
callback.onUpstreamChanged(network);
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
try {
|
|
||||||
String pkgName = mContext.getOpPackageName();
|
|
||||||
Log.i(TAG, "registerTetheringUpstreamCallback:" + pkgName);
|
|
||||||
mService.registerTetheringEventCallback(remoteCallback, pkgName);
|
|
||||||
mTetheringEventCallbacks.put(callback, remoteCallback);
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
throw e.rethrowFromSystemServer();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2683,17 +2632,7 @@ public class ConnectivityManager {
|
|||||||
@RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
|
@RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
|
||||||
public void unregisterTetheringEventCallback(
|
public void unregisterTetheringEventCallback(
|
||||||
@NonNull final OnTetheringEventCallback callback) {
|
@NonNull final OnTetheringEventCallback callback) {
|
||||||
synchronized (mTetheringEventCallbacks) {
|
getTetheringManager().unregisterTetheringEventCallback(callback);
|
||||||
ITetheringEventCallback remoteCallback = mTetheringEventCallbacks.remove(callback);
|
|
||||||
Preconditions.checkNotNull(remoteCallback, "callback was not registered.");
|
|
||||||
try {
|
|
||||||
String pkgName = mContext.getOpPackageName();
|
|
||||||
Log.i(TAG, "unregisterTetheringEventCallback:" + pkgName);
|
|
||||||
mService.unregisterTetheringEventCallback(remoteCallback, pkgName);
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
throw e.rethrowFromSystemServer();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -2710,11 +2649,7 @@ public class ConnectivityManager {
|
|||||||
@RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
|
@RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
|
||||||
@UnsupportedAppUsage
|
@UnsupportedAppUsage
|
||||||
public String[] getTetherableUsbRegexs() {
|
public String[] getTetherableUsbRegexs() {
|
||||||
try {
|
return getTetheringManager().getTetherableUsbRegexs();
|
||||||
return mService.getTetherableUsbRegexs();
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
throw e.rethrowFromSystemServer();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2730,11 +2665,7 @@ public class ConnectivityManager {
|
|||||||
@RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
|
@RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
|
||||||
@UnsupportedAppUsage
|
@UnsupportedAppUsage
|
||||||
public String[] getTetherableWifiRegexs() {
|
public String[] getTetherableWifiRegexs() {
|
||||||
try {
|
return getTetheringManager().getTetherableWifiRegexs();
|
||||||
return mService.getTetherableWifiRegexs();
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
throw e.rethrowFromSystemServer();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2750,11 +2681,7 @@ public class ConnectivityManager {
|
|||||||
@RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
|
@RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
|
||||||
@UnsupportedAppUsage
|
@UnsupportedAppUsage
|
||||||
public String[] getTetherableBluetoothRegexs() {
|
public String[] getTetherableBluetoothRegexs() {
|
||||||
try {
|
return getTetheringManager().getTetherableBluetoothRegexs();
|
||||||
return mService.getTetherableBluetoothRegexs();
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
throw e.rethrowFromSystemServer();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2776,13 +2703,7 @@ public class ConnectivityManager {
|
|||||||
*/
|
*/
|
||||||
@UnsupportedAppUsage
|
@UnsupportedAppUsage
|
||||||
public int setUsbTethering(boolean enable) {
|
public int setUsbTethering(boolean enable) {
|
||||||
try {
|
return getTetheringManager().setUsbTethering(enable);
|
||||||
String pkgName = mContext.getOpPackageName();
|
|
||||||
Log.i(TAG, "setUsbTethering caller:" + pkgName);
|
|
||||||
return mService.setUsbTethering(enable, pkgName);
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
throw e.rethrowFromSystemServer();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@hide} */
|
/** {@hide} */
|
||||||
@@ -2830,11 +2751,7 @@ public class ConnectivityManager {
|
|||||||
@RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
|
@RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
|
||||||
@UnsupportedAppUsage
|
@UnsupportedAppUsage
|
||||||
public int getLastTetherError(String iface) {
|
public int getLastTetherError(String iface) {
|
||||||
try {
|
return getTetheringManager().getLastTetherError(iface);
|
||||||
return mService.getLastTetherError(iface);
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
throw e.rethrowFromSystemServer();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
@@ -2900,14 +2817,8 @@ public class ConnectivityManager {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
getTetheringManager().requestLatestTetheringEntitlementResult(type, wrappedListener,
|
||||||
String pkgName = mContext.getOpPackageName();
|
showEntitlementUi);
|
||||||
Log.i(TAG, "getLatestTetheringEntitlementResult:" + pkgName);
|
|
||||||
mService.getLatestTetheringEntitlementResult(type, wrappedListener,
|
|
||||||
showEntitlementUi, pkgName);
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
throw e.rethrowFromSystemServer();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -4332,6 +4243,7 @@ public class ConnectivityManager {
|
|||||||
public void factoryReset() {
|
public void factoryReset() {
|
||||||
try {
|
try {
|
||||||
mService.factoryReset();
|
mService.factoryReset();
|
||||||
|
getTetheringManager().stopAllTethering();
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
throw e.rethrowFromSystemServer();
|
throw e.rethrowFromSystemServer();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ package android.net;
|
|||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.net.ConnectionInfo;
|
import android.net.ConnectionInfo;
|
||||||
import android.net.LinkProperties;
|
import android.net.LinkProperties;
|
||||||
import android.net.ITetheringEventCallback;
|
|
||||||
import android.net.Network;
|
import android.net.Network;
|
||||||
import android.net.NetworkCapabilities;
|
import android.net.NetworkCapabilities;
|
||||||
import android.net.NetworkInfo;
|
import android.net.NetworkInfo;
|
||||||
@@ -78,41 +77,31 @@ interface IConnectivityManager
|
|||||||
|
|
||||||
boolean requestRouteToHostAddress(int networkType, in byte[] hostAddress);
|
boolean requestRouteToHostAddress(int networkType, in byte[] hostAddress);
|
||||||
|
|
||||||
int tether(String iface, String callerPkg);
|
@UnsupportedAppUsage(maxTargetSdk = 29,
|
||||||
|
publicAlternatives = "Use {@code TetheringManager#getLastTetherError} as alternative")
|
||||||
int untether(String iface, String callerPkg);
|
|
||||||
|
|
||||||
@UnsupportedAppUsage
|
|
||||||
int getLastTetherError(String iface);
|
int getLastTetherError(String iface);
|
||||||
|
|
||||||
boolean isTetheringSupported(String callerPkg);
|
@UnsupportedAppUsage(maxTargetSdk = 29,
|
||||||
|
publicAlternatives = "Use {@code TetheringManager#getTetherableIfaces} as alternative")
|
||||||
void startTethering(int type, in ResultReceiver receiver, boolean showProvisioningUi,
|
|
||||||
String callerPkg);
|
|
||||||
|
|
||||||
void stopTethering(int type, String callerPkg);
|
|
||||||
|
|
||||||
@UnsupportedAppUsage
|
|
||||||
String[] getTetherableIfaces();
|
String[] getTetherableIfaces();
|
||||||
|
|
||||||
@UnsupportedAppUsage
|
@UnsupportedAppUsage(maxTargetSdk = 29,
|
||||||
|
publicAlternatives = "Use {@code TetheringManager#getTetheredIfaces} as alternative")
|
||||||
String[] getTetheredIfaces();
|
String[] getTetheredIfaces();
|
||||||
|
|
||||||
@UnsupportedAppUsage
|
@UnsupportedAppUsage(maxTargetSdk = 29,
|
||||||
|
publicAlternatives = "Use {@code TetheringManager#getTetheringErroredIfaces} "
|
||||||
|
+ "as Alternative")
|
||||||
String[] getTetheringErroredIfaces();
|
String[] getTetheringErroredIfaces();
|
||||||
|
|
||||||
String[] getTetheredDhcpRanges();
|
@UnsupportedAppUsage(maxTargetSdk = 29,
|
||||||
|
publicAlternatives = "Use {@code TetheringManager#getTetherableUsbRegexs} as alternative")
|
||||||
@UnsupportedAppUsage
|
|
||||||
String[] getTetherableUsbRegexs();
|
String[] getTetherableUsbRegexs();
|
||||||
|
|
||||||
@UnsupportedAppUsage
|
@UnsupportedAppUsage(maxTargetSdk = 29,
|
||||||
|
publicAlternatives = "Use {@code TetheringManager#getTetherableWifiRegexs} as alternative")
|
||||||
String[] getTetherableWifiRegexs();
|
String[] getTetherableWifiRegexs();
|
||||||
|
|
||||||
String[] getTetherableBluetoothRegexs();
|
|
||||||
|
|
||||||
int setUsbTethering(boolean enable, String callerPkg);
|
|
||||||
|
|
||||||
@UnsupportedAppUsage(maxTargetSdk = 28)
|
@UnsupportedAppUsage(maxTargetSdk = 28)
|
||||||
void reportInetCondition(int networkType, int percentage);
|
void reportInetCondition(int networkType, int percentage);
|
||||||
|
|
||||||
@@ -217,11 +206,5 @@ interface IConnectivityManager
|
|||||||
boolean isCallerCurrentAlwaysOnVpnApp();
|
boolean isCallerCurrentAlwaysOnVpnApp();
|
||||||
boolean isCallerCurrentAlwaysOnVpnLockdownApp();
|
boolean isCallerCurrentAlwaysOnVpnLockdownApp();
|
||||||
|
|
||||||
void getLatestTetheringEntitlementResult(int type, in ResultReceiver receiver,
|
|
||||||
boolean showEntitlementUi, String callerPkg);
|
|
||||||
|
|
||||||
void registerTetheringEventCallback(ITetheringEventCallback callback, String callerPkg);
|
|
||||||
void unregisterTetheringEventCallback(ITetheringEventCallback callback, String callerPkg);
|
|
||||||
|
|
||||||
IBinder startOrGetTestNetworkService();
|
IBinder startOrGetTestNetworkService();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10402,35 +10402,37 @@ public final class Settings {
|
|||||||
*/
|
*/
|
||||||
public static final String SMS_SHORT_CODE_RULE = "sms_short_code_rule";
|
public static final String SMS_SHORT_CODE_RULE = "sms_short_code_rule";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to select TCP's default initial receiver window size in segments - defaults to a build config value
|
* Used to select TCP's default initial receiver window size in segments - defaults to a
|
||||||
* @hide
|
* build config value.
|
||||||
*/
|
* @hide
|
||||||
public static final String TCP_DEFAULT_INIT_RWND = "tcp_default_init_rwnd";
|
*/
|
||||||
|
public static final String TCP_DEFAULT_INIT_RWND = "tcp_default_init_rwnd";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to disable Tethering on a device - defaults to true
|
* Used to disable Tethering on a device - defaults to true.
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public static final String TETHER_SUPPORTED = "tether_supported";
|
@SystemApi
|
||||||
|
public static final String TETHER_SUPPORTED = "tether_supported";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to require DUN APN on the device or not - defaults to a build config value
|
* Used to require DUN APN on the device or not - defaults to a build config value
|
||||||
* which defaults to false
|
* which defaults to false.
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public static final String TETHER_DUN_REQUIRED = "tether_dun_required";
|
public static final String TETHER_DUN_REQUIRED = "tether_dun_required";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to hold a gservices-provisioned apn value for DUN. If set, or the
|
* Used to hold a gservices-provisioned apn value for DUN. If set, or the
|
||||||
* corresponding build config values are set it will override the APN DB
|
* corresponding build config values are set it will override the APN DB
|
||||||
* values.
|
* values.
|
||||||
* Consists of a comma seperated list of strings:
|
* Consists of a comma separated list of strings:
|
||||||
* "name,apn,proxy,port,username,password,server,mmsc,mmsproxy,mmsport,mcc,mnc,auth,type"
|
* "name,apn,proxy,port,username,password,server,mmsc,mmsproxy,mmsport,mcc,mnc,auth,type"
|
||||||
* note that empty fields can be omitted: "name,apn,,,,,,,,,310,260,,DUN"
|
* note that empty fields can be omitted: "name,apn,,,,,,,,,310,260,,DUN"
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public static final String TETHER_DUN_APN = "tether_dun_apn";
|
public static final String TETHER_DUN_APN = "tether_dun_apn";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to disable trying to talk to any available tethering offload HAL.
|
* Used to disable trying to talk to any available tethering offload HAL.
|
||||||
|
|||||||
@@ -57,4 +57,7 @@ platform cert need to be included, as apps signed with the platform cert are exe
|
|||||||
<hidden-api-whitelisted-app package="com.android.terminal" />
|
<hidden-api-whitelisted-app package="com.android.terminal" />
|
||||||
<hidden-api-whitelisted-app package="com.android.wallpaper" />
|
<hidden-api-whitelisted-app package="com.android.wallpaper" />
|
||||||
<hidden-api-whitelisted-app package="jp.co.omronsoft.openwnn" />
|
<hidden-api-whitelisted-app package="jp.co.omronsoft.openwnn" />
|
||||||
|
<!-- STOPSHIP: Remove this when fixing all @hide usage for tethering.-->
|
||||||
|
<hidden-api-whitelisted-app package="com.android.networkstack.tethering" />
|
||||||
|
<hidden-api-whitelisted-app package="com.android.networkstack" />
|
||||||
</config>
|
</config>
|
||||||
|
|||||||
@@ -29,9 +29,11 @@ java_defaults {
|
|||||||
"netlink-client",
|
"netlink-client",
|
||||||
"networkstack-aidl-interfaces-unstable-java",
|
"networkstack-aidl-interfaces-unstable-java",
|
||||||
"android.hardware.tetheroffload.control-V1.0-java",
|
"android.hardware.tetheroffload.control-V1.0-java",
|
||||||
"tethering-client",
|
|
||||||
],
|
],
|
||||||
libs: ["unsupportedappusage"],
|
libs: [
|
||||||
|
"framework-tethering",
|
||||||
|
],
|
||||||
|
|
||||||
manifest: "AndroidManifestBase.xml",
|
manifest: "AndroidManifestBase.xml",
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,6 +92,10 @@ java_defaults {
|
|||||||
resource_dirs: [
|
resource_dirs: [
|
||||||
"res",
|
"res",
|
||||||
],
|
],
|
||||||
|
libs: [
|
||||||
|
"framework-tethering",
|
||||||
|
],
|
||||||
|
jarjar_rules: "jarjar-rules.txt",
|
||||||
optimize: {
|
optimize: {
|
||||||
proguard_flags_files: ["proguard.flags"],
|
proguard_flags_files: ["proguard.flags"],
|
||||||
},
|
},
|
||||||
@@ -104,7 +110,6 @@ android_app {
|
|||||||
manifest: "AndroidManifest_InProcess.xml",
|
manifest: "AndroidManifest_InProcess.xml",
|
||||||
// InProcessTethering is a replacement for Tethering
|
// InProcessTethering is a replacement for Tethering
|
||||||
overrides: ["Tethering"],
|
overrides: ["Tethering"],
|
||||||
// TODO: use PlatformNetworkPermissionConfig.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Updatable tethering packaged as an application
|
// Updatable tethering packaged as an application
|
||||||
|
|||||||
@@ -21,6 +21,21 @@
|
|||||||
android:sharedUserId="android.uid.networkstack">
|
android:sharedUserId="android.uid.networkstack">
|
||||||
<uses-sdk android:minSdkVersion="29" android:targetSdkVersion="29" />
|
<uses-sdk android:minSdkVersion="29" android:targetSdkVersion="29" />
|
||||||
|
|
||||||
|
<!-- Permissions must be defined here, and not in the base manifest, as the tethering
|
||||||
|
running in the system server process does not need any permission, and having
|
||||||
|
privileged permissions added would cause crashes on startup unless they are also
|
||||||
|
added to the privileged permissions whitelist for that package. -->
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||||
|
<uses-permission android:name="android.permission.BLUETOOTH" />
|
||||||
|
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
|
||||||
|
<uses-permission android:name="android.permission.BROADCAST_STICKY" />
|
||||||
|
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
|
||||||
|
<uses-permission android:name="android.permission.MANAGE_USB" />
|
||||||
|
<uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />
|
||||||
|
<uses-permission android:name="android.permission.READ_NETWORK_USAGE_HISTORY" />
|
||||||
|
<uses-permission android:name="android.permission.UPDATE_APP_OPS_STATS" />
|
||||||
|
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:process="com.android.networkstack.process"
|
android:process="com.android.networkstack.process"
|
||||||
android:extractNativeLibs="false"
|
android:extractNativeLibs="false"
|
||||||
|
|||||||
@@ -22,11 +22,9 @@
|
|||||||
android:process="system">
|
android:process="system">
|
||||||
<uses-sdk android:minSdkVersion="29" android:targetSdkVersion="29" />
|
<uses-sdk android:minSdkVersion="29" android:targetSdkVersion="29" />
|
||||||
<application>
|
<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"
|
<service android:name="com.android.server.connectivity.tethering.TetheringService"
|
||||||
android:process="system"
|
android:process="system"
|
||||||
android:permission="android.permission.NETWORK_STACK">
|
android:permission="android.permission.MAINLINE_NETWORK_STACK">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.net.ITetheringConnector.InProcess"/>
|
<action android:name="android.net.ITetheringConnector.InProcess"/>
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
|||||||
@@ -46,6 +46,12 @@
|
|||||||
|
|
||||||
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/priv-app/Tethering)
|
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/priv-app/Tethering)
|
||||||
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/priv-app/InProcessTethering)
|
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/priv-app/InProcessTethering)
|
||||||
|
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/InProcessTethering*)
|
||||||
|
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/APPS/InProcessTethering*)
|
||||||
|
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system_other/system/priv-app/InProcessTethering)
|
||||||
|
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/apex/com.android.tethering)
|
||||||
|
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/apex/com.android.tethering.apex)
|
||||||
|
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/ETC/com.android.tethering*)
|
||||||
|
|
||||||
# ******************************************************************
|
# ******************************************************************
|
||||||
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST ABOVE THIS BANNER
|
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST ABOVE THIS BANNER
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
apex {
|
apex {
|
||||||
name: "com.android.tethering",
|
name: "com.android.tethering",
|
||||||
|
java_libs: ["framework-tethering"],
|
||||||
apps: ["Tethering"],
|
apps: ["Tethering"],
|
||||||
manifest: "manifest.json",
|
manifest: "manifest.json",
|
||||||
key: "com.android.tethering.key",
|
key: "com.android.tethering.key",
|
||||||
|
|||||||
@@ -12,7 +12,6 @@
|
|||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
|
||||||
|
|
||||||
// AIDL interfaces between the core system and the tethering mainline module.
|
// AIDL interfaces between the core system and the tethering mainline module.
|
||||||
aidl_interface {
|
aidl_interface {
|
||||||
@@ -20,10 +19,7 @@ aidl_interface {
|
|||||||
local_include_dir: "src",
|
local_include_dir: "src",
|
||||||
include_dirs: ["frameworks/base/core/java"], // For framework parcelables.
|
include_dirs: ["frameworks/base/core/java"], // For framework parcelables.
|
||||||
srcs: [
|
srcs: [
|
||||||
"src/android/net/ITetherInternalCallback.aidl",
|
"src/android/net/*.aidl",
|
||||||
"src/android/net/ITetheringConnector.aidl",
|
|
||||||
"src/android/net/TetheringConfigurationParcel.aidl",
|
|
||||||
"src/android/net/TetherStatesParcel.aidl",
|
|
||||||
],
|
],
|
||||||
backend: {
|
backend: {
|
||||||
ndk: {
|
ndk: {
|
||||||
@@ -36,16 +32,32 @@ aidl_interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
java_library {
|
java_library {
|
||||||
name: "tethering-client",
|
name: "framework-tethering",
|
||||||
sdk_version: "system_current",
|
sdk_version: "system_current",
|
||||||
|
srcs: [
|
||||||
|
"src/android/net/TetheringManager.java",
|
||||||
|
":framework-tethering-annotations",
|
||||||
|
],
|
||||||
static_libs: [
|
static_libs: [
|
||||||
"tethering-aidl-interfaces-java",
|
"tethering-aidl-interfaces-java",
|
||||||
],
|
],
|
||||||
|
jarjar_rules: "jarjar-rules.txt",
|
||||||
|
installable: true,
|
||||||
|
|
||||||
|
libs: [
|
||||||
|
"android_system_stubs_current",
|
||||||
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is temporary file group which would be removed after TetheringManager is built
|
|
||||||
// into tethering-client. Will be done by aosp/1156906.
|
|
||||||
filegroup {
|
filegroup {
|
||||||
name: "tethering-manager",
|
name: "framework-tethering-srcs",
|
||||||
srcs: ["src/android/net/TetheringManager.java"],
|
srcs: [
|
||||||
|
"src/android/net/TetheringManager.java",
|
||||||
|
"src/android/net/IIntResultListener.aidl",
|
||||||
|
"src/android/net/ITetheringEventCallback.aidl",
|
||||||
|
"src/android/net/ITetheringConnector.aidl",
|
||||||
|
"src/android/net/TetheringConfigurationParcel.aidl",
|
||||||
|
"src/android/net/TetherStatesParcel.aidl",
|
||||||
|
],
|
||||||
|
path: "src"
|
||||||
}
|
}
|
||||||
|
|||||||
1
packages/Tethering/common/TetheringLib/jarjar-rules.txt
Normal file
1
packages/Tethering/common/TetheringLib/jarjar-rules.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
rule android.annotation.** com.android.networkstack.tethering.annotation.@1
|
||||||
@@ -16,13 +16,10 @@
|
|||||||
|
|
||||||
package android.net;
|
package android.net;
|
||||||
|
|
||||||
import android.net.Network;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback class for receiving tethering changed events
|
* Listener interface allowing objects to listen to various module event.
|
||||||
* @hide
|
* {@hide}
|
||||||
*/
|
*/
|
||||||
oneway interface ITetheringEventCallback
|
oneway interface IIntResultListener {
|
||||||
{
|
void onResult(int resultCode);
|
||||||
void onUpstreamChanged(in Network network);
|
|
||||||
}
|
}
|
||||||
@@ -15,23 +15,31 @@
|
|||||||
*/
|
*/
|
||||||
package android.net;
|
package android.net;
|
||||||
|
|
||||||
import android.net.ITetherInternalCallback;
|
import android.net.IIntResultListener;
|
||||||
|
import android.net.ITetheringEventCallback;
|
||||||
import android.os.ResultReceiver;
|
import android.os.ResultReceiver;
|
||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
oneway interface ITetheringConnector {
|
oneway interface ITetheringConnector {
|
||||||
void tether(String iface);
|
void tether(String iface, String callerPkg, IIntResultListener receiver);
|
||||||
|
|
||||||
void untether(String iface);
|
void untether(String iface, String callerPkg, IIntResultListener receiver);
|
||||||
|
|
||||||
void setUsbTethering(boolean enable);
|
void setUsbTethering(boolean enable, String callerPkg, IIntResultListener receiver);
|
||||||
|
|
||||||
void startTethering(int type, in ResultReceiver receiver, boolean showProvisioningUi);
|
void startTethering(int type, in ResultReceiver receiver, boolean showProvisioningUi,
|
||||||
|
String callerPkg);
|
||||||
|
|
||||||
void stopTethering(int type);
|
void stopTethering(int type, String callerPkg, IIntResultListener receiver);
|
||||||
|
|
||||||
void requestLatestTetheringEntitlementResult(int type, in ResultReceiver receiver,
|
void requestLatestTetheringEntitlementResult(int type, in ResultReceiver receiver,
|
||||||
boolean showEntitlementUi);
|
boolean showEntitlementUi, String callerPkg);
|
||||||
|
|
||||||
void registerTetherInternalCallback(ITetherInternalCallback callback);
|
void registerTetheringEventCallback(ITetheringEventCallback callback, String callerPkg);
|
||||||
|
|
||||||
|
void unregisterTetheringEventCallback(ITetheringEventCallback callback, String callerPkg);
|
||||||
|
|
||||||
|
void isTetheringSupported(String callerPkg, IIntResultListener receiver);
|
||||||
|
|
||||||
|
void stopAllTethering(String callerPkg, IIntResultListener receiver);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,14 +21,15 @@ import android.net.TetheringConfigurationParcel;
|
|||||||
import android.net.TetherStatesParcel;
|
import android.net.TetherStatesParcel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback class for receiving tethering changed events
|
* Callback class for receiving tethering changed events.
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
oneway interface ITetherInternalCallback
|
oneway interface ITetheringEventCallback
|
||||||
{
|
{
|
||||||
|
void onCallbackStarted(in Network network, in TetheringConfigurationParcel config,
|
||||||
|
in TetherStatesParcel states);
|
||||||
|
void onCallbackStopped(int errorCode);
|
||||||
void onUpstreamChanged(in Network network);
|
void onUpstreamChanged(in Network network);
|
||||||
void onConfigurationChanged(in TetheringConfigurationParcel config);
|
void onConfigurationChanged(in TetheringConfigurationParcel config);
|
||||||
void onTetherStatesChanged(in TetherStatesParcel states);
|
void onTetherStatesChanged(in TetherStatesParcel states);
|
||||||
void onCallbackCreated(in Network network, in TetheringConfigurationParcel config,
|
|
||||||
in TetherStatesParcel states);
|
|
||||||
}
|
}
|
||||||
@@ -15,94 +15,141 @@
|
|||||||
*/
|
*/
|
||||||
package android.net;
|
package android.net;
|
||||||
|
|
||||||
import static android.Manifest.permission.NETWORK_STACK;
|
|
||||||
import static android.net.ConnectivityManager.TETHER_ERROR_NO_ERROR;
|
import static android.net.ConnectivityManager.TETHER_ERROR_NO_ERROR;
|
||||||
import static android.net.ConnectivityManager.TETHER_ERROR_SERVICE_UNAVAIL;
|
|
||||||
|
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.annotation.Nullable;
|
import android.content.Context;
|
||||||
import android.net.util.SharedLog;
|
import android.net.ConnectivityManager.OnTetheringEventCallback;
|
||||||
import android.os.ConditionVariable;
|
import android.os.ConditionVariable;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.RemoteCallbackList;
|
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.os.ResultReceiver;
|
import android.os.ResultReceiver;
|
||||||
import android.util.Slog;
|
import android.util.ArrayMap;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
import com.android.internal.annotations.GuardedBy;
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
|
||||||
import java.util.StringJoiner;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service used to communicate with the tethering, which is running in a separate module.
|
* This class provides the APIs to control the tethering service.
|
||||||
|
* <p> The primary responsibilities of this class are to provide the APIs for applications to
|
||||||
|
* start tethering, stop tethering, query configuration and query status.
|
||||||
|
*
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
|
// TODO: make it @SystemApi
|
||||||
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 TetheringManager sInstance;
|
private static TetheringManager sInstance;
|
||||||
|
|
||||||
@Nullable
|
private final ITetheringConnector mConnector;
|
||||||
private ITetheringConnector mConnector;
|
private final TetheringCallbackInternal mCallback;
|
||||||
private TetherInternalCallback mCallback;
|
private final Context mContext;
|
||||||
private Network mTetherUpstream;
|
private final ArrayMap<OnTetheringEventCallback, ITetheringEventCallback>
|
||||||
|
mTetheringEventCallbacks = new ArrayMap<>();
|
||||||
|
|
||||||
private TetheringConfigurationParcel mTetheringConfiguration;
|
private TetheringConfigurationParcel mTetheringConfiguration;
|
||||||
private TetherStatesParcel mTetherStatesParcel;
|
private TetherStatesParcel mTetherStatesParcel;
|
||||||
|
|
||||||
private final RemoteCallbackList<ITetheringEventCallback> mTetheringEventCallbacks =
|
public static final int TETHER_ERROR_NO_ERROR = 0;
|
||||||
new RemoteCallbackList<>();
|
public static final int TETHER_ERROR_UNKNOWN_IFACE = 1;
|
||||||
@GuardedBy("mLog")
|
public static final int TETHER_ERROR_SERVICE_UNAVAIL = 2;
|
||||||
private final SharedLog mLog = new SharedLog(TAG);
|
public static final int TETHER_ERROR_UNSUPPORTED = 3;
|
||||||
|
public static final int TETHER_ERROR_UNAVAIL_IFACE = 4;
|
||||||
private TetheringManager() { }
|
public static final int TETHER_ERROR_MASTER_ERROR = 5;
|
||||||
|
public static final int TETHER_ERROR_TETHER_IFACE_ERROR = 6;
|
||||||
|
public static final int TETHER_ERROR_UNTETHER_IFACE_ERROR = 7;
|
||||||
|
public static final int TETHER_ERROR_ENABLE_NAT_ERROR = 8;
|
||||||
|
public static final int TETHER_ERROR_DISABLE_NAT_ERROR = 9;
|
||||||
|
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_DHCPSERVER_ERROR = 12;
|
||||||
|
public static final int TETHER_ERROR_ENTITLEMENT_UNKONWN = 13;
|
||||||
|
public static final int TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION = 14;
|
||||||
|
public static final int TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION = 15;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the TetheringManager singleton instance.
|
* Create a TetheringManager object for interacting with the tethering service.
|
||||||
*/
|
*/
|
||||||
public static synchronized TetheringManager getInstance() {
|
public TetheringManager(@NonNull final Context context, @NonNull final IBinder service) {
|
||||||
if (sInstance == null) {
|
mContext = context;
|
||||||
sInstance = new TetheringManager();
|
mConnector = ITetheringConnector.Stub.asInterface(service);
|
||||||
}
|
mCallback = new TetheringCallbackInternal();
|
||||||
return sInstance;
|
|
||||||
}
|
|
||||||
|
|
||||||
private class TetheringConnection implements
|
final String pkgName = mContext.getOpPackageName();
|
||||||
ConnectivityModuleConnector.ModuleServiceCallback {
|
Log.i(TAG, "registerTetheringEventCallback:" + pkgName);
|
||||||
@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 {
|
try {
|
||||||
mConnector.registerTetherInternalCallback(mCallback);
|
mConnector.registerTetheringEventCallback(mCallback, pkgName);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
e.rethrowFromSystemServer();
|
throw new IllegalStateException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class TetherInternalCallback extends ITetherInternalCallback.Stub {
|
private interface RequestHelper {
|
||||||
private final ConditionVariable mWaitForCallback = new ConditionVariable(false);
|
void runRequest(IIntResultListener listener);
|
||||||
private static final int EVENT_CALLBACK_TIMEOUT_MS = 60_000;
|
}
|
||||||
|
|
||||||
|
private class RequestDispatcher {
|
||||||
|
private final ConditionVariable mWaiting;
|
||||||
|
public int mRemoteResult;
|
||||||
|
|
||||||
|
private final IIntResultListener mListener = new IIntResultListener.Stub() {
|
||||||
|
@Override
|
||||||
|
public void onResult(final int resultCode) {
|
||||||
|
mRemoteResult = resultCode;
|
||||||
|
mWaiting.open();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
RequestDispatcher() {
|
||||||
|
mWaiting = new ConditionVariable();
|
||||||
|
}
|
||||||
|
|
||||||
|
int waitForResult(final RequestHelper request) {
|
||||||
|
request.runRequest(mListener);
|
||||||
|
if (!mWaiting.block(DEFAULT_TIMEOUT_MS)) {
|
||||||
|
throw new IllegalStateException("Callback timeout");
|
||||||
|
}
|
||||||
|
|
||||||
|
throwIfPermissionFailure(mRemoteResult);
|
||||||
|
|
||||||
|
return mRemoteResult;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void throwIfPermissionFailure(final int errorCode) {
|
||||||
|
switch (errorCode) {
|
||||||
|
case TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION:
|
||||||
|
throw new SecurityException("No android.permission.TETHER_PRIVILEGED"
|
||||||
|
+ " or android.permission.WRITE_SETTINGS permission");
|
||||||
|
case TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION:
|
||||||
|
throw new SecurityException(
|
||||||
|
"No android.permission.ACCESS_NETWORK_STATE permission");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TetheringCallbackInternal extends ITetheringEventCallback.Stub {
|
||||||
|
private int mError = TETHER_ERROR_NO_ERROR;
|
||||||
|
private final ConditionVariable mWaitForCallback = new ConditionVariable();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onUpstreamChanged(Network network) {
|
public void onCallbackStarted(Network network, TetheringConfigurationParcel config,
|
||||||
mTetherUpstream = network;
|
TetherStatesParcel states) {
|
||||||
reportUpstreamChanged(network);
|
mTetheringConfiguration = config;
|
||||||
|
mTetherStatesParcel = states;
|
||||||
|
mWaitForCallback.open();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCallbackStopped(int errorCode) {
|
||||||
|
mError = errorCode;
|
||||||
|
mWaitForCallback.open();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onUpstreamChanged(Network network) { }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onConfigurationChanged(TetheringConfigurationParcel config) {
|
public void onConfigurationChanged(TetheringConfigurationParcel config) {
|
||||||
mTetheringConfiguration = config;
|
mTetheringConfiguration = config;
|
||||||
@@ -113,49 +160,10 @@ public class TetheringManager {
|
|||||||
mTetherStatesParcel = states;
|
mTetherStatesParcel = states;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public void waitForStarted() {
|
||||||
public void onCallbackCreated(Network network, TetheringConfigurationParcel config,
|
mWaitForCallback.block(DEFAULT_TIMEOUT_MS);
|
||||||
TetherStatesParcel states) {
|
throwIfPermissionFailure(mError);
|
||||||
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");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -165,108 +173,110 @@ public class TetheringManager {
|
|||||||
* IP network interface is available, dhcp will still run and traffic will be
|
* IP network interface is available, dhcp will still run and traffic will be
|
||||||
* allowed between the tethered devices and this device, though upstream net
|
* allowed between the tethered devices and this device, though upstream net
|
||||||
* access will of course fail until an upstream network interface becomes
|
* 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
|
* active.
|
||||||
* #getTetherableIfaces() to ensure corresponding interface is available for
|
|
||||||
* tethering before calling #tether().
|
|
||||||
*
|
*
|
||||||
* @deprecated The only usages should be in PanService and Wifi P2P which
|
* @deprecated The only usages is PanService. It uses this for legacy reasons
|
||||||
* need direct access.
|
* and will migrate away as soon as possible.
|
||||||
*
|
*
|
||||||
* {@hide}
|
* @param iface the interface name to tether.
|
||||||
|
* @return error a {@code TETHER_ERROR} value indicating success or failure type
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public int tether(@NonNull String iface) {
|
public int tether(@NonNull final String iface) {
|
||||||
if (mConnector == null) {
|
final String callerPkg = mContext.getOpPackageName();
|
||||||
Slog.wtf(TAG, "Tethering not ready yet");
|
Log.i(TAG, "tether caller:" + callerPkg);
|
||||||
return TETHER_ERROR_SERVICE_UNAVAIL;
|
final RequestDispatcher dispatcher = new RequestDispatcher();
|
||||||
}
|
|
||||||
try {
|
return dispatcher.waitForResult(listener -> {
|
||||||
mConnector.tether(iface);
|
try {
|
||||||
} catch (RemoteException e) {
|
mConnector.tether(iface, callerPkg, listener);
|
||||||
e.rethrowFromSystemServer();
|
} catch (RemoteException e) {
|
||||||
}
|
throw new IllegalStateException(e);
|
||||||
return TETHER_ERROR_NO_ERROR;
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stop tethering the named interface.
|
* Stop tethering the named interface.
|
||||||
*
|
*
|
||||||
* @deprecated
|
* @deprecated The only usages is PanService. It uses this for legacy reasons
|
||||||
* {@hide}
|
* and will migrate away as soon as possible.
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public int untether(@NonNull String iface) {
|
public int untether(@NonNull final String iface) {
|
||||||
if (mConnector == null) {
|
final String callerPkg = mContext.getOpPackageName();
|
||||||
Slog.wtf(TAG, "Tethering not ready yet");
|
Log.i(TAG, "untether caller:" + callerPkg);
|
||||||
return TETHER_ERROR_SERVICE_UNAVAIL;
|
|
||||||
}
|
final RequestDispatcher dispatcher = new RequestDispatcher();
|
||||||
try {
|
|
||||||
mConnector.untether(iface);
|
return dispatcher.waitForResult(listener -> {
|
||||||
} catch (RemoteException e) {
|
try {
|
||||||
e.rethrowFromSystemServer();
|
mConnector.untether(iface, callerPkg, listener);
|
||||||
}
|
} catch (RemoteException e) {
|
||||||
return TETHER_ERROR_NO_ERROR;
|
throw new IllegalStateException(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempt to both alter the mode of USB and Tethering of USB. WARNING: New client should not
|
* Attempt to both alter the mode of USB and Tethering of USB.
|
||||||
* 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
|
* @deprecated New client should not use this API anymore. All clients should use
|
||||||
* {@hide}
|
* #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
|
@Deprecated
|
||||||
public int setUsbTethering(boolean enable) {
|
public int setUsbTethering(final boolean enable) {
|
||||||
if (mConnector == null) {
|
final String callerPkg = mContext.getOpPackageName();
|
||||||
Slog.wtf(TAG, "Tethering not ready yet");
|
Log.i(TAG, "setUsbTethering caller:" + callerPkg);
|
||||||
return TETHER_ERROR_SERVICE_UNAVAIL;
|
|
||||||
}
|
final RequestDispatcher dispatcher = new RequestDispatcher();
|
||||||
try {
|
|
||||||
mConnector.setUsbTethering(enable);
|
return dispatcher.waitForResult(listener -> {
|
||||||
} catch (RemoteException e) {
|
try {
|
||||||
e.rethrowFromSystemServer();
|
mConnector.setUsbTethering(enable, callerPkg, listener);
|
||||||
}
|
} catch (RemoteException e) {
|
||||||
return TETHER_ERROR_NO_ERROR;
|
throw new IllegalStateException(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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(int type, @NonNull ResultReceiver receiver,
|
public void startTethering(final int type, @NonNull final ResultReceiver receiver,
|
||||||
boolean showProvisioningUi) {
|
final boolean showProvisioningUi) {
|
||||||
if (mConnector == null) {
|
final String callerPkg = mContext.getOpPackageName();
|
||||||
Slog.wtf(TAG, "Tethering not ready yet");
|
Log.i(TAG, "startTethering caller:" + callerPkg);
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
mConnector.startTethering(type, receiver, showProvisioningUi);
|
mConnector.startTethering(type, receiver, showProvisioningUi, callerPkg);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
e.rethrowFromSystemServer();
|
throw new IllegalStateException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stops tethering for the given type. Also cancels any provisioning rechecks for that type if
|
* Stops tethering for the given type. Also cancels any provisioning rechecks for that type if
|
||||||
* applicable.
|
* applicable.
|
||||||
*
|
|
||||||
* {@hide}
|
|
||||||
*/
|
*/
|
||||||
public void stopTethering(int type) {
|
public void stopTethering(final int type) {
|
||||||
if (mConnector == null) {
|
final String callerPkg = mContext.getOpPackageName();
|
||||||
Slog.wtf(TAG, "Tethering not ready yet");
|
Log.i(TAG, "stopTethering caller:" + callerPkg);
|
||||||
return;
|
|
||||||
}
|
final RequestDispatcher dispatcher = new RequestDispatcher();
|
||||||
try {
|
|
||||||
mConnector.stopTethering(type);
|
dispatcher.waitForResult(listener -> {
|
||||||
} catch (RemoteException e) {
|
try {
|
||||||
e.rethrowFromSystemServer();
|
mConnector.stopTethering(type, callerPkg, listener);
|
||||||
}
|
} catch (RemoteException e) {
|
||||||
|
throw new IllegalStateException(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -277,47 +287,109 @@ public class TetheringManager {
|
|||||||
* if it's really needed.
|
* if it's really needed.
|
||||||
*/
|
*/
|
||||||
// TODO: improve the usage of ResultReceiver, b/145096122
|
// TODO: improve the usage of ResultReceiver, b/145096122
|
||||||
public void requestLatestTetheringEntitlementResult(int type, @NonNull ResultReceiver receiver,
|
public void requestLatestTetheringEntitlementResult(final int type,
|
||||||
boolean showEntitlementUi) {
|
@NonNull final ResultReceiver receiver, final boolean showEntitlementUi) {
|
||||||
if (mConnector == null) {
|
final String callerPkg = mContext.getOpPackageName();
|
||||||
Slog.wtf(TAG, "Tethering not ready yet");
|
Log.i(TAG, "getLatestTetheringEntitlementResult caller:" + callerPkg);
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
mConnector.requestLatestTetheringEntitlementResult(type, receiver, showEntitlementUi);
|
mConnector.requestLatestTetheringEntitlementResult(type, receiver, showEntitlementUi,
|
||||||
|
callerPkg);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
e.rethrowFromSystemServer();
|
throw new IllegalStateException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register tethering event callback.
|
* Start listening to tethering change events. Any new added callback will receive the last
|
||||||
|
* tethering status right away. If callback is registered,
|
||||||
|
* {@link OnTetheringEventCallback#onUpstreamChanged} will immediately be called. If tethering
|
||||||
|
* has no upstream or disabled, the argument of callback will be null. The same callback object
|
||||||
|
* cannot be registered twice.
|
||||||
*
|
*
|
||||||
* {@hide}
|
* @param executor the executor on which callback will be invoked.
|
||||||
|
* @param callback the callback to be called when tethering has change events.
|
||||||
*/
|
*/
|
||||||
public void registerTetheringEventCallback(@NonNull ITetheringEventCallback callback) {
|
public void registerTetheringEventCallback(@NonNull Executor executor,
|
||||||
mTetheringEventCallbacks.register(callback);
|
@NonNull OnTetheringEventCallback callback) {
|
||||||
|
final String callerPkg = mContext.getOpPackageName();
|
||||||
|
Log.i(TAG, "registerTetheringEventCallback caller:" + callerPkg);
|
||||||
|
|
||||||
|
synchronized (mTetheringEventCallbacks) {
|
||||||
|
if (!mTetheringEventCallbacks.containsKey(callback)) {
|
||||||
|
throw new IllegalArgumentException("callback was already registered.");
|
||||||
|
}
|
||||||
|
final ITetheringEventCallback remoteCallback = new ITetheringEventCallback.Stub() {
|
||||||
|
@Override
|
||||||
|
public void onUpstreamChanged(Network network) throws RemoteException {
|
||||||
|
executor.execute(() -> {
|
||||||
|
callback.onUpstreamChanged(network);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCallbackStarted(Network network, TetheringConfigurationParcel config,
|
||||||
|
TetherStatesParcel states) {
|
||||||
|
executor.execute(() -> {
|
||||||
|
callback.onUpstreamChanged(network);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCallbackStopped(int errorCode) {
|
||||||
|
executor.execute(() -> {
|
||||||
|
throwIfPermissionFailure(errorCode);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onConfigurationChanged(TetheringConfigurationParcel config) { }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTetherStatesChanged(TetherStatesParcel states) { }
|
||||||
|
};
|
||||||
|
try {
|
||||||
|
mConnector.registerTetheringEventCallback(remoteCallback, callerPkg);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
throw new IllegalStateException(e);
|
||||||
|
}
|
||||||
|
mTetheringEventCallbacks.put(callback, remoteCallback);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unregister tethering event callback.
|
* Remove tethering event callback previously registered with
|
||||||
|
* {@link #registerTetheringEventCallback}.
|
||||||
*
|
*
|
||||||
* {@hide}
|
* @param callback previously registered callback.
|
||||||
*/
|
*/
|
||||||
public void unregisterTetheringEventCallback(@NonNull ITetheringEventCallback callback) {
|
public void unregisterTetheringEventCallback(@NonNull final OnTetheringEventCallback callback) {
|
||||||
mTetheringEventCallbacks.unregister(callback);
|
final String callerPkg = mContext.getOpPackageName();
|
||||||
|
Log.i(TAG, "unregisterTetheringEventCallback caller:" + callerPkg);
|
||||||
|
|
||||||
|
synchronized (mTetheringEventCallbacks) {
|
||||||
|
ITetheringEventCallback remoteCallback = mTetheringEventCallbacks.remove(callback);
|
||||||
|
if (remoteCallback == null) {
|
||||||
|
throw new IllegalArgumentException("callback was not registered.");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
mConnector.unregisterTetheringEventCallback(remoteCallback, callerPkg);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
throw new IllegalStateException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a more detailed error code after a Tethering or Untethering
|
* Get a more detailed error code after a Tethering or Untethering
|
||||||
* request asynchronously failed.
|
* request asynchronously failed.
|
||||||
*
|
*
|
||||||
* {@hide}
|
* @param iface The name of the interface of interest
|
||||||
|
* @return error The error code of the last error tethering or untethering the named
|
||||||
|
* interface
|
||||||
*/
|
*/
|
||||||
public int getLastTetherError(@NonNull String iface) {
|
public int getLastTetherError(@NonNull final String iface) {
|
||||||
if (!mCallback.awaitCallbackCreation()) {
|
mCallback.waitForStarted();
|
||||||
throw new NullPointerException("callback was not ready yet");
|
|
||||||
}
|
|
||||||
if (mTetherStatesParcel == null) return TETHER_ERROR_NO_ERROR;
|
if (mTetherStatesParcel == null) return TETHER_ERROR_NO_ERROR;
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
@@ -334,12 +406,11 @@ public class TetheringManager {
|
|||||||
* USB network interfaces. If USB tethering is not supported by the
|
* USB network interfaces. If USB tethering is not supported by the
|
||||||
* device, this list should be empty.
|
* device, this list should be empty.
|
||||||
*
|
*
|
||||||
* {@hide}
|
* @return an array of 0 or more regular expression Strings defining
|
||||||
|
* what interfaces are considered tetherable usb interfaces.
|
||||||
*/
|
*/
|
||||||
public @NonNull String[] getTetherableUsbRegexs() {
|
public @NonNull String[] getTetherableUsbRegexs() {
|
||||||
if (!mCallback.awaitCallbackCreation()) {
|
mCallback.waitForStarted();
|
||||||
throw new NullPointerException("callback was not ready yet");
|
|
||||||
}
|
|
||||||
return mTetheringConfiguration.tetherableUsbRegexs;
|
return mTetheringConfiguration.tetherableUsbRegexs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -348,12 +419,11 @@ public class TetheringManager {
|
|||||||
* Wifi network interfaces. If Wifi tethering is not supported by the
|
* Wifi network interfaces. If Wifi tethering is not supported by the
|
||||||
* device, this list should be empty.
|
* device, this list should be empty.
|
||||||
*
|
*
|
||||||
* {@hide}
|
* @return an array of 0 or more regular expression Strings defining
|
||||||
|
* what interfaces are considered tetherable wifi interfaces.
|
||||||
*/
|
*/
|
||||||
public @NonNull String[] getTetherableWifiRegexs() {
|
public @NonNull String[] getTetherableWifiRegexs() {
|
||||||
if (!mCallback.awaitCallbackCreation()) {
|
mCallback.waitForStarted();
|
||||||
throw new NullPointerException("callback was not ready yet");
|
|
||||||
}
|
|
||||||
return mTetheringConfiguration.tetherableWifiRegexs;
|
return mTetheringConfiguration.tetherableWifiRegexs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -362,12 +432,11 @@ public class TetheringManager {
|
|||||||
* Bluetooth network interfaces. If Bluetooth tethering is not supported by the
|
* Bluetooth network interfaces. If Bluetooth tethering is not supported by the
|
||||||
* device, this list should be empty.
|
* device, this list should be empty.
|
||||||
*
|
*
|
||||||
* {@hide}
|
* @return an array of 0 or more regular expression Strings defining
|
||||||
|
* what interfaces are considered tetherable bluetooth interfaces.
|
||||||
*/
|
*/
|
||||||
public @NonNull String[] getTetherableBluetoothRegexs() {
|
public @NonNull String[] getTetherableBluetoothRegexs() {
|
||||||
if (!mCallback.awaitCallbackCreation()) {
|
mCallback.waitForStarted();
|
||||||
throw new NullPointerException("callback was not ready yet");
|
|
||||||
}
|
|
||||||
return mTetheringConfiguration.tetherableBluetoothRegexs;
|
return mTetheringConfiguration.tetherableBluetoothRegexs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -375,40 +444,42 @@ public class TetheringManager {
|
|||||||
* Get the set of tetherable, available interfaces. This list is limited by
|
* Get the set of tetherable, available interfaces. This list is limited by
|
||||||
* device configuration and current interface existence.
|
* device configuration and current interface existence.
|
||||||
*
|
*
|
||||||
* {@hide}
|
* @return an array of 0 or more Strings of tetherable interface names.
|
||||||
*/
|
*/
|
||||||
public @NonNull String[] getTetherableIfaces() {
|
public @NonNull String[] getTetherableIfaces() {
|
||||||
if (!mCallback.awaitCallbackCreation()) {
|
mCallback.waitForStarted();
|
||||||
throw new NullPointerException("callback was not ready yet");
|
|
||||||
}
|
|
||||||
if (mTetherStatesParcel == null) return new String[0];
|
if (mTetherStatesParcel == null) return new String[0];
|
||||||
|
|
||||||
return mTetherStatesParcel.availableList;
|
return mTetherStatesParcel.availableList;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the set of tethered interfaces.
|
* Get the set of tethered interfaces.
|
||||||
*
|
*
|
||||||
* {@hide}
|
* @return an array of 0 or more String of currently tethered interface names.
|
||||||
*/
|
*/
|
||||||
public @NonNull String[] getTetheredIfaces() {
|
public @NonNull String[] getTetheredIfaces() {
|
||||||
if (!mCallback.awaitCallbackCreation()) {
|
mCallback.waitForStarted();
|
||||||
throw new NullPointerException("callback was not ready yet");
|
|
||||||
}
|
|
||||||
if (mTetherStatesParcel == null) return new String[0];
|
if (mTetherStatesParcel == null) return new String[0];
|
||||||
|
|
||||||
return mTetherStatesParcel.tetheredList;
|
return mTetherStatesParcel.tetheredList;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the set of interface names which attempted to tether but
|
* Get the set of interface names which attempted to tether but
|
||||||
* failed.
|
* failed. Re-attempting to tether may cause them to reset to the Tethered
|
||||||
|
* state. Alternatively, causing the interface to be destroyed and recreated
|
||||||
|
* may cause them to reset to the available state.
|
||||||
|
* {@link ConnectivityManager#getLastTetherError} can be used to get more
|
||||||
|
* information on the cause of the errors.
|
||||||
*
|
*
|
||||||
* {@hide}
|
* @return an array of 0 or more String indicating the interface names
|
||||||
|
* which failed to tether.
|
||||||
*/
|
*/
|
||||||
public @NonNull String[] getTetheringErroredIfaces() {
|
public @NonNull String[] getTetheringErroredIfaces() {
|
||||||
if (!mCallback.awaitCallbackCreation()) {
|
mCallback.waitForStarted();
|
||||||
throw new NullPointerException("callback was not ready yet");
|
|
||||||
}
|
|
||||||
if (mTetherStatesParcel == null) return new String[0];
|
if (mTetherStatesParcel == null) return new String[0];
|
||||||
|
|
||||||
return mTetherStatesParcel.erroredIfaceList;
|
return mTetherStatesParcel.erroredIfaceList;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -416,123 +487,49 @@ 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() {
|
||||||
if (!mCallback.awaitCallbackCreation()) {
|
mCallback.waitForStarted();
|
||||||
throw new NullPointerException("callback was not ready yet");
|
|
||||||
}
|
|
||||||
return mTetheringConfiguration.legacyDhcpRanges;
|
return mTetheringConfiguration.legacyDhcpRanges;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the device allows for tethering.
|
* Check if the device allows for tethering. It may be disabled via
|
||||||
|
* {@code ro.tether.denied} system property, Settings.TETHER_SUPPORTED or
|
||||||
|
* due to device configuration.
|
||||||
*
|
*
|
||||||
* {@hide}
|
* @return a boolean - {@code true} indicating Tethering is supported.
|
||||||
*/
|
*/
|
||||||
public boolean hasTetherableConfiguration() {
|
public boolean isTetheringSupported() {
|
||||||
if (!mCallback.awaitCallbackCreation()) {
|
final String callerPkg = mContext.getOpPackageName();
|
||||||
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;
|
final RequestDispatcher dispatcher = new RequestDispatcher();
|
||||||
|
final int ret = dispatcher.waitForResult(listener -> {
|
||||||
|
try {
|
||||||
|
mConnector.isTetheringSupported(callerPkg, listener);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
throw new IllegalStateException(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return ret == TETHER_ERROR_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Log a message in the local log.
|
* Stop all active tethering.
|
||||||
*/
|
*/
|
||||||
private void log(@NonNull String message) {
|
public void stopAllTethering() {
|
||||||
synchronized (mLog) {
|
final String callerPkg = mContext.getOpPackageName();
|
||||||
mLog.log(message);
|
Log.i(TAG, "stopAllTethering caller:" + callerPkg);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
final RequestDispatcher dispatcher = new RequestDispatcher();
|
||||||
* Log a condition that should never happen.
|
dispatcher.waitForResult(listener -> {
|
||||||
*/
|
try {
|
||||||
private void logWtf(@NonNull String message, @Nullable Throwable e) {
|
mConnector.stopAllTethering(callerPkg, listener);
|
||||||
Slog.wtf(TAG, message);
|
} catch (RemoteException e) {
|
||||||
synchronized (mLog) {
|
throw new IllegalStateException(e);
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
15
packages/Tethering/jarjar-rules.txt
Normal file
15
packages/Tethering/jarjar-rules.txt
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
# These must be kept in sync with the framework-tethering-shared-srcs filegroup.
|
||||||
|
# If there are files in that filegroup that do not appear here, the classes in the
|
||||||
|
# module will be overwritten by the ones in the framework.
|
||||||
|
# Don't jar-jar the entire package because tethering still use some internal classes
|
||||||
|
# (like TrafficStatsConstants in com.android.internal.util)
|
||||||
|
# TODO: simply these when tethering is built as system_current.
|
||||||
|
rule com.android.internal.util.BitUtils* com.android.networkstack.tethering.util.BitUtils@1
|
||||||
|
rule com.android.internal.util.IndentingPrintWriter.java* com.android.networkstack.tethering.util.IndentingPrintWriter.java@1
|
||||||
|
rule com.android.internal.util.IState.java* com.android.networkstack.tethering.util.IState.java@1
|
||||||
|
rule com.android.internal.util.MessageUtils* com.android.networkstack.tethering.util.MessageUtils@1
|
||||||
|
rule com.android.internal.util.Preconditions* com.android.networkstack.tethering.util.Preconditions@1
|
||||||
|
rule com.android.internal.util.State* com.android.networkstack.tethering.util.State@1
|
||||||
|
rule com.android.internal.util.StateMachine* com.android.networkstack.tethering.util.StateMachine@1
|
||||||
|
|
||||||
|
rule android.net.LocalLog* com.android.networkstack.tethering.LocalLog@1
|
||||||
@@ -1 +1,9 @@
|
|||||||
#TBD
|
# Keep class's integer static field for MessageUtils to parsing their name.
|
||||||
|
-keep class com.android.server.connectivity.tethering.Tethering$TetherMasterSM {
|
||||||
|
static final int CMD_*;
|
||||||
|
static final int EVENT_*;
|
||||||
|
}
|
||||||
|
|
||||||
|
-keepclassmembers class android.net.ip.IpServer {
|
||||||
|
static final int CMD_*;
|
||||||
|
}
|
||||||
|
|||||||
@@ -30,7 +30,6 @@ import android.net.InterfaceConfiguration;
|
|||||||
import android.net.IpPrefix;
|
import android.net.IpPrefix;
|
||||||
import android.net.LinkAddress;
|
import android.net.LinkAddress;
|
||||||
import android.net.LinkProperties;
|
import android.net.LinkProperties;
|
||||||
import android.net.NetworkStackClient;
|
|
||||||
import android.net.RouteInfo;
|
import android.net.RouteInfo;
|
||||||
import android.net.dhcp.DhcpServerCallbacks;
|
import android.net.dhcp.DhcpServerCallbacks;
|
||||||
import android.net.dhcp.DhcpServingParamsParcel;
|
import android.net.dhcp.DhcpServingParamsParcel;
|
||||||
@@ -122,7 +121,7 @@ public class IpServer extends StateMachine {
|
|||||||
* @param state one of STATE_*
|
* @param state one of STATE_*
|
||||||
* @param lastError one of ConnectivityManager.TETHER_ERROR_*
|
* @param lastError one of ConnectivityManager.TETHER_ERROR_*
|
||||||
*/
|
*/
|
||||||
public void updateInterfaceState(IpServer who, int state, int lastError) {}
|
public void updateInterfaceState(IpServer who, int state, int lastError) { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notify that |who| has new LinkProperties.
|
* Notify that |who| has new LinkProperties.
|
||||||
@@ -130,11 +129,11 @@ public class IpServer extends StateMachine {
|
|||||||
* @param who the calling instance of IpServer
|
* @param who the calling instance of IpServer
|
||||||
* @param newLp the new LinkProperties to report
|
* @param newLp the new LinkProperties to report
|
||||||
*/
|
*/
|
||||||
public void updateLinkProperties(IpServer who, LinkProperties newLp) {}
|
public void updateLinkProperties(IpServer who, LinkProperties newLp) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Capture IpServer dependencies, for injection. */
|
/** Capture IpServer dependencies, for injection. */
|
||||||
public static class Dependencies {
|
public abstract static class Dependencies {
|
||||||
/** Create a RouterAdvertisementDaemon instance to be used by IpServer.*/
|
/** Create a RouterAdvertisementDaemon instance to be used by IpServer.*/
|
||||||
public RouterAdvertisementDaemon getRouterAdvertisementDaemon(InterfaceParams ifParams) {
|
public RouterAdvertisementDaemon getRouterAdvertisementDaemon(InterfaceParams ifParams) {
|
||||||
return new RouterAdvertisementDaemon(ifParams);
|
return new RouterAdvertisementDaemon(ifParams);
|
||||||
@@ -149,13 +148,9 @@ public class IpServer extends StateMachine {
|
|||||||
return NetdService.getInstance();
|
return NetdService.getInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Create a DhcpServer instance to be used by IpServer. */
|
||||||
* Create a DhcpServer instance to be used by IpServer.
|
public abstract void makeDhcpServer(String ifName, DhcpServingParamsParcel params,
|
||||||
*/
|
DhcpServerCallbacks cb);
|
||||||
public void makeDhcpServer(String ifName, DhcpServingParamsParcel params,
|
|
||||||
DhcpServerCallbacks cb) {
|
|
||||||
NetworkStackClient.getInstance().makeDhcpServer(ifName, params, cb);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final int BASE_IFACE = Protocol.BASE_TETHERING + 100;
|
private static final int BASE_IFACE = Protocol.BASE_TETHERING + 100;
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package com.android.server.connectivity.tethering;
|
package com.android.server.connectivity.tethering;
|
||||||
|
|
||||||
|
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
|
||||||
import static android.hardware.usb.UsbManager.USB_CONFIGURED;
|
import static android.hardware.usb.UsbManager.USB_CONFIGURED;
|
||||||
import static android.hardware.usb.UsbManager.USB_CONNECTED;
|
import static android.hardware.usb.UsbManager.USB_CONNECTED;
|
||||||
import static android.hardware.usb.UsbManager.USB_FUNCTION_RNDIS;
|
import static android.hardware.usb.UsbManager.USB_FUNCTION_RNDIS;
|
||||||
@@ -63,7 +64,7 @@ import android.hardware.usb.UsbManager;
|
|||||||
import android.net.INetd;
|
import android.net.INetd;
|
||||||
import android.net.INetworkPolicyManager;
|
import android.net.INetworkPolicyManager;
|
||||||
import android.net.INetworkStatsService;
|
import android.net.INetworkStatsService;
|
||||||
import android.net.ITetherInternalCallback;
|
import android.net.ITetheringEventCallback;
|
||||||
import android.net.IpPrefix;
|
import android.net.IpPrefix;
|
||||||
import android.net.LinkAddress;
|
import android.net.LinkAddress;
|
||||||
import android.net.LinkProperties;
|
import android.net.LinkProperties;
|
||||||
@@ -89,6 +90,7 @@ import android.os.Handler;
|
|||||||
import android.os.INetworkManagementService;
|
import android.os.INetworkManagementService;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
|
import android.os.RemoteCallbackList;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.os.ResultReceiver;
|
import android.os.ResultReceiver;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
@@ -103,7 +105,6 @@ import android.util.SparseArray;
|
|||||||
import com.android.internal.annotations.VisibleForTesting;
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
|
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
|
||||||
import com.android.internal.notification.SystemNotificationChannels;
|
import com.android.internal.notification.SystemNotificationChannels;
|
||||||
import com.android.internal.util.DumpUtils;
|
|
||||||
import com.android.internal.util.IndentingPrintWriter;
|
import com.android.internal.util.IndentingPrintWriter;
|
||||||
import com.android.internal.util.MessageUtils;
|
import com.android.internal.util.MessageUtils;
|
||||||
import com.android.internal.util.Protocol;
|
import com.android.internal.util.Protocol;
|
||||||
@@ -162,6 +163,8 @@ public class Tethering {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private final SharedLog mLog = new SharedLog(TAG);
|
private final SharedLog mLog = new SharedLog(TAG);
|
||||||
|
private final RemoteCallbackList<ITetheringEventCallback> mTetheringEventCallbacks =
|
||||||
|
new RemoteCallbackList<>();
|
||||||
|
|
||||||
// used to synchronize public access to members
|
// used to synchronize public access to members
|
||||||
private final Object mPublicSync;
|
private final Object mPublicSync;
|
||||||
@@ -188,8 +191,8 @@ public class Tethering {
|
|||||||
private final NetdCallback mNetdCallback;
|
private final NetdCallback mNetdCallback;
|
||||||
private final UserRestrictionActionListener mTetheringRestriction;
|
private final UserRestrictionActionListener mTetheringRestriction;
|
||||||
private int mActiveDataSubId = INVALID_SUBSCRIPTION_ID;
|
private int mActiveDataSubId = INVALID_SUBSCRIPTION_ID;
|
||||||
// All the usage of mTetherInternalCallback should run in the same thread.
|
// All the usage of mTetheringEventCallback should run in the same thread.
|
||||||
private ITetherInternalCallback mTetherInternalCallback = null;
|
private ITetheringEventCallback mTetheringEventCallback = null;
|
||||||
|
|
||||||
private volatile TetheringConfiguration mConfig;
|
private volatile TetheringConfiguration mConfig;
|
||||||
private InterfaceSet mCurrentUpstreamIfaceSet;
|
private InterfaceSet mCurrentUpstreamIfaceSet;
|
||||||
@@ -573,6 +576,11 @@ public class Tethering {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean isTetherProvisioningRequired() {
|
||||||
|
final TetheringConfiguration cfg = mConfig;
|
||||||
|
return mEntitlementMgr.isTetherProvisioningRequired(cfg);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Figure out how to update for local hotspot mode interfaces.
|
// TODO: Figure out how to update for local hotspot mode interfaces.
|
||||||
private void sendTetherStateChangedBroadcast() {
|
private void sendTetherStateChangedBroadcast() {
|
||||||
if (!mDeps.isTetheringSupported()) return;
|
if (!mDeps.isTetheringSupported()) return;
|
||||||
@@ -588,7 +596,7 @@ public class Tethering {
|
|||||||
boolean bluetoothTethered = false;
|
boolean bluetoothTethered = false;
|
||||||
|
|
||||||
final TetheringConfiguration cfg = mConfig;
|
final TetheringConfiguration cfg = mConfig;
|
||||||
final TetherStatesParcel mTetherStatesParcel = new TetherStatesParcel();
|
mTetherStatesParcel = new TetherStatesParcel();
|
||||||
|
|
||||||
synchronized (mPublicSync) {
|
synchronized (mPublicSync) {
|
||||||
for (int i = 0; i < mTetherStates.size(); i++) {
|
for (int i = 0; i < mTetherStates.size(); i++) {
|
||||||
@@ -1796,47 +1804,67 @@ public class Tethering {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Register tethering event callback */
|
/** Register tethering event callback */
|
||||||
void registerTetherInternalCallback(ITetherInternalCallback callback) {
|
void registerTetheringEventCallback(ITetheringEventCallback callback) {
|
||||||
mHandler.post(() -> {
|
mHandler.post(() -> {
|
||||||
mTetherInternalCallback = callback;
|
mTetheringEventCallbacks.register(callback);
|
||||||
try {
|
try {
|
||||||
mTetherInternalCallback.onCallbackCreated(mTetherUpstream,
|
callback.onCallbackStarted(mTetherUpstream, mConfig.toStableParcelable(),
|
||||||
mConfig.toStableParcelable(), mTetherStatesParcel);
|
mTetherStatesParcel);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
// Not really very much to do here.
|
// Not really very much to do here.
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void reportUpstreamChanged(Network network) {
|
/** Unregister tethering event callback */
|
||||||
// Don't need to synchronized mTetherInternalCallback because all the usage of this variable
|
void unregisterTetheringEventCallback(ITetheringEventCallback callback) {
|
||||||
// should run at the same thread.
|
mHandler.post(() -> {
|
||||||
if (mTetherInternalCallback == null) return;
|
mTetheringEventCallbacks.unregister(callback);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void reportUpstreamChanged(Network network) {
|
||||||
|
final int length = mTetheringEventCallbacks.beginBroadcast();
|
||||||
try {
|
try {
|
||||||
mTetherInternalCallback.onUpstreamChanged(network);
|
for (int i = 0; i < length; i++) {
|
||||||
} catch (RemoteException e) {
|
try {
|
||||||
// Not really very much to do here.
|
mTetheringEventCallbacks.getBroadcastItem(i).onUpstreamChanged(network);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
// Not really very much to do here.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
mTetheringEventCallbacks.finishBroadcast();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void reportConfigurationChanged(TetheringConfigurationParcel config) {
|
private void reportConfigurationChanged(TetheringConfigurationParcel config) {
|
||||||
if (mTetherInternalCallback == null) return;
|
final int length = mTetheringEventCallbacks.beginBroadcast();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
mTetherInternalCallback.onConfigurationChanged(config);
|
for (int i = 0; i < length; i++) {
|
||||||
} catch (RemoteException e) {
|
try {
|
||||||
// Not really very much to do here.
|
mTetheringEventCallbacks.getBroadcastItem(i).onConfigurationChanged(config);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
// Not really very much to do here.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
mTetheringEventCallbacks.finishBroadcast();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void reportTetherStateChanged(TetherStatesParcel states) {
|
private void reportTetherStateChanged(TetherStatesParcel states) {
|
||||||
if (mTetherInternalCallback == null) return;
|
final int length = mTetheringEventCallbacks.beginBroadcast();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
mTetherInternalCallback.onTetherStatesChanged(states);
|
for (int i = 0; i < length; i++) {
|
||||||
} catch (RemoteException e) {
|
try {
|
||||||
// Not really very much to do here.
|
mTetheringEventCallbacks.getBroadcastItem(i).onTetherStatesChanged(states);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
// Not really very much to do here.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
mTetheringEventCallbacks.finishBroadcast();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1844,7 +1872,11 @@ public class Tethering {
|
|||||||
// Binder.java closes the resource for us.
|
// Binder.java closes the resource for us.
|
||||||
@SuppressWarnings("resource")
|
@SuppressWarnings("resource")
|
||||||
final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
|
final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
|
||||||
if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
|
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
|
||||||
|
!= PERMISSION_GRANTED) {
|
||||||
|
pw.println("Permission Denial: can't dump.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
pw.println("Tethering:");
|
pw.println("Tethering:");
|
||||||
pw.increaseIndent();
|
pw.increaseIndent();
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ import java.util.ArrayList;
|
|||||||
*
|
*
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public class TetheringDependencies {
|
public abstract class TetheringDependencies {
|
||||||
/**
|
/**
|
||||||
* Get a reference to the offload hardware interface to be used by tethering.
|
* Get a reference to the offload hardware interface to be used by tethering.
|
||||||
*/
|
*/
|
||||||
@@ -66,9 +66,7 @@ public class TetheringDependencies {
|
|||||||
/**
|
/**
|
||||||
* Get dependencies to be used by IpServer.
|
* Get dependencies to be used by IpServer.
|
||||||
*/
|
*/
|
||||||
public IpServer.Dependencies getIpServerDependencies() {
|
public abstract IpServer.Dependencies getIpServerDependencies();
|
||||||
return new IpServer.Dependencies();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates whether tethering is supported on the device.
|
* Indicates whether tethering is supported on the device.
|
||||||
@@ -80,9 +78,7 @@ public class TetheringDependencies {
|
|||||||
/**
|
/**
|
||||||
* Get the NetworkRequest that should be fulfilled by the default network.
|
* Get the NetworkRequest that should be fulfilled by the default network.
|
||||||
*/
|
*/
|
||||||
public NetworkRequest getDefaultNetworkRequest() {
|
public abstract NetworkRequest getDefaultNetworkRequest();
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a reference to the EntitlementManager to be used by tethering.
|
* Get a reference to the EntitlementManager to be used by tethering.
|
||||||
@@ -138,14 +134,10 @@ public class TetheringDependencies {
|
|||||||
/**
|
/**
|
||||||
* Get tethering thread looper.
|
* Get tethering thread looper.
|
||||||
*/
|
*/
|
||||||
public Looper getTetheringLooper() {
|
public abstract Looper getTetheringLooper();
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get Context of TetheringSerice.
|
* Get Context of TetheringSerice.
|
||||||
*/
|
*/
|
||||||
public Context getContext() {
|
public abstract Context getContext();
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,20 +16,36 @@
|
|||||||
|
|
||||||
package com.android.server.connectivity.tethering;
|
package com.android.server.connectivity.tethering;
|
||||||
|
|
||||||
|
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
|
||||||
|
import static android.net.TetheringManager.TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION;
|
||||||
|
import static android.net.TetheringManager.TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION;
|
||||||
|
import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
|
||||||
|
import static android.net.TetheringManager.TETHER_ERROR_UNSUPPORTED;
|
||||||
|
|
||||||
import android.app.Service;
|
import android.app.Service;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.net.ConnectivityManager;
|
import android.net.ConnectivityManager;
|
||||||
import android.net.ITetherInternalCallback;
|
import android.net.IIntResultListener;
|
||||||
|
import android.net.INetworkStackConnector;
|
||||||
import android.net.ITetheringConnector;
|
import android.net.ITetheringConnector;
|
||||||
|
import android.net.ITetheringEventCallback;
|
||||||
import android.net.NetworkRequest;
|
import android.net.NetworkRequest;
|
||||||
|
import android.net.dhcp.DhcpServerCallbacks;
|
||||||
|
import android.net.dhcp.DhcpServingParamsParcel;
|
||||||
|
import android.net.ip.IpServer;
|
||||||
import android.net.util.SharedLog;
|
import android.net.util.SharedLog;
|
||||||
|
import android.os.Binder;
|
||||||
import android.os.HandlerThread;
|
import android.os.HandlerThread;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
|
import android.os.RemoteException;
|
||||||
import android.os.ResultReceiver;
|
import android.os.ResultReceiver;
|
||||||
|
import android.os.ServiceManager;
|
||||||
import android.os.SystemProperties;
|
import android.os.SystemProperties;
|
||||||
|
import android.os.UserManager;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
@@ -52,6 +68,7 @@ public class TetheringService extends Service {
|
|||||||
private Context mContext;
|
private Context mContext;
|
||||||
private TetheringDependencies mDeps;
|
private TetheringDependencies mDeps;
|
||||||
private Tethering mTethering;
|
private Tethering mTethering;
|
||||||
|
private UserManager mUserManager;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
@@ -59,6 +76,7 @@ public class TetheringService extends Service {
|
|||||||
mDeps = getTetheringDependencies();
|
mDeps = getTetheringDependencies();
|
||||||
mContext = mDeps.getContext();
|
mContext = mDeps.getContext();
|
||||||
mTethering = makeTethering(mDeps);
|
mTethering = makeTethering(mDeps);
|
||||||
|
mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -74,7 +92,7 @@ public class TetheringService extends Service {
|
|||||||
*/
|
*/
|
||||||
private synchronized IBinder makeConnector() {
|
private synchronized IBinder makeConnector() {
|
||||||
if (mConnector == null) {
|
if (mConnector == null) {
|
||||||
mConnector = new TetheringConnector(mTethering);
|
mConnector = new TetheringConnector(mTethering, TetheringService.this);
|
||||||
}
|
}
|
||||||
return mConnector;
|
return mConnector;
|
||||||
}
|
}
|
||||||
@@ -87,55 +105,197 @@ public class TetheringService extends Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static class TetheringConnector extends ITetheringConnector.Stub {
|
private static class TetheringConnector extends ITetheringConnector.Stub {
|
||||||
private final Tethering mService;
|
private final TetheringService mService;
|
||||||
|
private final Tethering mTethering;
|
||||||
|
|
||||||
TetheringConnector(Tethering tether) {
|
TetheringConnector(Tethering tether, TetheringService service) {
|
||||||
mService = tether;
|
mTethering = tether;
|
||||||
|
mService = service;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void tether(String iface) {
|
public void tether(String iface, String callerPkg, IIntResultListener listener) {
|
||||||
mService.tether(iface);
|
if (checkAndNotifyCommonError(callerPkg, listener)) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
listener.onResult(mTethering.tether(iface));
|
||||||
|
} catch (RemoteException e) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void untether(String iface) {
|
public void untether(String iface, String callerPkg, IIntResultListener listener) {
|
||||||
mService.untether(iface);
|
if (checkAndNotifyCommonError(callerPkg, listener)) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
listener.onResult(mTethering.untether(iface));
|
||||||
|
} catch (RemoteException e) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setUsbTethering(boolean enable) {
|
public void setUsbTethering(boolean enable, String callerPkg, IIntResultListener listener) {
|
||||||
mService.setUsbTethering(enable);
|
if (checkAndNotifyCommonError(callerPkg, listener)) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
listener.onResult(mTethering.setUsbTethering(enable));
|
||||||
|
} catch (RemoteException e) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void startTethering(int type, ResultReceiver receiver, boolean showProvisioningUi) {
|
public void startTethering(int type, ResultReceiver receiver, boolean showProvisioningUi,
|
||||||
mService.startTethering(type, receiver, showProvisioningUi);
|
String callerPkg) {
|
||||||
|
if (checkAndNotifyCommonError(callerPkg, receiver)) return;
|
||||||
|
|
||||||
|
mTethering.startTethering(type, receiver, showProvisioningUi);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void stopTethering(int type) {
|
public void stopTethering(int type, String callerPkg, IIntResultListener listener) {
|
||||||
mService.stopTethering(type);
|
if (checkAndNotifyCommonError(callerPkg, listener)) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
mTethering.stopTethering(type);
|
||||||
|
listener.onResult(TETHER_ERROR_NO_ERROR);
|
||||||
|
} catch (RemoteException e) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void requestLatestTetheringEntitlementResult(int type, ResultReceiver receiver,
|
public void requestLatestTetheringEntitlementResult(int type, ResultReceiver receiver,
|
||||||
boolean showEntitlementUi) {
|
boolean showEntitlementUi, String callerPkg) {
|
||||||
mService.requestLatestTetheringEntitlementResult(type, receiver, showEntitlementUi);
|
if (checkAndNotifyCommonError(callerPkg, receiver)) return;
|
||||||
|
|
||||||
|
mTethering.requestLatestTetheringEntitlementResult(type, receiver, showEntitlementUi);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void registerTetherInternalCallback(ITetherInternalCallback callback) {
|
public void registerTetheringEventCallback(ITetheringEventCallback callback,
|
||||||
mService.registerTetherInternalCallback(callback);
|
String callerPkg) {
|
||||||
|
try {
|
||||||
|
if (!mService.hasTetherAccessPermission()) {
|
||||||
|
callback.onCallbackStopped(TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mTethering.registerTetheringEventCallback(callback);
|
||||||
|
} catch (RemoteException e) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void unregisterTetheringEventCallback(ITetheringEventCallback callback,
|
||||||
|
String callerPkg) {
|
||||||
|
try {
|
||||||
|
if (!mService.hasTetherAccessPermission()) {
|
||||||
|
callback.onCallbackStopped(TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mTethering.unregisterTetheringEventCallback(callback);
|
||||||
|
} catch (RemoteException e) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stopAllTethering(String callerPkg, IIntResultListener listener) {
|
||||||
|
if (checkAndNotifyCommonError(callerPkg, listener)) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
mTethering.untetherAll();
|
||||||
|
listener.onResult(TETHER_ERROR_NO_ERROR);
|
||||||
|
} catch (RemoteException e) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void isTetheringSupported(String callerPkg, IIntResultListener listener) {
|
||||||
|
if (checkAndNotifyCommonError(callerPkg, listener)) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
listener.onResult(TETHER_ERROR_NO_ERROR);
|
||||||
|
} catch (RemoteException e) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter writer,
|
||||||
|
@Nullable String[] args) {
|
||||||
|
mTethering.dump(fd, writer, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean checkAndNotifyCommonError(String callerPkg, IIntResultListener listener) {
|
||||||
|
try {
|
||||||
|
if (!mService.hasTetherChangePermission(callerPkg)) {
|
||||||
|
listener.onResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!mService.isTetheringSupported()) {
|
||||||
|
listener.onResult(TETHER_ERROR_UNSUPPORTED);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean checkAndNotifyCommonError(String callerPkg, ResultReceiver receiver) {
|
||||||
|
if (!mService.hasTetherChangePermission(callerPkg)) {
|
||||||
|
receiver.send(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION, null);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!mService.isTetheringSupported()) {
|
||||||
|
receiver.send(TETHER_ERROR_UNSUPPORTED, null);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
// if ro.tether.denied = true we default to no tethering
|
||||||
protected void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter writer,
|
// gservices could set the secure setting to 1 though to enable it on a build where it
|
||||||
@Nullable String[] args) {
|
// had previously been turned off.
|
||||||
mTethering.dump(fd, writer, args);
|
private boolean isTetheringSupported() {
|
||||||
|
final int defaultVal =
|
||||||
|
SystemProperties.get("ro.tether.denied").equals("true") ? 0 : 1;
|
||||||
|
final boolean tetherSupported = Settings.Global.getInt(mContext.getContentResolver(),
|
||||||
|
Settings.Global.TETHER_SUPPORTED, defaultVal) != 0;
|
||||||
|
final boolean tetherEnabledInSettings = tetherSupported
|
||||||
|
&& !mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING);
|
||||||
|
|
||||||
|
return tetherEnabledInSettings && mTethering.hasTetherableConfiguration();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean hasTetherChangePermission(String callerPkg) {
|
||||||
|
if (checkCallingOrSelfPermission(
|
||||||
|
android.Manifest.permission.TETHER_PRIVILEGED) == PERMISSION_GRANTED) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mTethering.isTetherProvisioningRequired()) return false;
|
||||||
|
|
||||||
|
|
||||||
|
int uid = Binder.getCallingUid();
|
||||||
|
// If callerPkg's uid is not same as Binder.getCallingUid(),
|
||||||
|
// checkAndNoteWriteSettingsOperation will return false and the operation will be denied.
|
||||||
|
if (Settings.checkAndNoteWriteSettingsOperation(mContext, uid, callerPkg,
|
||||||
|
false /* throwException */)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasTetherAccessPermission() {
|
||||||
|
if (checkCallingOrSelfPermission(
|
||||||
|
android.Manifest.permission.TETHER_PRIVILEGED) == PERMISSION_GRANTED) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (checkCallingOrSelfPermission(
|
||||||
|
android.Manifest.permission.ACCESS_NETWORK_STATE) == PERMISSION_GRANTED) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An injection method for testing.
|
* An injection method for testing.
|
||||||
*/
|
*/
|
||||||
@@ -159,20 +319,55 @@ public class TetheringService extends Service {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isTetheringSupported() {
|
public boolean isTetheringSupported() {
|
||||||
int defaultVal =
|
return TetheringService.this.isTetheringSupported();
|
||||||
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
|
@Override
|
||||||
public Context getContext() {
|
public Context getContext() {
|
||||||
return TetheringService.this;
|
return TetheringService.this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IpServer.Dependencies getIpServerDependencies() {
|
||||||
|
return new IpServer.Dependencies() {
|
||||||
|
@Override
|
||||||
|
public void makeDhcpServer(String ifName, DhcpServingParamsParcel params,
|
||||||
|
DhcpServerCallbacks cb) {
|
||||||
|
try {
|
||||||
|
final INetworkStackConnector service = getNetworkStackConnector();
|
||||||
|
if (service == null) return;
|
||||||
|
|
||||||
|
service.makeDhcpServer(ifName, params, cb);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
e.rethrowFromSystemServer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: replace this by NetworkStackClient#getRemoteConnector after refactoring
|
||||||
|
// networkStackClient.
|
||||||
|
static final int NETWORKSTACK_TIMEOUT_MS = 60_000;
|
||||||
|
private INetworkStackConnector getNetworkStackConnector() {
|
||||||
|
IBinder connector;
|
||||||
|
try {
|
||||||
|
final long before = System.currentTimeMillis();
|
||||||
|
while ((connector = ServiceManager.getService(
|
||||||
|
Context.NETWORK_STACK_SERVICE)) == null) {
|
||||||
|
if (System.currentTimeMillis() - before > NETWORKSTACK_TIMEOUT_MS) {
|
||||||
|
Log.wtf(TAG, "Timeout, fail to get INetworkStackConnector");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Thread.sleep(200);
|
||||||
|
}
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Log.wtf(TAG, "Interrupted, fail to get INetworkStackConnector");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return INetworkStackConnector.Stub.asInterface(connector);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return mDeps;
|
return mDeps;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,10 +33,12 @@ android_test {
|
|||||||
"android.test.runner",
|
"android.test.runner",
|
||||||
"android.test.base",
|
"android.test.base",
|
||||||
"android.test.mock",
|
"android.test.mock",
|
||||||
|
"framework-tethering",
|
||||||
],
|
],
|
||||||
jni_libs: [
|
jni_libs: [
|
||||||
// For mockito extended
|
// For mockito extended
|
||||||
"libdexmakerjvmtiagent",
|
"libdexmakerjvmtiagent",
|
||||||
"libstaticjvmtiagent",
|
"libstaticjvmtiagent",
|
||||||
],
|
],
|
||||||
|
jarjar_rules: "jarjar-rules.txt",
|
||||||
}
|
}
|
||||||
|
|||||||
11
packages/Tethering/tests/unit/jarjar-rules.txt
Normal file
11
packages/Tethering/tests/unit/jarjar-rules.txt
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
# Don't jar-jar the entire package because this test use some
|
||||||
|
# internal classes (like ArrayUtils in com.android.internal.util)
|
||||||
|
rule com.android.internal.util.BitUtils* com.android.networkstack.tethering.util.BitUtils@1
|
||||||
|
rule com.android.internal.util.IndentingPrintWriter.java* com.android.networkstack.tethering.util.IndentingPrintWriter.java@1
|
||||||
|
rule com.android.internal.util.IState.java* com.android.networkstack.tethering.util.IState.java@1
|
||||||
|
rule com.android.internal.util.MessageUtils* com.android.networkstack.tethering.util.MessageUtils@1
|
||||||
|
rule com.android.internal.util.Preconditions* com.android.networkstack.tethering.util.Preconditions@1
|
||||||
|
rule com.android.internal.util.State* com.android.networkstack.tethering.util.State@1
|
||||||
|
rule com.android.internal.util.StateMachine* com.android.networkstack.tethering.util.StateMachine@1
|
||||||
|
|
||||||
|
rule android.net.LocalLog* com.android.networkstack.tethering.LocalLog@1
|
||||||
@@ -72,7 +72,7 @@ import android.hardware.usb.UsbManager;
|
|||||||
import android.net.INetd;
|
import android.net.INetd;
|
||||||
import android.net.INetworkPolicyManager;
|
import android.net.INetworkPolicyManager;
|
||||||
import android.net.INetworkStatsService;
|
import android.net.INetworkStatsService;
|
||||||
import android.net.ITetherInternalCallback;
|
import android.net.ITetheringEventCallback;
|
||||||
import android.net.InterfaceConfiguration;
|
import android.net.InterfaceConfiguration;
|
||||||
import android.net.IpPrefix;
|
import android.net.IpPrefix;
|
||||||
import android.net.LinkAddress;
|
import android.net.LinkAddress;
|
||||||
@@ -81,6 +81,7 @@ import android.net.MacAddress;
|
|||||||
import android.net.Network;
|
import android.net.Network;
|
||||||
import android.net.NetworkCapabilities;
|
import android.net.NetworkCapabilities;
|
||||||
import android.net.NetworkInfo;
|
import android.net.NetworkInfo;
|
||||||
|
import android.net.NetworkRequest;
|
||||||
import android.net.NetworkState;
|
import android.net.NetworkState;
|
||||||
import android.net.NetworkUtils;
|
import android.net.NetworkUtils;
|
||||||
import android.net.RouteInfo;
|
import android.net.RouteInfo;
|
||||||
@@ -167,6 +168,7 @@ public class TetheringTest {
|
|||||||
@Mock private IDhcpServer mDhcpServer;
|
@Mock private IDhcpServer mDhcpServer;
|
||||||
@Mock private INetd mNetd;
|
@Mock private INetd mNetd;
|
||||||
@Mock private UserManager mUserManager;
|
@Mock private UserManager mUserManager;
|
||||||
|
@Mock private NetworkRequest mNetworkRequest;
|
||||||
|
|
||||||
private final MockIpServerDependencies mIpServerDependencies =
|
private final MockIpServerDependencies mIpServerDependencies =
|
||||||
spy(new MockIpServerDependencies());
|
spy(new MockIpServerDependencies());
|
||||||
@@ -310,6 +312,11 @@ public class TetheringTest {
|
|||||||
return mIpServerDependencies;
|
return mIpServerDependencies;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NetworkRequest getDefaultNetworkRequest() {
|
||||||
|
return mNetworkRequest;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isTetheringSupported() {
|
public boolean isTetheringSupported() {
|
||||||
mIsTetheringSupportedCalls++;
|
mIsTetheringSupportedCalls++;
|
||||||
@@ -1039,7 +1046,7 @@ public class TetheringTest {
|
|||||||
expectedInteractionsWithShowNotification);
|
expectedInteractionsWithShowNotification);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class TestTetherInternalCallback extends ITetherInternalCallback.Stub {
|
private class TestTetheringEventCallback extends ITetheringEventCallback.Stub {
|
||||||
private final ArrayList<Network> mActualUpstreams = new ArrayList<>();
|
private final ArrayList<Network> mActualUpstreams = new ArrayList<>();
|
||||||
private final ArrayList<TetheringConfigurationParcel> mTetheringConfigs =
|
private final ArrayList<TetheringConfigurationParcel> mTetheringConfigs =
|
||||||
new ArrayList<>();
|
new ArrayList<>();
|
||||||
@@ -1100,13 +1107,16 @@ public class TetheringTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCallbackCreated(Network network, TetheringConfigurationParcel config,
|
public void onCallbackStarted(Network network, TetheringConfigurationParcel config,
|
||||||
TetherStatesParcel states) {
|
TetherStatesParcel states) {
|
||||||
mActualUpstreams.add(network);
|
mActualUpstreams.add(network);
|
||||||
mTetheringConfigs.add(config);
|
mTetheringConfigs.add(config);
|
||||||
mTetherStates.add(states);
|
mTetherStates.add(states);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCallbackStopped(int errorCode) { }
|
||||||
|
|
||||||
public void assertNoUpstreamChangeCallback() {
|
public void assertNoUpstreamChangeCallback() {
|
||||||
assertTrue(mActualUpstreams.isEmpty());
|
assertTrue(mActualUpstreams.isEmpty());
|
||||||
}
|
}
|
||||||
@@ -1115,10 +1125,20 @@ public class TetheringTest {
|
|||||||
assertTrue(mTetheringConfigs.isEmpty());
|
assertTrue(mTetheringConfigs.isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void assertNoStateChangeCallback() {
|
||||||
|
assertTrue(mTetherStates.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
public void assertStateChangeCallback() {
|
public void assertStateChangeCallback() {
|
||||||
assertFalse(mTetherStates.isEmpty());
|
assertFalse(mTetherStates.isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void assertNoCallback() {
|
||||||
|
assertNoUpstreamChangeCallback();
|
||||||
|
assertNoConfigChangeCallback();
|
||||||
|
assertNoStateChangeCallback();
|
||||||
|
}
|
||||||
|
|
||||||
private void assertTetherConfigParcelEqual(@NonNull TetheringConfigurationParcel actual,
|
private void assertTetherConfigParcelEqual(@NonNull TetheringConfigurationParcel actual,
|
||||||
@NonNull TetheringConfigurationParcel expect) {
|
@NonNull TetheringConfigurationParcel expect) {
|
||||||
assertEquals(actual.subId, expect.subId);
|
assertEquals(actual.subId, expect.subId);
|
||||||
@@ -1139,18 +1159,19 @@ public class TetheringTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRegisterTetherInternalCallback() throws Exception {
|
public void testRegisterTetheringEventCallback() throws Exception {
|
||||||
TestTetherInternalCallback callback = new TestTetherInternalCallback();
|
TestTetheringEventCallback callback = new TestTetheringEventCallback();
|
||||||
|
TestTetheringEventCallback callback2 = new TestTetheringEventCallback();
|
||||||
|
|
||||||
// 1. Register one callback before running any tethering.
|
// 1. Register one callback before running any tethering.
|
||||||
mTethering.registerTetherInternalCallback(callback);
|
mTethering.registerTetheringEventCallback(callback);
|
||||||
mLooper.dispatchAll();
|
mLooper.dispatchAll();
|
||||||
callback.expectUpstreamChanged(new Network[] {null});
|
callback.expectUpstreamChanged(new Network[] {null});
|
||||||
callback.expectConfigurationChanged(
|
callback.expectConfigurationChanged(
|
||||||
mTethering.getTetheringConfiguration().toStableParcelable());
|
mTethering.getTetheringConfiguration().toStableParcelable());
|
||||||
TetherStatesParcel tetherState = callback.pollTetherStatesChanged();
|
TetherStatesParcel tetherState = callback.pollTetherStatesChanged();
|
||||||
assertEquals(tetherState, null);
|
assertEquals(tetherState, null);
|
||||||
// 2. Enable wifi tethering
|
// 2. Enable wifi tethering.
|
||||||
NetworkState upstreamState = buildMobileDualStackUpstreamState();
|
NetworkState upstreamState = buildMobileDualStackUpstreamState();
|
||||||
when(mUpstreamNetworkMonitor.getCurrentPreferredUpstream()).thenReturn(upstreamState);
|
when(mUpstreamNetworkMonitor.getCurrentPreferredUpstream()).thenReturn(upstreamState);
|
||||||
when(mUpstreamNetworkMonitor.selectPreferredUpstreamType(any()))
|
when(mUpstreamNetworkMonitor.selectPreferredUpstreamType(any()))
|
||||||
@@ -1168,14 +1189,26 @@ public class TetheringTest {
|
|||||||
assertArrayEquals(tetherState.tetheredList, new String[] {TEST_WLAN_IFNAME});
|
assertArrayEquals(tetherState.tetheredList, new String[] {TEST_WLAN_IFNAME});
|
||||||
callback.expectUpstreamChanged(upstreamState.network);
|
callback.expectUpstreamChanged(upstreamState.network);
|
||||||
|
|
||||||
// 3. Disable wifi tethering.
|
// 3. Register second callback.
|
||||||
|
mTethering.registerTetheringEventCallback(callback2);
|
||||||
|
mLooper.dispatchAll();
|
||||||
|
callback2.expectUpstreamChanged(upstreamState.network);
|
||||||
|
callback2.expectConfigurationChanged(
|
||||||
|
mTethering.getTetheringConfiguration().toStableParcelable());
|
||||||
|
tetherState = callback2.pollTetherStatesChanged();
|
||||||
|
assertEquals(tetherState.tetheredList, new String[] {TEST_WLAN_IFNAME});
|
||||||
|
|
||||||
|
// 4. Unregister first callback and disable wifi tethering
|
||||||
|
mTethering.unregisterTetheringEventCallback(callback);
|
||||||
|
mLooper.dispatchAll();
|
||||||
mTethering.stopTethering(TETHERING_WIFI);
|
mTethering.stopTethering(TETHERING_WIFI);
|
||||||
sendWifiApStateChanged(WifiManager.WIFI_AP_STATE_DISABLED);
|
sendWifiApStateChanged(WifiManager.WIFI_AP_STATE_DISABLED);
|
||||||
mLooper.dispatchAll();
|
mLooper.dispatchAll();
|
||||||
tetherState = callback.pollTetherStatesChanged();
|
tetherState = callback2.pollTetherStatesChanged();
|
||||||
assertArrayEquals(tetherState.availableList, new String[] {TEST_WLAN_IFNAME});
|
assertArrayEquals(tetherState.availableList, new String[] {TEST_WLAN_IFNAME});
|
||||||
mLooper.dispatchAll();
|
mLooper.dispatchAll();
|
||||||
callback.expectUpstreamChanged(new Network[] {null});
|
callback2.expectUpstreamChanged(new Network[] {null});
|
||||||
|
callback.assertNoCallback();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ java_library {
|
|||||||
|
|
||||||
libs: [
|
libs: [
|
||||||
"android.hidl.manager-V1.0-java",
|
"android.hidl.manager-V1.0-java",
|
||||||
|
"framework-tethering"
|
||||||
],
|
],
|
||||||
|
|
||||||
plugins: [
|
plugins: [
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ java_library_static {
|
|||||||
"android.hardware.tv.cec-V1.0-java",
|
"android.hardware.tv.cec-V1.0-java",
|
||||||
"app-compat-annotations",
|
"app-compat-annotations",
|
||||||
"vintf-vibrator-java",
|
"vintf-vibrator-java",
|
||||||
|
"framework-tethering",
|
||||||
],
|
],
|
||||||
|
|
||||||
required: [
|
required: [
|
||||||
|
|||||||
@@ -77,7 +77,6 @@ import android.net.INetworkPolicyListener;
|
|||||||
import android.net.INetworkPolicyManager;
|
import android.net.INetworkPolicyManager;
|
||||||
import android.net.INetworkStatsService;
|
import android.net.INetworkStatsService;
|
||||||
import android.net.ISocketKeepaliveCallback;
|
import android.net.ISocketKeepaliveCallback;
|
||||||
import android.net.ITetheringEventCallback;
|
|
||||||
import android.net.InetAddresses;
|
import android.net.InetAddresses;
|
||||||
import android.net.IpMemoryStore;
|
import android.net.IpMemoryStore;
|
||||||
import android.net.IpPrefix;
|
import android.net.IpPrefix;
|
||||||
@@ -278,8 +277,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
|
|
||||||
private MockableSystemProperties mSystemProperties;
|
private MockableSystemProperties mSystemProperties;
|
||||||
|
|
||||||
private TetheringManager mTetheringManager;
|
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
protected final PermissionMonitor mPermissionMonitor;
|
protected final PermissionMonitor mPermissionMonitor;
|
||||||
|
|
||||||
@@ -866,13 +863,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
return NetworkStackClient.getInstance();
|
return NetworkStackClient.getInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a reference to the TetheringManager.
|
|
||||||
*/
|
|
||||||
public TetheringManager getTetheringManager() {
|
|
||||||
return TetheringManager.getInstance();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see ProxyTracker
|
* @see ProxyTracker
|
||||||
*/
|
*/
|
||||||
@@ -1072,8 +1062,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
|
|
||||||
mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
|
mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
|
||||||
|
|
||||||
mTetheringManager = mDeps.getTetheringManager();
|
|
||||||
|
|
||||||
mPermissionMonitor = new PermissionMonitor(mContext, mNetd);
|
mPermissionMonitor = new PermissionMonitor(mContext, mNetd);
|
||||||
|
|
||||||
// Set up the listener for user state for creating user VPNs.
|
// Set up the listener for user state for creating user VPNs.
|
||||||
@@ -1887,14 +1875,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
}
|
}
|
||||||
mHandler.sendMessage(mHandler.obtainMessage(
|
mHandler.sendMessage(mHandler.obtainMessage(
|
||||||
EVENT_DATA_SAVER_CHANGED, restrictBackground ? 1 : 0, 0));
|
EVENT_DATA_SAVER_CHANGED, restrictBackground ? 1 : 0, 0));
|
||||||
|
|
||||||
// TODO: relocate this specific callback in Tethering.
|
|
||||||
if (restrictBackground) {
|
|
||||||
log("onRestrictBackgroundChanged(true): disabling tethering");
|
|
||||||
mTetheringManager.stopTethering(ConnectivityManager.TETHERING_WIFI);
|
|
||||||
mTetheringManager.stopTethering(ConnectivityManager.TETHERING_USB);
|
|
||||||
mTetheringManager.stopTethering(ConnectivityManager.TETHERING_BLUETOOTH);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -2024,12 +2004,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, pid, uid);
|
NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, pid, uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void enforceTetherAccessPermission() {
|
|
||||||
mContext.enforceCallingOrSelfPermission(
|
|
||||||
android.Manifest.permission.ACCESS_NETWORK_STATE,
|
|
||||||
"ConnectivityService");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void enforceControlAlwaysOnVpnPermission() {
|
private void enforceControlAlwaysOnVpnPermission() {
|
||||||
mContext.enforceCallingOrSelfPermission(
|
mContext.enforceCallingOrSelfPermission(
|
||||||
android.Manifest.permission.CONTROL_ALWAYS_ON_VPN,
|
android.Manifest.permission.CONTROL_ALWAYS_ON_VPN,
|
||||||
@@ -2462,12 +2436,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
pw.println();
|
pw.println();
|
||||||
mKeepaliveTracker.dump(pw);
|
mKeepaliveTracker.dump(pw);
|
||||||
|
|
||||||
pw.println();
|
|
||||||
pw.println("TetheringManager logs:");
|
|
||||||
pw.increaseIndent();
|
|
||||||
TetheringManager.getInstance().dump(pw);
|
|
||||||
pw.decreaseIndent();
|
|
||||||
|
|
||||||
pw.println();
|
pw.println();
|
||||||
dumpAvoidBadWifiSettings(pw);
|
dumpAvoidBadWifiSettings(pw);
|
||||||
|
|
||||||
@@ -3993,183 +3961,55 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// javadoc from interface
|
|
||||||
@Override
|
|
||||||
public int tether(String iface, String callerPkg) {
|
|
||||||
ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
|
|
||||||
if (isTetheringSupported()) {
|
|
||||||
return mTetheringManager.tether(iface);
|
|
||||||
} else {
|
|
||||||
return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// javadoc from interface
|
|
||||||
@Override
|
|
||||||
public int untether(String iface, String callerPkg) {
|
|
||||||
ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
|
|
||||||
|
|
||||||
if (isTetheringSupported()) {
|
|
||||||
return mTetheringManager.untether(iface);
|
|
||||||
} else {
|
|
||||||
return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// javadoc from interface
|
|
||||||
@Override
|
@Override
|
||||||
|
@Deprecated
|
||||||
public int getLastTetherError(String iface) {
|
public int getLastTetherError(String iface) {
|
||||||
enforceTetherAccessPermission();
|
final TetheringManager tm = (TetheringManager) mContext.getSystemService(
|
||||||
|
Context.TETHERING_SERVICE);
|
||||||
if (isTetheringSupported()) {
|
return tm.getLastTetherError(iface);
|
||||||
return mTetheringManager.getLastTetherError(iface);
|
|
||||||
} else {
|
|
||||||
return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO - proper iface API for selection by property, inspection, etc
|
|
||||||
@Override
|
|
||||||
public String[] getTetherableUsbRegexs() {
|
|
||||||
enforceTetherAccessPermission();
|
|
||||||
if (isTetheringSupported()) {
|
|
||||||
return mTetheringManager.getTetherableUsbRegexs();
|
|
||||||
} else {
|
|
||||||
return new String[0];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String[] getTetherableWifiRegexs() {
|
@Deprecated
|
||||||
enforceTetherAccessPermission();
|
|
||||||
if (isTetheringSupported()) {
|
|
||||||
return mTetheringManager.getTetherableWifiRegexs();
|
|
||||||
} else {
|
|
||||||
return new String[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String[] getTetherableBluetoothRegexs() {
|
|
||||||
enforceTetherAccessPermission();
|
|
||||||
if (isTetheringSupported()) {
|
|
||||||
return mTetheringManager.getTetherableBluetoothRegexs();
|
|
||||||
} else {
|
|
||||||
return new String[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int setUsbTethering(boolean enable, String callerPkg) {
|
|
||||||
ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
|
|
||||||
if (isTetheringSupported()) {
|
|
||||||
return mTetheringManager.setUsbTethering(enable);
|
|
||||||
} else {
|
|
||||||
return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO - move iface listing, queries, etc to new module
|
|
||||||
// javadoc from interface
|
|
||||||
@Override
|
|
||||||
public String[] getTetherableIfaces() {
|
public String[] getTetherableIfaces() {
|
||||||
enforceTetherAccessPermission();
|
final TetheringManager tm = (TetheringManager) mContext.getSystemService(
|
||||||
return mTetheringManager.getTetherableIfaces();
|
Context.TETHERING_SERVICE);
|
||||||
|
return tm.getTetherableIfaces();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Deprecated
|
||||||
public String[] getTetheredIfaces() {
|
public String[] getTetheredIfaces() {
|
||||||
enforceTetherAccessPermission();
|
final TetheringManager tm = (TetheringManager) mContext.getSystemService(
|
||||||
return mTetheringManager.getTetheredIfaces();
|
Context.TETHERING_SERVICE);
|
||||||
|
return tm.getTetheredIfaces();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Deprecated
|
||||||
public String[] getTetheringErroredIfaces() {
|
public String[] getTetheringErroredIfaces() {
|
||||||
enforceTetherAccessPermission();
|
final TetheringManager tm = (TetheringManager) mContext.getSystemService(
|
||||||
return mTetheringManager.getTetheringErroredIfaces();
|
Context.TETHERING_SERVICE);
|
||||||
|
|
||||||
|
return tm.getTetheringErroredIfaces();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String[] getTetheredDhcpRanges() {
|
@Deprecated
|
||||||
enforceSettingsPermission();
|
public String[] getTetherableUsbRegexs() {
|
||||||
return mTetheringManager.getTetheredDhcpRanges();
|
final TetheringManager tm = (TetheringManager) mContext.getSystemService(
|
||||||
|
Context.TETHERING_SERVICE);
|
||||||
|
|
||||||
|
return tm.getTetherableUsbRegexs();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isTetheringSupported(String callerPkg) {
|
@Deprecated
|
||||||
ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
|
public String[] getTetherableWifiRegexs() {
|
||||||
return isTetheringSupported();
|
final TetheringManager tm = (TetheringManager) mContext.getSystemService(
|
||||||
}
|
Context.TETHERING_SERVICE);
|
||||||
|
return tm.getTetherableWifiRegexs();
|
||||||
// if ro.tether.denied = true we default to no tethering
|
|
||||||
// gservices could set the secure setting to 1 though to enable it on a build where it
|
|
||||||
// had previously been turned off.
|
|
||||||
private boolean isTetheringSupported() {
|
|
||||||
int defaultVal = encodeBool(!mSystemProperties.get("ro.tether.denied").equals("true"));
|
|
||||||
boolean tetherSupported = toBool(Settings.Global.getInt(mContext.getContentResolver(),
|
|
||||||
Settings.Global.TETHER_SUPPORTED, defaultVal));
|
|
||||||
boolean tetherEnabledInSettings = tetherSupported
|
|
||||||
&& !mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING);
|
|
||||||
|
|
||||||
// Elevate to system UID to avoid caller requiring MANAGE_USERS permission.
|
|
||||||
boolean adminUser = false;
|
|
||||||
final long token = Binder.clearCallingIdentity();
|
|
||||||
try {
|
|
||||||
adminUser = mUserManager.isAdminUser();
|
|
||||||
} finally {
|
|
||||||
Binder.restoreCallingIdentity(token);
|
|
||||||
}
|
|
||||||
|
|
||||||
return tetherEnabledInSettings && adminUser
|
|
||||||
&& mTetheringManager.hasTetherableConfiguration();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void startTethering(int type, ResultReceiver receiver, boolean showProvisioningUi,
|
|
||||||
String callerPkg) {
|
|
||||||
ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
|
|
||||||
if (!isTetheringSupported()) {
|
|
||||||
receiver.send(ConnectivityManager.TETHER_ERROR_UNSUPPORTED, null);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mTetheringManager.startTethering(type, receiver, showProvisioningUi);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void stopTethering(int type, String callerPkg) {
|
|
||||||
ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
|
|
||||||
mTetheringManager.stopTethering(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get 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.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void getLatestTetheringEntitlementResult(int type, ResultReceiver receiver,
|
|
||||||
boolean showEntitlementUi, String callerPkg) {
|
|
||||||
ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
|
|
||||||
mTetheringManager.requestLatestTetheringEntitlementResult(
|
|
||||||
type, receiver, showEntitlementUi);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Register tethering event callback. */
|
|
||||||
@Override
|
|
||||||
public void registerTetheringEventCallback(ITetheringEventCallback callback,
|
|
||||||
String callerPkg) {
|
|
||||||
ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
|
|
||||||
mTetheringManager.registerTetheringEventCallback(callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Unregister tethering event callback. */
|
|
||||||
@Override
|
|
||||||
public void unregisterTetheringEventCallback(ITetheringEventCallback callback,
|
|
||||||
String callerPkg) {
|
|
||||||
ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
|
|
||||||
mTetheringManager.unregisterTetheringEventCallback(callback);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called when we lose the default network and have no replacement yet.
|
// Called when we lose the default network and have no replacement yet.
|
||||||
@@ -7050,14 +6890,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
// Turn airplane mode off
|
// Turn airplane mode off
|
||||||
setAirplaneMode(false);
|
setAirplaneMode(false);
|
||||||
|
|
||||||
if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING)) {
|
|
||||||
// Untether
|
|
||||||
String pkgName = mContext.getOpPackageName();
|
|
||||||
for (String tether : getTetheredIfaces()) {
|
|
||||||
untether(tether, pkgName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_VPN)) {
|
if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_VPN)) {
|
||||||
// Remove always-on package
|
// Remove always-on package
|
||||||
synchronized (mVpns) {
|
synchronized (mVpns) {
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package com.android.server;
|
package com.android.server;
|
||||||
|
|
||||||
|
import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK;
|
||||||
import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_CRITICAL;
|
import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_CRITICAL;
|
||||||
import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_HIGH;
|
import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_HIGH;
|
||||||
import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_NORMAL;
|
import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_NORMAL;
|
||||||
@@ -40,8 +41,8 @@ import android.database.sqlite.SQLiteCompatibilityWalFlags;
|
|||||||
import android.database.sqlite.SQLiteGlobal;
|
import android.database.sqlite.SQLiteGlobal;
|
||||||
import android.hardware.display.DisplayManagerInternal;
|
import android.hardware.display.DisplayManagerInternal;
|
||||||
import android.net.ConnectivityModuleConnector;
|
import android.net.ConnectivityModuleConnector;
|
||||||
|
import android.net.ITetheringConnector;
|
||||||
import android.net.NetworkStackClient;
|
import android.net.NetworkStackClient;
|
||||||
import android.net.TetheringManager;
|
|
||||||
import android.os.BaseBundle;
|
import android.os.BaseBundle;
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
@@ -2212,8 +2213,14 @@ public final class SystemServer {
|
|||||||
|
|
||||||
traceBeginAndSlog("StartTethering");
|
traceBeginAndSlog("StartTethering");
|
||||||
try {
|
try {
|
||||||
// Tethering must start after ConnectivityService and NetworkStack.
|
// TODO: hide implementation details, b/146312721.
|
||||||
TetheringManager.getInstance().start();
|
ConnectivityModuleConnector.getInstance().startModuleService(
|
||||||
|
ITetheringConnector.class.getName(),
|
||||||
|
PERMISSION_MAINLINE_NETWORK_STACK, service -> {
|
||||||
|
ServiceManager.addService(Context.TETHERING_SERVICE, service,
|
||||||
|
false /* allowIsolated */,
|
||||||
|
DUMP_FLAG_PRIORITY_HIGH | DUMP_FLAG_PRIORITY_NORMAL);
|
||||||
|
});
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
reportWtf("starting Tethering", e);
|
reportWtf("starting Tethering", e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,14 +10,12 @@ java_library_static {
|
|||||||
srcs: [
|
srcs: [
|
||||||
":net-module-utils-srcs",
|
":net-module-utils-srcs",
|
||||||
":services.net-sources",
|
":services.net-sources",
|
||||||
":tethering-manager",
|
|
||||||
],
|
],
|
||||||
static_libs: [
|
static_libs: [
|
||||||
"dnsresolver_aidl_interface-V2-java",
|
"dnsresolver_aidl_interface-V2-java",
|
||||||
"netd_aidl_interface-unstable-java",
|
"netd_aidl_interface-unstable-java",
|
||||||
"netlink-client",
|
"netlink-client",
|
||||||
"networkstack-client",
|
"networkstack-client",
|
||||||
"tethering-client",
|
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -25,8 +23,6 @@ filegroup {
|
|||||||
name: "services-tethering-shared-srcs",
|
name: "services-tethering-shared-srcs",
|
||||||
srcs: [
|
srcs: [
|
||||||
":framework-annotations",
|
":framework-annotations",
|
||||||
"java/android/net/ConnectivityModuleConnector.java",
|
|
||||||
"java/android/net/NetworkStackClient.java",
|
|
||||||
"java/android/net/util/NetdService.java",
|
"java/android/net/util/NetdService.java",
|
||||||
"java/android/net/util/NetworkConstants.java",
|
"java/android/net/util/NetworkConstants.java",
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ import android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET
|
|||||||
import android.net.NetworkCapabilities.TRANSPORT_CELLULAR
|
import android.net.NetworkCapabilities.TRANSPORT_CELLULAR
|
||||||
import android.net.NetworkRequest
|
import android.net.NetworkRequest
|
||||||
import android.net.TestNetworkStackClient
|
import android.net.TestNetworkStackClient
|
||||||
import android.net.TetheringManager
|
|
||||||
import android.net.metrics.IpConnectivityLog
|
import android.net.metrics.IpConnectivityLog
|
||||||
import android.os.ConditionVariable
|
import android.os.ConditionVariable
|
||||||
import android.os.IBinder
|
import android.os.IBinder
|
||||||
@@ -169,7 +168,6 @@ class ConnectivityServiceIntegrationTest {
|
|||||||
val deps = spy(ConnectivityService.Dependencies())
|
val deps = spy(ConnectivityService.Dependencies())
|
||||||
doReturn(networkStackClient).`when`(deps).networkStack
|
doReturn(networkStackClient).`when`(deps).networkStack
|
||||||
doReturn(metricsLogger).`when`(deps).metricsLogger
|
doReturn(metricsLogger).`when`(deps).metricsLogger
|
||||||
doReturn(mock(TetheringManager::class.java)).`when`(deps).getTetheringManager()
|
|
||||||
doReturn(mock(ProxyTracker::class.java)).`when`(deps).makeProxyTracker(any(), any())
|
doReturn(mock(ProxyTracker::class.java)).`when`(deps).makeProxyTracker(any(), any())
|
||||||
doReturn(mock(MockableSystemProperties::class.java)).`when`(deps).systemProperties
|
doReturn(mock(MockableSystemProperties::class.java)).`when`(deps).systemProperties
|
||||||
doReturn(TestNetIdManager()).`when`(deps).makeNetIdManager()
|
doReturn(TestNetIdManager()).`when`(deps).makeNetIdManager()
|
||||||
|
|||||||
@@ -164,7 +164,6 @@ import android.net.ProxyInfo;
|
|||||||
import android.net.ResolverParamsParcel;
|
import android.net.ResolverParamsParcel;
|
||||||
import android.net.RouteInfo;
|
import android.net.RouteInfo;
|
||||||
import android.net.SocketKeepalive;
|
import android.net.SocketKeepalive;
|
||||||
import android.net.TetheringManager;
|
|
||||||
import android.net.UidRange;
|
import android.net.UidRange;
|
||||||
import android.net.metrics.IpConnectivityLog;
|
import android.net.metrics.IpConnectivityLog;
|
||||||
import android.net.shared.NetworkMonitorUtils;
|
import android.net.shared.NetworkMonitorUtils;
|
||||||
@@ -1133,7 +1132,6 @@ public class ConnectivityServiceTest {
|
|||||||
doReturn(new TestNetIdManager()).when(deps).makeNetIdManager();
|
doReturn(new TestNetIdManager()).when(deps).makeNetIdManager();
|
||||||
doReturn(mNetworkStack).when(deps).getNetworkStack();
|
doReturn(mNetworkStack).when(deps).getNetworkStack();
|
||||||
doReturn(systemProperties).when(deps).getSystemProperties();
|
doReturn(systemProperties).when(deps).getSystemProperties();
|
||||||
doReturn(mock(TetheringManager.class)).when(deps).getTetheringManager();
|
|
||||||
doReturn(mock(ProxyTracker.class)).when(deps).makeProxyTracker(any(), any());
|
doReturn(mock(ProxyTracker.class)).when(deps).makeProxyTracker(any(), any());
|
||||||
doReturn(mMetricsService).when(deps).getMetricsLogger();
|
doReturn(mMetricsService).when(deps).getMetricsLogger();
|
||||||
doReturn(true).when(deps).queryUserAccess(anyInt(), anyInt());
|
doReturn(true).when(deps).queryUserAccess(anyInt(), anyInt());
|
||||||
|
|||||||
Reference in New Issue
Block a user