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