blob: 89f34c471afd4ce103d9425ac0230a1d0a19593b [file] [log] [blame]
/*
* Copyright (C) 2009 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 android.telephony.cts;
import static androidx.test.InstrumentationRegistry.getContext;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import android.annotation.NonNull;
import android.content.Context;
import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.telephony.Annotation.RadioPowerState;
import android.telephony.Annotation.SimActivationState;
import android.telephony.BarringInfo;
import android.telephony.CellIdentity;
import android.telephony.CellInfo;
import android.telephony.CellLocation;
import android.telephony.LinkCapacityEstimate;
import android.telephony.NetworkRegistrationInfo;
import android.telephony.PhysicalChannelConfig;
import android.telephony.PreciseCallState;
import android.telephony.PreciseDataConnectionState;
import android.telephony.ServiceState;
import android.telephony.SignalStrength;
import android.telephony.SmsManager;
import android.telephony.TelephonyCallback;
import android.telephony.TelephonyDisplayInfo;
import android.telephony.TelephonyManager;
import android.telephony.TelephonyManager.DataEnabledReason;
import android.telephony.emergency.EmergencyNumber;
import android.telephony.ims.ImsReasonInfo;
import android.text.TextUtils;
import android.util.Log;
import androidx.test.InstrumentationRegistry;
import com.android.compatibility.common.util.ShellIdentityUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Executor;
public class TelephonyCallbackTest {
public static final long WAIT_TIME = 1000;
private static final String TEST_EMERGENCY_NUMBER = "998877665544332211";
private boolean mOnActiveDataSubscriptionIdChanged;
private boolean mOnCallForwardingIndicatorChangedCalled;
private boolean mOnCallStateChangedCalled;
private boolean mOnCellLocationChangedCalled;
private boolean mOnUserMobileDataStateChanged;
private boolean mOnDataActivityCalled;
private boolean mOnDataConnectionStateChangedCalled;
private boolean mOnDataConnectionStateChangedWithNetworkTypeCalled;
private boolean mOnMessageWaitingIndicatorChangedCalled;
private boolean mOnCellInfoChangedCalled;
private boolean mOnServiceStateChangedCalled;
private boolean mOnPreciseCallStateChangedCalled;
private boolean mOnCallDisconnectCauseChangedCalled;
private boolean mOnImsCallDisconnectCauseChangedCalled;
private EmergencyNumber mOnOutgoingSmsEmergencyNumberChanged;
private boolean mOnPreciseDataConnectionStateChanged;
private boolean mOnRadioPowerStateChangedCalled;
private boolean mVoiceActivationStateChangedCalled;
private boolean mSrvccStateChangedCalled;
private boolean mOnBarringInfoChangedCalled;
private boolean mOnRegistrationFailedCalled;
private boolean mOnTelephonyDisplayInfoChanged;
private boolean mOnPhysicalChannelConfigCalled;
private boolean mOnDataEnabledChangedCalled;
private boolean mOnLinkCapacityEstimateChangedCalled;
@RadioPowerState
private int mRadioPowerState;
@SimActivationState
private int mVoiceActivationState;
private ServiceState mServiceState;
private boolean mOnAllowedNetworkTypesChangedCalled;
private int mAllowedNetworkTypeReason = -1;
private long mAllowedNetworkTypeValue = -1;
private BarringInfo mBarringInfo;
private PreciseDataConnectionState mPreciseDataConnectionState;
private PreciseCallState mPreciseCallState;
private SignalStrength mSignalStrength;
private TelephonyManager mTelephonyManager;
private final Object mLock = new Object();
private static final String TAG = "android.telephony.cts.TelephonyCallbackTest";
private static ConnectivityManager mCm;
private HandlerThread mHandlerThread;
private Handler mHandler;
private PackageManager mPackageManager;
private static final List<Integer> DATA_CONNECTION_STATE = Arrays.asList(
TelephonyManager.DATA_CONNECTED,
TelephonyManager.DATA_DISCONNECTED,
TelephonyManager.DATA_CONNECTING,
TelephonyManager.DATA_UNKNOWN,
TelephonyManager.DATA_SUSPENDED
);
private static final List<Integer> PRECISE_CALL_STATE = Arrays.asList(
PreciseCallState.PRECISE_CALL_STATE_ACTIVE,
PreciseCallState.PRECISE_CALL_STATE_ALERTING,
PreciseCallState.PRECISE_CALL_STATE_DIALING,
PreciseCallState.PRECISE_CALL_STATE_DISCONNECTED,
PreciseCallState.PRECISE_CALL_STATE_DISCONNECTING,
PreciseCallState.PRECISE_CALL_STATE_HOLDING,
PreciseCallState.PRECISE_CALL_STATE_IDLE,
PreciseCallState.PRECISE_CALL_STATE_INCOMING,
PreciseCallState.PRECISE_CALL_STATE_NOT_VALID,
PreciseCallState.PRECISE_CALL_STATE_WAITING
);
private Executor mSimpleExecutor = new Executor() {
@Override
public void execute(Runnable r) {
r.run();
}
};
@Before
public void setUp() throws Exception {
mTelephonyManager =
(TelephonyManager) getContext().getSystemService(Context.TELEPHONY_SERVICE);
mCm = (ConnectivityManager) getContext().getSystemService(Context.CONNECTIVITY_SERVICE);
mHandlerThread = new HandlerThread("TelephonyCallbackTest");
mHandlerThread.start();
mHandler = new Handler(mHandlerThread.getLooper());
mPackageManager = getContext().getPackageManager();
}
@After
public void tearDown() throws Exception {
if (mHandlerThread != null) {
mHandlerThread.quitSafely();
}
}
@Test
public void testTelephonyCallback() {
if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
return;
}
Looper.prepare();
new TelephonyCallback();
}
private void registerTelephonyCallbackWithPermission(@NonNull TelephonyCallback callback) {
ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
(tm) -> tm.registerTelephonyCallback(mSimpleExecutor, callback));
}
private void registerTelephonyCallback(@NonNull TelephonyCallback callback) {
mTelephonyManager.registerTelephonyCallback(mSimpleExecutor, callback);
}
private void registerTelephonyCallback(@NonNull TelephonyCallback callback,
boolean renounceFine, boolean renounceCoarse) {
int includeLocationData = TelephonyManager.INCLUDE_LOCATION_DATA_FINE;
if (renounceFine && renounceCoarse) {
includeLocationData = TelephonyManager.INCLUDE_LOCATION_DATA_NONE;
} else if (renounceFine) {
includeLocationData = TelephonyManager.INCLUDE_LOCATION_DATA_COARSE;
}
mTelephonyManager.registerTelephonyCallback(includeLocationData, mSimpleExecutor,
callback);
}
private void unRegisterTelephonyCallback(boolean condition,
@NonNull TelephonyCallback callback) throws Exception {
synchronized (mLock) {
condition = false;
mTelephonyManager.unregisterTelephonyCallback(callback);
mLock.wait(WAIT_TIME);
assertFalse(condition);
}
}
private ServiceStateListener mServiceStateCallback;
private class ServiceStateListener extends TelephonyCallback
implements TelephonyCallback.ServiceStateListener {
@Override
public void onServiceStateChanged(ServiceState serviceState) {
synchronized (mLock) {
mOnServiceStateChangedCalled = true;
mServiceState = serviceState;
mLock.notify();
}
}
}
@Test
public void testOnServiceStateChangedByRegisterTelephonyCallback() throws Throwable {
if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
return;
}
assertFalse(mOnServiceStateChangedCalled);
mHandler.post(() -> {
mServiceStateCallback = new ServiceStateListener();
registerTelephonyCallback(mServiceStateCallback);
});
synchronized (mLock) {
if (!mOnServiceStateChangedCalled) {
mLock.wait(WAIT_TIME);
}
}
assertTrue(mOnServiceStateChangedCalled);
// Test unregister
unRegisterTelephonyCallback(mOnServiceStateChangedCalled, mServiceStateCallback);
}
@Test
public void testOnServiceStateChangedByRegisterTelephonyCallbackWithLocationRenounce()
throws Throwable {
if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
return;
}
assertFalse(mOnServiceStateChangedCalled);
mHandler.post(() -> {
mServiceStateCallback = new ServiceStateListener();
registerTelephonyCallback(mServiceStateCallback, true, true);
});
synchronized (mLock) {
if (!mOnServiceStateChangedCalled) {
mLock.wait(WAIT_TIME);
}
}
assertTrue(mOnServiceStateChangedCalled);
assertServiceStateLocationSanitization(mServiceState);
// Test unregister
unRegisterTelephonyCallback(mOnServiceStateChangedCalled, mServiceStateCallback);
}
@Test
public void testOnServiceStateChangedByRegisterTelephonyCallbackWithCoarseRenounce()
throws Throwable {
if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
return;
}
assertFalse(mOnServiceStateChangedCalled);
mHandler.post(() -> {
mServiceStateCallback = new ServiceStateListener();
registerTelephonyCallback(mServiceStateCallback, false, true);
});
synchronized (mLock) {
if (!mOnServiceStateChangedCalled) {
mLock.wait(WAIT_TIME);
}
}
assertTrue(mOnServiceStateChangedCalled);
// Test unregister
unRegisterTelephonyCallback(mOnServiceStateChangedCalled, mServiceStateCallback);
}
@Test
public void testOnServiceStateChangedByRegisterTelephonyCallbackWithFineOnlyRenounce()
throws Throwable {
if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
return;
}
assertFalse(mOnServiceStateChangedCalled);
mHandler.post(() -> {
mServiceStateCallback = new ServiceStateListener();
registerTelephonyCallback(mServiceStateCallback, true, false);
});
synchronized (mLock) {
if (!mOnServiceStateChangedCalled) {
mLock.wait(WAIT_TIME);
}
}
assertTrue(mOnServiceStateChangedCalled);
assertServiceStateFineLocationSanitization(mServiceState);
// Test unregister
unRegisterTelephonyCallback(mOnServiceStateChangedCalled, mServiceStateCallback);
}
private void assertServiceStateFineLocationSanitization(ServiceState state) {
if (state == null) return;
if (state.getNetworkRegistrationInfoList() != null) {
for (NetworkRegistrationInfo nrs : state.getNetworkRegistrationInfoList()) {
assertNull(nrs.getCellIdentity());
}
}
}
private void assertServiceStateLocationSanitization(ServiceState state) {
if (state == null) return;
assertServiceStateFineLocationSanitization(state);
assertTrue(TextUtils.isEmpty(state.getOperatorAlphaLong()));
assertTrue(TextUtils.isEmpty(state.getOperatorAlphaShort()));
assertTrue(TextUtils.isEmpty(state.getOperatorNumeric()));
}
@Test
public void testOnUnRegisterFollowedByRegisterTelephonyCallback() throws Throwable {
if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
return;
}
assertFalse(mOnServiceStateChangedCalled);
mHandler.post(() -> {
mServiceStateCallback = new ServiceStateListener();
registerTelephonyCallback(mServiceStateCallback);
});
synchronized (mLock) {
if (!mOnServiceStateChangedCalled) {
mLock.wait(WAIT_TIME);
}
}
assertTrue(mOnServiceStateChangedCalled);
// reset and un-register
mOnServiceStateChangedCalled = false;
if (mServiceStateCallback != null) {
// un-register the listener
mTelephonyManager.unregisterTelephonyCallback(mServiceStateCallback);
}
synchronized (mLock) {
if (!mOnServiceStateChangedCalled) {
mLock.wait(WAIT_TIME);
}
}
assertFalse(mOnServiceStateChangedCalled);
// re-register the listener
registerTelephonyCallback(mServiceStateCallback);
synchronized (mLock) {
if (!mOnServiceStateChangedCalled) {
mLock.wait(WAIT_TIME);
}
}
assertTrue(mOnServiceStateChangedCalled);
// Test unregister
unRegisterTelephonyCallback(mOnServiceStateChangedCalled, mServiceStateCallback);
}
private SignalStrengthsListener mSignalStrengthsCallback;
private class SignalStrengthsListener extends TelephonyCallback
implements TelephonyCallback.SignalStrengthsListener {
@Override
public void onSignalStrengthsChanged(SignalStrength signalStrength) {
synchronized (mLock) {
mSignalStrength = signalStrength;
mLock.notify();
}
}
}
private void getSignalStrength() {
mSignalStrength.getCdmaDbm();
mSignalStrength.getCdmaEcio();
mSignalStrength.getEvdoDbm();
mSignalStrength.getEvdoEcio();
mSignalStrength.getEvdoSnr();
mSignalStrength.getGsmBitErrorRate();
mSignalStrength.getGsmSignalStrength();
mSignalStrength.isGsm();
mSignalStrength.getLevel();
}
@Test
public void testOnSignalStrengthsChangedByRegisterTelephonyCallback() throws Throwable {
if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
return;
}
assertTrue(mSignalStrength == null);
mHandler.post(() -> {
mSignalStrengthsCallback = new SignalStrengthsListener();
registerTelephonyCallback(mSignalStrengthsCallback);
});
synchronized (mLock) {
if (mSignalStrength == null) {
mLock.wait(WAIT_TIME);
}
}
assertTrue(mSignalStrength != null);
// Call SignalStrength methods to make sure they do not throw any exceptions
getSignalStrength();
// Test unregister
unRegisterTelephonyCallback(mSignalStrength == null, mSignalStrengthsCallback);
}
private MessageWaitingIndicatorListener mMessageWaitingIndicatorCallback;
private class MessageWaitingIndicatorListener extends TelephonyCallback
implements TelephonyCallback.MessageWaitingIndicatorListener {
@Override
public void onMessageWaitingIndicatorChanged(boolean mwi) {
synchronized (mLock) {
mOnMessageWaitingIndicatorChangedCalled = true;
mLock.notify();
}
}
}
@Test
public void testOnMessageWaitingIndicatorChangedByRegisterTelephonyCallback()
throws Throwable {
if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
return;
}
assertFalse(mOnMessageWaitingIndicatorChangedCalled);
mHandler.post(() -> {
mMessageWaitingIndicatorCallback = new MessageWaitingIndicatorListener();
registerTelephonyCallback(mMessageWaitingIndicatorCallback);
});
synchronized (mLock) {
if (!mOnMessageWaitingIndicatorChangedCalled) {
mLock.wait(WAIT_TIME);
}
}
assertTrue(mOnMessageWaitingIndicatorChangedCalled);
// Test unregister
unRegisterTelephonyCallback(mOnMessageWaitingIndicatorChangedCalled,
mMessageWaitingIndicatorCallback);
}
private PreciseCallStateListener mPreciseCallStateCallback;
private class PreciseCallStateListener extends TelephonyCallback
implements TelephonyCallback.PreciseCallStateListener {
@Override
public void onPreciseCallStateChanged(PreciseCallState preciseCallState) {
synchronized (mLock) {
mOnPreciseCallStateChangedCalled = true;
mPreciseCallState = preciseCallState;
mLock.notify();
}
}
}
@Test
public void testOnPreciseCallStateChangedByRegisterTelephonyCallback() throws Throwable {
if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
Log.d(TAG, "Skipping test that requires FEATURE_TELEPHONY");
return;
}
assertThat(mOnPreciseCallStateChangedCalled).isFalse();
mHandler.post(() -> {
mPreciseCallStateCallback = new PreciseCallStateListener();
registerTelephonyCallbackWithPermission(mPreciseCallStateCallback);
});
synchronized (mLock) {
if (!mOnPreciseCallStateChangedCalled) {
mLock.wait(WAIT_TIME);
}
}
Log.d(TAG, "testOnPreciseCallStateChangedByRegisterTelephonyCallback: "
+ mOnPreciseCallStateChangedCalled);
assertThat(mOnPreciseCallStateChangedCalled).isTrue();
assertThat(mPreciseCallState.getForegroundCallState()).isIn(PRECISE_CALL_STATE);
assertThat(mPreciseCallState.getBackgroundCallState()).isIn(PRECISE_CALL_STATE);
assertThat(mPreciseCallState.getRingingCallState()).isIn(PRECISE_CALL_STATE);
// Test unregister
unRegisterTelephonyCallback(mOnPreciseCallStateChangedCalled,
mPreciseCallStateCallback);
}
private CallDisconnectCauseListener mCallDisconnectCauseCallback;
private class CallDisconnectCauseListener extends TelephonyCallback
implements TelephonyCallback.CallDisconnectCauseListener {
@Override
public void onCallDisconnectCauseChanged(int disconnectCause,
int preciseDisconnectCause) {
synchronized (mLock) {
mOnCallDisconnectCauseChangedCalled = true;
mLock.notify();
}
}
}
@Test
public void testOnCallDisconnectCauseChangedByRegisterTelephonyCallback() throws Throwable {
if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
Log.d(TAG, "Skipping test that requires FEATURE_TELEPHONY");
return;
}
assertThat(mOnCallDisconnectCauseChangedCalled).isFalse();
mHandler.post(() -> {
mCallDisconnectCauseCallback = new CallDisconnectCauseListener();
registerTelephonyCallbackWithPermission(mCallDisconnectCauseCallback);
});
synchronized (mLock) {
if (!mOnCallDisconnectCauseChangedCalled) {
mLock.wait(WAIT_TIME);
}
}
assertThat(mOnCallDisconnectCauseChangedCalled).isTrue();
// Test unregister
unRegisterTelephonyCallback(mOnCallDisconnectCauseChangedCalled,
mCallDisconnectCauseCallback);
}
private ImsCallDisconnectCauseListener mImsCallDisconnectCauseCallback;
private class ImsCallDisconnectCauseListener extends TelephonyCallback
implements TelephonyCallback.ImsCallDisconnectCauseListener {
@Override
public void onImsCallDisconnectCauseChanged(ImsReasonInfo imsReason) {
synchronized (mLock) {
mOnImsCallDisconnectCauseChangedCalled = true;
mLock.notify();
}
}
}
@Test
public void testOnImsCallDisconnectCauseChangedByRegisterTelephonyCallback() throws Throwable {
if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
Log.d(TAG, "Skipping test that requires FEATURE_TELEPHONY");
return;
}
assertThat(mOnImsCallDisconnectCauseChangedCalled).isFalse();
mHandler.post(() -> {
mImsCallDisconnectCauseCallback = new ImsCallDisconnectCauseListener();
registerTelephonyCallbackWithPermission(mImsCallDisconnectCauseCallback);
});
synchronized (mLock) {
if (!mOnImsCallDisconnectCauseChangedCalled) {
mLock.wait(WAIT_TIME);
}
}
assertThat(mOnImsCallDisconnectCauseChangedCalled).isTrue();
// Test unregister
unRegisterTelephonyCallback(mOnImsCallDisconnectCauseChangedCalled,
mImsCallDisconnectCauseCallback);
}
private SrvccStateListener mSrvccStateCallback;
private class SrvccStateListener extends TelephonyCallback
implements TelephonyCallback.SrvccStateListener {
@Override
public void onSrvccStateChanged(int state) {
synchronized (mLock) {
mSrvccStateChangedCalled = true;
mLock.notify();
}
}
}
@Test
public void testOSrvccStateChangedByRegisterTelephonyCallback() throws Throwable {
if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
Log.d(TAG, "Skipping test that requires FEATURE_TELEPHONY");
return;
}
assertThat(mSrvccStateChangedCalled).isFalse();
mHandler.post(() -> {
mSrvccStateCallback = new SrvccStateListener();
registerTelephonyCallbackWithPermission(mSrvccStateCallback);
});
synchronized (mLock) {
if (!mSrvccStateChangedCalled) {
mLock.wait(WAIT_TIME);
}
}
Log.d(TAG, "testOSrvccStateChangedByRegisterTelephonyCallback");
assertThat(mSrvccStateChangedCalled).isTrue();
// Test unregister
unRegisterTelephonyCallback(mSrvccStateChangedCalled, mSrvccStateCallback);
}
private RadioPowerStateListener mRadioPowerStateCallback;
private class RadioPowerStateListener extends TelephonyCallback
implements TelephonyCallback.RadioPowerStateListener {
@Override
public void onRadioPowerStateChanged(int state) {
synchronized (mLock) {
mRadioPowerState = state;
mOnRadioPowerStateChangedCalled = true;
mLock.notify();
}
}
}
@Test
public void testOnRadioPowerStateChangedByRegisterTelephonyCallback() throws Throwable {
if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
Log.d(TAG, "Skipping test that requires FEATURE_TELEPHONY");
return;
}
assertThat(mOnRadioPowerStateChangedCalled).isFalse();
mHandler.post(() -> {
mRadioPowerStateCallback = new RadioPowerStateListener();
registerTelephonyCallbackWithPermission(mRadioPowerStateCallback);
});
synchronized (mLock) {
if (!mOnRadioPowerStateChangedCalled) {
mLock.wait(WAIT_TIME);
}
}
Log.d(TAG, "testOnRadioPowerStateChangedByRegisterTelephonyCallback: "
+ mRadioPowerState);
assertThat(mTelephonyManager.getRadioPowerState()).isEqualTo(mRadioPowerState);
// Test unregister
unRegisterTelephonyCallback(mOnRadioPowerStateChangedCalled,
mRadioPowerStateCallback);
}
private VoiceActivationStateListener mVoiceActivationStateCallback;
private class VoiceActivationStateListener extends TelephonyCallback
implements TelephonyCallback.VoiceActivationStateListener {
@Override
public void onVoiceActivationStateChanged(int state) {
synchronized (mLock) {
mVoiceActivationState = state;
mVoiceActivationStateChangedCalled = true;
mLock.notify();
}
}
}
@Test
public void testOnVoiceActivationStateChangedByRegisterTelephonyCallback() throws Throwable {
if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
return;
}
assertThat(mVoiceActivationStateChangedCalled).isFalse();
mHandler.post(() -> {
mVoiceActivationStateCallback = new VoiceActivationStateListener();
registerTelephonyCallbackWithPermission(mVoiceActivationStateCallback);
});
synchronized (mLock) {
if (!mVoiceActivationStateChangedCalled) {
mLock.wait(WAIT_TIME);
}
}
Log.d(TAG, "testOnVoiceActivationStateChangedByRegisterTelephonyCallback: "
+ mVoiceActivationState);
int state = ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
(tm) -> tm.getVoiceActivationState());
assertEquals(state, mVoiceActivationState);
// Test unregister
unRegisterTelephonyCallback(mVoiceActivationStateChangedCalled,
mVoiceActivationStateCallback);
}
private PreciseDataConnectionStateListener mPreciseDataConnectionStateCallback;
private class PreciseDataConnectionStateListener extends TelephonyCallback
implements TelephonyCallback.PreciseDataConnectionStateListener {
@Override
public void onPreciseDataConnectionStateChanged(
PreciseDataConnectionState state) {
synchronized (mLock) {
mOnPreciseDataConnectionStateChanged = true;
mPreciseDataConnectionState = state;
mLock.notify();
}
}
}
private void getPreciseDataConnectionState() {
// Ensure that no exceptions are thrown
mPreciseDataConnectionState.getNetworkType();
mPreciseDataConnectionState.getLinkProperties();
mPreciseDataConnectionState.getLastCauseCode();
mPreciseDataConnectionState.getLinkProperties();
mPreciseDataConnectionState.getApnSetting();
mPreciseDataConnectionState.getTransportType();
mPreciseDataConnectionState.getId();
// Deprecated in R
assertEquals(mPreciseDataConnectionState.getDataConnectionState(),
mPreciseDataConnectionState.getState());
assertEquals(mPreciseDataConnectionState.getDataConnectionFailCause(),
mPreciseDataConnectionState.getLastCauseCode());
// Superseded in R by getApnSetting()
mPreciseDataConnectionState.getDataConnectionApnTypeBitMask();
mPreciseDataConnectionState.getDataConnectionApn();
}
@Test
public void testOnPreciseDataConnectionStateChangedByRegisterTelephonyCallback()
throws Throwable {
if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
Log.d(TAG, "Skipping test that requires FEATURE_TELEPHONY");
return;
}
assertThat(mOnCallDisconnectCauseChangedCalled).isFalse();
mHandler.post(() -> {
mPreciseDataConnectionStateCallback =
new PreciseDataConnectionStateListener();
registerTelephonyCallbackWithPermission(mPreciseDataConnectionStateCallback);
});
synchronized (mLock) {
if (!mOnPreciseDataConnectionStateChanged) {
mLock.wait(WAIT_TIME);
}
}
assertThat(mOnPreciseDataConnectionStateChanged).isTrue();
assertThat(mPreciseDataConnectionState.getState())
.isIn(DATA_CONNECTION_STATE);
getPreciseDataConnectionState();
// Test unregister
unRegisterTelephonyCallback(mOnPreciseDataConnectionStateChanged,
mPreciseDataConnectionStateCallback);
}
private DisplayInfoListener mDisplayInfoCallback;
private class DisplayInfoListener extends TelephonyCallback
implements TelephonyCallback.DisplayInfoListener {
@Override
public void onDisplayInfoChanged(TelephonyDisplayInfo displayInfo) {
synchronized (mLock) {
mOnTelephonyDisplayInfoChanged = true;
mLock.notify();
}
}
}
@Test
public void testOnDisplayInfoChangedByRegisterTelephonyCallback() throws Exception {
if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
return;
}
assertThat(mOnTelephonyDisplayInfoChanged).isFalse();
mHandler.post(() -> {
mDisplayInfoCallback = new DisplayInfoListener();
registerTelephonyCallback(mDisplayInfoCallback);
});
synchronized (mLock) {
if (!mOnTelephonyDisplayInfoChanged) {
mLock.wait(WAIT_TIME);
}
}
assertTrue(mOnTelephonyDisplayInfoChanged);
// Test unregister
unRegisterTelephonyCallback(mOnTelephonyDisplayInfoChanged, mDisplayInfoCallback);
}
private CallForwardingIndicatorListener mCallForwardingIndicatorCallback;
private class CallForwardingIndicatorListener extends TelephonyCallback
implements TelephonyCallback.CallForwardingIndicatorListener {
@Override
public void onCallForwardingIndicatorChanged(boolean cfi) {
synchronized (mLock) {
mOnCallForwardingIndicatorChangedCalled = true;
mLock.notify();
}
}
}
@Test
public void testOnCallForwardingIndicatorChangedByRegisterTelephonyCallback()
throws Throwable {
if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
return;
}
assertFalse(mOnCallForwardingIndicatorChangedCalled);
mHandler.post(() -> {
mCallForwardingIndicatorCallback = new CallForwardingIndicatorListener();
registerTelephonyCallback(mCallForwardingIndicatorCallback);
});
synchronized (mLock) {
if (!mOnCallForwardingIndicatorChangedCalled) {
mLock.wait(WAIT_TIME);
}
}
assertTrue(mOnCallForwardingIndicatorChangedCalled);
// Test unregister
unRegisterTelephonyCallback(mOnCallForwardingIndicatorChangedCalled,
mCallForwardingIndicatorCallback);
}
private CellLocationListener mCellLocationCallback;
private class CellLocationListener extends TelephonyCallback
implements TelephonyCallback.CellLocationListener {
@Override
public void onCellLocationChanged(CellLocation location) {
synchronized (mLock) {
mOnCellLocationChangedCalled = true;
mLock.notify();
}
}
}
@Test
public void testOnCellLocationChangedByRegisterTelephonyCallback() throws Throwable {
if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
return;
}
assertFalse(mOnCellLocationChangedCalled);
TelephonyManagerTest.grantLocationPermissions();
mHandler.post(() -> {
mCellLocationCallback = new CellLocationListener();
registerTelephonyCallback(mCellLocationCallback);
});
synchronized (mLock) {
if (!mOnCellLocationChangedCalled) {
mLock.wait(WAIT_TIME);
}
}
assertTrue(mOnCellLocationChangedCalled);
// Test unregister
unRegisterTelephonyCallback(mOnCellLocationChangedCalled, mCellLocationCallback);
}
private CallStateListener mCallStateCallback;
private class CallStateListener extends TelephonyCallback
implements TelephonyCallback.CallStateListener {
@Override
public void onCallStateChanged(int state) {
synchronized (mLock) {
mOnCallStateChangedCalled = true;
mLock.notify();
}
}
}
@Test
public void testOnCallStateChangedByRegisterTelephonyCallback() throws Throwable {
if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
return;
}
assertFalse(mOnCallStateChangedCalled);
mCallStateCallback = new CallStateListener();
registerTelephonyCallback(mCallStateCallback);
synchronized (mLock) {
if (!mOnCallStateChangedCalled) {
mLock.wait(WAIT_TIME);
}
}
assertTrue(mOnCallStateChangedCalled);
// Test unregister
unRegisterTelephonyCallback(mOnCallStateChangedCalled, mCallStateCallback);
}
private DataConnectionStateListener mDataConnectionStateCallback;
private class DataConnectionStateListener extends TelephonyCallback
implements TelephonyCallback.DataConnectionStateListener {
@Override
public void onDataConnectionStateChanged(int state, int networkType) {
synchronized (mLock) {
mOnDataConnectionStateChangedCalled = true;
mOnDataConnectionStateChangedWithNetworkTypeCalled = true;
if (mOnDataConnectionStateChangedCalled
&& mOnDataConnectionStateChangedWithNetworkTypeCalled) {
mLock.notify();
}
}
}
}
@Test
public void testOnDataConnectionStateChangedByRegisterTelephonyCallback() throws Throwable {
if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
return;
}
assertFalse(mOnDataConnectionStateChangedCalled);
assertFalse(mOnDataConnectionStateChangedWithNetworkTypeCalled);
mHandler.post(() -> {
mDataConnectionStateCallback = new DataConnectionStateListener();
registerTelephonyCallback(mDataConnectionStateCallback);
});
synchronized (mLock) {
if (!mOnDataConnectionStateChangedCalled ||
!mOnDataConnectionStateChangedWithNetworkTypeCalled) {
mLock.wait(WAIT_TIME);
}
}
assertTrue(mOnDataConnectionStateChangedCalled);
assertTrue(mOnDataConnectionStateChangedWithNetworkTypeCalled);
// Test unregister
unRegisterTelephonyCallback(mOnDataConnectionStateChangedCalled,
mDataConnectionStateCallback);
}
private DataActivityListener mDataActivityCallback;
private class DataActivityListener extends TelephonyCallback
implements TelephonyCallback.DataActivityListener {
@Override
public void onDataActivity(int direction) {
synchronized (mLock) {
mOnDataActivityCalled = true;
mLock.notify();
}
}
}
@Test
public void testOnDataActivityByRegisterTelephonyCallback() throws Throwable {
if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
return;
}
assertFalse(mOnDataActivityCalled);
mHandler.post(() -> {
mDataActivityCallback = new DataActivityListener();
registerTelephonyCallback(mDataActivityCallback);
});
synchronized (mLock) {
if (!mOnDataActivityCalled) {
mLock.wait(WAIT_TIME);
}
}
assertTrue(mOnDataActivityCalled);
// Test unregister
unRegisterTelephonyCallback(mOnDataActivityCalled, mDataActivityCallback);
}
private CellInfoListener mCellInfoCallback;
private class CellInfoListener extends TelephonyCallback
implements TelephonyCallback.CellInfoListener {
@Override
public void onCellInfoChanged(List<CellInfo> cellInfo) {
synchronized (mLock) {
mOnCellInfoChangedCalled = true;
mLock.notify();
}
}
}
@Test
public void testOnCellInfoChangedByRegisterTelephonyCallback() throws Throwable {
if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
return;
}
assertFalse(mOnDataActivityCalled);
TelephonyManagerTest.grantLocationPermissions();
mHandler.post(() -> {
mCellInfoCallback = new CellInfoListener();
registerTelephonyCallback(mCellInfoCallback);
});
synchronized (mLock) {
if (!mOnCellInfoChangedCalled) {
mLock.wait(WAIT_TIME);
}
}
assertTrue(mOnCellInfoChangedCalled);
// Test unregister
unRegisterTelephonyCallback(mOnCellInfoChangedCalled, mCellInfoCallback);
}
private UserMobileDataStateListener mUserMobileDataStateCallback;
private class UserMobileDataStateListener extends TelephonyCallback
implements TelephonyCallback.UserMobileDataStateListener {
@Override
public void onUserMobileDataStateChanged(boolean state) {
synchronized (mLock) {
mOnUserMobileDataStateChanged = true;
mLock.notify();
}
}
}
@Test
public void testOnUserMobileDataStateChangedByRegisterTelephonyCallback() throws Throwable {
if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
return;
}
assertFalse(mOnUserMobileDataStateChanged);
mHandler.post(() -> {
mUserMobileDataStateCallback = new UserMobileDataStateListener();
registerTelephonyCallback(mUserMobileDataStateCallback);
});
synchronized (mLock) {
if (!mOnUserMobileDataStateChanged) {
mLock.wait(WAIT_TIME);
}
}
assertTrue(mOnUserMobileDataStateChanged);
// Test unregister
unRegisterTelephonyCallback(mOnUserMobileDataStateChanged, mUserMobileDataStateCallback);
}
private OutgoingEmergencySmsListener mOutgoingEmergencySmsCallback;
private class OutgoingEmergencySmsListener extends TelephonyCallback
implements TelephonyCallback.OutgoingEmergencySmsListener {
@Override
public void onOutgoingEmergencySms(EmergencyNumber emergencyNumber, int subId) {
synchronized (mLock) {
Log.i(TAG, "onOutgoingEmergencySms: emergencyNumber=" + emergencyNumber);
mOnOutgoingSmsEmergencyNumberChanged = emergencyNumber;
mLock.notify();
}
}
}
@Test
public void testOnOutgoingSmsEmergencyNumberChangedByRegisterTelephonyCallback()
throws Throwable {
if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
return;
}
TelephonyUtils.addTestEmergencyNumber(
InstrumentationRegistry.getInstrumentation(), TEST_EMERGENCY_NUMBER);
assertNull(mOnOutgoingSmsEmergencyNumberChanged);
mHandler.post(() -> {
mOutgoingEmergencySmsCallback = new OutgoingEmergencySmsListener();
registerTelephonyCallbackWithPermission(mOutgoingEmergencySmsCallback);
SmsManager.getDefault().sendTextMessage(
TEST_EMERGENCY_NUMBER, null,
"testOutgoingSmsListenerCtsByRegisterTelephonyCallback",
null, null);
});
try {
synchronized (mLock) {
if (mOnOutgoingSmsEmergencyNumberChanged == null) {
mLock.wait(WAIT_TIME);
}
}
} catch (InterruptedException e) {
Log.e(TAG, "Operation interrupted.");
} finally {
TelephonyUtils.removeTestEmergencyNumber(
InstrumentationRegistry.getInstrumentation(), TEST_EMERGENCY_NUMBER);
}
assertNotNull(mOnOutgoingSmsEmergencyNumberChanged);
assertEquals(mOnOutgoingSmsEmergencyNumberChanged.getNumber(), TEST_EMERGENCY_NUMBER);
// Test unregister
unRegisterTelephonyCallback(mOnOutgoingSmsEmergencyNumberChanged == null,
mOutgoingEmergencySmsCallback);
// Disable suppressing blocking.
TelephonyUtils.endBlockSuppression(InstrumentationRegistry.getInstrumentation());
}
private ActiveDataSubscriptionIdListener mActiveDataSubscriptionIdCallback;
private class ActiveDataSubscriptionIdListener extends TelephonyCallback
implements TelephonyCallback.ActiveDataSubscriptionIdListener {
@Override
public void onActiveDataSubscriptionIdChanged(int subId) {
synchronized (mLock) {
mOnActiveDataSubscriptionIdChanged = true;
mLock.notify();
}
}
}
@Test
public void testOnActiveDataSubscriptionIdChangedByRegisterTelephonyCallback()
throws Throwable {
if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
return;
}
assertFalse(mOnActiveDataSubscriptionIdChanged);
mHandler.post(() -> {
mActiveDataSubscriptionIdCallback =
new ActiveDataSubscriptionIdListener();
registerTelephonyCallback(mActiveDataSubscriptionIdCallback);
});
synchronized (mLock) {
if (!mOnActiveDataSubscriptionIdChanged) {
mLock.wait(WAIT_TIME);
}
}
assertTrue(mOnActiveDataSubscriptionIdChanged);
// Test unregister
unRegisterTelephonyCallback(mOnActiveDataSubscriptionIdChanged,
mActiveDataSubscriptionIdCallback);
}
private BarringInfoListener mBarringInfoCallback;
private class BarringInfoListener extends TelephonyCallback
implements TelephonyCallback.BarringInfoListener {
@Override
public void onBarringInfoChanged(BarringInfo barringInfo) {
synchronized (mLock) {
mOnBarringInfoChangedCalled = true;
mBarringInfo = barringInfo;
mLock.notify();
}
}
}
@Test
public void testOnBarringInfoChangedByRegisterTelephonyCallback() throws Throwable {
if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
return;
}
assertFalse(mOnBarringInfoChangedCalled);
mHandler.post(() -> {
mBarringInfoCallback = new BarringInfoListener();
registerTelephonyCallbackWithPermission(mBarringInfoCallback);
});
synchronized (mLock) {
if (!mOnBarringInfoChangedCalled) {
mLock.wait(WAIT_TIME);
}
}
assertTrue(mOnBarringInfoChangedCalled);
assertBarringInfoSane(mBarringInfo);
// Test unregister
unRegisterTelephonyCallback(mOnBarringInfoChangedCalled, mBarringInfoCallback);
}
private static final int[] sBarringServiceInfoTypes = new int[]{
BarringInfo.BARRING_SERVICE_TYPE_CS_SERVICE,
BarringInfo.BARRING_SERVICE_TYPE_PS_SERVICE,
BarringInfo.BARRING_SERVICE_TYPE_CS_VOICE,
BarringInfo.BARRING_SERVICE_TYPE_MO_SIGNALLING,
BarringInfo.BARRING_SERVICE_TYPE_MO_DATA,
BarringInfo.BARRING_SERVICE_TYPE_CS_FALLBACK,
BarringInfo.BARRING_SERVICE_TYPE_MMTEL_VOICE,
BarringInfo.BARRING_SERVICE_TYPE_MMTEL_VIDEO,
BarringInfo.BARRING_SERVICE_TYPE_EMERGENCY,
BarringInfo.BARRING_SERVICE_TYPE_SMS
};
private static void assertBarringInfoSane(BarringInfo barringInfo) {
assertNotNull(barringInfo);
// Flags to track whether we have had unknown and known barring types reported
boolean hasBarringTypeUnknown = false;
boolean hasBarringTypeKnown = false;
for (int bsiType : sBarringServiceInfoTypes) {
BarringInfo.BarringServiceInfo bsi = barringInfo.getBarringServiceInfo(bsiType);
assertNotNull(bsi);
switch (bsi.getBarringType()) {
case BarringInfo.BarringServiceInfo.BARRING_TYPE_UNKNOWN:
hasBarringTypeUnknown = true;
assertFalse(bsi.isConditionallyBarred());
assertEquals(0, bsi.getConditionalBarringFactor());
assertEquals(0, bsi.getConditionalBarringTimeSeconds());
assertFalse(bsi.isBarred());
break;
case BarringInfo.BarringServiceInfo.BARRING_TYPE_NONE:
hasBarringTypeKnown = true;
// Unless conditional barring is active, all conditional barring fields
// should be "unset".
assertFalse(bsi.isConditionallyBarred());
assertEquals(0, bsi.getConditionalBarringFactor());
assertEquals(0, bsi.getConditionalBarringTimeSeconds());
assertFalse(bsi.isBarred());
break;
case BarringInfo.BarringServiceInfo.BARRING_TYPE_UNCONDITIONAL:
hasBarringTypeKnown = true;
// Unless conditional barring is active, all conditional barring fields
// should be "unset".
assertFalse(bsi.isConditionallyBarred());
assertEquals(0, bsi.getConditionalBarringFactor());
assertEquals(0, bsi.getConditionalBarringTimeSeconds());
assertTrue(bsi.isBarred());
break;
case BarringInfo.BarringServiceInfo.BARRING_TYPE_CONDITIONAL:
hasBarringTypeKnown = true;
// If conditional barring is active, then the barring time and factor must
// be known (set), but the device may or may not be barred at the moment,
// so isConditionallyBarred() can be either true or false (hence not checked).
assertNotEquals(0, bsi.getConditionalBarringFactor());
assertNotEquals(0, bsi.getConditionalBarringTimeSeconds());
assertEquals(bsi.isBarred(), bsi.isConditionallyBarred());
break;
}
}
// If any barring type is unknown, then barring is not supported so all must be
// unknown. If any type is known, then all that are not reported are assumed to
// be not barred.
assertNotEquals(hasBarringTypeUnknown, hasBarringTypeKnown);
}
private RegistrationFailedListener mRegistrationFailedCallback;
private class RegistrationFailedListener extends TelephonyCallback
implements TelephonyCallback.RegistrationFailedListener {
@Override
public void onRegistrationFailed(CellIdentity cid, String chosenPlmn,
int domain, int causeCode, int additionalCauseCode) {
synchronized (mLock) {
mOnRegistrationFailedCalled = true;
mLock.notify();
}
}
}
@Test
public void testOnRegistrationFailedByRegisterTelephonyCallback() throws Throwable {
if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
return;
}
assertFalse(mOnBarringInfoChangedCalled);
mHandler.post(() -> {
mRegistrationFailedCallback = new RegistrationFailedListener();
registerTelephonyCallbackWithPermission(mRegistrationFailedCallback);
});
synchronized (mLock) {
if (!mOnBarringInfoChangedCalled) {
mLock.wait(WAIT_TIME);
}
}
// Assert that in the WAIT_TIME interval, the listener wasn't invoked. While this is
// **technically** a flaky test, in practice this flake should happen approximately never
// as it would mean that a registered phone is failing to reselect during CTS at this
// exact moment.
//
// What the test is verifying is that there is no "auto" callback for registration
// failure because unlike other PSL registrants, this one is not called upon registration.
assertFalse(mOnRegistrationFailedCalled);
// Test unregister
unRegisterTelephonyCallback(mOnRegistrationFailedCalled, mRegistrationFailedCallback);
}
private PhysicalChannelConfigListener mPhysicalChannelConfigCallback;
private class PhysicalChannelConfigListener extends TelephonyCallback
implements TelephonyCallback.PhysicalChannelConfigListener {
@Override
public void onPhysicalChannelConfigChanged(
@NonNull List<PhysicalChannelConfig> configs) {
synchronized (mLock) {
mOnPhysicalChannelConfigCalled = true;
mLock.notify();
}
}
}
@Test
public void testOnPhysicalChannelConfigChanged() throws Throwable {
if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
Log.d(TAG, "Skipping test that requires FEATURE_TELEPHONY");
return;
}
assertFalse(mOnPhysicalChannelConfigCalled);
mHandler.post(() -> {
mPhysicalChannelConfigCallback =
new PhysicalChannelConfigListener();
registerTelephonyCallbackWithPermission(mPhysicalChannelConfigCallback);
});
synchronized (mLock) {
while (!mOnPhysicalChannelConfigCalled) {
mLock.wait(WAIT_TIME);
}
}
assertTrue(mOnPhysicalChannelConfigCalled);
// Test unregister
unRegisterTelephonyCallback(mOnPhysicalChannelConfigCalled,
mPhysicalChannelConfigCallback);
}
private DataEnabledListener mDataEnabledCallback;
private class DataEnabledListener extends TelephonyCallback
implements TelephonyCallback.DataEnabledListener {
@Override
public void onDataEnabledChanged(boolean enabled, @DataEnabledReason int reason) {
synchronized (mLock) {
mOnDataEnabledChangedCalled = true;
mLock.notify();
}
}
}
@Test
public void testOnDataEnabledChangedByRegisterTelephonyCallback() throws Throwable {
if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
Log.d(TAG, "Skipping test that requires FEATURE_TELEPHONY");
return;
}
assertFalse(mOnDataEnabledChangedCalled);
mHandler.post(() -> {
mDataEnabledCallback = new DataEnabledListener();
registerTelephonyCallbackWithPermission(mDataEnabledCallback);
});
synchronized (mLock) {
while (!mOnDataEnabledChangedCalled) {
mLock.wait(WAIT_TIME);
}
}
assertTrue(mOnDataEnabledChangedCalled);
// Test unregister
unRegisterTelephonyCallback(mOnDataEnabledChangedCalled, mDataEnabledCallback);
}
private AllowedNetworkTypesListener mAllowedNetworkTypesCallback;
private class AllowedNetworkTypesListener extends TelephonyCallback
implements TelephonyCallback.AllowedNetworkTypesListener {
@Override
public void onAllowedNetworkTypesChanged(int reason, long allowedNetworkType) {
synchronized (mLock) {
Log.d(TAG, "onAllowedNetworkTypesChanged");
mAllowedNetworkTypeReason = reason;
mAllowedNetworkTypeValue = allowedNetworkType;
mOnAllowedNetworkTypesChangedCalled = true;
mLock.notify();
}
}
}
@Test
public void testOnAllowedNetworkTypesChangedByRegisterPhoneStateListener() throws Throwable {
if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
Log.d(TAG, "Skipping test that requires FEATURE_TELEPHONY");
return;
}
long originalAllowedNetworkTypeUser = ShellIdentityUtils.invokeMethodWithShellPermissions(
mTelephonyManager, (tm) -> {
return tm.getAllowedNetworkTypesForReason(
TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER);
});
assertFalse(mOnAllowedNetworkTypesChangedCalled);
mHandler.post(() -> {
mAllowedNetworkTypesCallback = new AllowedNetworkTypesListener();
registerTelephonyCallbackWithPermission(mAllowedNetworkTypesCallback);
ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
mTelephonyManager,
(tm) -> tm.setAllowedNetworkTypesForReason(
TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER,
TelephonyManager.NETWORK_TYPE_BITMASK_NR));
});
synchronized (mLock) {
if (!mOnAllowedNetworkTypesChangedCalled) {
mLock.wait(WAIT_TIME);
}
}
long allowedNetworkTypeUser = ShellIdentityUtils.invokeMethodWithShellPermissions(
mTelephonyManager, (tm) -> {
return tm.getAllowedNetworkTypesForReason(
TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER);
});
assertEquals(TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER, mAllowedNetworkTypeReason);
assertEquals(allowedNetworkTypeUser, mAllowedNetworkTypeValue);
// Test unregister
unRegisterTelephonyCallback(mOnAllowedNetworkTypesChangedCalled,
mAllowedNetworkTypesCallback);
// Recover the allowed network type user settings.
ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
mTelephonyManager,
(tm) -> tm.setAllowedNetworkTypesForReason(
TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER,
originalAllowedNetworkTypeUser));
}
private LinkCapacityEstimateChangedListener mLinkCapacityEstimateChangedListener;
private class LinkCapacityEstimateChangedListener extends TelephonyCallback
implements TelephonyCallback.LinkCapacityEstimateChangedListener {
@Override
public void onLinkCapacityEstimateChanged(
List<LinkCapacityEstimate> linkCapacityEstimateList) {
synchronized (mLock) {
int lceType = linkCapacityEstimateList.get(0).getType();
if (lceType == LinkCapacityEstimate.LCE_TYPE_COMBINED
|| lceType == LinkCapacityEstimate.LCE_TYPE_PRIMARY
|| lceType == LinkCapacityEstimate.LCE_TYPE_SECONDARY) {
mOnLinkCapacityEstimateChangedCalled = true;
}
mLock.notify();
}
}
}
@Test
public void testOnLinkCapacityEstimateChangedByRegisterPhoneStateListener() throws Throwable {
if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
return;
}
assertFalse(mOnLinkCapacityEstimateChangedCalled);
mHandler.post(() -> {
mLinkCapacityEstimateChangedListener = new LinkCapacityEstimateChangedListener();
registerTelephonyCallbackWithPermission(mLinkCapacityEstimateChangedListener);
});
synchronized (mLock) {
while (!mOnLinkCapacityEstimateChangedCalled) {
mLock.wait(WAIT_TIME);
}
}
assertTrue(mOnLinkCapacityEstimateChangedCalled);
// Test unregister
unRegisterTelephonyCallback(mOnLinkCapacityEstimateChangedCalled,
mLinkCapacityEstimateChangedListener);
}
}