Merge "Close tethering when UI entitlement fails"
am: c3b3a5fa2e
Change-Id: I22ee932f2a9250f11e8bc9e27c03b86884440603
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index 0b1a98e..9986809 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -233,6 +233,10 @@
// permission is changed according to entitlement check result.
mEntitlementMgr = mDeps.getEntitlementManager(mContext, mTetherMasterSM, mLog,
TetherMasterSM.EVENT_UPSTREAM_PERMISSION_CHANGED, systemProperties);
+ mEntitlementMgr.setOnUiEntitlementFailedListener((int downstream) -> {
+ mLog.log("OBSERVED UiEnitlementFailed");
+ stopTethering(downstream);
+ });
mCarrierConfigChange = new VersionedBroadcastListener(
"CarrierConfigChangeListener", mContext, mHandler, filter,
diff --git a/services/core/java/com/android/server/connectivity/tethering/EntitlementManager.java b/services/core/java/com/android/server/connectivity/tethering/EntitlementManager.java
index 5c45397..764a6eb 100644
--- a/services/core/java/com/android/server/connectivity/tethering/EntitlementManager.java
+++ b/services/core/java/com/android/server/connectivity/tethering/EntitlementManager.java
@@ -109,6 +109,7 @@
private boolean mCellularUpstreamPermitted = true;
private boolean mUsingCellularAsUpstream = false;
private boolean mNeedReRunProvisioningUi = false;
+ private OnUiEntitlementFailedListener mListener;
public EntitlementManager(Context ctx, StateMachine tetherMasterSM, SharedLog log,
int permissionChangeMessageCode, MockableSystemProperties systemProperties) {
@@ -129,6 +130,20 @@
null, mHandler);
}
+ public void setOnUiEntitlementFailedListener(final OnUiEntitlementFailedListener listener) {
+ mListener = listener;
+ }
+
+ /** Callback fired when UI entitlement failed. */
+ public interface OnUiEntitlementFailedListener {
+ /**
+ * Ui entitlement check fails in |downstream|.
+ *
+ * @param downstream tethering type from ConnectivityManager.TETHERING_{@code *}.
+ */
+ void onUiEntitlementFailed(int downstream);
+ }
+
/**
* Pass a new TetheringConfiguration instance each time when
* Tethering#updateConfiguration() is called.
@@ -337,7 +352,9 @@
*/
protected void runSilentTetherProvisioning(int type) {
if (DBG) Log.d(TAG, "runSilentTetherProvisioning: " + type);
- ResultReceiver receiver = buildProxyReceiver(type, null);
+ // For silent provisioning, settings would stop tethering when entitlement fail.
+ ResultReceiver receiver = buildProxyReceiver(type,
+ false/* notifyFail */, null);
Intent intent = new Intent();
intent.putExtra(EXTRA_ADD_TETHER_TYPE, type);
@@ -358,7 +375,8 @@
*/
@VisibleForTesting
protected void runUiTetherProvisioning(int type) {
- ResultReceiver receiver = buildProxyReceiver(type, null);
+ ResultReceiver receiver = buildProxyReceiver(type,
+ true/* notifyFail */, null);
runUiTetherProvisioning(type, receiver);
}
@@ -555,12 +573,16 @@
}
}
- private ResultReceiver buildProxyReceiver(int type, final ResultReceiver receiver) {
+ private ResultReceiver buildProxyReceiver(int type, boolean notifyFail,
+ final ResultReceiver receiver) {
ResultReceiver rr = new ResultReceiver(mHandler) {
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
int updatedCacheValue = updateEntitlementCacheValue(type, resultCode);
addDownstreamMapping(type, updatedCacheValue);
+ if (updatedCacheValue == TETHER_ERROR_PROVISION_FAILED && notifyFail) {
+ mListener.onUiEntitlementFailed(type);
+ }
if (receiver != null) receiver.send(updatedCacheValue, null);
}
};
@@ -627,7 +649,7 @@
if (cacheValue == TETHER_ERROR_NO_ERROR || !showEntitlementUi) {
receiver.send(cacheValue, null);
} else {
- ResultReceiver proxy = buildProxyReceiver(downstream, receiver);
+ ResultReceiver proxy = buildProxyReceiver(downstream, false/* notifyFail */, receiver);
runUiTetherProvisioning(downstream, proxy);
}
}
diff --git a/tests/net/java/com/android/server/connectivity/tethering/EntitlementManagerTest.java b/tests/net/java/com/android/server/connectivity/tethering/EntitlementManagerTest.java
index 9eab4be..d28ab70 100644
--- a/tests/net/java/com/android/server/connectivity/tethering/EntitlementManagerTest.java
+++ b/tests/net/java/com/android/server/connectivity/tethering/EntitlementManagerTest.java
@@ -31,6 +31,8 @@
import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.ContentResolver;
@@ -80,6 +82,7 @@
@Mock private MockableSystemProperties mSystemProperties;
@Mock private Resources mResources;
@Mock private SharedLog mLog;
+ @Mock private EntitlementManager.OnUiEntitlementFailedListener mEntitlementFailedListener;
// Like so many Android system APIs, these cannot be mocked because it is marked final.
// We have to use the real versions.
@@ -109,7 +112,6 @@
public class WrappedEntitlementManager extends EntitlementManager {
public int fakeEntitlementResult = TETHER_ERROR_ENTITLEMENT_UNKONWN;
- public boolean everRunUiEntitlement = false;
public int uiProvisionCount = 0;
public int silentProvisionCount = 0;
@@ -118,20 +120,22 @@
super(ctx, target, log, what, systemProperties);
}
- @Override
- protected void runUiTetherProvisioning(int type, ResultReceiver receiver) {
- everRunUiEntitlement = true;
- receiver.send(fakeEntitlementResult, null);
+ public void reset() {
+ fakeEntitlementResult = TETHER_ERROR_ENTITLEMENT_UNKONWN;
+ uiProvisionCount = 0;
+ silentProvisionCount = 0;
}
@Override
- protected void runUiTetherProvisioning(int type) {
+ protected void runUiTetherProvisioning(int type, ResultReceiver receiver) {
uiProvisionCount++;
+ receiver.send(fakeEntitlementResult, null);
}
@Override
protected void runSilentTetherProvisioning(int type) {
silentProvisionCount++;
+ addDownstreamMapping(type, fakeEntitlementResult);
}
}
@@ -157,6 +161,7 @@
mSM = new TestStateMachine();
mEnMgr = new WrappedEntitlementManager(mMockContext, mSM, mLog, EVENT_EM_UPDATE,
mSystemProperties);
+ mEnMgr.setOnUiEntitlementFailedListener(mEntitlementFailedListener);
mEnMgr.updateConfiguration(
new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID));
}
@@ -246,7 +251,6 @@
final CountDownLatch mCallbacklatch = new CountDownLatch(1);
// 1. Entitlement check is not required.
mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR;
- mEnMgr.everRunUiEntitlement = false;
ResultReceiver receiver = new ResultReceiver(null) {
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
@@ -257,13 +261,13 @@
mEnMgr.getLatestTetheringEntitlementResult(TETHERING_WIFI, receiver, true);
mLooper.dispatchAll();
callbackTimeoutHelper(mCallbacklatch);
- assertFalse(mEnMgr.everRunUiEntitlement);
+ assertEquals(0, mEnMgr.uiProvisionCount);
+ mEnMgr.reset();
setupForRequiredProvisioning();
mEnMgr.updateConfiguration(new TetheringConfiguration(mMockContext, mLog,
INVALID_SUBSCRIPTION_ID));
// 2. No cache value and don't need to run entitlement check.
- mEnMgr.everRunUiEntitlement = false;
receiver = new ResultReceiver(null) {
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
@@ -274,10 +278,10 @@
mEnMgr.getLatestTetheringEntitlementResult(TETHERING_WIFI, receiver, false);
mLooper.dispatchAll();
callbackTimeoutHelper(mCallbacklatch);
- assertFalse(mEnMgr.everRunUiEntitlement);
+ assertEquals(0, mEnMgr.uiProvisionCount);
+ mEnMgr.reset();
// 3. No cache value and ui entitlement check is needed.
mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISION_FAILED;
- mEnMgr.everRunUiEntitlement = false;
receiver = new ResultReceiver(null) {
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
@@ -288,10 +292,10 @@
mEnMgr.getLatestTetheringEntitlementResult(TETHERING_WIFI, receiver, true);
mLooper.dispatchAll();
callbackTimeoutHelper(mCallbacklatch);
- assertTrue(mEnMgr.everRunUiEntitlement);
+ assertEquals(1, mEnMgr.uiProvisionCount);
+ mEnMgr.reset();
// 4. Cache value is TETHER_ERROR_PROVISION_FAILED and don't need to run entitlement check.
mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR;
- mEnMgr.everRunUiEntitlement = false;
receiver = new ResultReceiver(null) {
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
@@ -302,10 +306,10 @@
mEnMgr.getLatestTetheringEntitlementResult(TETHERING_WIFI, receiver, false);
mLooper.dispatchAll();
callbackTimeoutHelper(mCallbacklatch);
- assertFalse(mEnMgr.everRunUiEntitlement);
+ assertEquals(0, mEnMgr.uiProvisionCount);
+ mEnMgr.reset();
// 5. Cache value is TETHER_ERROR_PROVISION_FAILED and ui entitlement check is needed.
mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR;
- mEnMgr.everRunUiEntitlement = false;
receiver = new ResultReceiver(null) {
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
@@ -316,10 +320,10 @@
mEnMgr.getLatestTetheringEntitlementResult(TETHERING_WIFI, receiver, true);
mLooper.dispatchAll();
callbackTimeoutHelper(mCallbacklatch);
- assertTrue(mEnMgr.everRunUiEntitlement);
+ assertEquals(1, mEnMgr.uiProvisionCount);
+ mEnMgr.reset();
// 6. Cache value is TETHER_ERROR_NO_ERROR.
mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR;
- mEnMgr.everRunUiEntitlement = false;
receiver = new ResultReceiver(null) {
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
@@ -330,9 +334,9 @@
mEnMgr.getLatestTetheringEntitlementResult(TETHERING_WIFI, receiver, true);
mLooper.dispatchAll();
callbackTimeoutHelper(mCallbacklatch);
- assertFalse(mEnMgr.everRunUiEntitlement);
+ assertEquals(0, mEnMgr.uiProvisionCount);
+ mEnMgr.reset();
// 7. Test get value for other downstream type.
- mEnMgr.everRunUiEntitlement = false;
receiver = new ResultReceiver(null) {
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
@@ -343,7 +347,8 @@
mEnMgr.getLatestTetheringEntitlementResult(TETHERING_USB, receiver, false);
mLooper.dispatchAll();
callbackTimeoutHelper(mCallbacklatch);
- assertFalse(mEnMgr.everRunUiEntitlement);
+ assertEquals(0, mEnMgr.uiProvisionCount);
+ mEnMgr.reset();
}
void callbackTimeoutHelper(final CountDownLatch latch) throws Exception {
@@ -358,15 +363,15 @@
mEnMgr.notifyUpstream(true);
mEnMgr.updateConfiguration(new TetheringConfiguration(mMockContext, mLog,
INVALID_SUBSCRIPTION_ID));
+ mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISION_FAILED;
mEnMgr.startProvisioningIfNeeded(TETHERING_WIFI, true);
mLooper.dispatchAll();
- mEnMgr.addDownstreamMapping(TETHERING_WIFI, TETHER_ERROR_PROVISION_FAILED);
assertFalse(mEnMgr.isCellularUpstreamPermitted());
mEnMgr.stopProvisioningIfNeeded(TETHERING_WIFI);
mLooper.dispatchAll();
+ mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR;
mEnMgr.startProvisioningIfNeeded(TETHERING_WIFI, true);
mLooper.dispatchAll();
- mEnMgr.addDownstreamMapping(TETHERING_WIFI, TETHER_ERROR_NO_ERROR);
assertTrue(mEnMgr.isCellularUpstreamPermitted());
}
@@ -376,17 +381,17 @@
mEnMgr.notifyUpstream(true);
mEnMgr.updateConfiguration(new TetheringConfiguration(mMockContext, mLog,
INVALID_SUBSCRIPTION_ID));
+ mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISION_FAILED;
mEnMgr.startProvisioningIfNeeded(TETHERING_WIFI, true);
mLooper.dispatchAll();
- mEnMgr.addDownstreamMapping(TETHERING_WIFI, TETHER_ERROR_PROVISION_FAILED);
assertFalse(mEnMgr.isCellularUpstreamPermitted());
+ mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISION_FAILED;
mEnMgr.startProvisioningIfNeeded(TETHERING_USB, true);
mLooper.dispatchAll();
- mEnMgr.addDownstreamMapping(TETHERING_USB, TETHER_ERROR_PROVISION_FAILED);
assertFalse(mEnMgr.isCellularUpstreamPermitted());
+ mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISION_FAILED;
mEnMgr.startProvisioningIfNeeded(TETHERING_BLUETOOTH, true);
mLooper.dispatchAll();
- mEnMgr.addDownstreamMapping(TETHERING_BLUETOOTH, TETHER_ERROR_PROVISION_FAILED);
assertFalse(mEnMgr.isCellularUpstreamPermitted());
}
@@ -396,14 +401,14 @@
mEnMgr.notifyUpstream(true);
mEnMgr.updateConfiguration(new TetheringConfiguration(mMockContext, mLog,
INVALID_SUBSCRIPTION_ID));
+ mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR;
mEnMgr.startProvisioningIfNeeded(TETHERING_WIFI, true);
mLooper.dispatchAll();
- mEnMgr.addDownstreamMapping(TETHERING_WIFI, TETHER_ERROR_NO_ERROR);
assertTrue(mEnMgr.isCellularUpstreamPermitted());
mLooper.dispatchAll();
+ mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISION_FAILED;
mEnMgr.startProvisioningIfNeeded(TETHERING_USB, true);
mLooper.dispatchAll();
- mEnMgr.addDownstreamMapping(TETHERING_USB, TETHER_ERROR_PROVISION_FAILED);
assertTrue(mEnMgr.isCellularUpstreamPermitted());
mEnMgr.stopProvisioningIfNeeded(TETHERING_WIFI);
mLooper.dispatchAll();
@@ -417,48 +422,71 @@
mEnMgr.updateConfiguration(new TetheringConfiguration(mMockContext, mLog,
INVALID_SUBSCRIPTION_ID));
// 1. start ui provisioning, upstream is mobile
+ mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR;
mEnMgr.notifyUpstream(true);
mLooper.dispatchAll();
mEnMgr.startProvisioningIfNeeded(TETHERING_USB, true);
mLooper.dispatchAll();
- assertTrue(mEnMgr.uiProvisionCount == 1);
- assertTrue(mEnMgr.silentProvisionCount == 0);
- mEnMgr.addDownstreamMapping(TETHERING_USB, TETHER_ERROR_PROVISION_FAILED);
+ assertEquals(1, mEnMgr.uiProvisionCount);
+ assertEquals(0, mEnMgr.silentProvisionCount);
+ assertTrue(mEnMgr.isCellularUpstreamPermitted());
+ mEnMgr.reset();
// 2. start no-ui provisioning
+ mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR;
mEnMgr.startProvisioningIfNeeded(TETHERING_WIFI, false);
mLooper.dispatchAll();
- assertTrue(mEnMgr.silentProvisionCount == 1);
- assertTrue(mEnMgr.uiProvisionCount == 1);
- mEnMgr.addDownstreamMapping(TETHERING_WIFI, TETHER_ERROR_PROVISION_FAILED);
+ assertEquals(0, mEnMgr.uiProvisionCount);
+ assertEquals(1, mEnMgr.silentProvisionCount);
+ assertTrue(mEnMgr.isCellularUpstreamPermitted());
+ mEnMgr.reset();
// 3. tear down mobile, then start ui provisioning
mEnMgr.notifyUpstream(false);
mLooper.dispatchAll();
mEnMgr.startProvisioningIfNeeded(TETHERING_BLUETOOTH, true);
mLooper.dispatchAll();
- assertTrue(mEnMgr.uiProvisionCount == 1);
- assertTrue(mEnMgr.silentProvisionCount == 1);
+ assertEquals(0, mEnMgr.uiProvisionCount);
+ assertEquals(0, mEnMgr.silentProvisionCount);
+ mEnMgr.reset();
// 4. switch upstream back to mobile
+ mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR;
mEnMgr.notifyUpstream(true);
mLooper.dispatchAll();
- assertTrue(mEnMgr.uiProvisionCount == 2);
- assertTrue(mEnMgr.silentProvisionCount == 1);
- mEnMgr.addDownstreamMapping(TETHERING_BLUETOOTH, TETHER_ERROR_PROVISION_FAILED);
+ assertEquals(1, mEnMgr.uiProvisionCount);
+ assertEquals(0, mEnMgr.silentProvisionCount);
+ assertTrue(mEnMgr.isCellularUpstreamPermitted());
+ mEnMgr.reset();
// 5. tear down mobile, then switch SIM
mEnMgr.notifyUpstream(false);
mLooper.dispatchAll();
mEnMgr.reevaluateSimCardProvisioning();
- assertTrue(mEnMgr.uiProvisionCount == 2);
- assertTrue(mEnMgr.silentProvisionCount == 1);
+ assertEquals(0, mEnMgr.uiProvisionCount);
+ assertEquals(0, mEnMgr.silentProvisionCount);
+ mEnMgr.reset();
// 6. switch upstream back to mobile again
+ mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISION_FAILED;
mEnMgr.notifyUpstream(true);
mLooper.dispatchAll();
- assertTrue(mEnMgr.uiProvisionCount == 2);
- assertTrue(mEnMgr.silentProvisionCount == 4);
- mEnMgr.addDownstreamMapping(TETHERING_USB, TETHER_ERROR_PROVISION_FAILED);
- mEnMgr.addDownstreamMapping(TETHERING_WIFI, TETHER_ERROR_PROVISION_FAILED);
- mEnMgr.addDownstreamMapping(TETHERING_BLUETOOTH, TETHER_ERROR_PROVISION_FAILED);
+ assertEquals(0, mEnMgr.uiProvisionCount);
+ assertEquals(3, mEnMgr.silentProvisionCount);
+ mEnMgr.reset();
}
+ @Test
+ public void testCallStopTetheringWhenUiProvisioningFail() {
+ setupForRequiredProvisioning();
+ mEnMgr.updateConfiguration(new TetheringConfiguration(mMockContext, mLog,
+ INVALID_SUBSCRIPTION_ID));
+ verify(mEntitlementFailedListener, times(0)).onUiEntitlementFailed(TETHERING_WIFI);
+ mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISION_FAILED;
+ mEnMgr.notifyUpstream(true);
+ mLooper.dispatchAll();
+ mEnMgr.startProvisioningIfNeeded(TETHERING_WIFI, true);
+ mLooper.dispatchAll();
+ assertEquals(1, mEnMgr.uiProvisionCount);
+ verify(mEntitlementFailedListener, times(1)).onUiEntitlementFailed(TETHERING_WIFI);
+ }
+
+
public class TestStateMachine extends StateMachine {
public final ArrayList<Message> messages = new ArrayList<>();
private final State