Merge "Add get last entitlement value callback API"
am: 4163ff7928
Change-Id: I1961297c3fa31f5575ae3a11a3fc90d695cb7de5
This commit is contained in:
@@ -3070,6 +3070,7 @@ package android.net {
|
||||
method @RequiresPermission(android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD) public android.net.SocketKeepalive createNattKeepalive(@NonNull android.net.Network, @NonNull java.io.FileDescriptor, @NonNull java.net.InetAddress, @NonNull java.net.InetAddress, @NonNull java.util.concurrent.Executor, @NonNull android.net.SocketKeepalive.Callback);
|
||||
method public boolean getAvoidBadWifi();
|
||||
method @RequiresPermission(android.Manifest.permission.LOCAL_MAC_ADDRESS) public String getCaptivePortalServerUrl();
|
||||
method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void getLatestTetheringEntitlementValue(int, boolean, @NonNull android.net.ConnectivityManager.TetheringEntitlementValueListener, @Nullable android.os.Handler);
|
||||
method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public boolean isTetheringSupported();
|
||||
method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD, "android.permission.NETWORK_STACK"}) public void setAirplaneMode(boolean);
|
||||
method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void startTethering(int, boolean, android.net.ConnectivityManager.OnStartTetheringCallback);
|
||||
@@ -3080,6 +3081,9 @@ package android.net {
|
||||
field public static final int TETHERING_BLUETOOTH = 2; // 0x2
|
||||
field public static final int TETHERING_USB = 1; // 0x1
|
||||
field public static final int TETHERING_WIFI = 0; // 0x0
|
||||
field public static final int TETHER_ERROR_ENTITLEMENT_UNKONWN = 13; // 0xd
|
||||
field public static final int TETHER_ERROR_NO_ERROR = 0; // 0x0
|
||||
field public static final int TETHER_ERROR_PROVISION_FAILED = 11; // 0xb
|
||||
}
|
||||
|
||||
public abstract static class ConnectivityManager.OnStartTetheringCallback {
|
||||
@@ -3088,6 +3092,11 @@ package android.net {
|
||||
method public void onTetheringStarted();
|
||||
}
|
||||
|
||||
public abstract static class ConnectivityManager.TetheringEntitlementValueListener {
|
||||
ctor public ConnectivityManager.TetheringEntitlementValueListener();
|
||||
method public void onEntitlementResult(int);
|
||||
}
|
||||
|
||||
public final class IpPrefix implements android.os.Parcelable {
|
||||
ctor public IpPrefix(java.net.InetAddress, int);
|
||||
ctor public IpPrefix(String);
|
||||
|
||||
@@ -2581,6 +2581,7 @@ public class ConnectivityManager {
|
||||
}
|
||||
|
||||
/** {@hide} */
|
||||
@SystemApi
|
||||
public static final int TETHER_ERROR_NO_ERROR = 0;
|
||||
/** {@hide} */
|
||||
public static final int TETHER_ERROR_UNKNOWN_IFACE = 1;
|
||||
@@ -2603,9 +2604,13 @@ public class ConnectivityManager {
|
||||
/** {@hide} */
|
||||
public static final int TETHER_ERROR_IFACE_CFG_ERROR = 10;
|
||||
/** {@hide} */
|
||||
@SystemApi
|
||||
public static final int TETHER_ERROR_PROVISION_FAILED = 11;
|
||||
/** {@hide} */
|
||||
public static final int TETHER_ERROR_DHCPSERVER_ERROR = 12;
|
||||
/** {@hide} */
|
||||
@SystemApi
|
||||
public static final int TETHER_ERROR_ENTITLEMENT_UNKONWN = 13;
|
||||
|
||||
/**
|
||||
* Get a more detailed error code after a Tethering or Untethering
|
||||
@@ -2627,6 +2632,65 @@ public class ConnectivityManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for use with {@link #getLatestTetheringEntitlementValue} to find out whether
|
||||
* entitlement succeeded.
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
public abstract static class TetheringEntitlementValueListener {
|
||||
/**
|
||||
* Called to notify entitlement result.
|
||||
*
|
||||
* @param resultCode a int value of entitlement result. It may be one of
|
||||
* {@link #TETHER_ERROR_NO_ERROR},
|
||||
* {@link #TETHER_ERROR_PROVISION_FAILED}, or
|
||||
* {@link #TETHER_ERROR_ENTITLEMENT_UNKONWN}.
|
||||
*/
|
||||
public void onEntitlementResult(int resultCode) {}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the last value of the entitlement check on this downstream. If the cached value is
|
||||
* {@link #TETHER_ERROR_NO_ERROR} or showEntitlementUi argument is false, it just return the
|
||||
* cached value. Otherwise, a UI-based entitlement check would be performed. It is not
|
||||
* guaranteed that the UI-based entitlement check will complete in any specific time period
|
||||
* and may in fact never complete. Any successful entitlement check the platform performs for
|
||||
* any reason will update the cached value.
|
||||
*
|
||||
* @param type the downstream type of tethering. Must be one of
|
||||
* {@link #TETHERING_WIFI},
|
||||
* {@link #TETHERING_USB}, or
|
||||
* {@link #TETHERING_BLUETOOTH}.
|
||||
* @param showEntitlementUi a boolean indicating whether to run UI-based entitlement check.
|
||||
* @param listener an {@link TetheringEntitlementValueListener} which will be called to notify
|
||||
* the caller of the result of entitlement check. The listener may be called zero or
|
||||
* one time.
|
||||
* @param handler {@link Handler} to specify the thread upon which the listener will be invoked.
|
||||
* {@hide}
|
||||
*/
|
||||
@SystemApi
|
||||
@RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
|
||||
public void getLatestTetheringEntitlementValue(int type, boolean showEntitlementUi,
|
||||
@NonNull final TetheringEntitlementValueListener listener, @Nullable Handler handler) {
|
||||
Preconditions.checkNotNull(listener, "TetheringEntitlementValueListener cannot be null.");
|
||||
ResultReceiver wrappedListener = new ResultReceiver(handler) {
|
||||
@Override
|
||||
protected void onReceiveResult(int resultCode, Bundle resultData) {
|
||||
listener.onEntitlementResult(resultCode);
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
String pkgName = mContext.getOpPackageName();
|
||||
Log.i(TAG, "getLatestTetheringEntitlementValue:" + pkgName);
|
||||
mService.getLatestTetheringEntitlementValue(type, wrappedListener,
|
||||
showEntitlementUi, pkgName);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Report network connectivity status. This is currently used only
|
||||
* to alter status bar UI.
|
||||
|
||||
@@ -197,4 +197,7 @@ interface IConnectivityManager
|
||||
int getConnectionOwnerUid(in ConnectionInfo connectionInfo);
|
||||
boolean isCallerCurrentAlwaysOnVpnApp();
|
||||
boolean isCallerCurrentAlwaysOnVpnLockdownApp();
|
||||
|
||||
void getLatestTetheringEntitlementValue(int type, in ResultReceiver receiver,
|
||||
boolean showEntitlementUi, String callerPkg);
|
||||
}
|
||||
|
||||
@@ -3643,6 +3643,20 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
mTethering.stopTethering(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the latest value of the tethering entitlement check.
|
||||
*
|
||||
* Note: Allow privileged apps who have TETHER_PRIVILEGED permission to access. If it turns
|
||||
* out some such apps are observed to abuse this API, change to per-UID limits on this API
|
||||
* if it's really needed.
|
||||
*/
|
||||
@Override
|
||||
public void getLatestTetheringEntitlementValue(int type, ResultReceiver receiver,
|
||||
boolean showEntitlementUi, String callerPkg) {
|
||||
ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
|
||||
mTethering.getLatestTetheringEntitlementValue(type, receiver, showEntitlementUi);
|
||||
}
|
||||
|
||||
// Called when we lose the default network and have no replacement yet.
|
||||
// This will automatically be cleared after X seconds or a new default network
|
||||
// becomes CONNECTED, whichever happens first. The timer is started by the
|
||||
|
||||
@@ -121,7 +121,6 @@ import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*
|
||||
@@ -223,7 +222,8 @@ public class Tethering extends BaseNetworkObserver {
|
||||
|
||||
IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(ACTION_CARRIER_CONFIG_CHANGED);
|
||||
mEntitlementMgr = mDeps.getEntitlementManager(mContext, mLog, systemProperties);
|
||||
mEntitlementMgr = mDeps.getEntitlementManager(mContext, mTetherMasterSM,
|
||||
mLog, systemProperties);
|
||||
mCarrierConfigChange = new VersionedBroadcastListener(
|
||||
"CarrierConfigChangeListener", mContext, smHandler, filter,
|
||||
(Intent ignored) -> {
|
||||
@@ -470,6 +470,7 @@ public class Tethering extends BaseNetworkObserver {
|
||||
} else {
|
||||
sendTetherResult(receiver, resultCode);
|
||||
}
|
||||
mEntitlementMgr.updateEntitlementCacheValue(type, resultCode);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1662,6 +1663,14 @@ public class Tethering extends BaseNetworkObserver {
|
||||
mUpstreamNetworkMonitor.startTrackDefaultNetwork(mDeps.getDefaultNetworkRequest());
|
||||
}
|
||||
|
||||
/** Get the latest value of the tethering entitlement check. */
|
||||
public void getLatestTetheringEntitlementValue(int type, ResultReceiver receiver,
|
||||
boolean showEntitlementUi) {
|
||||
if (receiver != null) {
|
||||
mEntitlementMgr.getLatestTetheringEntitlementValue(type, receiver, showEntitlementUi);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
|
||||
// Binder.java closes the resource for us.
|
||||
|
||||
@@ -21,6 +21,9 @@ import static android.net.ConnectivityManager.EXTRA_PROVISION_CALLBACK;
|
||||
import static android.net.ConnectivityManager.EXTRA_REM_TETHER_TYPE;
|
||||
import static android.net.ConnectivityManager.EXTRA_RUN_PROVISION;
|
||||
import static android.net.ConnectivityManager.EXTRA_SET_ALARM;
|
||||
import static android.net.ConnectivityManager.TETHER_ERROR_ENTITLEMENT_UNKONWN;
|
||||
import static android.net.ConnectivityManager.TETHER_ERROR_NO_ERROR;
|
||||
import static android.net.ConnectivityManager.TETHER_ERROR_PROVISION_FAILED;
|
||||
|
||||
import static com.android.internal.R.string.config_wifi_tether_enable;
|
||||
|
||||
@@ -31,15 +34,21 @@ import android.content.Intent;
|
||||
import android.content.res.Resources;
|
||||
import android.net.util.SharedLog;
|
||||
import android.os.Binder;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Parcel;
|
||||
import android.os.PersistableBundle;
|
||||
import android.os.ResultReceiver;
|
||||
import android.os.UserHandle;
|
||||
import android.provider.Settings;
|
||||
import android.telephony.CarrierConfigManager;
|
||||
import android.util.ArraySet;
|
||||
import android.util.Log;
|
||||
import android.util.SparseIntArray;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.util.StateMachine;
|
||||
import com.android.server.connectivity.MockableSystemProperties;
|
||||
|
||||
/**
|
||||
@@ -50,6 +59,7 @@ import com.android.server.connectivity.MockableSystemProperties;
|
||||
*/
|
||||
public class EntitlementManager {
|
||||
private static final String TAG = EntitlementManager.class.getSimpleName();
|
||||
private static final boolean DBG = false;
|
||||
|
||||
// {@link ComponentName} of the Service used to run tether provisioning.
|
||||
private static final ComponentName TETHER_SERVICE = ComponentName.unflattenFromString(
|
||||
@@ -65,15 +75,19 @@ public class EntitlementManager {
|
||||
private final Context mContext;
|
||||
private final MockableSystemProperties mSystemProperties;
|
||||
private final SharedLog mLog;
|
||||
private final Handler mMasterHandler;
|
||||
private final SparseIntArray mEntitlementCacheValue;
|
||||
@Nullable
|
||||
private TetheringConfiguration mConfig;
|
||||
|
||||
public EntitlementManager(Context ctx, SharedLog log,
|
||||
public EntitlementManager(Context ctx, StateMachine tetherMasterSM, SharedLog log,
|
||||
MockableSystemProperties systemProperties) {
|
||||
mContext = ctx;
|
||||
mLog = log;
|
||||
mLog = log.forSubComponent(TAG);
|
||||
mCurrentTethers = new ArraySet<Integer>();
|
||||
mSystemProperties = systemProperties;
|
||||
mEntitlementCacheValue = new SparseIntArray();
|
||||
mMasterHandler = tetherMasterSM.getHandler();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -128,6 +142,10 @@ public class EntitlementManager {
|
||||
* Reference ConnectivityManager.TETHERING_{@code *} for each tether type.
|
||||
*/
|
||||
public void reevaluateSimCardProvisioning() {
|
||||
synchronized (mEntitlementCacheValue) {
|
||||
mEntitlementCacheValue.clear();
|
||||
}
|
||||
|
||||
if (!mConfig.hasMobileHotspotProvisionApp()) return;
|
||||
if (carrierConfigAffirmsEntitlementCheckNotRequired()) return;
|
||||
|
||||
@@ -175,6 +193,11 @@ public class EntitlementManager {
|
||||
}
|
||||
|
||||
public void runUiTetherProvisioningAndEnable(int type, ResultReceiver receiver) {
|
||||
runUiTetherProvisioning(type, receiver);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
protected void runUiTetherProvisioning(int type, ResultReceiver receiver) {
|
||||
Intent intent = new Intent(Settings.ACTION_TETHER_PROVISIONING);
|
||||
intent.putExtra(EXTRA_ADD_TETHER_TYPE, type);
|
||||
intent.putExtra(EXTRA_PROVISION_CALLBACK, receiver);
|
||||
@@ -221,4 +244,70 @@ public class EntitlementManager {
|
||||
Binder.restoreCallingIdentity(ident);
|
||||
}
|
||||
}
|
||||
|
||||
private ResultReceiver buildProxyReceiver(int type, final ResultReceiver receiver) {
|
||||
ResultReceiver rr = new ResultReceiver(mMasterHandler) {
|
||||
@Override
|
||||
protected void onReceiveResult(int resultCode, Bundle resultData) {
|
||||
int updatedCacheValue = updateEntitlementCacheValue(type, resultCode);
|
||||
receiver.send(updatedCacheValue, null);
|
||||
}
|
||||
};
|
||||
|
||||
return writeToParcel(rr);
|
||||
}
|
||||
|
||||
private ResultReceiver writeToParcel(final ResultReceiver receiver) {
|
||||
// This is necessary to avoid unmarshalling issues when sending the receiver
|
||||
// across processes.
|
||||
Parcel parcel = Parcel.obtain();
|
||||
receiver.writeToParcel(parcel, 0);
|
||||
parcel.setDataPosition(0);
|
||||
ResultReceiver receiverForSending = ResultReceiver.CREATOR.createFromParcel(parcel);
|
||||
parcel.recycle();
|
||||
return receiverForSending;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the last entitlement value to internal cache
|
||||
*
|
||||
* @param type tethering type from ConnectivityManager.TETHERING_{@code *}
|
||||
* @param resultCode last entitlement value
|
||||
* @return the last updated entitlement value
|
||||
*/
|
||||
public int updateEntitlementCacheValue(int type, int resultCode) {
|
||||
if (DBG) {
|
||||
Log.d(TAG, "updateEntitlementCacheValue: " + type + ", result: " + resultCode);
|
||||
}
|
||||
synchronized (mEntitlementCacheValue) {
|
||||
if (resultCode == TETHER_ERROR_NO_ERROR) {
|
||||
mEntitlementCacheValue.put(type, resultCode);
|
||||
return resultCode;
|
||||
} else {
|
||||
mEntitlementCacheValue.put(type, TETHER_ERROR_PROVISION_FAILED);
|
||||
return TETHER_ERROR_PROVISION_FAILED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Get the last value of the tethering entitlement check. */
|
||||
public void getLatestTetheringEntitlementValue(int downstream, ResultReceiver receiver,
|
||||
boolean showEntitlementUi) {
|
||||
if (!isTetherProvisioningRequired()) {
|
||||
receiver.send(TETHER_ERROR_NO_ERROR, null);
|
||||
return;
|
||||
}
|
||||
|
||||
final int cacheValue;
|
||||
synchronized (mEntitlementCacheValue) {
|
||||
cacheValue = mEntitlementCacheValue.get(
|
||||
downstream, TETHER_ERROR_ENTITLEMENT_UNKONWN);
|
||||
}
|
||||
if (cacheValue == TETHER_ERROR_NO_ERROR || !showEntitlementUi) {
|
||||
receiver.send(cacheValue, null);
|
||||
} else {
|
||||
ResultReceiver proxy = buildProxyReceiver(downstream, receiver);
|
||||
runUiTetherProvisioning(downstream, proxy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,8 +81,8 @@ public class TetheringDependencies {
|
||||
/**
|
||||
* Get a reference to the EntitlementManager to be used by tethering.
|
||||
*/
|
||||
public EntitlementManager getEntitlementManager(Context ctx, SharedLog log,
|
||||
MockableSystemProperties systemProperties) {
|
||||
return new EntitlementManager(ctx, log, systemProperties);
|
||||
public EntitlementManager getEntitlementManager(Context ctx, StateMachine target,
|
||||
SharedLog log, MockableSystemProperties systemProperties) {
|
||||
return new EntitlementManager(ctx, target, log, systemProperties);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,8 +16,16 @@
|
||||
|
||||
package com.android.server.connectivity.tethering;
|
||||
|
||||
import static android.net.ConnectivityManager.TETHERING_USB;
|
||||
import static android.net.ConnectivityManager.TETHERING_WIFI;
|
||||
import static android.net.ConnectivityManager.TETHER_ERROR_ENTITLEMENT_UNKONWN;
|
||||
import static android.net.ConnectivityManager.TETHER_ERROR_NO_ERROR;
|
||||
import static android.net.ConnectivityManager.TETHER_ERROR_PROVISION_FAILED;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.mockito.Matchers.anyBoolean;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Matchers.eq;
|
||||
@@ -27,12 +35,22 @@ import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.net.util.SharedLog;
|
||||
import android.os.Bundle;
|
||||
import android.os.Message;
|
||||
import android.os.PersistableBundle;
|
||||
import android.os.ResultReceiver;
|
||||
import android.os.test.TestLooper;
|
||||
import android.provider.Settings;
|
||||
import android.support.test.filters.SmallTest;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
import android.telephony.CarrierConfigManager;
|
||||
import android.test.mock.MockContentResolver;
|
||||
|
||||
import com.android.internal.R;
|
||||
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.FakeSettingsProvider;
|
||||
import com.android.server.connectivity.MockableSystemProperties;
|
||||
|
||||
import org.junit.After;
|
||||
@@ -42,6 +60,10 @@ import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@SmallTest
|
||||
public final class EntitlementManagerTest {
|
||||
@@ -51,7 +73,6 @@ public final class EntitlementManagerTest {
|
||||
|
||||
@Mock private CarrierConfigManager mCarrierConfigManager;
|
||||
@Mock private Context mContext;
|
||||
@Mock private ContentResolver mContent;
|
||||
@Mock private MockableSystemProperties mSystemProperties;
|
||||
@Mock private Resources mResources;
|
||||
@Mock private SharedLog mLog;
|
||||
@@ -59,15 +80,49 @@ public final class EntitlementManagerTest {
|
||||
// Like so many Android system APIs, these cannot be mocked because it is marked final.
|
||||
// We have to use the real versions.
|
||||
private final PersistableBundle mCarrierConfig = new PersistableBundle();
|
||||
private final TestLooper mLooper = new TestLooper();
|
||||
private Context mMockContext;
|
||||
private MockContentResolver mContentResolver;
|
||||
|
||||
private EntitlementManager mEnMgr;
|
||||
private TestStateMachine mSM;
|
||||
private WrappedEntitlementManager mEnMgr;
|
||||
|
||||
private class MockContext extends BroadcastInterceptingContext {
|
||||
MockContext(Context base) {
|
||||
super(base);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Resources getResources() {
|
||||
return mResources;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContentResolver getContentResolver() {
|
||||
return mContentResolver;
|
||||
}
|
||||
}
|
||||
|
||||
public class WrappedEntitlementManager extends EntitlementManager {
|
||||
public int fakeEntitlementResult = TETHER_ERROR_ENTITLEMENT_UNKONWN;
|
||||
public boolean everRunUiEntitlement = false;
|
||||
|
||||
public WrappedEntitlementManager(Context ctx, StateMachine target,
|
||||
SharedLog log, MockableSystemProperties systemProperties) {
|
||||
super(ctx, target, log, systemProperties);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void runUiTetherProvisioning(int type, ResultReceiver receiver) {
|
||||
everRunUiEntitlement = true;
|
||||
receiver.send(fakeEntitlementResult, null);
|
||||
}
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
when(mContext.getResources()).thenReturn(mResources);
|
||||
when(mContext.getContentResolver()).thenReturn(mContent);
|
||||
when(mResources.getStringArray(R.array.config_tether_dhcp_range))
|
||||
.thenReturn(new String[0]);
|
||||
when(mResources.getStringArray(R.array.config_tether_usb_regexs))
|
||||
@@ -80,12 +135,21 @@ public final class EntitlementManagerTest {
|
||||
.thenReturn(new int[0]);
|
||||
when(mLog.forSubComponent(anyString())).thenReturn(mLog);
|
||||
|
||||
mEnMgr = new EntitlementManager(mContext, mLog, mSystemProperties);
|
||||
mEnMgr.updateConfiguration(new TetheringConfiguration(mContext, mLog));
|
||||
mContentResolver = new MockContentResolver();
|
||||
mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
|
||||
mMockContext = new MockContext(mContext);
|
||||
mSM = new TestStateMachine();
|
||||
mEnMgr = new WrappedEntitlementManager(mMockContext, mSM, mLog, mSystemProperties);
|
||||
mEnMgr.updateConfiguration(new TetheringConfiguration(mMockContext, mLog));
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {}
|
||||
public void tearDown() throws Exception {
|
||||
if (mSM != null) {
|
||||
mSM.quit();
|
||||
mSM = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void setupForRequiredProvisioning() {
|
||||
// Produce some acceptable looking provision app setting if requested.
|
||||
@@ -104,7 +168,7 @@ public final class EntitlementManagerTest {
|
||||
@Test
|
||||
public void canRequireProvisioning() {
|
||||
setupForRequiredProvisioning();
|
||||
mEnMgr.updateConfiguration(new TetheringConfiguration(mContext, mLog));
|
||||
mEnMgr.updateConfiguration(new TetheringConfiguration(mMockContext, mLog));
|
||||
assertTrue(mEnMgr.isTetherProvisioningRequired());
|
||||
}
|
||||
|
||||
@@ -113,7 +177,7 @@ public final class EntitlementManagerTest {
|
||||
setupForRequiredProvisioning();
|
||||
when(mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE))
|
||||
.thenReturn(null);
|
||||
mEnMgr.updateConfiguration(new TetheringConfiguration(mContext, mLog));
|
||||
mEnMgr.updateConfiguration(new TetheringConfiguration(mMockContext, mLog));
|
||||
// Couldn't get the CarrierConfigManager, but still had a declared provisioning app.
|
||||
// Therefore provisioning still be required.
|
||||
assertTrue(mEnMgr.isTetherProvisioningRequired());
|
||||
@@ -123,7 +187,7 @@ public final class EntitlementManagerTest {
|
||||
public void toleratesCarrierConfigMissing() {
|
||||
setupForRequiredProvisioning();
|
||||
when(mCarrierConfigManager.getConfig()).thenReturn(null);
|
||||
mEnMgr.updateConfiguration(new TetheringConfiguration(mContext, mLog));
|
||||
mEnMgr.updateConfiguration(new TetheringConfiguration(mMockContext, mLog));
|
||||
// We still have a provisioning app configured, so still require provisioning.
|
||||
assertTrue(mEnMgr.isTetherProvisioningRequired());
|
||||
}
|
||||
@@ -133,12 +197,143 @@ public final class EntitlementManagerTest {
|
||||
setupForRequiredProvisioning();
|
||||
when(mResources.getStringArray(R.array.config_mobile_hotspot_provision_app))
|
||||
.thenReturn(null);
|
||||
mEnMgr.updateConfiguration(new TetheringConfiguration(mContext, mLog));
|
||||
mEnMgr.updateConfiguration(new TetheringConfiguration(mMockContext, mLog));
|
||||
assertFalse(mEnMgr.isTetherProvisioningRequired());
|
||||
when(mResources.getStringArray(R.array.config_mobile_hotspot_provision_app))
|
||||
.thenReturn(new String[] {"malformedApp"});
|
||||
mEnMgr.updateConfiguration(new TetheringConfiguration(mContext, mLog));
|
||||
mEnMgr.updateConfiguration(new TetheringConfiguration(mMockContext, mLog));
|
||||
assertFalse(mEnMgr.isTetherProvisioningRequired());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetLastEntitlementCacheValue() throws Exception {
|
||||
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) {
|
||||
assertEquals(TETHER_ERROR_NO_ERROR, resultCode);
|
||||
mCallbacklatch.countDown();
|
||||
}
|
||||
};
|
||||
mEnMgr.getLatestTetheringEntitlementValue(TETHERING_WIFI, receiver, true);
|
||||
callbackTimeoutHelper(mCallbacklatch);
|
||||
assertFalse(mEnMgr.everRunUiEntitlement);
|
||||
|
||||
setupForRequiredProvisioning();
|
||||
mEnMgr.updateConfiguration(new TetheringConfiguration(mMockContext, mLog));
|
||||
// 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) {
|
||||
assertEquals(TETHER_ERROR_ENTITLEMENT_UNKONWN, resultCode);
|
||||
mCallbacklatch.countDown();
|
||||
}
|
||||
};
|
||||
mEnMgr.getLatestTetheringEntitlementValue(TETHERING_WIFI, receiver, false);
|
||||
callbackTimeoutHelper(mCallbacklatch);
|
||||
assertFalse(mEnMgr.everRunUiEntitlement);
|
||||
// 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) {
|
||||
assertEquals(TETHER_ERROR_PROVISION_FAILED, resultCode);
|
||||
mCallbacklatch.countDown();
|
||||
}
|
||||
};
|
||||
mEnMgr.getLatestTetheringEntitlementValue(TETHERING_WIFI, receiver, true);
|
||||
mLooper.dispatchAll();
|
||||
callbackTimeoutHelper(mCallbacklatch);
|
||||
assertTrue(mEnMgr.everRunUiEntitlement);
|
||||
// 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) {
|
||||
assertEquals(TETHER_ERROR_PROVISION_FAILED, resultCode);
|
||||
mCallbacklatch.countDown();
|
||||
}
|
||||
};
|
||||
mEnMgr.getLatestTetheringEntitlementValue(TETHERING_WIFI, receiver, false);
|
||||
callbackTimeoutHelper(mCallbacklatch);
|
||||
assertFalse(mEnMgr.everRunUiEntitlement);
|
||||
// 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) {
|
||||
assertEquals(TETHER_ERROR_NO_ERROR, resultCode);
|
||||
mCallbacklatch.countDown();
|
||||
}
|
||||
};
|
||||
mEnMgr.getLatestTetheringEntitlementValue(TETHERING_WIFI, receiver, true);
|
||||
mLooper.dispatchAll();
|
||||
callbackTimeoutHelper(mCallbacklatch);
|
||||
assertTrue(mEnMgr.everRunUiEntitlement);
|
||||
// 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) {
|
||||
assertEquals(TETHER_ERROR_NO_ERROR, resultCode);
|
||||
mCallbacklatch.countDown();
|
||||
}
|
||||
};
|
||||
mEnMgr.getLatestTetheringEntitlementValue(TETHERING_WIFI, receiver, true);
|
||||
callbackTimeoutHelper(mCallbacklatch);
|
||||
assertFalse(mEnMgr.everRunUiEntitlement);
|
||||
// 7. Test get value for other downstream type.
|
||||
mEnMgr.everRunUiEntitlement = false;
|
||||
receiver = new ResultReceiver(null) {
|
||||
@Override
|
||||
protected void onReceiveResult(int resultCode, Bundle resultData) {
|
||||
assertEquals(TETHER_ERROR_ENTITLEMENT_UNKONWN, resultCode);
|
||||
mCallbacklatch.countDown();
|
||||
}
|
||||
};
|
||||
mEnMgr.getLatestTetheringEntitlementValue(TETHERING_USB, receiver, false);
|
||||
callbackTimeoutHelper(mCallbacklatch);
|
||||
assertFalse(mEnMgr.everRunUiEntitlement);
|
||||
}
|
||||
|
||||
void callbackTimeoutHelper(final CountDownLatch latch) throws Exception {
|
||||
if (!latch.await(1, TimeUnit.SECONDS)) {
|
||||
fail("Timout, fail to recieve callback");
|
||||
}
|
||||
}
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user