Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c3b3a5fa authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Close tethering when UI entitlement fails"

parents 6bd5cf2b 29b7014d
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -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,
+26 −4
Original line number Diff line number Diff line
@@ -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);
        }
    }
+73 −45
Original line number Diff line number Diff line
@@ -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