blob: a5fa8345febe1f2268b40951ef6b9940536f9277 [file] [log] [blame]
package com.android.clockwork.cellular;
import static com.android.clockwork.cellular.WearCellularMediator.ACTION_ESIM_TEST_MODE;
import static com.android.clockwork.cellular.WearCellularMediator.CELL_AUTO_OFF;
import static com.android.clockwork.cellular.WearCellularMediator.CELL_AUTO_ON;
import static com.android.clockwork.cellular.WearCellularMediator.ENABLE_CELLULAR_ON_BOOT_URI;
import static com.android.clockwork.cellular.WearCellularMediator.EXTRA_IN_ESIM_TEST_MODE;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyBoolean;
import static org.mockito.Mockito.anyLong;
import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.AlarmManager;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Handler;
import android.os.Message;
import android.provider.Settings;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.euicc.EuiccManager;
import android.util.Log;
import com.android.clockwork.common.DeviceEnableSetting;
import com.android.clockwork.common.ThermalEmergencyTracker;
import com.android.clockwork.common.ThermalEmergencyTracker.ThermalEmergencyMode;
import com.android.clockwork.connectivity.WearConnectivityPackageManager;
import com.android.clockwork.flags.BooleanFlag;
import com.android.clockwork.power.PowerTracker;
import com.android.ims.ImsManager;
import com.android.internal.telephony.IccCardConstants;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.TelephonyIntents;
import com.google.android.clockwork.signaldetector.SignalStateDetector;
import com.google.android.clockwork.signaldetector.SignalStateModel;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.LooperMode;
import org.robolectric.shadows.ShadowApplication;
import org.robolectric.shadows.ShadowLog;
import java.util.ArrayList;
import java.util.BitSet;
/** Test for {@link WearCellularMediator} */
@RunWith(RobolectricTestRunner.class)
@LooperMode(LooperMode.Mode.LEGACY)
public class WearCellularMediatorTest {
private static final String CELL_AUTO_SETTING_KEY = "clockwork_cell_auto_setting";
private static final Uri CELL_AUTO_SETTING_URI =
Settings.System.getUriFor(CELL_AUTO_SETTING_KEY);
private static final Uri CELL_ON_URI = Settings.Global.getUriFor(Settings.Global.CELL_ON);
final ShadowApplication shadowApplication = ShadowApplication.getInstance();
private final ArrayList<SubscriptionInfo> activeSubInfoList = new ArrayList<>();
@Captor
ArgumentCaptor<Message> msgCaptor;
@Captor
ArgumentCaptor<AlarmManager.OnAlarmListener> mAlarmListenerCaptor;
@Mock
Handler mockHandler;
@Mock
PowerTracker mockPowerTracker;
@Mock
DeviceEnableSetting mockDeviceEnableSetting;
@Mock
WearConnectivityPackageManager mockWearConnectivityPackageManager;
@Mock
BooleanFlag mockUserAbsentRadiosOffFlag;
@Mock
SignalStateDetector mMockSignalStateDetector;
@Mock
AlarmManager mockAlarmManager;
@Mock
TelephonyManager mockTelephonyManager;
@Mock
EuiccManager mockEuiccManager;
@Mock
SubscriptionManager mockSubscriptionManager;
@Mock
WearCellularMediatorSettings mockSettings;
@Mock
SubscriptionInfo mockEsimSubInfo;
@Mock
SubscriptionInfo mockPsimSubInfo;
@Mock
TwinnedNumberBlocker mTwinNumberBlocker;
@Mock ImsManager mImsManager;
private ContentResolver mContentResolver;
private Context mContext;
private WearCellularMediator mMediator;
private BitSet mBitSet;
@Before
public void setUp() {
ShadowLog.setLoggable("WearCellularMediator", Log.VERBOSE);
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mContentResolver = mContext.getContentResolver();
initMockSubscriptions();
when(mockSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn(activeSubInfoList);
when(mockSettings.isVoiceTwinningEnabled()).thenReturn(true);
when(mockSettings.isWearEsimDevice()).thenReturn(false);
when(mockSettings.getCellAutoSetting()).thenReturn(CELL_AUTO_ON);
when(mockSettings.getCellState()).thenReturn(PhoneConstants.CELL_ON_FLAG);
when(mockSettings.getRadioOnState()).thenReturn(
WearCellularMediator.RADIO_ON_STATE_UNKNOWN);
when(mockSettings.shouldTurnCellularOffDuringPowerSave()).thenReturn(true);
when(mockSettings.shouldTurnCellularOffWhenWifiConnected()).thenReturn(true);
when(mockSettings.getMobileSignalDetectorAllowed()).thenReturn(true);
when(mockPowerTracker.isInPowerSave()).thenReturn(false);
when(mockDeviceEnableSetting.affectsCellular()).thenReturn(true);
when(mockDeviceEnableSetting.isDeviceEnabled()).thenReturn(true);
when(mockUserAbsentRadiosOffFlag.isEnabled()).thenReturn(true);
when(mImsManager.isWfcEnabledByPlatform()).thenReturn(false);
when(mImsManager.isWfcEnabledByUser()).thenReturn(false);
when(mImsManager.isWfcProvisionedOnDevice()).thenReturn(false);
mMediator = new WearCellularMediator(
mContext,
mContentResolver,
mockAlarmManager,
mockTelephonyManager,
mockEuiccManager,
mockSubscriptionManager,
mockSettings,
mockPowerTracker,
mockDeviceEnableSetting,
mockWearConnectivityPackageManager,
mockUserAbsentRadiosOffFlag,
mMockSignalStateDetector,
mTwinNumberBlocker);
mMediator.mHandler = mockHandler;
mMediator.mImsManagerForTesting = mImsManager;
// disable cell lingering to allow easier testing for most test cases
mMediator.setCellLingerDuration(-999);
mMediator.onBootCompleted(true);
mMediator.onUserUnlocked();
when(mMockSignalStateDetector.isStarted()).thenReturn(true);
mBitSet = new BitSet(PowerTracker.MAX_DOZE_MODE_INDEX);
when(mockPowerTracker.getDozeModeAllowListedFeatures())
.thenReturn(mBitSet);
}
private void initMockSubscriptions() {
when(mockEsimSubInfo.isEmbedded()).thenReturn(true);
when(mockPsimSubInfo.isEmbedded()).thenReturn(false);
}
@Test
public void testOnBootComplete() {
assertEquals(0, Settings.Global.getInt(
mContentResolver, Settings.Global.ENABLE_CELLULAR_ON_BOOT, 1));
verify(mockUserAbsentRadiosOffFlag).addListener(any());
verifyPowerChange(WearCellularMediator.MSG_DISABLE_CELL,
WearCellularMediator.Reason.OFF_PROXY_CONNECTED);
}
@Test
public void testInitWithContext() {
verify(mockPowerTracker).addListener(mMediator);
assertTrue(shadowApplication.hasReceiverForIntent(
new Intent(WearCellularMediator.ACTION_SUBSCRIPTION_PHONE_STATE_CHANGED)));
assertTrue(shadowApplication.hasReceiverForIntent(
new Intent(WearCellularMediator.ACTION_EXIT_CELL_LINGER)));
assertTrue(shadowApplication.hasReceiverForIntent(
new Intent(ACTION_ESIM_TEST_MODE)));
assertTrue(shadowApplication.hasReceiverForIntent(
new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)));
}
@Test
public void testEnforceCellularOnBoot() {
Settings.Global.putInt(mContentResolver, Settings.Global.ENABLE_CELLULAR_ON_BOOT, 999);
mContentResolver.notifyChange(ENABLE_CELLULAR_ON_BOOT_URI, null);
assertEquals(0, Settings.Global.getInt(
mContentResolver, Settings.Global.ENABLE_CELLULAR_ON_BOOT, 1));
}
@Test
public void testTurnCellAutoOff() {
when(mockSettings.getCellAutoSetting()).thenReturn(CELL_AUTO_OFF);
mContentResolver.notifyChange(CELL_AUTO_SETTING_URI, null);
verifyPowerChange(WearCellularMediator.MSG_ENABLE_CELL,
WearCellularMediator.Reason.ON_NO_CELL_AUTO);
}
@Test
public void testHighBandwidthRequest() {
mMediator.updateNumHighBandwidthRequests(1);
verifyPowerChange(WearCellularMediator.MSG_ENABLE_CELL,
WearCellularMediator.Reason.ON_NETWORK_REQUEST);
}
@Test
public void testCellularTransportRequest() {
mMediator.updateNumCellularRequests(1);
verifyPowerChange(WearCellularMediator.MSG_ENABLE_CELL,
WearCellularMediator.Reason.ON_NETWORK_REQUEST);
// Going into power save mode should turn cell off.
when(mockPowerTracker.isInPowerSave()).thenReturn(true);
mMediator.onPowerSaveModeChanged();
verifyPowerChange(WearCellularMediator.MSG_DISABLE_CELL,
WearCellularMediator.Reason.OFF_POWER_SAVE);
}
@Test
public void testActivityMode() {
mMediator.updateNumCellularRequests(1);
verifyPowerChange(WearCellularMediator.MSG_ENABLE_CELL,
WearCellularMediator.Reason.ON_NETWORK_REQUEST);
mMediator.updateActivityMode(true);
verifyPowerChange(WearCellularMediator.MSG_DISABLE_CELL,
WearCellularMediator.Reason.OFF_ACTIVITY_MODE);
mMediator.updateActivityMode(false);
verifyPowerChange(WearCellularMediator.MSG_ENABLE_CELL,
WearCellularMediator.Reason.ON_NETWORK_REQUEST);
}
@Test
public void testActivityMode_cellOnNoAuto() {
when(mockSettings.getCellAutoSetting()).thenReturn(CELL_AUTO_OFF);
mMediator.onBootCompleted(true);
reset(mockHandler);
mMediator.updateActivityMode(true);
verifyPowerChange(WearCellularMediator.MSG_ENABLE_CELL,
WearCellularMediator.Reason.ON_NO_CELL_AUTO);
}
@Test
public void testThermalEmergencyDisablesCell() {
//set cell to known state
mMediator.updateNumCellularRequests(1);
verifyPowerChange(WearCellularMediator.MSG_ENABLE_CELL,
WearCellularMediator.Reason.ON_NETWORK_REQUEST);
mMediator.updateThermalEmergencyMode(
new ThermalEmergencyMode(ThermalEmergencyTracker.THERMAL_EMERGENCY_LEVEL_CELL));
verifyPowerChange(WearCellularMediator.MSG_DISABLE_CELL,
WearCellularMediator.Reason.OFF_THERMAL_EMERGENCY);
mMediator.updateThermalEmergencyMode(new ThermalEmergencyMode(0));
verifyPowerChange(WearCellularMediator.MSG_ENABLE_CELL,
WearCellularMediator.Reason.ON_NETWORK_REQUEST);
}
@Test
public void testDeviceIdleUserAbsent() {
mMediator.updateNumCellularRequests(1);
verifyPowerChange(WearCellularMediator.MSG_ENABLE_CELL,
WearCellularMediator.Reason.ON_NETWORK_REQUEST);
when(mockPowerTracker.isDeviceIdle()).thenReturn(true);
mMediator.onDeviceIdleModeChanged();
verifyPowerChange(WearCellularMediator.MSG_DISABLE_CELL,
WearCellularMediator.Reason.OFF_USER_ABSENT);
when(mockUserAbsentRadiosOffFlag.isEnabled()).thenReturn(false);
mMediator.onUserAbsentRadiosOffChanged(false);
verifyPowerChange(WearCellularMediator.MSG_ENABLE_CELL,
WearCellularMediator.Reason.ON_NETWORK_REQUEST);
when(mockPowerTracker.isDeviceIdle()).thenReturn(false);
mMediator.onDeviceIdleModeChanged();
verifyPowerChange(WearCellularMediator.MSG_ENABLE_CELL,
WearCellularMediator.Reason.ON_NETWORK_REQUEST);
when(mockPowerTracker.isDeviceIdle()).thenReturn(true);
mMediator.onDeviceIdleModeChanged();
verifyPowerChange(WearCellularMediator.MSG_ENABLE_CELL,
WearCellularMediator.Reason.ON_NETWORK_REQUEST);
when(mockUserAbsentRadiosOffFlag.isEnabled()).thenReturn(true);
mMediator.onUserAbsentRadiosOffChanged(true);
verifyPowerChange(WearCellularMediator.MSG_DISABLE_CELL,
WearCellularMediator.Reason.OFF_USER_ABSENT);
when(mockPowerTracker.isDeviceIdle()).thenReturn(false);
mMediator.onDeviceIdleModeChanged();
verifyPowerChange(WearCellularMediator.MSG_ENABLE_CELL,
WearCellularMediator.Reason.ON_NETWORK_REQUEST);
}
@Test
public void testReturnFromDeviceIdle() {
when(mockPowerTracker.isDeviceIdle()).thenReturn(true);
mMediator.onDeviceIdleModeChanged();
mMediator.onProxyConnectedChange(false);
reset(mockHandler); // reset tracking radio changes
when(mockPowerTracker.isDeviceIdle()).thenReturn(false);
mMediator.onDeviceIdleModeChanged();
// delay cell radio
verify(mockHandler, never()).sendMessage(any()); // no radio changes
verify(mockAlarmManager).set(eq(AlarmManager.ELAPSED_REALTIME),
anyLong(), anyString(), mAlarmListenerCaptor.capture(), eq(null));
mAlarmListenerCaptor.getValue().onAlarm();
verifyPowerChange(WearCellularMediator.MSG_ENABLE_CELL,
WearCellularMediator.Reason.ON_PROXY_DISCONNECTED);
}
@Test
public void testReturnFromDeviceIdleCancelDelay() {
when(mockPowerTracker.isDeviceIdle()).thenReturn(true);
mMediator.onDeviceIdleModeChanged();
mMediator.onProxyConnectedChange(false);
reset(mockHandler); // reset tracking radio changes
when(mockPowerTracker.isDeviceIdle()).thenReturn(false);
mMediator.onDeviceIdleModeChanged();
// delay entered
verify(mockAlarmManager).set(eq(AlarmManager.ELAPSED_REALTIME),
anyLong(), anyString(), mAlarmListenerCaptor.capture(), eq(null));
mMediator.onProxyConnectedChange(true); // Proxy was connected before idle
verify(mockAlarmManager).cancel(eq(mAlarmListenerCaptor.getValue()));
}
@Test
public void testBootCompletedAfterSimReady_ProxyDisconnected() {
reset(mockAlarmManager);
mMediator = new WearCellularMediator(
mContext,
mContentResolver,
mockAlarmManager,
mockTelephonyManager,
mockEuiccManager,
mockSubscriptionManager,
mockSettings,
mockPowerTracker,
mockDeviceEnableSetting,
mockWearConnectivityPackageManager,
mockUserAbsentRadiosOffFlag,
mMockSignalStateDetector,
mTwinNumberBlocker);
mMediator.mHandler = mockHandler;
when(mockSettings.isWearEsimDevice()).thenReturn(true);
when(mockSettings.isEsimProfileDeactivated()).thenReturn(false);
Intent simIntent = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
simIntent.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE,
IccCardConstants.INTENT_VALUE_ICC_LOADED);
mContext.sendBroadcast(simIntent);
reset(mockHandler); // reset tracking radio changes
// assert cell radio delayed
doAnswer(invocation -> {
Message message = invocation.getArgument(0);
assertTrue(message.what != WearCellularMediator.MSG_ENABLE_CELL);
return null;
}).when(mockHandler).sendMessage(any());
mMediator.onBootCompleted(false);
mMediator.onUserUnlocked();
verify(mockAlarmManager).set(eq(AlarmManager.ELAPSED_REALTIME),
anyLong(), anyString(), mAlarmListenerCaptor.capture(), eq(null));
reset(mockHandler);
mAlarmListenerCaptor.getValue().onAlarm();
verifyPowerChange(WearCellularMediator.MSG_ENABLE_CELL,
WearCellularMediator.Reason.ON_PROXY_DISCONNECTED);
}
@Test
public void testBootCompleted_cellOn() {
when(mockSettings.getCellAutoSetting()).thenReturn(CELL_AUTO_OFF);
when(mockSettings.isWearEsimDevice()).thenReturn(true);
reset(mockHandler);
mMediator.onBootCompleted(false);
when(mockSettings.isEsimProfileDeactivated()).thenReturn(false);
Intent simIntent = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
simIntent.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE,
IccCardConstants.INTENT_VALUE_ICC_LOADED);
mContext.sendBroadcast(simIntent);
verifyPowerChange(WearCellularMediator.MSG_ENABLE_CELL,
WearCellularMediator.Reason.ON_NO_CELL_AUTO);
}
@Test
public void testDeviceIdleAllowListedFeature() {
mMediator.updateNumCellularRequests(1);
mBitSet.set(PowerTracker.DOZE_MODE_CELLULAR_INDEX);
verifyPowerChange(WearCellularMediator.MSG_ENABLE_CELL,
WearCellularMediator.Reason.ON_NETWORK_REQUEST);
verify(mockHandler, atLeastOnce()).sendMessage(msgCaptor.capture());
reset(mockHandler);
when(mockPowerTracker.isDeviceIdle()).thenReturn(true);
mMediator.onDeviceIdleModeChanged();
verify(mockHandler, never()).sendMessage(msgCaptor.capture());
}
@Test
public void testDeviceIdleBlockListedFeature() {
mMediator.updateNumCellularRequests(1);
verifyPowerChange(WearCellularMediator.MSG_ENABLE_CELL,
WearCellularMediator.Reason.ON_NETWORK_REQUEST);
when(mockPowerTracker.isDeviceIdle()).thenReturn(true);
mMediator.onDeviceIdleModeChanged();
verifyPowerChange(WearCellularMediator.MSG_DISABLE_CELL,
WearCellularMediator.Reason.OFF_USER_ABSENT);
}
@Test
public void testInPhoneCall() {
Intent intent = new Intent(WearCellularMediator.ACTION_SUBSCRIPTION_PHONE_STATE_CHANGED);
intent.putExtra(TelephonyManager.EXTRA_STATE, TelephonyManager.EXTRA_STATE_OFFHOOK);
mContext.sendBroadcast(intent);
verifyPowerChange(WearCellularMediator.MSG_ENABLE_CELL,
WearCellularMediator.Reason.ON_PHONE_CALL);
}
@Test
public void testEsimTestMode() {
when(mockSettings.isWearEsimDevice()).thenReturn(true);
Intent intent = new Intent(ACTION_ESIM_TEST_MODE);
intent.putExtra(EXTRA_IN_ESIM_TEST_MODE, true);
mContext.sendBroadcast(intent);
verifyPowerChange(WearCellularMediator.MSG_ENABLE_CELL,
WearCellularMediator.Reason.ON_ESIM_TEST_MODE);
}
@Test
public void testProxyDisconnect() {
mMediator.onProxyConnectedChange(false);
verifyPowerChange(WearCellularMediator.MSG_ENABLE_CELL,
WearCellularMediator.Reason.ON_PROXY_DISCONNECTED);
}
@Test
public void testProxyDisconnect_EsimDevice_Present() {
activeSubInfoList.add(mockEsimSubInfo);
mMediator.updateActiveEsimSubscriptionStatus();
when(mockSettings.isWearEsimDevice()).thenReturn(true);
when(mockSettings.isEsimProfileDeactivated()).thenReturn(false);
Intent simIntent = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
simIntent.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE,
IccCardConstants.INTENT_VALUE_ICC_LOADED);
mContext.sendBroadcast(simIntent);
mContentResolver.notifyChange(
WearCellularMediatorSettings.ESIM_PROFILE_ACTIVATION_SETTING_URI, null);
mMediator.onProxyConnectedChange(false);
verifyPowerChange(WearCellularMediator.MSG_ENABLE_CELL,
WearCellularMediator.Reason.ON_PROXY_DISCONNECTED);
}
@Test
public void testProxyDisconnect_EsimDevice_PresentButDeactivated() {
activeSubInfoList.add(mockEsimSubInfo);
mMediator.updateActiveEsimSubscriptionStatus();
when(mockSettings.isWearEsimDevice()).thenReturn(true);
when(mockSettings.isEsimProfileDeactivated()).thenReturn(true);
mContentResolver.notifyChange(
WearCellularMediatorSettings.ESIM_PROFILE_ACTIVATION_SETTING_URI, null);
mMediator.onProxyConnectedChange(false);
verifyPowerChange(WearCellularMediator.MSG_DISABLE_CELL,
WearCellularMediator.Reason.OFF_ESIM_DEACTIVATED);
}
@Test
public void testProxyDisconnect_EsimDevice_NoEsimOrPsimInstalled() {
when(mockSettings.isWearEsimDevice()).thenReturn(true);
when(mockSettings.isEsimProfileDeactivated()).thenReturn(false);
Intent simIntent = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
simIntent.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE,
IccCardConstants.INTENT_VALUE_ICC_ABSENT);
mContext.sendBroadcast(simIntent);
mMediator.onProxyConnectedChange(false);
verifyPowerChange(WearCellularMediator.MSG_DISABLE_CELL,
WearCellularMediator.Reason.OFF_SIM_ABSENT);
}
@Test
public void testProxyDisconnect_EsimDevice_NoEsimOrPsimInstalled_cellOn() {
when(mockSettings.getCellAutoSetting()).thenReturn(CELL_AUTO_OFF);
when(mockSettings.isWearEsimDevice()).thenReturn(true);
mMediator.onBootCompleted(false);
reset(mockHandler);
when(mockSettings.isEsimProfileDeactivated()).thenReturn(false);
Intent simIntent = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
simIntent.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE,
IccCardConstants.INTENT_VALUE_ICC_ABSENT);
mContext.sendBroadcast(simIntent);
mMediator.onProxyConnectedChange(false);
verifyPowerChange(WearCellularMediator.MSG_ENABLE_CELL,
WearCellularMediator.Reason.ON_NO_CELL_AUTO);
}
@Test
public void testProxyDisconnect_EsimDevice_NoEsimAndPsimNotReady() {
when(mockSettings.isWearEsimDevice()).thenReturn(true);
when(mockSettings.isEsimProfileDeactivated()).thenReturn(false);
Intent simIntent = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
simIntent.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE,
IccCardConstants.INTENT_VALUE_ICC_NOT_READY);
mContext.sendBroadcast(simIntent);
mMediator.onProxyConnectedChange(false);
verifyPowerChange(WearCellularMediator.MSG_DISABLE_CELL,
WearCellularMediator.Reason.OFF_SIM_ABSENT);
}
@Test
public void testProxyDisconnect_EsimDevice_NoEsimAndPsimUnknown() {
when(mockSettings.isWearEsimDevice()).thenReturn(true);
when(mockSettings.isEsimProfileDeactivated()).thenReturn(false);
Intent simIntent = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
simIntent.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE,
IccCardConstants.INTENT_VALUE_ICC_UNKNOWN);
mContext.sendBroadcast(simIntent);
mMediator.onProxyConnectedChange(false);
verifyPowerChange(WearCellularMediator.MSG_DISABLE_CELL,
WearCellularMediator.Reason.OFF_SIM_ABSENT);
}
@Test
public void testProxyDisconnect_EsimDevice_PsimInstalledButNoEsim() {
when(mockSettings.isWearEsimDevice()).thenReturn(true);
when(mockSettings.isEsimProfileDeactivated()).thenReturn(false);
Intent simIntent = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
simIntent.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE,
IccCardConstants.INTENT_VALUE_ICC_READY);
mContext.sendBroadcast(simIntent);
mMediator.onProxyConnectedChange(false);
verifyPowerChange(WearCellularMediator.MSG_ENABLE_CELL,
WearCellularMediator.Reason.ON_PROXY_DISCONNECTED);
}
@Test
public void testProxyDisconnect_EsimDevice_EsimInstalledButNoPsim() {
activeSubInfoList.add(mockPsimSubInfo);
activeSubInfoList.add(mockEsimSubInfo);
mMediator.updateActiveEsimSubscriptionStatus();
when(mockSettings.isWearEsimDevice()).thenReturn(true);
when(mockSettings.isEsimProfileDeactivated()).thenReturn(false);
Intent simIntent = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
simIntent.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE,
IccCardConstants.INTENT_VALUE_ICC_ABSENT);
mContext.sendBroadcast(simIntent);
mMediator.onProxyConnectedChange(false);
verifyPowerChange(WearCellularMediator.MSG_ENABLE_CELL,
WearCellularMediator.Reason.ON_PROXY_DISCONNECTED);
}
@Test
public void testProxyDisconnect_EsimDevice_OnlyDeletedSubscriptionsPresent() {
activeSubInfoList.add(mockPsimSubInfo);
mMediator.updateActiveEsimSubscriptionStatus();
when(mockSettings.isWearEsimDevice()).thenReturn(true);
when(mockSettings.isEsimProfileDeactivated()).thenReturn(false);
Intent simIntent = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
simIntent.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE,
IccCardConstants.INTENT_VALUE_ICC_ABSENT);
mContext.sendBroadcast(simIntent);
mMediator.onProxyConnectedChange(false);
verifyPowerChange(WearCellularMediator.MSG_DISABLE_CELL,
WearCellularMediator.Reason.OFF_SIM_ABSENT);
}
/**
* As of b/243985741, mediator behavior no longer changes when voice twinning changes.
*/
@Test
public void testToggleVoiceTwinning_DoesNothing() {
when(mockSettings.isVoiceTwinningEnabled()).thenReturn(false);
mContentResolver.notifyChange(
WearCellularMediatorSettings.VOICE_TWINNING_SETTING_URI, null);
verify(mockSettings, never()).setCellAutoSetting(CELL_AUTO_OFF);
verify(mockSettings, never()).setCellAutoSetting(CELL_AUTO_ON);
reset(mockSettings);
when(mockSettings.isVoiceTwinningEnabled()).thenReturn(true);
mContentResolver.notifyChange(
WearCellularMediatorSettings.VOICE_TWINNING_SETTING_URI, null);
verify(mockSettings, never()).setCellAutoSetting(CELL_AUTO_OFF);
verify(mockSettings, never()).setCellAutoSetting(CELL_AUTO_ON);
}
@Test
public void testTurnCellStateOff() {
// Turn radio on first.
mMediator.onProxyConnectedChange(false);
reset(mockTelephonyManager);
when(mockSettings.getCellState()).thenReturn(PhoneConstants.CELL_OFF_FLAG);
mContentResolver.notifyChange(WearCellularMediator.CELL_ON_URI, null);
verifyPowerChange(WearCellularMediator.MSG_DISABLE_CELL,
WearCellularMediator.Reason.OFF_CELL_SETTING);
// Cell radio stays off even if proxy disconnect.
mMediator.onProxyConnectedChange(false);
verifyPowerChange(WearCellularMediator.MSG_DISABLE_CELL,
WearCellularMediator.Reason.OFF_CELL_SETTING);
// Cell radio stays off even if network request.
mMediator.updateNumHighBandwidthRequests(1);
mMediator.updateNumCellularRequests(1);
verifyPowerChange(WearCellularMediator.MSG_DISABLE_CELL,
WearCellularMediator.Reason.OFF_CELL_SETTING);
// Cell radio should be turned on if in call broadcast received.
Intent intent = new Intent(WearCellularMediator.ACTION_SUBSCRIPTION_PHONE_STATE_CHANGED);
intent.putExtra(TelephonyManager.EXTRA_STATE, TelephonyManager.EXTRA_STATE_OFFHOOK);
mContext.sendBroadcast(intent);
verifyPowerChange(WearCellularMediator.MSG_ENABLE_CELL,
WearCellularMediator.Reason.ON_PHONE_CALL);
}
@Test
public void testInPowerSave() {
// Turn radio on first.
mMediator.onProxyConnectedChange(false);
when(mockPowerTracker.isInPowerSave()).thenReturn(true);
mMediator.onPowerSaveModeChanged();
verifyPowerChange(WearCellularMediator.MSG_DISABLE_CELL,
WearCellularMediator.Reason.OFF_POWER_SAVE);
// But the incall broadcast should turn it back on.
Intent intent = new Intent(WearCellularMediator.ACTION_SUBSCRIPTION_PHONE_STATE_CHANGED);
intent.putExtra(TelephonyManager.EXTRA_STATE, TelephonyManager.EXTRA_STATE_OFFHOOK);
mContext.sendBroadcast(intent);
verifyPowerChange(WearCellularMediator.MSG_ENABLE_CELL,
WearCellularMediator.Reason.ON_PHONE_CALL);
}
@Test
public void testInPowerSave_CellOnNoAuto() {
when(mockSettings.getCellAutoSetting()).thenReturn(CELL_AUTO_OFF);
mMediator.onBootCompleted(true);
when(mockPowerTracker.isInPowerSave()).thenReturn(true);
reset(mockHandler);
mMediator.onPowerSaveModeChanged();
verifyPowerChange(WearCellularMediator.MSG_ENABLE_CELL,
WearCellularMediator.Reason.ON_NO_CELL_AUTO);
}
@Test
public void tesCellularOffDuringPowerSaveSettingIsFalse() {
// Turn radio on first.
mMediator.onProxyConnectedChange(false);
when(mockSettings.shouldTurnCellularOffDuringPowerSave()).thenReturn(false);
when(mockPowerTracker.isInPowerSave()).thenReturn(true);
mMediator.onPowerSaveModeChanged();
// Because power save change should have been ignored, last change should have been due to
// proxy disconnecting.
verifyPowerChange(WearCellularMediator.MSG_ENABLE_CELL,
WearCellularMediator.Reason.ON_PROXY_DISCONNECTED);
}
@Test
public void testSimCardAbsent() {
// Turn radio on first.
mMediator.onProxyConnectedChange(false);
reset(mockTelephonyManager);
Intent simIntent = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
simIntent.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE,
IccCardConstants.INTENT_VALUE_ICC_ABSENT);
mContext.sendBroadcast(simIntent);
verifyPowerChange(WearCellularMediator.MSG_DISABLE_CELL,
WearCellularMediator.Reason.OFF_SIM_ABSENT);
// Incall broadcast should turn it back on.
Intent intent = new Intent(WearCellularMediator.ACTION_SUBSCRIPTION_PHONE_STATE_CHANGED);
intent.putExtra(TelephonyManager.EXTRA_STATE, TelephonyManager.EXTRA_STATE_OFFHOOK);
mContext.sendBroadcast(intent);
verifyPowerChange(WearCellularMediator.MSG_ENABLE_CELL,
WearCellularMediator.Reason.ON_PHONE_CALL);
}
@Test
public void testEsimInitialBoot_noIccState_radioOff() {
when(mockSettings.isWearEsimDevice()).thenReturn(true);
// Turn radio on first.
mMediator.onProxyConnectedChange(false);
Intent simIntent = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
simIntent.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE,
WearCellularMediator.ICC_WEAR_INITIAL_BOOT);
mContext.sendBroadcast(simIntent);
verifyPowerChange(WearCellularMediator.MSG_DISABLE_CELL,
WearCellularMediator.Reason.OFF_INITIAL_BOOT);
}
@Test
public void testEsimInitialBoot_noIccState_cellOn() {
when(mockSettings.getCellAutoSetting()).thenReturn(CELL_AUTO_OFF);
when(mockSettings.isWearEsimDevice()).thenReturn(true);
mMediator.onBootCompleted(true);
reset(mockHandler);
Intent simIntent = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
simIntent.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE,
WearCellularMediator.ICC_WEAR_INITIAL_BOOT);
mContext.sendBroadcast(simIntent);
verifyPowerChange(WearCellularMediator.MSG_ENABLE_CELL,
WearCellularMediator.Reason.ON_NO_CELL_AUTO);
}
@Test
public void testDeviceDisabled_cellularNotAffected() {
when(mockDeviceEnableSetting.affectsCellular()).thenReturn(false);
when(mockDeviceEnableSetting.isDeviceEnabled()).thenReturn(false);
mMediator.onDeviceEnableChanged();
verify(mockTelephonyManager, never()).setRadioPower(anyBoolean());
mMediator.onProxyConnectedChange(false);
verifyPowerChange(WearCellularMediator.MSG_ENABLE_CELL,
WearCellularMediator.Reason.ON_PROXY_DISCONNECTED);
verify(mockTelephonyManager, never()).setRadioPower(anyBoolean());
}
@Test
public void testDeviceDisabled_thenProxyDisconnect() {
when(mockDeviceEnableSetting.isDeviceEnabled()).thenReturn(false);
mMediator.onDeviceEnableChanged();
verifyPowerChange(WearCellularMediator.MSG_DISABLE_CELL,
WearCellularMediator.Reason.OFF_DEVICE_DISABLED);
mMediator.onProxyConnectedChange(false);
verifyPowerChange(WearCellularMediator.MSG_DISABLE_CELL,
WearCellularMediator.Reason.OFF_DEVICE_DISABLED);
verify(mockTelephonyManager, never()).setRadioPower(anyBoolean());
}
@Test
public void testProxyDisconnect_thenDeviceDisabled() {
mMediator.onProxyConnectedChange(false);
verifyPowerChange(WearCellularMediator.MSG_ENABLE_CELL,
WearCellularMediator.Reason.ON_PROXY_DISCONNECTED);
when(mockDeviceEnableSetting.isDeviceEnabled()).thenReturn(false);
mMediator.onDeviceEnableChanged();
verifyPowerChange(WearCellularMediator.MSG_DISABLE_CELL,
WearCellularMediator.Reason.OFF_DEVICE_DISABLED);
when(mockDeviceEnableSetting.isDeviceEnabled()).thenReturn(true);
mMediator.onDeviceEnableChanged();
verifyPowerChange(WearCellularMediator.MSG_ENABLE_CELL,
WearCellularMediator.Reason.ON_PROXY_DISCONNECTED);
}
@Test
public void testProxyDisconnect_thenWifiConnectChange() {
mMediator.onProxyConnectedChange(false);
verifyPowerChange(
WearCellularMediator.MSG_ENABLE_CELL,
WearCellularMediator.Reason.ON_PROXY_DISCONNECTED);
// Radio turned off when Wifi connected.
mMediator.onWifiConnectedChange(true);
verifyPowerChange(
WearCellularMediator.MSG_DISABLE_CELL,
WearCellularMediator.Reason.OFF_WIFI_CONNECTED);
// Radio turned back on when Wifi disconnected.
mMediator.onWifiConnectedChange(false);
verifyPowerChange(
WearCellularMediator.MSG_ENABLE_CELL,
WearCellularMediator.Reason.ON_PROXY_DISCONNECTED);
}
@Test
public void testWifiConnect_thenProxyDisconnect() {
mMediator.onWifiConnectedChange(true);
verifyPowerChange(
WearCellularMediator.MSG_DISABLE_CELL,
WearCellularMediator.Reason.OFF_PROXY_CONNECTED);
// Radio is kept off since Wifi is still connected.
mMediator.onProxyConnectedChange(false);
verifyPowerChange(
WearCellularMediator.MSG_DISABLE_CELL,
WearCellularMediator.Reason.OFF_WIFI_CONNECTED);
// Radio turned on when Wifi disconnected.
mMediator.onWifiConnectedChange(false);
verifyPowerChange(
WearCellularMediator.MSG_ENABLE_CELL,
WearCellularMediator.Reason.ON_PROXY_DISCONNECTED);
}
@Test
public void testWifiConnect_cellularMediatingOff_doesNothing() {
// Disable the mediating behavior.
when(mockSettings.shouldTurnCellularOffWhenWifiConnected()).thenReturn(false);
mMediator.onProxyConnectedChange(false);
verifyPowerChange(
WearCellularMediator.MSG_ENABLE_CELL,
WearCellularMediator.Reason.ON_PROXY_DISCONNECTED);
// Radio is kept on since the flag is disabled.
mMediator.onWifiConnectedChange(true);
verifyPowerChange(
WearCellularMediator.MSG_ENABLE_CELL,
WearCellularMediator.Reason.ON_PROXY_DISCONNECTED);
// Radio is kept on since the flag is disabled.
mMediator.onWifiConnectedChange(false);
verifyPowerChange(
WearCellularMediator.MSG_ENABLE_CELL,
WearCellularMediator.Reason.ON_PROXY_DISCONNECTED);
}
@Test
public void testWifiConnect_noActiveVoWifi_doesNothing() {
// Disable per device flag to test VoWIFI enabled status.
when(mockSettings.shouldTurnCellularOffWhenWifiConnected()).thenReturn(false);
mMediator.onProxyConnectedChange(false);
verifyPowerChange(
WearCellularMediator.MSG_ENABLE_CELL,
WearCellularMediator.Reason.ON_PROXY_DISCONNECTED);
// Radio is kept on since per device flag is disabled and VoWIFI is not yet active.
mMediator.onWifiConnectedChange(true);
verifyPowerChange(
WearCellularMediator.MSG_ENABLE_CELL,
WearCellularMediator.Reason.ON_PROXY_DISCONNECTED);
}
@Test
public void testVoWifiActive_thenWifiConnected() {
// Disable per device flag to test VoWIFI enabled status.
when(mockSettings.shouldTurnCellularOffWhenWifiConnected()).thenReturn(false);
when(mImsManager.isWfcEnabledByPlatform()).thenReturn(true);
when(mImsManager.isWfcEnabledByUser()).thenReturn(true);
when(mImsManager.isWfcProvisionedOnDevice()).thenReturn(true);
activeSubInfoList.add(mockEsimSubInfo);
mMediator.updateActiveEsimSubscriptionStatus();
mMediator.onProxyConnectedChange(false);
verifyPowerChange(
WearCellularMediator.MSG_ENABLE_CELL,
WearCellularMediator.Reason.ON_PROXY_DISCONNECTED);
// Radio is turned off since VoWIFI is active and WIFI is connected now.
mMediator.onWifiConnectedChange(true);
verifyPowerChange(
WearCellularMediator.MSG_DISABLE_CELL,
WearCellularMediator.Reason.OFF_WIFI_CONNECTED);
}
@Test
public void testDeviceDisabled_onBoot() {
mMediator = new WearCellularMediator(
mContext,
mContentResolver,
mockAlarmManager,
mockTelephonyManager,
mockEuiccManager,
mockSubscriptionManager,
mockSettings,
mockPowerTracker,
mockDeviceEnableSetting,
mockWearConnectivityPackageManager,
mockUserAbsentRadiosOffFlag,
mMockSignalStateDetector,
mTwinNumberBlocker);
mMediator.mHandler = mockHandler;
// Disable the device.
when(mockDeviceEnableSetting.isDeviceEnabled()).thenReturn(false);
// disable cell lingering to allow easier testing for most test cases
mMediator.setCellLingerDuration(-999);
mMediator.onBootCompleted(false);
mMediator.onUserUnlocked();
verifyPowerChange(WearCellularMediator.MSG_DISABLE_CELL,
WearCellularMediator.Reason.OFF_DEVICE_DISABLED);
verify(mockTelephonyManager, never()).setRadioPower(anyBoolean());
// Enabling the device should allow the radio to come on again.
when(mockDeviceEnableSetting.isDeviceEnabled()).thenReturn(true);
mMediator.onDeviceEnableChanged();
verifyPowerChange(WearCellularMediator.MSG_ENABLE_CELL,
WearCellularMediator.Reason.ON_PROXY_DISCONNECTED);
}
@Test
public void testGetRadioOnState() {
reset(mockTelephonyManager);
// We replaced mMediator.mHandler in setUp() so instantiate it again here so that we can
// test the getRadioOnState() in the real Handler.
mMediator = new WearCellularMediator(
mContext,
mockAlarmManager,
mockTelephonyManager,
mockEuiccManager,
mockSubscriptionManager,
mockSettings,
mockPowerTracker,
mockDeviceEnableSetting,
mockWearConnectivityPackageManager,
mockUserAbsentRadiosOffFlag);
Message simAbsentMsg = Message.obtain(mMediator.mHandler,
WearCellularMediator.MSG_DISABLE_CELL,
new WearCellularMediator.RadioStateChangeReqInfo(
WearCellularMediator.Reason.OFF_SIM_ABSENT,
WearCellularMediator.TriggerEvent.SIM_STATE_CHANGED));
mMediator.mHandler.handleMessage(simAbsentMsg);
verify(mockWearConnectivityPackageManager).onCellularRadioState(false);
verify(mockTelephonyManager).setRadioPower(false);
verifyLatestDecision(WearCellularMediator.Reason.OFF_SIM_ABSENT);
}
@Test
public void testOnSignalStateChanged_noProxy_noSignal() {
mMediator.onProxyConnectedChange(false);
reset(mockHandler);
mMediator.onSignalStateChanged(SignalStateModel.STATE_NO_SIGNAL);
verifyPowerChange(WearCellularMediator.MSG_DISABLE_CELL,
WearCellularMediator.Reason.OFF_NO_SIGNAL);
}
@Test
public void testNoSignalWithProxyConnected_disablesRadio() {
mMediator.onSignalStateChanged(SignalStateModel.STATE_NO_SIGNAL);
verifyPowerChange(WearCellularMediator.MSG_DISABLE_CELL,
WearCellularMediator.Reason.OFF_NO_SIGNAL);
}
@Test
public void testUnstableSignalWithProxyConnected_disablesRadio() {
mMediator.onSignalStateChanged(SignalStateModel.STATE_UNSTABLE_SIGNAL);
verifyPowerChange(WearCellularMediator.MSG_DISABLE_CELL,
WearCellularMediator.Reason.OFF_UNSTABLE_SIGNAL);
}
@Test
public void testUnstableSignal_cellOnNoAuto() {
when(mockSettings.getCellAutoSetting()).thenReturn(CELL_AUTO_OFF);
mMediator.onBootCompleted(true);
reset(mockHandler);
mMediator.onSignalStateChanged(SignalStateModel.STATE_UNSTABLE_SIGNAL);
verifyPowerChange(WearCellularMediator.MSG_ENABLE_CELL,
WearCellularMediator.Reason.ON_NO_CELL_AUTO);
}
@Test
public void testNoSignal_cellOnNoAuto() {
when(mockSettings.getCellAutoSetting()).thenReturn(CELL_AUTO_OFF);
mMediator.onBootCompleted(true);
reset(mockHandler);
mMediator.onSignalStateChanged(SignalStateModel.STATE_NO_SIGNAL);
verifyPowerChange(WearCellularMediator.MSG_ENABLE_CELL,
WearCellularMediator.Reason.ON_NO_CELL_AUTO);
}
@Test
public void testDetectorDisallowed_stopsDetector() {
when(mockSettings.getMobileSignalDetectorAllowed()).thenReturn(false);
mContentResolver.notifyChange(WearCellularMediator.MOBILE_SIGNAL_DETECTOR_URI, null);
verify(mMockSignalStateDetector).stopDetector();
}
@Test
public void testChangesBeforeBootDoNothing() {
// Reinstantiate so we can test without boot completed
mMediator = new WearCellularMediator(
mContext,
mContentResolver,
mockAlarmManager,
mockTelephonyManager,
mockEuiccManager,
mockSubscriptionManager,
mockSettings,
mockPowerTracker,
mockDeviceEnableSetting,
mockWearConnectivityPackageManager,
mockUserAbsentRadiosOffFlag,
mMockSignalStateDetector,
mTwinNumberBlocker);
// Disable cell linger for simpler verification
mMediator.setCellLingerDuration(-999L);
mMediator.mHandler = mockHandler;
reset(mockHandler);
// Poke at the various settings, ensure never trying to update state
mMediator.onProxyConnectedChange(false);
verify(mockHandler, never()).sendMessage(msgCaptor.capture());
mMediator.onProxyConnectedChange(true);
verify(mockHandler, never()).sendMessage(msgCaptor.capture());
mMediator.updateNumHighBandwidthRequests(1);
mMediator.updateNumCellularRequests(1);
verify(mockHandler, never()).sendMessage(msgCaptor.capture());
mMediator.updateNumHighBandwidthRequests(0);
mMediator.updateNumCellularRequests(0);
verify(mockHandler, never()).sendMessage(msgCaptor.capture());
mMediator.onDeviceEnableChanged();
verify(mockHandler, never()).sendMessage(msgCaptor.capture());
mMediator.onBootCompleted(true);
mMediator.onUserUnlocked();
// Verify state changes occur after boot completed
verifyPowerChange(WearCellularMediator.MSG_DISABLE_CELL,
WearCellularMediator.Reason.OFF_PROXY_CONNECTED);
}
@Test
public void testDirectBoot_proxyDisconnected() {
// Reinstantiate so we can test without boot completed
mMediator = new WearCellularMediator(
mContext,
mContentResolver,
mockAlarmManager,
mockTelephonyManager,
mockEuiccManager,
mockSubscriptionManager,
mockSettings,
mockPowerTracker,
mockDeviceEnableSetting,
mockWearConnectivityPackageManager,
mockUserAbsentRadiosOffFlag,
mMockSignalStateDetector,
mTwinNumberBlocker);
// Disable cell linger for simpler verification
mMediator.setCellLingerDuration(-999L);
mMediator.mHandler = mockHandler;
reset(mockHandler);
mMediator.onBootCompleted(false);
mMediator.onProxyConnectedChange(false);
// Verify state changes occur after boot completed
verifyPowerChange(WearCellularMediator.MSG_DISABLE_CELL,
WearCellularMediator.Reason.OFF_DIRECTBOOT);
}
@Test
public void testCellLingerWhenProxyConnected() {
mMediator.setCellLingerDuration(5000L);
reset(mockHandler);
mMediator.onProxyConnectedChange(true);
// verify that instead of toggling cell directly, we set an alarm to do so
verify(mockHandler, never()).sendMessage(msgCaptor.capture());
verify(mockAlarmManager).setWindow(eq(AlarmManager.ELAPSED_REALTIME),
anyLong(), anyLong(), eq(mMediator.exitCellLingerIntent));
// when the alarm hits, then we turn off the radio
mContext.sendBroadcast(new Intent(WearCellularMediator.ACTION_EXIT_CELL_LINGER));
verifyPowerChange(WearCellularMediator.MSG_DISABLE_CELL,
WearCellularMediator.Reason.OFF_PROXY_CONNECTED);
}
/**
* Even if we might turn on the radio for other reasons, if the reason we're keeping the
* radio off reduces to PROXY_CONNECTED, then lingering is enforced by implication.
*/
@Test
public void testImpliedCellLingering() {
mMediator.onProxyConnectedChange(true);
reset(mockHandler);
mMediator.setCellLingerDuration(5000L);
mMediator.updateNumCellularRequests(1);
verifyPowerChange(WearCellularMediator.MSG_ENABLE_CELL,
WearCellularMediator.Reason.ON_NETWORK_REQUEST);
reset(mockHandler);
mMediator.updateNumCellularRequests(0);
verify(mockHandler, never()).sendMessage(msgCaptor.capture());
verify(mockAlarmManager).setWindow(eq(AlarmManager.ELAPSED_REALTIME),
anyLong(), anyLong(), eq(mMediator.exitCellLingerIntent));
// when the alarm hits, then we turn off the radio
mContext.sendBroadcast(new Intent(WearCellularMediator.ACTION_EXIT_CELL_LINGER));
verifyPowerChange(WearCellularMediator.MSG_DISABLE_CELL,
WearCellularMediator.Reason.OFF_PROXY_CONNECTED);
}
@Test
public void testCellLingerOnlySetsOneAlarm() {
mMediator.setCellLingerDuration(5000L);
reset(mockHandler);
// call update a few times in a row
mMediator.onProxyConnectedChange(true);
mMediator.onProxyConnectedChange(true);
mMediator.onProxyConnectedChange(true);
mMediator.onProxyConnectedChange(true);
verify(mockAlarmManager, times(1)).setWindow(eq(AlarmManager.ELAPSED_REALTIME),
anyLong(), anyLong(), eq(mMediator.exitCellLingerIntent));
// but after the alarm hits, we can set another one again (but only one)
mContext.sendBroadcast(new Intent(WearCellularMediator.ACTION_EXIT_CELL_LINGER));
mMediator.onProxyConnectedChange(true);
mMediator.onProxyConnectedChange(true);
mMediator.onProxyConnectedChange(true);
verify(mockAlarmManager, times(2)).setWindow(eq(AlarmManager.ELAPSED_REALTIME),
anyLong(), anyLong(), eq(mMediator.exitCellLingerIntent));
}
private void verifyLatestDecision(WearCellularMediator.Reason reason) {
assertEquals(reason, mMediator.getDecisionHistory().getMostRecentEvent().reason);
}
private void verifyPowerChange(int what, WearCellularMediator.Reason reason) {
verify(mockHandler, atLeastOnce()).sendMessage(msgCaptor.capture());
WearCellularMediator.Reason r;
r = ((WearCellularMediator.RadioStateChangeReqInfo) msgCaptor.getValue().obj).mReason;
assertEquals("Failure reason: " + r.name(), what, msgCaptor.getValue().what);
assertEquals(reason, r);
}
}