Merge changes Ic98e3bcb,Idb0c55fc,Ia8649061,I5e7e5a87 into nyc-mr1-dev
* changes: Give WakeupMessage the ability to transport an object as well. Don't treat the lingerExpired broadcast specially. Add a test for mobile data always on. Add a FakeSettingsProvider and use it in ConnectivityServiceTest.
This commit is contained in:
committed by
Android (Google) Code Review
commit
3e2bfbd135
@@ -45,24 +45,32 @@ public class WakeupMessage implements AlarmManager.OnAlarmListener {
|
|||||||
protected final String mCmdName;
|
protected final String mCmdName;
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
protected final int mCmd, mArg1, mArg2;
|
protected final int mCmd, mArg1, mArg2;
|
||||||
|
@VisibleForTesting
|
||||||
|
protected final Object mObj;
|
||||||
private boolean mScheduled;
|
private boolean mScheduled;
|
||||||
|
|
||||||
public WakeupMessage(Context context, Handler handler,
|
public WakeupMessage(Context context, Handler handler,
|
||||||
String cmdName, int cmd, int arg1, int arg2) {
|
String cmdName, int cmd, int arg1, int arg2, Object obj) {
|
||||||
mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
|
mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
|
||||||
mHandler = handler;
|
mHandler = handler;
|
||||||
mCmdName = cmdName;
|
mCmdName = cmdName;
|
||||||
mCmd = cmd;
|
mCmd = cmd;
|
||||||
mArg1 = arg1;
|
mArg1 = arg1;
|
||||||
mArg2 = arg2;
|
mArg2 = arg2;
|
||||||
|
mObj = obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
public WakeupMessage(Context context, Handler handler, String cmdName, int cmd, int arg1) {
|
public WakeupMessage(Context context, Handler handler, String cmdName, int cmd, int arg1) {
|
||||||
this(context, handler, cmdName, cmd, arg1, 0);
|
this(context, handler, cmdName, cmd, arg1, 0, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WakeupMessage(Context context, Handler handler,
|
||||||
|
String cmdName, int cmd, int arg1, int arg2) {
|
||||||
|
this(context, handler, cmdName, cmd, arg1, arg2, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public WakeupMessage(Context context, Handler handler, String cmdName, int cmd) {
|
public WakeupMessage(Context context, Handler handler, String cmdName, int cmd) {
|
||||||
this(context, handler, cmdName, cmd, 0, 0);
|
this(context, handler, cmdName, cmd, 0, 0, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -99,7 +107,7 @@ public class WakeupMessage implements AlarmManager.OnAlarmListener {
|
|||||||
mScheduled = false;
|
mScheduled = false;
|
||||||
}
|
}
|
||||||
if (stillScheduled) {
|
if (stillScheduled) {
|
||||||
Message msg = mHandler.obtainMessage(mCmd, mArg1, mArg2);
|
Message msg = mHandler.obtainMessage(mCmd, mArg1, mArg2, mObj);
|
||||||
mHandler.handleMessage(msg);
|
mHandler.handleMessage(msg);
|
||||||
msg.recycle();
|
msg.recycle();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ public class WakeupMessageTest {
|
|||||||
private static final int TEST_CMD = 18;
|
private static final int TEST_CMD = 18;
|
||||||
private static final int TEST_ARG1 = 33;
|
private static final int TEST_ARG1 = 33;
|
||||||
private static final int TEST_ARG2 = 182;
|
private static final int TEST_ARG2 = 182;
|
||||||
|
private static final Object TEST_OBJ = "hello";
|
||||||
|
|
||||||
@Mock AlarmManager mAlarmManager;
|
@Mock AlarmManager mAlarmManager;
|
||||||
WakeupMessage mMessage;
|
WakeupMessage mMessage;
|
||||||
@@ -92,7 +93,7 @@ public class WakeupMessageTest {
|
|||||||
mListenerCaptor.capture(), any(Handler.class));
|
mListenerCaptor.capture(), any(Handler.class));
|
||||||
|
|
||||||
mMessage = new WakeupMessage(context, mHandler, TEST_CMD_NAME, TEST_CMD, TEST_ARG1,
|
mMessage = new WakeupMessage(context, mHandler, TEST_CMD_NAME, TEST_CMD, TEST_ARG1,
|
||||||
TEST_ARG2);
|
TEST_ARG2, TEST_OBJ);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -114,6 +115,7 @@ public class WakeupMessageTest {
|
|||||||
assertEquals("what", TEST_CMD, mHandler.getLastMessage().what);
|
assertEquals("what", TEST_CMD, mHandler.getLastMessage().what);
|
||||||
assertEquals("arg1", TEST_ARG1, mHandler.getLastMessage().arg1);
|
assertEquals("arg1", TEST_ARG1, mHandler.getLastMessage().arg1);
|
||||||
assertEquals("arg2", TEST_ARG2, mHandler.getLastMessage().arg2);
|
assertEquals("arg2", TEST_ARG2, mHandler.getLastMessage().arg2);
|
||||||
|
assertEquals("obj", TEST_OBJ, mHandler.getLastMessage().obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -797,6 +797,17 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
return new NetworkRequest(netCap, TYPE_NONE, nextNetworkRequestId());
|
return new NetworkRequest(netCap, TYPE_NONE, nextNetworkRequestId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Used only for testing.
|
||||||
|
// TODO: Delete this and either:
|
||||||
|
// 1. Give Fake SettingsProvider the ability to send settings change notifications (requires
|
||||||
|
// changing ContentResolver to make registerContentObserver non-final).
|
||||||
|
// 2. Give FakeSettingsProvider an alternative notification mechanism and have the test use it
|
||||||
|
// by subclassing SettingsObserver.
|
||||||
|
@VisibleForTesting
|
||||||
|
void updateMobileDataAlwaysOn() {
|
||||||
|
mHandler.sendEmptyMessage(EVENT_CONFIGURE_MOBILE_DATA_ALWAYS_ON);
|
||||||
|
}
|
||||||
|
|
||||||
private void handleMobileDataAlwaysOn() {
|
private void handleMobileDataAlwaysOn() {
|
||||||
final boolean enable = (Settings.Global.getInt(
|
final boolean enable = (Settings.Global.getInt(
|
||||||
mContext.getContentResolver(), Settings.Global.MOBILE_DATA_ALWAYS_ON, 0) == 1);
|
mContext.getContentResolver(), Settings.Global.MOBILE_DATA_ALWAYS_ON, 0) == 1);
|
||||||
|
|||||||
@@ -0,0 +1,130 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.internal.util;
|
||||||
|
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.provider.Settings;
|
||||||
|
import android.test.mock.MockContentProvider;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fake for system settings.
|
||||||
|
*
|
||||||
|
* To use, ensure that the Context used by the test code returns a ContentResolver that uses this
|
||||||
|
* provider for the Settings authority:
|
||||||
|
*
|
||||||
|
* class MyTestContext extends MockContext {
|
||||||
|
* ...
|
||||||
|
* private final MockContentResolver mContentResolver;
|
||||||
|
* public MyTestContext(...) {
|
||||||
|
* ...
|
||||||
|
* mContentResolver = new MockContentResolver();
|
||||||
|
* mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
|
||||||
|
* }
|
||||||
|
* ...
|
||||||
|
* @Override
|
||||||
|
* public ContentResolver getContentResolver() {
|
||||||
|
* return mContentResolver;
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* As long as the code under test is using the test Context, the actual code under test does not
|
||||||
|
* need to be modified, and can access Settings using the normal static methods:
|
||||||
|
*
|
||||||
|
* Settings.Global.getInt(cr, "my_setting", 0); // Returns 0.
|
||||||
|
* Settings.Global.putInt(cr, "my_setting", 5);
|
||||||
|
* Settings.Global.getInt(cr, "my_setting", 0); // Returns 5.
|
||||||
|
*
|
||||||
|
* Note that this class cannot be used in the same process as real settings. This is because it
|
||||||
|
* works by passing an alternate ContentResolver to Settings operations. Unfortunately, the Settings
|
||||||
|
* class only fetches the content provider from the passed-in ContentResolver the first time it's
|
||||||
|
* used, and after that stores it in a per-process static.
|
||||||
|
*
|
||||||
|
* TODO: evaluate implementing settings change notifications. This would require:
|
||||||
|
*
|
||||||
|
* 1. Making ContentResolver#registerContentObserver non-final and overriding it in
|
||||||
|
* MockContentResolver.
|
||||||
|
* 2. Making FakeSettingsProvider take a ContentResolver argument.
|
||||||
|
* 3. Calling ContentResolver#notifyChange(getUriFor(table, arg), ...) on every settings change.
|
||||||
|
*/
|
||||||
|
public class FakeSettingsProvider extends MockContentProvider {
|
||||||
|
|
||||||
|
private static final String TAG = FakeSettingsProvider.class.getSimpleName();
|
||||||
|
private static final boolean DBG = false;
|
||||||
|
private static final String[] TABLES = { "system", "secure", "global" };
|
||||||
|
|
||||||
|
private final HashMap<String, HashMap<String, String>> mTables = new HashMap<>();
|
||||||
|
|
||||||
|
public FakeSettingsProvider() {
|
||||||
|
for (int i = 0; i < TABLES.length; i++) {
|
||||||
|
mTables.put(TABLES[i], new HashMap<String, String>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Uri getUriFor(String table, String key) {
|
||||||
|
switch (table) {
|
||||||
|
case "system":
|
||||||
|
return Settings.System.getUriFor(key);
|
||||||
|
case "secure":
|
||||||
|
return Settings.Secure.getUriFor(key);
|
||||||
|
case "global":
|
||||||
|
return Settings.Global.getUriFor(key);
|
||||||
|
default:
|
||||||
|
throw new UnsupportedOperationException("Unknown settings table " + table);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Bundle call(String method, String arg, Bundle extras) {
|
||||||
|
// Methods are "GET_system", "GET_global", "PUT_secure", etc.
|
||||||
|
String[] commands = method.split("_", 2);
|
||||||
|
String op = commands[0];
|
||||||
|
String table = commands[1];
|
||||||
|
|
||||||
|
Bundle out = new Bundle();
|
||||||
|
String value;
|
||||||
|
switch (op) {
|
||||||
|
case "GET":
|
||||||
|
value = mTables.get(table).get(arg);
|
||||||
|
if (value != null) {
|
||||||
|
if (DBG) {
|
||||||
|
Log.d(TAG, String.format("Returning fake setting %s.%s = %s",
|
||||||
|
table, arg, value));
|
||||||
|
}
|
||||||
|
out.putString(Settings.NameValueTable.VALUE, value);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "PUT":
|
||||||
|
value = extras.getString(Settings.NameValueTable.VALUE, null);
|
||||||
|
if (DBG) {
|
||||||
|
Log.d(TAG, String.format("Inserting fake setting %s.%s = %s",
|
||||||
|
table, arg, value));
|
||||||
|
}
|
||||||
|
if (value != null) {
|
||||||
|
mTables.get(table).put(arg, value);
|
||||||
|
} else {
|
||||||
|
mTables.get(table).remove(arg);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new UnsupportedOperationException("Unknown command " + method);
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.internal.util;
|
||||||
|
|
||||||
|
import android.content.ContentResolver;
|
||||||
|
import android.database.ContentObserver;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.provider.Settings;
|
||||||
|
import android.test.AndroidTestCase;
|
||||||
|
import android.test.mock.MockContentResolver;
|
||||||
|
import android.test.mock.MockContext;
|
||||||
|
import android.test.suitebuilder.annotation.SmallTest;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit tests for FakeSettingsProvider.
|
||||||
|
*/
|
||||||
|
public class FakeSettingsProviderTest extends AndroidTestCase {
|
||||||
|
|
||||||
|
private MockContentResolver mCr;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
mCr = new MockContentResolver();
|
||||||
|
mCr.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
|
||||||
|
}
|
||||||
|
|
||||||
|
@SmallTest
|
||||||
|
public void testBasicOperation() throws Exception {
|
||||||
|
String settingName = Settings.System.SCREEN_BRIGHTNESS;
|
||||||
|
|
||||||
|
try {
|
||||||
|
Settings.System.getInt(mCr, settingName);
|
||||||
|
fail("FakeSettingsProvider should start off empty.");
|
||||||
|
} catch (Settings.SettingNotFoundException expected) {}
|
||||||
|
|
||||||
|
// Check that fake settings can be written and read back.
|
||||||
|
Settings.System.putInt(mCr, settingName, 123);
|
||||||
|
assertEquals(123, Settings.System.getInt(mCr, settingName));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -26,6 +26,7 @@ import static org.mockito.Mockito.mock;
|
|||||||
|
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
|
import android.content.ContentResolver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.ContextWrapper;
|
import android.content.ContextWrapper;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
@@ -61,12 +62,15 @@ import android.os.Messenger;
|
|||||||
import android.os.MessageQueue.IdleHandler;
|
import android.os.MessageQueue.IdleHandler;
|
||||||
import android.os.Process;
|
import android.os.Process;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
|
import android.provider.Settings;
|
||||||
import android.test.AndroidTestCase;
|
import android.test.AndroidTestCase;
|
||||||
|
import android.test.mock.MockContentResolver;
|
||||||
import android.test.suitebuilder.annotation.LargeTest;
|
import android.test.suitebuilder.annotation.LargeTest;
|
||||||
import android.test.suitebuilder.annotation.SmallTest;
|
import android.test.suitebuilder.annotation.SmallTest;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.LogPrinter;
|
import android.util.LogPrinter;
|
||||||
|
|
||||||
|
import com.android.internal.util.FakeSettingsProvider;
|
||||||
import com.android.internal.util.WakeupMessage;
|
import com.android.internal.util.WakeupMessage;
|
||||||
import com.android.server.connectivity.NetworkAgentInfo;
|
import com.android.server.connectivity.NetworkAgentInfo;
|
||||||
import com.android.server.connectivity.NetworkMonitor;
|
import com.android.server.connectivity.NetworkMonitor;
|
||||||
@@ -118,27 +122,24 @@ public class ConnectivityServiceTest extends AndroidTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private class MockContext extends BroadcastInterceptingContext {
|
private class MockContext extends BroadcastInterceptingContext {
|
||||||
|
private final MockContentResolver mContentResolver;
|
||||||
|
|
||||||
MockContext(Context base) {
|
MockContext(Context base) {
|
||||||
super(base);
|
super(base);
|
||||||
|
mContentResolver = new MockContentResolver();
|
||||||
|
mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
|
public Object getSystemService(String name) {
|
||||||
// PendingIntents sent by the AlarmManager are not intercepted by
|
|
||||||
// BroadcastInterceptingContext so we must really register the receiver.
|
|
||||||
// This shouldn't effect the real NetworkMonitors as the action contains a random token.
|
|
||||||
if (filter.getAction(0).startsWith("android.net.netmon.lingerExpired")) {
|
|
||||||
return getBaseContext().registerReceiver(receiver, filter);
|
|
||||||
} else {
|
|
||||||
return super.registerReceiver(receiver, filter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object getSystemService (String name) {
|
|
||||||
if (name == Context.CONNECTIVITY_SERVICE) return mCm;
|
if (name == Context.CONNECTIVITY_SERVICE) return mCm;
|
||||||
return super.getSystemService(name);
|
return super.getSystemService(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ContentResolver getContentResolver() {
|
||||||
|
return mContentResolver;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -641,7 +642,6 @@ public class ConnectivityServiceTest extends AndroidTestCase {
|
|||||||
public void waitForIdle() {
|
public void waitForIdle() {
|
||||||
waitForIdle(TIMEOUT_MS);
|
waitForIdle(TIMEOUT_MS);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private interface Criteria {
|
private interface Criteria {
|
||||||
@@ -1477,6 +1477,73 @@ public class ConnectivityServiceTest extends AndroidTestCase {
|
|||||||
defaultNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
|
defaultNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SmallTest
|
||||||
|
public void testMobileDataAlwaysOn() throws Exception {
|
||||||
|
final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
|
||||||
|
final NetworkRequest cellRequest = new NetworkRequest.Builder()
|
||||||
|
.addTransportType(TRANSPORT_CELLULAR).build();
|
||||||
|
mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
|
||||||
|
|
||||||
|
final HandlerThread handlerThread = new HandlerThread("MobileDataAlwaysOnFactory");
|
||||||
|
handlerThread.start();
|
||||||
|
NetworkCapabilities filter = new NetworkCapabilities()
|
||||||
|
.addTransportType(TRANSPORT_CELLULAR)
|
||||||
|
.addCapability(NET_CAPABILITY_INTERNET);
|
||||||
|
final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
|
||||||
|
mServiceContext, "testFactory", filter);
|
||||||
|
testFactory.setScoreFilter(40);
|
||||||
|
|
||||||
|
// Register the factory and expect it to start looking for a network.
|
||||||
|
testFactory.expectAddRequests(1);
|
||||||
|
testFactory.register();
|
||||||
|
testFactory.waitForNetworkRequests(1);
|
||||||
|
assertTrue(testFactory.getMyStartRequested());
|
||||||
|
|
||||||
|
// Bring up wifi. The factory stops looking for a network.
|
||||||
|
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
|
||||||
|
testFactory.expectAddRequests(2); // Because the default request changes score twice.
|
||||||
|
mWiFiNetworkAgent.connect(true);
|
||||||
|
testFactory.waitForNetworkRequests(1);
|
||||||
|
assertFalse(testFactory.getMyStartRequested());
|
||||||
|
|
||||||
|
ContentResolver cr = mServiceContext.getContentResolver();
|
||||||
|
|
||||||
|
// Turn on mobile data always on. The factory starts looking again.
|
||||||
|
testFactory.expectAddRequests(1);
|
||||||
|
Settings.Global.putInt(cr, Settings.Global.MOBILE_DATA_ALWAYS_ON, 1);
|
||||||
|
mService.updateMobileDataAlwaysOn();
|
||||||
|
testFactory.waitForNetworkRequests(2);
|
||||||
|
assertTrue(testFactory.getMyStartRequested());
|
||||||
|
|
||||||
|
// Bring up cell data and check that the factory stops looking.
|
||||||
|
assertEquals(1, mCm.getAllNetworks().length);
|
||||||
|
mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
|
||||||
|
testFactory.expectAddRequests(2); // Because the cell request changes score twice.
|
||||||
|
mCellNetworkAgent.connect(true);
|
||||||
|
cellNetworkCallback.expectCallback(CallbackState.AVAILABLE);
|
||||||
|
testFactory.waitForNetworkRequests(2);
|
||||||
|
assertFalse(testFactory.getMyStartRequested()); // Because the cell network outscores us.
|
||||||
|
|
||||||
|
// Check that cell data stays up.
|
||||||
|
mService.waitForIdle();
|
||||||
|
verifyActiveNetwork(TRANSPORT_WIFI);
|
||||||
|
assertEquals(2, mCm.getAllNetworks().length);
|
||||||
|
|
||||||
|
// Turn off mobile data always on and expect the request to disappear...
|
||||||
|
testFactory.expectRemoveRequests(1);
|
||||||
|
Settings.Global.putInt(cr, Settings.Global.MOBILE_DATA_ALWAYS_ON, 0);
|
||||||
|
mService.updateMobileDataAlwaysOn();
|
||||||
|
testFactory.waitForNetworkRequests(1);
|
||||||
|
|
||||||
|
// ... and cell data to be torn down.
|
||||||
|
cellNetworkCallback.expectCallback(CallbackState.LOST);
|
||||||
|
assertEquals(1, mCm.getAllNetworks().length);
|
||||||
|
|
||||||
|
testFactory.unregister();
|
||||||
|
mCm.unregisterNetworkCallback(cellNetworkCallback);
|
||||||
|
handlerThread.quit();
|
||||||
|
}
|
||||||
|
|
||||||
private static class TestKeepaliveCallback extends PacketKeepaliveCallback {
|
private static class TestKeepaliveCallback extends PacketKeepaliveCallback {
|
||||||
|
|
||||||
public static enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
|
public static enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
|
||||||
|
|||||||
Reference in New Issue
Block a user