summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormarkchien <markchien@google.com>2019-12-05 12:04:59 +0800
committermarkchien <markchien@google.com>2020-01-14 20:15:31 +0800
commit3fe660bc4a0af8989cba574dfddce32e788e1afb (patch)
tree714870aa0db79f7e21d1cd65e3bf279242461233
parentcaa810011c007265305a540754bb8c58694b1181 (diff)
Allow opening tethering when data saver ON
When data saver enabled, tethering would be OFF. Currently settings would not allow user to turning tethering back. After aosp/1181583 is merged, user can turn tethering back without turning data saver OFF. Bug: 145711175 Bug: 142374233 Test: atest TetheringTests OFF/ON tethering when data saver ON Change-Id: I59e662ba771a563f5f1766ba29e05246b8280220
-rw-r--r--core/java/android/net/INetworkPolicyManager.aidl3
-rw-r--r--packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java35
-rw-r--r--packages/Tethering/src/com/android/server/connectivity/tethering/TetheringDependencies.java15
-rw-r--r--packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java6
-rw-r--r--packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java64
-rw-r--r--services/core/java/com/android/server/net/NetworkPolicyManagerService.java11
6 files changed, 93 insertions, 41 deletions
diff --git a/core/java/android/net/INetworkPolicyManager.aidl b/core/java/android/net/INetworkPolicyManager.aidl
index 385cb1d68b57..72a6b397a30c 100644
--- a/core/java/android/net/INetworkPolicyManager.aidl
+++ b/core/java/android/net/INetworkPolicyManager.aidl
@@ -57,9 +57,6 @@ interface INetworkPolicyManager {
@UnsupportedAppUsage
boolean getRestrictBackground();
- /** Callback used to change internal state on tethering */
- void onTetheringChanged(String iface, boolean tethering);
-
/** Gets the restrict background status based on the caller's UID:
1 - disabled
2 - whitelisted
diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java b/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java
index 301f805d3d03..d372d1aa88df 100644
--- a/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java
@@ -20,6 +20,7 @@ import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.hardware.usb.UsbManager.USB_CONFIGURED;
import static android.hardware.usb.UsbManager.USB_CONNECTED;
import static android.hardware.usb.UsbManager.USB_FUNCTION_RNDIS;
+import static android.net.ConnectivityManager.ACTION_RESTRICT_BACKGROUND_CHANGED;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
import static android.net.ConnectivityManager.EXTRA_NETWORK_INFO;
import static android.net.TetheringManager.ACTION_TETHER_STATE_CHANGED;
@@ -64,8 +65,8 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Resources;
import android.hardware.usb.UsbManager;
+import android.net.ConnectivityManager;
import android.net.INetd;
-import android.net.INetworkPolicyManager;
import android.net.ITetheringEventCallback;
import android.net.IpPrefix;
import android.net.LinkAddress;
@@ -176,7 +177,6 @@ public class Tethering {
private final Context mContext;
private final ArrayMap<String, TetherState> mTetherStates;
private final BroadcastReceiver mStateReceiver;
- private final INetworkPolicyManager mPolicyManager;
private final Looper mLooper;
private final StateMachine mTetherMasterSM;
private final OffloadController mOffloadController;
@@ -206,12 +206,12 @@ public class Tethering {
private boolean mWifiTetherRequested;
private Network mTetherUpstream;
private TetherStatesParcel mTetherStatesParcel;
+ private boolean mDataSaverEnabled = false;
public Tethering(TetheringDependencies deps) {
mLog.mark("Tethering.constructed");
mDeps = deps;
mContext = mDeps.getContext();
- mPolicyManager = mDeps.getINetworkPolicyManager();
mNetd = mDeps.getINetd(mContext);
mLooper = mDeps.getTetheringLooper();
@@ -288,6 +288,7 @@ public class Tethering {
filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
filter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
filter.addAction(UserManager.ACTION_USER_RESTRICTIONS_CHANGED);
+ filter.addAction(ACTION_RESTRICT_BACKGROUND_CHANGED);
mContext.registerReceiver(mStateReceiver, filter, null, handler);
}
@@ -484,7 +485,7 @@ public class Tethering {
}
private void setBluetoothTethering(final boolean enable, final ResultReceiver receiver) {
- final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+ final BluetoothAdapter adapter = mDeps.getBluetoothAdapter();
if (adapter == null || !adapter.isEnabled()) {
Log.w(TAG, "Tried to enable bluetooth tethering with null or disabled adapter. null: "
+ (adapter == null));
@@ -775,6 +776,9 @@ public class Tethering {
} else if (action.equals(UserManager.ACTION_USER_RESTRICTIONS_CHANGED)) {
mLog.log("OBSERVED user restrictions changed");
handleUserRestrictionAction();
+ } else if (action.equals(ACTION_RESTRICT_BACKGROUND_CHANGED)) {
+ mLog.log("OBSERVED data saver changed");
+ handleDataSaverChanged();
}
}
@@ -885,6 +889,20 @@ public class Tethering {
private void handleUserRestrictionAction() {
mTetheringRestriction.onUserRestrictionsChanged();
}
+
+ private void handleDataSaverChanged() {
+ final ConnectivityManager connMgr = (ConnectivityManager) mContext.getSystemService(
+ Context.CONNECTIVITY_SERVICE);
+ final boolean isDataSaverEnabled = connMgr.getRestrictBackgroundStatus()
+ != ConnectivityManager.RESTRICT_BACKGROUND_STATUS_DISABLED;
+
+ if (mDataSaverEnabled == isDataSaverEnabled) return;
+
+ mDataSaverEnabled = isDataSaverEnabled;
+ if (mDataSaverEnabled) {
+ untetherAll();
+ }
+ }
}
@VisibleForTesting
@@ -1982,15 +2000,6 @@ public class Tethering {
mLog.log(String.format("OBSERVED iface=%s state=%s error=%s", iface, state, error));
- try {
- // Notify that we're tethering (or not) this interface.
- // This is how data saver for instance knows if the user explicitly
- // turned on tethering (thus keeping us from being in data saver mode).
- mPolicyManager.onTetheringChanged(iface, state == IpServer.STATE_TETHERED);
- } catch (RemoteException e) {
- // Not really very much we can do here.
- }
-
// If TetherMasterSM is in ErrorState, TetherMasterSM stays there.
// Thus we give a chance for TetherMasterSM to recover to InitialState
// by sending CMD_CLEAR_ERROR
diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringDependencies.java b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringDependencies.java
index 79e99e8023ed..247ed4799327 100644
--- a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringDependencies.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringDependencies.java
@@ -16,9 +16,9 @@
package com.android.server.connectivity.tethering;
+import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.net.INetd;
-import android.net.INetworkPolicyManager;
import android.net.NetworkRequest;
import android.net.ip.IpServer;
import android.net.util.SharedLog;
@@ -106,14 +106,6 @@ public abstract class TetheringDependencies {
}
/**
- * Get a reference to INetworkPolicyManager to be used by tethering.
- */
- public INetworkPolicyManager getINetworkPolicyManager() {
- return INetworkPolicyManager.Stub.asInterface(
- ServiceManager.getService(Context.NETWORK_POLICY_SERVICE));
- }
-
- /**
* Get a reference to INetd to be used by tethering.
*/
public INetd getINetd(Context context) {
@@ -130,4 +122,9 @@ public abstract class TetheringDependencies {
* Get Context of TetheringSerice.
*/
public abstract Context getContext();
+
+ /**
+ * Get a reference to BluetoothAdapter to be used by tethering.
+ */
+ public abstract BluetoothAdapter getBluetoothAdapter();
}
diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java
index 99130d20e614..cb7d3920e693 100644
--- a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java
@@ -24,6 +24,7 @@ import static android.net.TetheringManager.TETHER_ERROR_UNSUPPORTED;
import static android.net.dhcp.IDhcpServer.STATUS_UNKNOWN_ERROR;
import android.app.Service;
+import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.content.Intent;
import android.net.IIntResultListener;
@@ -376,6 +377,11 @@ public class TetheringService extends Service {
}
return INetworkStackConnector.Stub.asInterface(connector);
}
+
+ @Override
+ public BluetoothAdapter getBluetoothAdapter() {
+ return BluetoothAdapter.getDefaultAdapter();
+ }
};
}
return mDeps;
diff --git a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java
index eaac159a87d8..467187697823 100644
--- a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java
+++ b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java
@@ -19,6 +19,9 @@ package com.android.server.connectivity.tethering;
import static android.hardware.usb.UsbManager.USB_CONFIGURED;
import static android.hardware.usb.UsbManager.USB_CONNECTED;
import static android.hardware.usb.UsbManager.USB_FUNCTION_RNDIS;
+import static android.net.ConnectivityManager.ACTION_RESTRICT_BACKGROUND_CHANGED;
+import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_DISABLED;
+import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_ENABLED;
import static android.net.RouteInfo.RTN_UNICAST;
import static android.net.TetheringManager.ACTION_TETHER_STATE_CHANGED;
import static android.net.TetheringManager.EXTRA_ACTIVE_LOCAL_ONLY;
@@ -53,6 +56,7 @@ import static org.mockito.Mockito.any;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.times;
@@ -61,6 +65,7 @@ import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
import android.app.usage.NetworkStatsManager;
+import android.bluetooth.BluetoothAdapter;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
@@ -69,6 +74,7 @@ import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.res.Resources;
import android.hardware.usb.UsbManager;
+import android.net.ConnectivityManager;
import android.net.INetd;
import android.net.INetworkPolicyManager;
import android.net.ITetheringEventCallback;
@@ -133,6 +139,7 @@ import java.net.Inet4Address;
import java.net.Inet6Address;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
import java.util.Vector;
@RunWith(AndroidJUnit4.class)
@@ -167,6 +174,7 @@ public class TetheringTest {
@Mock private INetd mNetd;
@Mock private UserManager mUserManager;
@Mock private NetworkRequest mNetworkRequest;
+ @Mock private ConnectivityManager mCm;
private final MockIpServerDependencies mIpServerDependencies =
spy(new MockIpServerDependencies());
@@ -218,6 +226,7 @@ public class TetheringTest {
if (Context.TELEPHONY_SERVICE.equals(name)) return mTelephonyManager;
if (Context.USER_SERVICE.equals(name)) return mUserManager;
if (Context.NETWORK_STATS_SERVICE.equals(name)) return mStatsManager;
+ if (Context.CONNECTIVITY_SERVICE.equals(name)) return mCm;
return super.getSystemService(name);
}
@@ -340,11 +349,6 @@ public class TetheringTest {
}
@Override
- public INetworkPolicyManager getINetworkPolicyManager() {
- return mPolicyManager;
- }
-
- @Override
public INetd getINetd(Context context) {
return mNetd;
}
@@ -358,6 +362,12 @@ public class TetheringTest {
public Context getContext() {
return mServiceContext;
}
+
+ @Override
+ public BluetoothAdapter getBluetoothAdapter() {
+ // TODO: add test for bluetooth tethering.
+ return null;
+ }
}
private static UpstreamNetworkState buildMobileUpstreamState(boolean withIPv4,
@@ -1349,6 +1359,50 @@ public class TetheringTest {
workingWifiP2pGroupClient(false);
}
+ private void setDataSaverEnabled(boolean enabled) {
+ final Intent intent = new Intent(ACTION_RESTRICT_BACKGROUND_CHANGED);
+ mServiceContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+
+ final int status = enabled ? RESTRICT_BACKGROUND_STATUS_ENABLED
+ : RESTRICT_BACKGROUND_STATUS_DISABLED;
+ when(mCm.getRestrictBackgroundStatus()).thenReturn(status);
+ mLooper.dispatchAll();
+ }
+
+ @Test
+ public void testDataSaverChanged() {
+ // Start Tethering.
+ final UpstreamNetworkState upstreamState = buildMobileIPv4UpstreamState();
+ runUsbTethering(upstreamState);
+ assertContains(Arrays.asList(mTethering.getTetheredIfaces()), TEST_USB_IFNAME);
+ // Data saver is ON.
+ setDataSaverEnabled(true);
+ // Verify that tethering should be disabled.
+ verify(mUsbManager, times(1)).setCurrentFunctions(UsbManager.FUNCTION_NONE);
+ mTethering.interfaceRemoved(TEST_USB_IFNAME);
+ mLooper.dispatchAll();
+ assertEquals(mTethering.getTetheredIfaces(), new String[0]);
+ reset(mUsbManager);
+
+ runUsbTethering(upstreamState);
+ // Verify that user can start tethering again without turning OFF data saver.
+ assertContains(Arrays.asList(mTethering.getTetheredIfaces()), TEST_USB_IFNAME);
+
+ // If data saver is keep ON with change event, tethering should not be OFF this time.
+ setDataSaverEnabled(true);
+ verify(mUsbManager, times(0)).setCurrentFunctions(UsbManager.FUNCTION_NONE);
+ assertContains(Arrays.asList(mTethering.getTetheredIfaces()), TEST_USB_IFNAME);
+
+ // If data saver is turned OFF, it should not change tethering.
+ setDataSaverEnabled(false);
+ verify(mUsbManager, times(0)).setCurrentFunctions(UsbManager.FUNCTION_NONE);
+ assertContains(Arrays.asList(mTethering.getTetheredIfaces()), TEST_USB_IFNAME);
+ }
+
+ private static <T> void assertContains(Collection<T> collection, T element) {
+ assertTrue(element + " not found in " + collection, collection.contains(element));
+ }
+
// TODO: Test that a request for hotspot mode doesn't interfere with an
// already operating tethering mode interface.
}
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 9cbcd329649b..b18b8c6da900 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -2869,17 +2869,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
@Override
- public void onTetheringChanged(String iface, boolean tethering) {
- // No need to enforce permission because setRestrictBackground() will do it.
- synchronized (mUidRulesFirstLock) {
- if (mRestrictBackground && tethering) {
- Log.d(TAG, "Tethering on (" + iface +"); disable Data Saver");
- setRestrictBackground(false);
- }
- }
- }
-
- @Override
public void setRestrictBackground(boolean restrictBackground) {
Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "setRestrictBackground");
try {