Merge "Close tethering when UI entitlement fails" am: c3b3a5fa2e

am: fed8661b68

Change-Id: I3132c0ae24ee4175b3c5283ce68add22af0fb90e
This commit is contained in:
markchien
2019-03-28 16:54:03 -07:00
committed by android-build-merger
3 changed files with 103 additions and 49 deletions

View File

@@ -233,6 +233,10 @@ public class Tethering extends BaseNetworkObserver {
// 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,

View File

@@ -109,6 +109,7 @@ public class EntitlementManager {
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 @@ public class EntitlementManager {
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 @@ public class EntitlementManager {
*/
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 @@ public class EntitlementManager {
*/
@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 @@ public class EntitlementManager {
}
}
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 @@ public class EntitlementManager {
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);
}
}

View File

@@ -31,6 +31,8 @@ import static org.junit.Assert.fail;
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 @@ public final class EntitlementManagerTest {
@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 final class EntitlementManagerTest {
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 @@ public final class EntitlementManagerTest {
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 @@ public final class EntitlementManagerTest {
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 @@ public final class EntitlementManagerTest {
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 @@ public final class EntitlementManagerTest {
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 @@ public final class EntitlementManagerTest {
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 @@ public final class EntitlementManagerTest {
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 @@ public final class EntitlementManagerTest {
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 @@ public final class EntitlementManagerTest {
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 @@ public final class EntitlementManagerTest {
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 @@ public final class EntitlementManagerTest {
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 @@ public final class EntitlementManagerTest {
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 @@ public final class EntitlementManagerTest {
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 @@ public final class EntitlementManagerTest {
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 @@ public final class EntitlementManagerTest {
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