Merge "Address the comment of aosp/1288493"

This commit is contained in:
Mark Chien
2020-05-08 10:30:49 +00:00
committed by Gerrit Code Review
5 changed files with 114 additions and 81 deletions

View File

@@ -37,6 +37,7 @@ import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.net.util.SharedLog; import android.net.util.SharedLog;
import android.os.Bundle; import android.os.Bundle;
import android.os.ConditionVariable;
import android.os.Handler; import android.os.Handler;
import android.os.Parcel; import android.os.Parcel;
import android.os.PersistableBundle; import android.os.PersistableBundle;
@@ -48,7 +49,6 @@ import android.telephony.CarrierConfigManager;
import android.util.SparseIntArray; import android.util.SparseIntArray;
import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.StateMachine;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.util.BitSet; import java.util.BitSet;
@@ -73,6 +73,7 @@ public class EntitlementManager {
private final ComponentName mSilentProvisioningService; private final ComponentName mSilentProvisioningService;
private static final int MS_PER_HOUR = 60 * 60 * 1000; private static final int MS_PER_HOUR = 60 * 60 * 1000;
private static final int DUMP_TIMEOUT = 10_000;
// The BitSet is the bit map of each enabled downstream types, ex: // The BitSet is the bit map of each enabled downstream types, ex:
// {@link TetheringManager.TETHERING_WIFI} // {@link TetheringManager.TETHERING_WIFI}
@@ -80,14 +81,13 @@ public class EntitlementManager {
// {@link TetheringManager.TETHERING_BLUETOOTH} // {@link TetheringManager.TETHERING_BLUETOOTH}
private final BitSet mCurrentDownstreams; private final BitSet mCurrentDownstreams;
private final Context mContext; private final Context mContext;
private final int mPermissionChangeMessageCode;
private final SharedLog mLog; private final SharedLog mLog;
private final SparseIntArray mEntitlementCacheValue; private final SparseIntArray mEntitlementCacheValue;
private final Handler mHandler; private final Handler mHandler;
private final StateMachine mTetherMasterSM;
// Key: TetheringManager.TETHERING_*(downstream). // Key: TetheringManager.TETHERING_*(downstream).
// Value: TetheringManager.TETHER_ERROR_{NO_ERROR or PROVISION_FAILED}(provisioning result). // Value: TetheringManager.TETHER_ERROR_{NO_ERROR or PROVISION_FAILED}(provisioning result).
private final SparseIntArray mCurrentEntitlementResults; private final SparseIntArray mCurrentEntitlementResults;
private final Runnable mPermissionChangeCallback;
private PendingIntent mProvisioningRecheckAlarm; private PendingIntent mProvisioningRecheckAlarm;
private boolean mLastCellularUpstreamPermitted = true; private boolean mLastCellularUpstreamPermitted = true;
private boolean mUsingCellularAsUpstream = false; private boolean mUsingCellularAsUpstream = false;
@@ -95,16 +95,15 @@ public class EntitlementManager {
private OnUiEntitlementFailedListener mListener; private OnUiEntitlementFailedListener mListener;
private TetheringConfigurationFetcher mFetcher; private TetheringConfigurationFetcher mFetcher;
public EntitlementManager(Context ctx, StateMachine tetherMasterSM, SharedLog log, public EntitlementManager(Context ctx, Handler h, SharedLog log,
int permissionChangeMessageCode) { Runnable callback) {
mContext = ctx; mContext = ctx;
mLog = log.forSubComponent(TAG); mLog = log.forSubComponent(TAG);
mCurrentDownstreams = new BitSet(); mCurrentDownstreams = new BitSet();
mCurrentEntitlementResults = new SparseIntArray(); mCurrentEntitlementResults = new SparseIntArray();
mEntitlementCacheValue = new SparseIntArray(); mEntitlementCacheValue = new SparseIntArray();
mTetherMasterSM = tetherMasterSM; mPermissionChangeCallback = callback;
mPermissionChangeMessageCode = permissionChangeMessageCode; mHandler = h;
mHandler = tetherMasterSM.getHandler();
mContext.registerReceiver(mReceiver, new IntentFilter(ACTION_PROVISIONING_ALARM), mContext.registerReceiver(mReceiver, new IntentFilter(ACTION_PROVISIONING_ALARM),
null, mHandler); null, mHandler);
mSilentProvisioningService = ComponentName.unflattenFromString( mSilentProvisioningService = ComponentName.unflattenFromString(
@@ -409,25 +408,25 @@ public class EntitlementManager {
} }
private void evaluateCellularPermission(final TetheringConfiguration config) { private void evaluateCellularPermission(final TetheringConfiguration config) {
final boolean oldPermitted = mLastCellularUpstreamPermitted; final boolean permitted = isCellularUpstreamPermitted(config);
mLastCellularUpstreamPermitted = isCellularUpstreamPermitted(config);
if (DBG) { if (DBG) {
mLog.i("Cellular permission change from " + oldPermitted mLog.i("Cellular permission change from " + mLastCellularUpstreamPermitted
+ " to " + mLastCellularUpstreamPermitted); + " to " + permitted);
} }
if (mLastCellularUpstreamPermitted != oldPermitted) { if (mLastCellularUpstreamPermitted != permitted) {
mLog.log("Cellular permission change: " + mLastCellularUpstreamPermitted); mLog.log("Cellular permission change: " + permitted);
mTetherMasterSM.sendMessage(mPermissionChangeMessageCode); mPermissionChangeCallback.run();
} }
// Only schedule periodic re-check when tether is provisioned // Only schedule periodic re-check when tether is provisioned
// and the result is ok. // and the result is ok.
if (mLastCellularUpstreamPermitted && mCurrentEntitlementResults.size() > 0) { if (permitted && mCurrentEntitlementResults.size() > 0) {
scheduleProvisioningRechecks(config); scheduleProvisioningRechecks(config);
} else { } else {
cancelTetherProvisioningRechecks(); cancelTetherProvisioningRechecks();
} }
mLastCellularUpstreamPermitted = permitted;
} }
/** /**
@@ -486,18 +485,25 @@ public class EntitlementManager {
* @param pw {@link PrintWriter} is used to print formatted * @param pw {@link PrintWriter} is used to print formatted
*/ */
public void dump(PrintWriter pw) { public void dump(PrintWriter pw) {
pw.print("isCellularUpstreamPermitted: "); final ConditionVariable mWaiting = new ConditionVariable();
pw.println(isCellularUpstreamPermitted()); mHandler.post(() -> {
for (int type = mCurrentDownstreams.nextSetBit(0); type >= 0; pw.print("isCellularUpstreamPermitted: ");
type = mCurrentDownstreams.nextSetBit(type + 1)) { pw.println(isCellularUpstreamPermitted());
pw.print("Type: "); for (int type = mCurrentDownstreams.nextSetBit(0); type >= 0;
pw.print(typeString(type)); type = mCurrentDownstreams.nextSetBit(type + 1)) {
if (mCurrentEntitlementResults.indexOfKey(type) > -1) { pw.print("Type: ");
pw.print(", Value: "); pw.print(typeString(type));
pw.println(errorString(mCurrentEntitlementResults.get(type))); if (mCurrentEntitlementResults.indexOfKey(type) > -1) {
} else { pw.print(", Value: ");
pw.println(", Value: empty"); pw.println(errorString(mCurrentEntitlementResults.get(type)));
} else {
pw.println(", Value: empty");
}
} }
mWaiting.open();
});
if (!mWaiting.block(DUMP_TIMEOUT)) {
pw.println("... dump timed out after " + DUMP_TIMEOUT + "ms");
} }
} }

View File

@@ -284,8 +284,9 @@ public class Tethering {
filter.addAction(ACTION_CARRIER_CONFIG_CHANGED); filter.addAction(ACTION_CARRIER_CONFIG_CHANGED);
// EntitlementManager will send EVENT_UPSTREAM_PERMISSION_CHANGED when cellular upstream // EntitlementManager will send EVENT_UPSTREAM_PERMISSION_CHANGED when cellular upstream
// 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, mHandler, mLog,
TetherMasterSM.EVENT_UPSTREAM_PERMISSION_CHANGED); () -> mTetherMasterSM.sendMessage(
TetherMasterSM.EVENT_UPSTREAM_PERMISSION_CHANGED));
mEntitlementMgr.setOnUiEntitlementFailedListener((int downstream) -> { mEntitlementMgr.setOnUiEntitlementFailedListener((int downstream) -> {
mLog.log("OBSERVED UiEnitlementFailed"); mLog.log("OBSERVED UiEnitlementFailed");
stopTethering(downstream); stopTethering(downstream);

View File

@@ -96,9 +96,9 @@ public abstract class TetheringDependencies {
/** /**
* Get a reference to the EntitlementManager to be used by tethering. * Get a reference to the EntitlementManager to be used by tethering.
*/ */
public EntitlementManager getEntitlementManager(Context ctx, StateMachine target, public EntitlementManager getEntitlementManager(Context ctx, Handler h, SharedLog log,
SharedLog log, int what) { Runnable callback) {
return new EntitlementManager(ctx, target, log, what); return new EntitlementManager(ctx, h, log, callback);
} }
/** /**

View File

@@ -37,6 +37,8 @@ import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.anyInt;
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.inOrder;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times; import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
@@ -45,7 +47,7 @@ import android.content.Context;
import android.content.res.Resources; import android.content.res.Resources;
import android.net.util.SharedLog; import android.net.util.SharedLog;
import android.os.Bundle; import android.os.Bundle;
import android.os.Message; import android.os.Handler;
import android.os.PersistableBundle; import android.os.PersistableBundle;
import android.os.ResultReceiver; import android.os.ResultReceiver;
import android.os.SystemProperties; import android.os.SystemProperties;
@@ -56,26 +58,22 @@ import android.telephony.CarrierConfigManager;
import androidx.test.filters.SmallTest; import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4; import androidx.test.runner.AndroidJUnit4;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
import com.android.internal.util.test.BroadcastInterceptingContext; import com.android.internal.util.test.BroadcastInterceptingContext;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.InOrder;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations;
import org.mockito.MockitoSession; import org.mockito.MockitoSession;
import org.mockito.quality.Strictness; import org.mockito.quality.Strictness;
import java.util.ArrayList;
@RunWith(AndroidJUnit4.class) @RunWith(AndroidJUnit4.class)
@SmallTest @SmallTest
public final class EntitlementManagerTest { public final class EntitlementManagerTest {
private static final int EVENT_EM_UPDATE = 1;
private static final String[] PROVISIONING_APP_NAME = {"some", "app"}; private static final String[] PROVISIONING_APP_NAME = {"some", "app"};
private static final String PROVISIONING_NO_UI_APP_NAME = "no_ui_app"; private static final String PROVISIONING_NO_UI_APP_NAME = "no_ui_app";
@@ -90,8 +88,8 @@ public final class EntitlementManagerTest {
private final PersistableBundle mCarrierConfig = new PersistableBundle(); private final PersistableBundle mCarrierConfig = new PersistableBundle();
private final TestLooper mLooper = new TestLooper(); private final TestLooper mLooper = new TestLooper();
private Context mMockContext; private Context mMockContext;
private Runnable mPermissionChangeCallback;
private TestStateMachine mSM;
private WrappedEntitlementManager mEnMgr; private WrappedEntitlementManager mEnMgr;
private TetheringConfiguration mConfig; private TetheringConfiguration mConfig;
private MockitoSession mMockingSession; private MockitoSession mMockingSession;
@@ -112,9 +110,9 @@ public final class EntitlementManagerTest {
public int uiProvisionCount = 0; public int uiProvisionCount = 0;
public int silentProvisionCount = 0; public int silentProvisionCount = 0;
public WrappedEntitlementManager(Context ctx, StateMachine target, public WrappedEntitlementManager(Context ctx, Handler h, SharedLog log,
SharedLog log, int what) { Runnable callback) {
super(ctx, target, log, what); super(ctx, h, log, callback);
} }
public void reset() { public void reset() {
@@ -169,8 +167,9 @@ public final class EntitlementManagerTest {
when(mLog.forSubComponent(anyString())).thenReturn(mLog); when(mLog.forSubComponent(anyString())).thenReturn(mLog);
mMockContext = new MockContext(mContext); mMockContext = new MockContext(mContext);
mSM = new TestStateMachine(); mPermissionChangeCallback = spy(() -> { });
mEnMgr = new WrappedEntitlementManager(mMockContext, mSM, mLog, EVENT_EM_UPDATE); mEnMgr = new WrappedEntitlementManager(mMockContext, new Handler(mLooper.getLooper()), mLog,
mPermissionChangeCallback);
mEnMgr.setOnUiEntitlementFailedListener(mEntitlementFailedListener); mEnMgr.setOnUiEntitlementFailedListener(mEntitlementFailedListener);
mConfig = new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID); mConfig = new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
mEnMgr.setTetheringConfigurationFetcher(() -> { mEnMgr.setTetheringConfigurationFetcher(() -> {
@@ -180,10 +179,6 @@ public final class EntitlementManagerTest {
@After @After
public void tearDown() throws Exception { public void tearDown() throws Exception {
if (mSM != null) {
mSM.quit();
mSM = null;
}
mMockingSession.finishMocking(); mMockingSession.finishMocking();
} }
@@ -350,68 +345,105 @@ public final class EntitlementManagerTest {
mEnMgr.reset(); mEnMgr.reset();
} }
private void assertPermissionChangeCallback(InOrder inOrder) {
inOrder.verify(mPermissionChangeCallback, times(1)).run();
}
private void assertNoPermissionChange(InOrder inOrder) {
inOrder.verifyNoMoreInteractions();
}
@Test @Test
public void verifyPermissionResult() { public void verifyPermissionResult() {
final InOrder inOrder = inOrder(mPermissionChangeCallback);
setupForRequiredProvisioning(); setupForRequiredProvisioning();
mEnMgr.notifyUpstream(true); mEnMgr.notifyUpstream(true);
mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISIONING_FAILED; mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISIONING_FAILED;
mEnMgr.startProvisioningIfNeeded(TETHERING_WIFI, true); mEnMgr.startProvisioningIfNeeded(TETHERING_WIFI, true);
mLooper.dispatchAll(); mLooper.dispatchAll();
// Permitted: true -> false
assertPermissionChangeCallback(inOrder);
assertFalse(mEnMgr.isCellularUpstreamPermitted()); assertFalse(mEnMgr.isCellularUpstreamPermitted());
mEnMgr.stopProvisioningIfNeeded(TETHERING_WIFI); mEnMgr.stopProvisioningIfNeeded(TETHERING_WIFI);
mLooper.dispatchAll(); mLooper.dispatchAll();
// Permitted: false -> false
assertNoPermissionChange(inOrder);
mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR; mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR;
mEnMgr.startProvisioningIfNeeded(TETHERING_WIFI, true); mEnMgr.startProvisioningIfNeeded(TETHERING_WIFI, true);
mLooper.dispatchAll(); mLooper.dispatchAll();
// Permitted: false -> true
assertPermissionChangeCallback(inOrder);
assertTrue(mEnMgr.isCellularUpstreamPermitted()); assertTrue(mEnMgr.isCellularUpstreamPermitted());
} }
@Test @Test
public void verifyPermissionIfAllNotApproved() { public void verifyPermissionIfAllNotApproved() {
final InOrder inOrder = inOrder(mPermissionChangeCallback);
setupForRequiredProvisioning(); setupForRequiredProvisioning();
mEnMgr.notifyUpstream(true); mEnMgr.notifyUpstream(true);
mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISIONING_FAILED; mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISIONING_FAILED;
mEnMgr.startProvisioningIfNeeded(TETHERING_WIFI, true); mEnMgr.startProvisioningIfNeeded(TETHERING_WIFI, true);
mLooper.dispatchAll(); mLooper.dispatchAll();
// Permitted: true -> false
assertPermissionChangeCallback(inOrder);
assertFalse(mEnMgr.isCellularUpstreamPermitted()); assertFalse(mEnMgr.isCellularUpstreamPermitted());
mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISIONING_FAILED; mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISIONING_FAILED;
mEnMgr.startProvisioningIfNeeded(TETHERING_USB, true); mEnMgr.startProvisioningIfNeeded(TETHERING_USB, true);
mLooper.dispatchAll(); mLooper.dispatchAll();
// Permitted: false -> false
assertNoPermissionChange(inOrder);
assertFalse(mEnMgr.isCellularUpstreamPermitted()); assertFalse(mEnMgr.isCellularUpstreamPermitted());
mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISIONING_FAILED; mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISIONING_FAILED;
mEnMgr.startProvisioningIfNeeded(TETHERING_BLUETOOTH, true); mEnMgr.startProvisioningIfNeeded(TETHERING_BLUETOOTH, true);
mLooper.dispatchAll(); mLooper.dispatchAll();
// Permitted: false -> false
assertNoPermissionChange(inOrder);
assertFalse(mEnMgr.isCellularUpstreamPermitted()); assertFalse(mEnMgr.isCellularUpstreamPermitted());
} }
@Test @Test
public void verifyPermissionIfAnyApproved() { public void verifyPermissionIfAnyApproved() {
final InOrder inOrder = inOrder(mPermissionChangeCallback);
setupForRequiredProvisioning(); setupForRequiredProvisioning();
mEnMgr.notifyUpstream(true); mEnMgr.notifyUpstream(true);
mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR; mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR;
mEnMgr.startProvisioningIfNeeded(TETHERING_WIFI, true); mEnMgr.startProvisioningIfNeeded(TETHERING_WIFI, true);
mLooper.dispatchAll(); mLooper.dispatchAll();
// Permitted: true -> true
assertNoPermissionChange(inOrder);
assertTrue(mEnMgr.isCellularUpstreamPermitted()); assertTrue(mEnMgr.isCellularUpstreamPermitted());
mLooper.dispatchAll();
mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISIONING_FAILED; mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISIONING_FAILED;
mEnMgr.startProvisioningIfNeeded(TETHERING_USB, true); mEnMgr.startProvisioningIfNeeded(TETHERING_USB, true);
mLooper.dispatchAll(); mLooper.dispatchAll();
// Permitted: true -> true
assertNoPermissionChange(inOrder);
assertTrue(mEnMgr.isCellularUpstreamPermitted()); assertTrue(mEnMgr.isCellularUpstreamPermitted());
mEnMgr.stopProvisioningIfNeeded(TETHERING_WIFI); mEnMgr.stopProvisioningIfNeeded(TETHERING_WIFI);
mLooper.dispatchAll(); mLooper.dispatchAll();
// Permitted: true -> false
assertPermissionChangeCallback(inOrder);
assertFalse(mEnMgr.isCellularUpstreamPermitted()); assertFalse(mEnMgr.isCellularUpstreamPermitted());
} }
@Test @Test
public void verifyPermissionWhenProvisioningNotStarted() { public void verifyPermissionWhenProvisioningNotStarted() {
final InOrder inOrder = inOrder(mPermissionChangeCallback);
assertTrue(mEnMgr.isCellularUpstreamPermitted()); assertTrue(mEnMgr.isCellularUpstreamPermitted());
assertNoPermissionChange(inOrder);
setupForRequiredProvisioning(); setupForRequiredProvisioning();
assertFalse(mEnMgr.isCellularUpstreamPermitted()); assertFalse(mEnMgr.isCellularUpstreamPermitted());
assertNoPermissionChange(inOrder);
} }
@Test @Test
public void testRunTetherProvisioning() { public void testRunTetherProvisioning() {
final InOrder inOrder = inOrder(mPermissionChangeCallback);
setupForRequiredProvisioning(); setupForRequiredProvisioning();
// 1. start ui provisioning, upstream is mobile // 1. start ui provisioning, upstream is mobile
mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR; mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR;
@@ -421,16 +453,22 @@ public final class EntitlementManagerTest {
mLooper.dispatchAll(); mLooper.dispatchAll();
assertEquals(1, mEnMgr.uiProvisionCount); assertEquals(1, mEnMgr.uiProvisionCount);
assertEquals(0, mEnMgr.silentProvisionCount); assertEquals(0, mEnMgr.silentProvisionCount);
// Permitted: true -> true
assertNoPermissionChange(inOrder);
assertTrue(mEnMgr.isCellularUpstreamPermitted()); assertTrue(mEnMgr.isCellularUpstreamPermitted());
mEnMgr.reset(); mEnMgr.reset();
// 2. start no-ui provisioning // 2. start no-ui provisioning
mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR; mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR;
mEnMgr.startProvisioningIfNeeded(TETHERING_WIFI, false); mEnMgr.startProvisioningIfNeeded(TETHERING_WIFI, false);
mLooper.dispatchAll(); mLooper.dispatchAll();
assertEquals(0, mEnMgr.uiProvisionCount); assertEquals(0, mEnMgr.uiProvisionCount);
assertEquals(1, mEnMgr.silentProvisionCount); assertEquals(1, mEnMgr.silentProvisionCount);
// Permitted: true -> true
assertNoPermissionChange(inOrder);
assertTrue(mEnMgr.isCellularUpstreamPermitted()); assertTrue(mEnMgr.isCellularUpstreamPermitted());
mEnMgr.reset(); 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();
@@ -438,44 +476,58 @@ public final class EntitlementManagerTest {
mLooper.dispatchAll(); mLooper.dispatchAll();
assertEquals(0, mEnMgr.uiProvisionCount); assertEquals(0, mEnMgr.uiProvisionCount);
assertEquals(0, mEnMgr.silentProvisionCount); assertEquals(0, mEnMgr.silentProvisionCount);
assertNoPermissionChange(inOrder);
mEnMgr.reset(); mEnMgr.reset();
// 4. switch upstream back to mobile // 4. switch upstream back to mobile
mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR; mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR;
mEnMgr.notifyUpstream(true); mEnMgr.notifyUpstream(true);
mLooper.dispatchAll(); mLooper.dispatchAll();
assertEquals(1, mEnMgr.uiProvisionCount); assertEquals(1, mEnMgr.uiProvisionCount);
assertEquals(0, mEnMgr.silentProvisionCount); assertEquals(0, mEnMgr.silentProvisionCount);
// Permitted: true -> true
assertNoPermissionChange(inOrder);
assertTrue(mEnMgr.isCellularUpstreamPermitted()); assertTrue(mEnMgr.isCellularUpstreamPermitted());
mEnMgr.reset(); 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(mConfig); mEnMgr.reevaluateSimCardProvisioning(mConfig);
assertEquals(0, mEnMgr.uiProvisionCount); assertEquals(0, mEnMgr.uiProvisionCount);
assertEquals(0, mEnMgr.silentProvisionCount); assertEquals(0, mEnMgr.silentProvisionCount);
assertNoPermissionChange(inOrder);
mEnMgr.reset(); mEnMgr.reset();
// 6. switch upstream back to mobile again // 6. switch upstream back to mobile again
mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISIONING_FAILED; mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISIONING_FAILED;
mEnMgr.notifyUpstream(true); mEnMgr.notifyUpstream(true);
mLooper.dispatchAll(); mLooper.dispatchAll();
assertEquals(0, mEnMgr.uiProvisionCount); assertEquals(0, mEnMgr.uiProvisionCount);
assertEquals(3, mEnMgr.silentProvisionCount); assertEquals(3, mEnMgr.silentProvisionCount);
// Permitted: true -> false
assertPermissionChangeCallback(inOrder);
assertFalse(mEnMgr.isCellularUpstreamPermitted()); assertFalse(mEnMgr.isCellularUpstreamPermitted());
mEnMgr.reset(); mEnMgr.reset();
// 7. start ui provisioning, upstream is mobile, downstream is ethernet // 7. start ui provisioning, upstream is mobile, downstream is ethernet
mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR; mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR;
mEnMgr.startProvisioningIfNeeded(TETHERING_ETHERNET, true); mEnMgr.startProvisioningIfNeeded(TETHERING_ETHERNET, true);
mLooper.dispatchAll(); mLooper.dispatchAll();
assertEquals(1, mEnMgr.uiProvisionCount); assertEquals(1, mEnMgr.uiProvisionCount);
assertEquals(0, mEnMgr.silentProvisionCount); assertEquals(0, mEnMgr.silentProvisionCount);
// Permitted: false -> true
assertPermissionChangeCallback(inOrder);
assertTrue(mEnMgr.isCellularUpstreamPermitted()); assertTrue(mEnMgr.isCellularUpstreamPermitted());
mEnMgr.reset(); mEnMgr.reset();
// 8. downstream is invalid // 8. downstream is invalid
mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR; mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR;
mEnMgr.startProvisioningIfNeeded(TETHERING_WIFI_P2P, true); mEnMgr.startProvisioningIfNeeded(TETHERING_WIFI_P2P, true);
mLooper.dispatchAll(); mLooper.dispatchAll();
assertEquals(0, mEnMgr.uiProvisionCount); assertEquals(0, mEnMgr.uiProvisionCount);
assertEquals(0, mEnMgr.silentProvisionCount); assertEquals(0, mEnMgr.silentProvisionCount);
assertNoPermissionChange(inOrder);
mEnMgr.reset(); mEnMgr.reset();
} }
@@ -491,32 +543,4 @@ public final class EntitlementManagerTest {
assertEquals(1, mEnMgr.uiProvisionCount); assertEquals(1, mEnMgr.uiProvisionCount);
verify(mEntitlementFailedListener, times(1)).onUiEntitlementFailed(TETHERING_WIFI); verify(mEntitlementFailedListener, times(1)).onUiEntitlementFailed(TETHERING_WIFI);
} }
public class TestStateMachine extends StateMachine {
public final ArrayList<Message> messages = new ArrayList<>();
private final State
mLoggingState = new EntitlementManagerTest.TestStateMachine.LoggingState();
class LoggingState extends State {
@Override public void enter() {
messages.clear();
}
@Override public void exit() {
messages.clear();
}
@Override public boolean processMessage(Message msg) {
messages.add(msg);
return false;
}
}
public TestStateMachine() {
super("EntitlementManagerTest.TestStateMachine", mLooper.getLooper());
addState(mLoggingState);
setInitialState(mLoggingState);
super.start();
}
}
} }

View File

@@ -367,9 +367,9 @@ public class TetheringTest {
} }
@Override @Override
public EntitlementManager getEntitlementManager(Context ctx, StateMachine target, public EntitlementManager getEntitlementManager(Context ctx, Handler h, SharedLog log,
SharedLog log, int what) { Runnable callback) {
mEntitleMgr = spy(super.getEntitlementManager(ctx, target, log, what)); mEntitleMgr = spy(super.getEntitlementManager(ctx, h, log, callback));
return mEntitleMgr; return mEntitleMgr;
} }
@@ -1754,10 +1754,12 @@ public class TetheringTest {
final FileDescriptor mockFd = mock(FileDescriptor.class); final FileDescriptor mockFd = mock(FileDescriptor.class);
final PrintWriter mockPw = mock(PrintWriter.class); final PrintWriter mockPw = mock(PrintWriter.class);
runUsbTethering(null); runUsbTethering(null);
mLooper.startAutoDispatch();
mTethering.dump(mockFd, mockPw, new String[0]); mTethering.dump(mockFd, mockPw, new String[0]);
verify(mConfig).dump(any()); verify(mConfig).dump(any());
verify(mEntitleMgr).dump(any()); verify(mEntitleMgr).dump(any());
verify(mOffloadCtrl).dump(any()); verify(mOffloadCtrl).dump(any());
mLooper.stopAutoDispatch();
} }
// TODO: Test that a request for hotspot mode doesn't interfere with an // TODO: Test that a request for hotspot mode doesn't interfere with an