Create central TelephonyListenerManager.
The TelephonyManager doesn't like have "too many" listeners registered on int at any given time. It will actually throw exceptions when this happens. To lighten the load from the SystemUI side, TelephonyListenerManager now ensures that only one listener is ever subscribed at any point. SystemUI can now use this class instead, piggy-backing on the possibly already subscribed listener to retrieve the events it cares about. Also, use Executors in CarrierTextController instead of Handlers. Bug: 179775696 Test: atest SystemUITests Change-Id: I626e80a91396161022e1fc6387598521f77bf4fc
This commit is contained in:
@@ -18,6 +18,7 @@ package com.android.keyguard;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.text.TextUtils;
|
||||
import android.text.method.SingleLineTransformationMethod;
|
||||
import android.util.AttributeSet;
|
||||
@@ -26,6 +27,7 @@ import android.widget.TextView;
|
||||
|
||||
import com.android.systemui.Dependency;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.telephony.TelephonyListenerManager;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
@@ -85,7 +87,10 @@ public class CarrierText extends TextView {
|
||||
mSeparator = getResources().getString(
|
||||
com.android.internal.R.string.kg_text_message_separator);
|
||||
mCarrierTextController = new CarrierTextController(mContext, mSeparator, mShowAirplaneMode,
|
||||
mShowMissingSim);
|
||||
mShowMissingSim, mContext.getSystemService(TelephonyManager.class),
|
||||
Dependency.get(TelephonyListenerManager.class),
|
||||
Dependency.get(Dependency.MAIN_EXECUTOR),
|
||||
Dependency.get(Dependency.BACKGROUND_EXECUTOR));
|
||||
mShouldMarquee = Dependency.get(KeyguardUpdateMonitor.class).isDeviceInteractive();
|
||||
setSelected(mShouldMarquee); // Allow marquee to work.
|
||||
}
|
||||
|
||||
@@ -16,20 +16,15 @@
|
||||
|
||||
package com.android.keyguard;
|
||||
|
||||
import static android.telephony.PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE;
|
||||
import static android.telephony.PhoneStateListener.LISTEN_NONE;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Resources;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.os.Handler;
|
||||
import android.telephony.PhoneStateListener;
|
||||
import android.telephony.ServiceState;
|
||||
import android.telephony.SubscriptionInfo;
|
||||
import android.telephony.SubscriptionManager;
|
||||
import android.telephony.TelephonyCallback.ActiveDataSubscriptionIdListener;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
@@ -40,11 +35,14 @@ import androidx.annotation.VisibleForTesting;
|
||||
import com.android.settingslib.WirelessUtils;
|
||||
import com.android.systemui.Dependency;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.dagger.qualifiers.Background;
|
||||
import com.android.systemui.dagger.qualifiers.Main;
|
||||
import com.android.systemui.keyguard.WakefulnessLifecycle;
|
||||
import com.android.systemui.telephony.TelephonyListenerManager;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import javax.inject.Inject;
|
||||
@@ -59,8 +57,6 @@ public class CarrierTextController {
|
||||
private static final String TAG = "CarrierTextController";
|
||||
|
||||
private final boolean mIsEmergencyCallCapable;
|
||||
private final Handler mMainHandler;
|
||||
private final Handler mBgHandler;
|
||||
private boolean mTelephonyCapable;
|
||||
private boolean mShowMissingSim;
|
||||
private boolean mShowAirplaneMode;
|
||||
@@ -73,6 +69,10 @@ public class CarrierTextController {
|
||||
@Nullable // Check for nullability before dispatching
|
||||
private CarrierTextCallback mCarrierTextCallback;
|
||||
private Context mContext;
|
||||
private final TelephonyManager mTelephonyManager;
|
||||
private final TelephonyListenerManager mTelephonyListenerManager;
|
||||
private final Executor mMainExecutor;
|
||||
private final Executor mBgExecutor;
|
||||
private CharSequence mSeparator;
|
||||
private WakefulnessLifecycle mWakefulnessLifecycle;
|
||||
private final WakefulnessLifecycle.Observer mWakefulnessObserver =
|
||||
@@ -129,14 +129,13 @@ public class CarrierTextController {
|
||||
}
|
||||
};
|
||||
|
||||
private int mActiveMobileDataSubscription = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
|
||||
private PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
|
||||
private final ActiveDataSubscriptionIdListener mPhoneStateListener =
|
||||
new ActiveDataSubscriptionIdListener() {
|
||||
@Override
|
||||
public void onActiveDataSubscriptionIdChanged(int subId) {
|
||||
mActiveMobileDataSubscription = subId;
|
||||
if (mNetworkSupported.get() && mCarrierTextCallback != null) {
|
||||
updateCarrierText();
|
||||
}
|
||||
if (mNetworkSupported.get() && mCarrierTextCallback != null) {
|
||||
updateCarrierText();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -163,9 +162,15 @@ public class CarrierTextController {
|
||||
* @param separator Separator between different parts of the text
|
||||
*/
|
||||
public CarrierTextController(Context context, CharSequence separator, boolean showAirplaneMode,
|
||||
boolean showMissingSim) {
|
||||
boolean showMissingSim, TelephonyManager telephonyManager,
|
||||
TelephonyListenerManager telephonyListenerManager,
|
||||
@Main Executor mainExecutor, @Background Executor bgExecutor) {
|
||||
mContext = context;
|
||||
mIsEmergencyCallCapable = getTelephonyManager().isVoiceCapable();
|
||||
mTelephonyManager = telephonyManager;
|
||||
mTelephonyListenerManager = telephonyListenerManager;
|
||||
mMainExecutor = mainExecutor;
|
||||
mBgExecutor = bgExecutor;
|
||||
mIsEmergencyCallCapable = mTelephonyManager.isVoiceCapable();
|
||||
|
||||
mShowAirplaneMode = showAirplaneMode;
|
||||
mShowMissingSim = showMissingSim;
|
||||
@@ -173,12 +178,10 @@ public class CarrierTextController {
|
||||
mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
|
||||
mSeparator = separator;
|
||||
mWakefulnessLifecycle = Dependency.get(WakefulnessLifecycle.class);
|
||||
mSimSlotsNumber = getTelephonyManager().getSupportedModemCount();
|
||||
mSimSlotsNumber = mTelephonyManager.getSupportedModemCount();
|
||||
mSimErrorState = new boolean[mSimSlotsNumber];
|
||||
mMainHandler = Dependency.get(Dependency.MAIN_HANDLER);
|
||||
mBgHandler = new Handler(Dependency.get(Dependency.BG_LOOPER));
|
||||
mKeyguardUpdateMonitor = Dependency.get(KeyguardUpdateMonitor.class);
|
||||
mBgHandler.post(() -> {
|
||||
mBgExecutor.execute(() -> {
|
||||
boolean supported =
|
||||
mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY);
|
||||
if (supported && mNetworkSupported.compareAndSet(false, supported)) {
|
||||
@@ -208,7 +211,7 @@ public class CarrierTextController {
|
||||
CharSequence carrierTextForSimIOError = getCarrierTextForSimState(
|
||||
TelephonyManager.SIM_STATE_CARD_IO_ERROR, carrier);
|
||||
// mSimErrorState has the state of each sim indexed by slotID.
|
||||
for (int index = 0; index < getTelephonyManager().getActiveModemCount(); index++) {
|
||||
for (int index = 0; index < mTelephonyManager.getActiveModemCount(); index++) {
|
||||
if (!mSimErrorState[index]) {
|
||||
continue;
|
||||
}
|
||||
@@ -247,26 +250,24 @@ public class CarrierTextController {
|
||||
* This call will always be processed in a background thread.
|
||||
*/
|
||||
private void handleSetListening(CarrierTextCallback callback) {
|
||||
TelephonyManager telephonyManager = getTelephonyManager();
|
||||
if (callback != null) {
|
||||
mCarrierTextCallback = callback;
|
||||
if (mNetworkSupported.get()) {
|
||||
// Keyguard update monitor expects callbacks from main thread
|
||||
mMainHandler.post(() -> mKeyguardUpdateMonitor.registerCallback(mCallback));
|
||||
mMainExecutor.execute(() -> mKeyguardUpdateMonitor.registerCallback(mCallback));
|
||||
mWakefulnessLifecycle.addObserver(mWakefulnessObserver);
|
||||
telephonyManager.listen(mPhoneStateListener,
|
||||
LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE);
|
||||
mTelephonyListenerManager.addActiveDataSubscriptionIdListener(mPhoneStateListener);
|
||||
} else {
|
||||
// Don't listen and clear out the text when the device isn't a phone.
|
||||
mMainHandler.post(() -> callback.updateCarrierInfo(
|
||||
mMainExecutor.execute(() -> callback.updateCarrierInfo(
|
||||
new CarrierTextCallbackInfo("", null, false, null)
|
||||
));
|
||||
}
|
||||
} else {
|
||||
mCarrierTextCallback = null;
|
||||
mMainHandler.post(() -> mKeyguardUpdateMonitor.removeCallback(mCallback));
|
||||
mMainExecutor.execute(() -> mKeyguardUpdateMonitor.removeCallback(mCallback));
|
||||
mWakefulnessLifecycle.removeObserver(mWakefulnessObserver);
|
||||
telephonyManager.listen(mPhoneStateListener, LISTEN_NONE);
|
||||
mTelephonyListenerManager.removeActiveDataSubscriptionIdListener(mPhoneStateListener);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -277,7 +278,7 @@ public class CarrierTextController {
|
||||
* @param callback Callback to provide text updates
|
||||
*/
|
||||
public void setListening(CarrierTextCallback callback) {
|
||||
mBgHandler.post(() -> handleSetListening(callback));
|
||||
mBgExecutor.execute(() -> handleSetListening(callback));
|
||||
}
|
||||
|
||||
protected List<SubscriptionInfo> getSubscriptionInfo() {
|
||||
@@ -400,7 +401,7 @@ public class CarrierTextController {
|
||||
protected void postToCallback(CarrierTextCallbackInfo info) {
|
||||
final CarrierTextCallback callback = mCarrierTextCallback;
|
||||
if (callback != null) {
|
||||
mMainHandler.post(() -> callback.updateCarrierInfo(info));
|
||||
mMainExecutor.execute(() -> callback.updateCarrierInfo(info));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -620,14 +621,25 @@ public class CarrierTextController {
|
||||
public static class Builder {
|
||||
private final Context mContext;
|
||||
private final String mSeparator;
|
||||
private final TelephonyManager mTelephonyManager;
|
||||
private final TelephonyListenerManager mTelephonyListenerManager;
|
||||
private final Executor mMainExecutor;
|
||||
private final Executor mBgExecutor;
|
||||
private boolean mShowAirplaneMode;
|
||||
private boolean mShowMissingSim;
|
||||
|
||||
@Inject
|
||||
public Builder(Context context, @Main Resources resources) {
|
||||
public Builder(Context context, @Main Resources resources,
|
||||
TelephonyManager telephonyManager,
|
||||
TelephonyListenerManager telephonyListenerManager, @Main Executor mainExecutor,
|
||||
@Background Executor bgExecutor) {
|
||||
mContext = context;
|
||||
mSeparator = resources.getString(
|
||||
com.android.internal.R.string.kg_text_message_separator);
|
||||
mTelephonyManager = telephonyManager;
|
||||
mTelephonyListenerManager = telephonyListenerManager;
|
||||
mMainExecutor = mainExecutor;
|
||||
mBgExecutor = bgExecutor;
|
||||
}
|
||||
|
||||
|
||||
@@ -643,7 +655,8 @@ public class CarrierTextController {
|
||||
|
||||
public CarrierTextController build() {
|
||||
return new CarrierTextController(
|
||||
mContext, mSeparator, mShowAirplaneMode, mShowMissingSim);
|
||||
mContext, mSeparator, mShowAirplaneMode, mShowMissingSim, mTelephonyManager,
|
||||
mTelephonyListenerManager, mMainExecutor, mBgExecutor);
|
||||
}
|
||||
}
|
||||
/**
|
||||
|
||||
@@ -22,7 +22,6 @@ import static android.content.Intent.ACTION_USER_REMOVED;
|
||||
import static android.content.Intent.ACTION_USER_STOPPED;
|
||||
import static android.content.Intent.ACTION_USER_UNLOCKED;
|
||||
import static android.os.BatteryManager.BATTERY_STATUS_UNKNOWN;
|
||||
import static android.telephony.PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE;
|
||||
|
||||
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT;
|
||||
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW;
|
||||
@@ -76,11 +75,11 @@ import android.provider.Settings;
|
||||
import android.service.dreams.DreamService;
|
||||
import android.service.dreams.IDreamManager;
|
||||
import android.telephony.CarrierConfigManager;
|
||||
import android.telephony.PhoneStateListener;
|
||||
import android.telephony.ServiceState;
|
||||
import android.telephony.SubscriptionInfo;
|
||||
import android.telephony.SubscriptionManager;
|
||||
import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
|
||||
import android.telephony.TelephonyCallback;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
@@ -107,6 +106,7 @@ import com.android.systemui.shared.system.TaskStackChangeListeners;
|
||||
import com.android.systemui.statusbar.FeatureFlags;
|
||||
import com.android.systemui.statusbar.StatusBarState;
|
||||
import com.android.systemui.statusbar.phone.KeyguardBypassController;
|
||||
import com.android.systemui.telephony.TelephonyListenerManager;
|
||||
import com.android.systemui.util.Assert;
|
||||
import com.android.systemui.util.RingerModeTracker;
|
||||
|
||||
@@ -290,6 +290,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
||||
private boolean mDeviceInteractive;
|
||||
private boolean mScreenOn;
|
||||
private SubscriptionManager mSubscriptionManager;
|
||||
private final TelephonyListenerManager mTelephonyListenerManager;
|
||||
private List<SubscriptionInfo> mSubscriptionInfo;
|
||||
private TrustManager mTrustManager;
|
||||
private UserManager mUserManager;
|
||||
@@ -358,7 +359,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
||||
};
|
||||
|
||||
@VisibleForTesting
|
||||
public PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
|
||||
public TelephonyCallback.ActiveDataSubscriptionIdListener mPhoneStateListener =
|
||||
new TelephonyCallback.ActiveDataSubscriptionIdListener() {
|
||||
@Override
|
||||
public void onActiveDataSubscriptionIdChanged(int subId) {
|
||||
mActiveMobileDataSubscription = subId;
|
||||
@@ -1614,9 +1616,11 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
||||
StatusBarStateController statusBarStateController,
|
||||
LockPatternUtils lockPatternUtils,
|
||||
AuthController authController,
|
||||
TelephonyListenerManager telephonyListenerManager,
|
||||
FeatureFlags featureFlags) {
|
||||
mContext = context;
|
||||
mSubscriptionManager = SubscriptionManager.from(context);
|
||||
mTelephonyListenerManager = telephonyListenerManager;
|
||||
mDeviceProvisioned = isDeviceProvisionedInSettingsDb();
|
||||
mStrongAuthTracker = new StrongAuthTracker(context, this::notifyStrongAuthStateChanged);
|
||||
mBackgroundExecutor = backgroundExecutor;
|
||||
@@ -1865,8 +1869,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
||||
mTelephonyManager =
|
||||
(TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
|
||||
if (mTelephonyManager != null) {
|
||||
mTelephonyManager.listen(mPhoneStateListener,
|
||||
LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE);
|
||||
mTelephonyListenerManager.addActiveDataSubscriptionIdListener(mPhoneStateListener);
|
||||
// Set initial sim states values.
|
||||
for (int slot = 0; slot < mTelephonyManager.getActiveModemCount(); slot++) {
|
||||
int state = mTelephonyManager.getSimState(slot);
|
||||
@@ -3123,7 +3126,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
||||
TelephonyManager telephony =
|
||||
(TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
|
||||
if (telephony != null) {
|
||||
telephony.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
|
||||
mTelephonyListenerManager.removeActiveDataSubscriptionIdListener(mPhoneStateListener);
|
||||
}
|
||||
|
||||
mSubscriptionManager.removeOnSubscriptionsChangedListener(mSubscriptionListener);
|
||||
|
||||
@@ -120,6 +120,7 @@ import com.android.systemui.statusbar.policy.SmartReplyConstants;
|
||||
import com.android.systemui.statusbar.policy.UserInfoController;
|
||||
import com.android.systemui.statusbar.policy.UserSwitcherController;
|
||||
import com.android.systemui.statusbar.policy.ZenModeController;
|
||||
import com.android.systemui.telephony.TelephonyListenerManager;
|
||||
import com.android.systemui.tracing.ProtoTracer;
|
||||
import com.android.systemui.tuner.TunablePadding.TunablePaddingService;
|
||||
import com.android.systemui.tuner.TunerService;
|
||||
@@ -350,6 +351,7 @@ public class Dependency {
|
||||
@Inject Lazy<MediaOutputDialogFactory> mMediaOutputDialogFactory;
|
||||
@Inject Lazy<DeviceConfigProxy> mDeviceConfigProxy;
|
||||
@Inject Lazy<NavigationBarOverlayController> mNavbarButtonsControllerLazy;
|
||||
@Inject Lazy<TelephonyListenerManager> mTelephonyListenerManager;
|
||||
|
||||
@Inject
|
||||
public Dependency() {
|
||||
@@ -545,6 +547,7 @@ public class Dependency {
|
||||
mProviders.put(StatusBar.class, mStatusBar::get);
|
||||
mProviders.put(ProtoTracer.class, mProtoTracer::get);
|
||||
mProviders.put(DeviceConfigProxy.class, mDeviceConfigProxy::get);
|
||||
mProviders.put(TelephonyListenerManager.class, mTelephonyListenerManager::get);
|
||||
|
||||
// TODO(b/118592525): to support multi-display , we start to add something which is
|
||||
// per-display, while others may be global. I think it's time to add
|
||||
|
||||
@@ -73,8 +73,8 @@ import android.provider.Settings;
|
||||
import android.service.dreams.IDreamManager;
|
||||
import android.sysprop.TelephonyProperties;
|
||||
import android.telecom.TelecomManager;
|
||||
import android.telephony.PhoneStateListener;
|
||||
import android.telephony.ServiceState;
|
||||
import android.telephony.TelephonyCallback;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.transition.AutoTransition;
|
||||
import android.transition.TransitionManager;
|
||||
@@ -138,6 +138,7 @@ import com.android.systemui.statusbar.NotificationShadeDepthController;
|
||||
import com.android.systemui.statusbar.NotificationShadeWindowController;
|
||||
import com.android.systemui.statusbar.policy.ConfigurationController;
|
||||
import com.android.systemui.statusbar.policy.KeyguardStateController;
|
||||
import com.android.systemui.telephony.TelephonyListenerManager;
|
||||
import com.android.systemui.util.EmergencyDialerConstants;
|
||||
import com.android.systemui.util.RingerModeTracker;
|
||||
import com.android.systemui.util.leak.RotationUtils;
|
||||
@@ -303,7 +304,8 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
|
||||
AudioManager audioManager, IDreamManager iDreamManager,
|
||||
DevicePolicyManager devicePolicyManager, LockPatternUtils lockPatternUtils,
|
||||
BroadcastDispatcher broadcastDispatcher,
|
||||
ConnectivityManager connectivityManager, TelephonyManager telephonyManager,
|
||||
ConnectivityManager connectivityManager,
|
||||
TelephonyListenerManager telephonyListenerManager,
|
||||
ContentResolver contentResolver, @Nullable Vibrator vibrator, @Main Resources resources,
|
||||
ConfigurationController configurationController, ActivityStarter activityStarter,
|
||||
KeyguardStateController keyguardStateController, UserManager userManager,
|
||||
@@ -361,7 +363,7 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
|
||||
context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY);
|
||||
|
||||
// get notified of phone state changes
|
||||
telephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_SERVICE_STATE);
|
||||
telephonyListenerManager.addServiceStateListener(mPhoneStateListener);
|
||||
contentResolver.registerContentObserver(
|
||||
Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON), true,
|
||||
mAirplaneModeObserver);
|
||||
@@ -2049,7 +2051,8 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
|
||||
}
|
||||
};
|
||||
|
||||
PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
|
||||
private final TelephonyCallback.ServiceStateListener mPhoneStateListener =
|
||||
new TelephonyCallback.ServiceStateListener() {
|
||||
@Override
|
||||
public void onServiceStateChanged(ServiceState serviceState) {
|
||||
if (!mHasTelephony) return;
|
||||
|
||||
@@ -22,7 +22,6 @@ import static android.net.wifi.WifiManager.TrafficStateCallback.DATA_ACTIVITY_IN
|
||||
import static android.net.wifi.WifiManager.TrafficStateCallback.DATA_ACTIVITY_INOUT;
|
||||
import static android.net.wifi.WifiManager.TrafficStateCallback.DATA_ACTIVITY_NONE;
|
||||
import static android.net.wifi.WifiManager.TrafficStateCallback.DATA_ACTIVITY_OUT;
|
||||
import static android.telephony.PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.content.BroadcastReceiver;
|
||||
@@ -44,11 +43,11 @@ import android.os.Looper;
|
||||
import android.provider.Settings;
|
||||
import android.telephony.CarrierConfigManager;
|
||||
import android.telephony.CellSignalStrength;
|
||||
import android.telephony.PhoneStateListener;
|
||||
import android.telephony.ServiceState;
|
||||
import android.telephony.SubscriptionInfo;
|
||||
import android.telephony.SubscriptionManager;
|
||||
import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
|
||||
import android.telephony.TelephonyCallback;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.text.TextUtils;
|
||||
import android.util.FeatureFlagUtils;
|
||||
@@ -74,6 +73,7 @@ import com.android.systemui.demomode.DemoMode;
|
||||
import com.android.systemui.demomode.DemoModeController;
|
||||
import com.android.systemui.settings.CurrentUserTracker;
|
||||
import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
|
||||
import com.android.systemui.telephony.TelephonyListenerManager;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.PrintWriter;
|
||||
@@ -108,6 +108,7 @@ public class NetworkControllerImpl extends BroadcastReceiver
|
||||
|
||||
private final Context mContext;
|
||||
private final TelephonyManager mPhone;
|
||||
private final TelephonyListenerManager mTelephonyListenerManager;
|
||||
private final WifiManager mWifiManager;
|
||||
private final ConnectivityManager mConnectivityManager;
|
||||
private final SubscriptionManager mSubscriptionManager;
|
||||
@@ -121,7 +122,7 @@ public class NetworkControllerImpl extends BroadcastReceiver
|
||||
private final boolean mProviderModel;
|
||||
private Config mConfig;
|
||||
|
||||
private PhoneStateListener mPhoneStateListener;
|
||||
private TelephonyCallback.ActiveDataSubscriptionIdListener mPhoneStateListener;
|
||||
private int mActiveMobileDataSubscription = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
|
||||
|
||||
// Subcontrollers.
|
||||
@@ -201,12 +202,14 @@ public class NetworkControllerImpl extends BroadcastReceiver
|
||||
BroadcastDispatcher broadcastDispatcher,
|
||||
ConnectivityManager connectivityManager,
|
||||
TelephonyManager telephonyManager,
|
||||
TelephonyListenerManager telephonyListenerManager,
|
||||
@Nullable WifiManager wifiManager,
|
||||
NetworkScoreManager networkScoreManager,
|
||||
AccessPointControllerImpl accessPointController,
|
||||
DemoModeController demoModeController) {
|
||||
this(context, connectivityManager,
|
||||
telephonyManager,
|
||||
telephonyListenerManager,
|
||||
wifiManager,
|
||||
networkScoreManager,
|
||||
SubscriptionManager.from(context), Config.readConfig(context), bgLooper,
|
||||
@@ -222,7 +225,9 @@ public class NetworkControllerImpl extends BroadcastReceiver
|
||||
|
||||
@VisibleForTesting
|
||||
NetworkControllerImpl(Context context, ConnectivityManager connectivityManager,
|
||||
TelephonyManager telephonyManager, WifiManager wifiManager,
|
||||
TelephonyManager telephonyManager,
|
||||
TelephonyListenerManager telephonyListenerManager,
|
||||
WifiManager wifiManager,
|
||||
NetworkScoreManager networkScoreManager,
|
||||
SubscriptionManager subManager, Config config, Looper bgLooper,
|
||||
CallbackHandler callbackHandler,
|
||||
@@ -233,6 +238,7 @@ public class NetworkControllerImpl extends BroadcastReceiver
|
||||
BroadcastDispatcher broadcastDispatcher,
|
||||
DemoModeController demoModeController) {
|
||||
mContext = context;
|
||||
mTelephonyListenerManager = telephonyListenerManager;
|
||||
mConfig = config;
|
||||
mReceiverHandler = new Handler(bgLooper);
|
||||
mCallbackHandler = callbackHandler;
|
||||
@@ -372,23 +378,20 @@ public class NetworkControllerImpl extends BroadcastReceiver
|
||||
// exclusively for status bar icons.
|
||||
mConnectivityManager.registerDefaultNetworkCallback(callback, mReceiverHandler);
|
||||
// Register the listener on our bg looper
|
||||
mPhoneStateListener = new PhoneStateListener(mReceiverHandler::post) {
|
||||
@Override
|
||||
public void onActiveDataSubscriptionIdChanged(int subId) {
|
||||
// For data switching from A to B, we assume B is validated for up to 2 seconds iff:
|
||||
// 1) A and B are in the same subscription group e.g. CBRS data switch. And
|
||||
// 2) A was validated before the switch.
|
||||
// This is to provide smooth transition for UI without showing cross during data
|
||||
// switch.
|
||||
if (keepCellularValidationBitInSwitch(mActiveMobileDataSubscription, subId)) {
|
||||
if (DEBUG) Log.d(TAG, ": mForceCellularValidated to true.");
|
||||
mForceCellularValidated = true;
|
||||
mReceiverHandler.removeCallbacks(mClearForceValidated);
|
||||
mReceiverHandler.postDelayed(mClearForceValidated, 2000);
|
||||
}
|
||||
mActiveMobileDataSubscription = subId;
|
||||
doUpdateMobileControllers();
|
||||
mPhoneStateListener = subId -> {
|
||||
// For data switching from A to B, we assume B is validated for up to 2 seconds iff:
|
||||
// 1) A and B are in the same subscription group e.g. CBRS data switch. And
|
||||
// 2) A was validated before the switch.
|
||||
// This is to provide smooth transition for UI without showing cross during data
|
||||
// switch.
|
||||
if (keepCellularValidationBitInSwitch(mActiveMobileDataSubscription, subId)) {
|
||||
if (DEBUG) Log.d(TAG, ": mForceCellularValidated to true.");
|
||||
mForceCellularValidated = true;
|
||||
mReceiverHandler.removeCallbacks(mClearForceValidated);
|
||||
mReceiverHandler.postDelayed(mClearForceValidated, 2000);
|
||||
}
|
||||
mActiveMobileDataSubscription = subId;
|
||||
doUpdateMobileControllers();
|
||||
};
|
||||
|
||||
mDemoModeController.addCallback(this);
|
||||
@@ -428,7 +431,7 @@ public class NetworkControllerImpl extends BroadcastReceiver
|
||||
mSubscriptionListener = new SubListener();
|
||||
}
|
||||
mSubscriptionManager.addOnSubscriptionsChangedListener(mSubscriptionListener);
|
||||
mPhone.listen(mPhoneStateListener, LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE);
|
||||
mTelephonyListenerManager.addActiveDataSubscriptionIdListener(mPhoneStateListener);
|
||||
|
||||
// broadcasts
|
||||
IntentFilter filter = new IntentFilter();
|
||||
|
||||
@@ -42,8 +42,7 @@ import android.os.RemoteException;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.provider.Settings;
|
||||
import android.telephony.PhoneStateListener;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.telephony.TelephonyCallback;
|
||||
import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
import android.util.SparseBooleanArray;
|
||||
@@ -69,6 +68,7 @@ import com.android.systemui.plugins.qs.DetailAdapter;
|
||||
import com.android.systemui.qs.QSUserSwitcherEvent;
|
||||
import com.android.systemui.qs.tiles.UserDetailView;
|
||||
import com.android.systemui.statusbar.phone.SystemUIDialog;
|
||||
import com.android.systemui.telephony.TelephonyListenerManager;
|
||||
import com.android.systemui.user.CreateUserActivity;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
@@ -105,6 +105,7 @@ public class UserSwitcherController implements Dumpable {
|
||||
protected final Handler mHandler;
|
||||
private final ActivityStarter mActivityStarter;
|
||||
private final BroadcastDispatcher mBroadcastDispatcher;
|
||||
private final TelephonyListenerManager mTelephonyListenerManager;
|
||||
private final IActivityTaskManager mActivityTaskManager;
|
||||
|
||||
private ArrayList<UserRecord> mUsers = new ArrayList<>();
|
||||
@@ -127,9 +128,11 @@ public class UserSwitcherController implements Dumpable {
|
||||
public UserSwitcherController(Context context, KeyguardStateController keyguardStateController,
|
||||
@Main Handler handler, ActivityStarter activityStarter,
|
||||
BroadcastDispatcher broadcastDispatcher, UiEventLogger uiEventLogger,
|
||||
TelephonyListenerManager telephonyListenerManager,
|
||||
IActivityTaskManager activityTaskManager) {
|
||||
mContext = context;
|
||||
mBroadcastDispatcher = broadcastDispatcher;
|
||||
mTelephonyListenerManager = telephonyListenerManager;
|
||||
mActivityTaskManager = activityTaskManager;
|
||||
mUiEventLogger = uiEventLogger;
|
||||
mUserDetailAdapter = new UserDetailAdapter(this, mContext, mUiEventLogger);
|
||||
@@ -458,18 +461,15 @@ public class UserSwitcherController implements Dumpable {
|
||||
}
|
||||
|
||||
private void listenForCallState() {
|
||||
final TelephonyManager tele =
|
||||
(TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
|
||||
if (tele != null) {
|
||||
tele.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
|
||||
}
|
||||
mTelephonyListenerManager.addCallStateListener(mPhoneStateListener);
|
||||
}
|
||||
|
||||
private final PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
|
||||
private final TelephonyCallback.CallStateListener mPhoneStateListener =
|
||||
new TelephonyCallback.CallStateListener() {
|
||||
private int mCallState;
|
||||
|
||||
@Override
|
||||
public void onCallStateChanged(int state, String incomingNumber) {
|
||||
public void onCallStateChanged(int state) {
|
||||
if (mCallState == state) return;
|
||||
if (DEBUG) Log.v(TAG, "Call state changed: " + state);
|
||||
mCallState = state;
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.systemui.telephony;
|
||||
|
||||
import android.telephony.ServiceState;
|
||||
import android.telephony.TelephonyCallback.ActiveDataSubscriptionIdListener;
|
||||
import android.telephony.TelephonyCallback.CallStateListener;
|
||||
import android.telephony.TelephonyCallback.ServiceStateListener;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
class TelephonyCallback extends android.telephony.TelephonyCallback
|
||||
implements ActiveDataSubscriptionIdListener, CallStateListener, ServiceStateListener {
|
||||
|
||||
private final List<ActiveDataSubscriptionIdListener> mActiveDataSubscriptionIdListeners =
|
||||
new ArrayList<>();
|
||||
private final List<CallStateListener> mCallStateListeners = new ArrayList<>();
|
||||
private final List<ServiceStateListener> mServiceStateListeners = new ArrayList<>();
|
||||
|
||||
@Inject
|
||||
TelephonyCallback() {
|
||||
}
|
||||
|
||||
boolean hasAnyListeners() {
|
||||
return !mActiveDataSubscriptionIdListeners.isEmpty()
|
||||
|| !mCallStateListeners.isEmpty()
|
||||
|| !mServiceStateListeners.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActiveDataSubscriptionIdChanged(int subId) {
|
||||
mActiveDataSubscriptionIdListeners.forEach(listener -> {
|
||||
listener.onActiveDataSubscriptionIdChanged(subId);
|
||||
});
|
||||
}
|
||||
|
||||
void addActiveDataSubscriptionIdListener(ActiveDataSubscriptionIdListener listener) {
|
||||
mActiveDataSubscriptionIdListeners.add(listener);
|
||||
}
|
||||
|
||||
void removeActiveDataSubscriptionIdListener(ActiveDataSubscriptionIdListener listener) {
|
||||
mActiveDataSubscriptionIdListeners.remove(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCallStateChanged(int state) {
|
||||
mCallStateListeners.forEach(listener -> {
|
||||
listener.onCallStateChanged(state);
|
||||
});
|
||||
}
|
||||
|
||||
void addCallStateListener(CallStateListener listener) {
|
||||
mCallStateListeners.add(listener);
|
||||
}
|
||||
|
||||
void removeCallStateListener(CallStateListener listener) {
|
||||
mCallStateListeners.remove(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceStateChanged(@NonNull ServiceState serviceState) {
|
||||
mServiceStateListeners.forEach(listener -> {
|
||||
listener.onServiceStateChanged(serviceState);
|
||||
});
|
||||
}
|
||||
|
||||
void addServiceStateListener(ServiceStateListener listener) {
|
||||
mServiceStateListeners.add(listener);
|
||||
}
|
||||
|
||||
void removeServiceStateListener(ServiceStateListener listener) {
|
||||
mServiceStateListeners.remove(listener);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.systemui.telephony;
|
||||
|
||||
import android.telephony.PhoneStateListener;
|
||||
import android.telephony.TelephonyCallback.ActiveDataSubscriptionIdListener;
|
||||
import android.telephony.TelephonyCallback.CallStateListener;
|
||||
import android.telephony.TelephonyCallback.ServiceStateListener;
|
||||
import android.telephony.TelephonyManager;
|
||||
|
||||
import com.android.systemui.dagger.SysUISingleton;
|
||||
import com.android.systemui.dagger.qualifiers.Main;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
/**
|
||||
* Wrapper around {@link TelephonyManager#listen(PhoneStateListener, int)}.
|
||||
*
|
||||
* The TelephonyManager complains if too many places in code register a listener. This class
|
||||
* encapsulates SystemUI's usage of this function, reducing it down to a single listener.
|
||||
*
|
||||
* See also
|
||||
* {@link TelephonyManager#registerTelephonyCallback(Executor, android.telephony.TelephonyCallback)}
|
||||
*/
|
||||
@SysUISingleton
|
||||
public class TelephonyListenerManager {
|
||||
private final TelephonyManager mTelephonyManager;
|
||||
private final Executor mExecutor;
|
||||
private final TelephonyCallback mTelephonyCallback;
|
||||
|
||||
private boolean mListening = false;
|
||||
|
||||
@Inject
|
||||
public TelephonyListenerManager(TelephonyManager telephonyManager, @Main Executor executor,
|
||||
TelephonyCallback telephonyCallback) {
|
||||
mTelephonyManager = telephonyManager;
|
||||
mExecutor = executor;
|
||||
mTelephonyCallback = telephonyCallback;
|
||||
}
|
||||
|
||||
/** */
|
||||
public void addActiveDataSubscriptionIdListener(ActiveDataSubscriptionIdListener listener) {
|
||||
mTelephonyCallback.addActiveDataSubscriptionIdListener(listener);
|
||||
updateListening();
|
||||
}
|
||||
|
||||
/** */
|
||||
public void removeActiveDataSubscriptionIdListener(ActiveDataSubscriptionIdListener listener) {
|
||||
mTelephonyCallback.removeActiveDataSubscriptionIdListener(listener);
|
||||
updateListening();
|
||||
}
|
||||
|
||||
/** */
|
||||
public void addCallStateListener(CallStateListener listener) {
|
||||
mTelephonyCallback.addCallStateListener(listener);
|
||||
updateListening();
|
||||
}
|
||||
|
||||
/** */
|
||||
public void removeCallStateListener(CallStateListener listener) {
|
||||
mTelephonyCallback.removeCallStateListener(listener);
|
||||
updateListening();
|
||||
}
|
||||
|
||||
/** */
|
||||
public void addServiceStateListener(ServiceStateListener listener) {
|
||||
mTelephonyCallback.addServiceStateListener(listener);
|
||||
updateListening();
|
||||
}
|
||||
|
||||
/** */
|
||||
public void removeServiceStateListener(ServiceStateListener listener) {
|
||||
mTelephonyCallback.removeServiceStateListener(listener);
|
||||
updateListening();
|
||||
}
|
||||
|
||||
|
||||
private void updateListening() {
|
||||
if (!mListening && mTelephonyCallback.hasAnyListeners()) {
|
||||
mListening = true;
|
||||
mTelephonyManager.registerTelephonyCallback(mExecutor, mTelephonyCallback);
|
||||
} else if (mListening && !mTelephonyCallback.hasAnyListeners()) {
|
||||
mTelephonyManager.unregisterTelephonyCallback(mTelephonyCallback);
|
||||
mListening = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,12 +21,13 @@ import static android.telephony.SubscriptionManager.DATA_ROAMING_DISABLE;
|
||||
import static android.telephony.SubscriptionManager.DATA_ROAMING_ENABLE;
|
||||
import static android.telephony.SubscriptionManager.NAME_SOURCE_CARRIER_ID;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static junit.framework.Assert.assertTrue;
|
||||
import static junit.framework.TestCase.assertFalse;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
@@ -40,10 +41,6 @@ import static org.mockito.Mockito.when;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.net.wifi.WifiInfo;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.Looper;
|
||||
import android.os.Process;
|
||||
import android.provider.Settings;
|
||||
import android.telephony.ServiceState;
|
||||
import android.telephony.SubscriptionInfo;
|
||||
@@ -51,13 +48,14 @@ import android.telephony.SubscriptionManager;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.test.suitebuilder.annotation.SmallTest;
|
||||
import android.testing.AndroidTestingRunner;
|
||||
import android.testing.TestableLooper;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.android.systemui.Dependency;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.keyguard.WakefulnessLifecycle;
|
||||
import com.android.systemui.telephony.TelephonyListenerManager;
|
||||
import com.android.systemui.util.concurrency.FakeExecutor;
|
||||
import com.android.systemui.util.time.FakeSystemClock;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -73,7 +71,6 @@ import java.util.List;
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner.class)
|
||||
@TestableLooper.RunWithLooper
|
||||
public class CarrierTextControllerTest extends SysuiTestCase {
|
||||
|
||||
private static final CharSequence SEPARATOR = " \u2014 ";
|
||||
@@ -103,24 +100,25 @@ public class CarrierTextControllerTest extends SysuiTestCase {
|
||||
@Mock
|
||||
private TelephonyManager mTelephonyManager;
|
||||
@Mock
|
||||
private TelephonyListenerManager mTelephonyListenerManager;
|
||||
private FakeSystemClock mFakeSystemClock = new FakeSystemClock();
|
||||
private FakeExecutor mMainExecutor = new FakeExecutor(mFakeSystemClock);
|
||||
private FakeExecutor mBgExecutor = new FakeExecutor(mFakeSystemClock);
|
||||
@Mock
|
||||
private SubscriptionManager mSubscriptionManager;
|
||||
private CarrierTextController.CarrierTextCallbackInfo mCarrierTextCallbackInfo;
|
||||
|
||||
private CarrierTextController mCarrierTextController;
|
||||
private TestableLooper mTestableLooper;
|
||||
|
||||
private Void checkMainThread(InvocationOnMock inv) {
|
||||
Looper mainLooper = Dependency.get(Dependency.MAIN_HANDLER).getLooper();
|
||||
if (!mainLooper.isCurrentThread()) {
|
||||
fail("This call should be done from the main thread");
|
||||
}
|
||||
assertThat(mMainExecutor.isExecuting()).isTrue();
|
||||
assertThat(mBgExecutor.isExecuting()).isFalse();
|
||||
return null;
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mTestableLooper = TestableLooper.get(this);
|
||||
|
||||
mContext.addMockSystemService(WifiManager.class, mWifiManager);
|
||||
mContext.addMockSystemService(PackageManager.class, mPackageManager);
|
||||
@@ -132,9 +130,6 @@ public class CarrierTextControllerTest extends SysuiTestCase {
|
||||
mContext.getOrCreateTestableResources().addOverride(
|
||||
R.string.airplane_mode, AIRPLANE_MODE_TEXT);
|
||||
mDependency.injectMockDependency(WakefulnessLifecycle.class);
|
||||
mDependency.injectTestDependency(Dependency.MAIN_HANDLER,
|
||||
new Handler(mTestableLooper.getLooper()));
|
||||
mDependency.injectTestDependency(Dependency.BG_LOOPER, mTestableLooper.getLooper());
|
||||
mDependency.injectTestDependency(KeyguardUpdateMonitor.class, mKeyguardUpdateMonitor);
|
||||
|
||||
doAnswer(this::checkMainThread).when(mKeyguardUpdateMonitor)
|
||||
@@ -147,30 +142,21 @@ public class CarrierTextControllerTest extends SysuiTestCase {
|
||||
when(mTelephonyManager.getSupportedModemCount()).thenReturn(3);
|
||||
when(mTelephonyManager.getActiveModemCount()).thenReturn(3);
|
||||
|
||||
mCarrierTextController = new CarrierTextController(mContext, SEPARATOR, true, true);
|
||||
mCarrierTextController = new CarrierTextController(
|
||||
mContext, SEPARATOR, true, true,
|
||||
mTelephonyManager, mTelephonyListenerManager, mMainExecutor,
|
||||
mBgExecutor);
|
||||
// This should not start listening on any of the real dependencies but will test that
|
||||
// callbacks in mKeyguardUpdateMonitor are done in the mTestableLooper thread
|
||||
mCarrierTextController.setListening(mCarrierTextCallback);
|
||||
mTestableLooper.processAllMessages();
|
||||
FakeExecutor.exhaustExecutors(mMainExecutor, mBgExecutor);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testKeyguardUpdateMonitorCalledInMainThread() throws Exception {
|
||||
// This test will run on the main looper (which is not the same as the looper set as MAIN
|
||||
// for CarrierTextCallback. This will fail if calls to mKeyguardUpdateMonitor are not done
|
||||
// through the looper set in the set up
|
||||
HandlerThread thread = new HandlerThread("testThread",
|
||||
Process.THREAD_PRIORITY_BACKGROUND);
|
||||
thread.start();
|
||||
TestableLooper testableLooper = new TestableLooper(thread.getLooper());
|
||||
Handler h = new Handler(testableLooper.getLooper());
|
||||
h.post(() -> {
|
||||
mCarrierTextController.setListening(null);
|
||||
mCarrierTextController.setListening(mCarrierTextCallback);
|
||||
});
|
||||
testableLooper.processAllMessages();
|
||||
mTestableLooper.processAllMessages();
|
||||
thread.quitSafely();
|
||||
mCarrierTextController.setListening(null);
|
||||
mCarrierTextController.setListening(mCarrierTextCallback);
|
||||
FakeExecutor.exhaustExecutors(mMainExecutor, mBgExecutor);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -189,7 +175,7 @@ public class CarrierTextControllerTest extends SysuiTestCase {
|
||||
ArgumentCaptor.forClass(
|
||||
CarrierTextController.CarrierTextCallbackInfo.class);
|
||||
|
||||
mTestableLooper.processAllMessages();
|
||||
FakeExecutor.exhaustExecutors(mMainExecutor, mBgExecutor);
|
||||
verify(mCarrierTextCallback).updateCarrierInfo(captor.capture());
|
||||
assertEquals(AIRPLANE_MODE_TEXT, captor.getValue().carrierText);
|
||||
}
|
||||
@@ -212,7 +198,7 @@ public class CarrierTextControllerTest extends SysuiTestCase {
|
||||
ArgumentCaptor.forClass(
|
||||
CarrierTextController.CarrierTextCallbackInfo.class);
|
||||
|
||||
mTestableLooper.processAllMessages();
|
||||
FakeExecutor.exhaustExecutors(mMainExecutor, mBgExecutor);
|
||||
verify(mCarrierTextCallback).updateCarrierInfo(captor.capture());
|
||||
assertEquals("TEST_CARRIER" + SEPARATOR + INVALID_CARD_TEXT, captor.getValue().carrierText);
|
||||
// There's only one subscription in the list
|
||||
@@ -224,7 +210,7 @@ public class CarrierTextControllerTest extends SysuiTestCase {
|
||||
when(mTelephonyManager.getActiveModemCount()).thenReturn(1);
|
||||
// Update carrier text. It should ignore error state of subId 3 in inactive slotId.
|
||||
mCarrierTextController.updateCarrierText();
|
||||
mTestableLooper.processAllMessages();
|
||||
FakeExecutor.exhaustExecutors(mMainExecutor, mBgExecutor);
|
||||
verify(mCarrierTextCallback).updateCarrierInfo(captor.capture());
|
||||
assertEquals("TEST_CARRIER", captor.getValue().carrierText);
|
||||
}
|
||||
@@ -260,7 +246,7 @@ public class CarrierTextControllerTest extends SysuiTestCase {
|
||||
mCarrierTextController.mCallback.onSimStateChanged(0, 1,
|
||||
TelephonyManager.SIM_STATE_CARD_IO_ERROR);
|
||||
|
||||
mTestableLooper.processAllMessages();
|
||||
FakeExecutor.exhaustExecutors(mMainExecutor, mBgExecutor);
|
||||
verify(mCarrierTextCallback).updateCarrierInfo(
|
||||
any(CarrierTextController.CarrierTextCallbackInfo.class));
|
||||
}
|
||||
@@ -269,7 +255,7 @@ public class CarrierTextControllerTest extends SysuiTestCase {
|
||||
public void testCallback() {
|
||||
reset(mCarrierTextCallback);
|
||||
mCarrierTextController.postToCallback(mCarrierTextCallbackInfo);
|
||||
mTestableLooper.processAllMessages();
|
||||
FakeExecutor.exhaustExecutors(mMainExecutor, mBgExecutor);
|
||||
|
||||
ArgumentCaptor<CarrierTextController.CarrierTextCallbackInfo> captor =
|
||||
ArgumentCaptor.forClass(
|
||||
@@ -286,7 +272,7 @@ public class CarrierTextControllerTest extends SysuiTestCase {
|
||||
mCarrierTextController.setListening(null);
|
||||
|
||||
// This shouldn't produce NPE
|
||||
mTestableLooper.processAllMessages();
|
||||
FakeExecutor.exhaustExecutors(mMainExecutor, mBgExecutor);
|
||||
verify(mCarrierTextCallback).updateCarrierInfo(any());
|
||||
}
|
||||
|
||||
@@ -306,7 +292,7 @@ public class CarrierTextControllerTest extends SysuiTestCase {
|
||||
CarrierTextController.CarrierTextCallbackInfo.class);
|
||||
|
||||
mCarrierTextController.updateCarrierText();
|
||||
mTestableLooper.processAllMessages();
|
||||
FakeExecutor.exhaustExecutors(mMainExecutor, mBgExecutor);
|
||||
verify(mCarrierTextCallback).updateCarrierInfo(captor.capture());
|
||||
|
||||
CarrierTextController.CarrierTextCallbackInfo info = captor.getValue();
|
||||
@@ -331,7 +317,7 @@ public class CarrierTextControllerTest extends SysuiTestCase {
|
||||
CarrierTextController.CarrierTextCallbackInfo.class);
|
||||
|
||||
mCarrierTextController.updateCarrierText();
|
||||
mTestableLooper.processAllMessages();
|
||||
FakeExecutor.exhaustExecutors(mMainExecutor, mBgExecutor);
|
||||
verify(mCarrierTextCallback).updateCarrierInfo(captor.capture());
|
||||
|
||||
CarrierTextController.CarrierTextCallbackInfo info = captor.getValue();
|
||||
@@ -356,7 +342,7 @@ public class CarrierTextControllerTest extends SysuiTestCase {
|
||||
CarrierTextController.CarrierTextCallbackInfo.class);
|
||||
|
||||
mCarrierTextController.updateCarrierText();
|
||||
mTestableLooper.processAllMessages();
|
||||
FakeExecutor.exhaustExecutors(mMainExecutor, mBgExecutor);
|
||||
verify(mCarrierTextCallback).updateCarrierInfo(captor.capture());
|
||||
|
||||
assertTrue("Carrier text should be empty, instead it's " + captor.getValue().carrierText,
|
||||
@@ -385,7 +371,7 @@ public class CarrierTextControllerTest extends SysuiTestCase {
|
||||
CarrierTextController.CarrierTextCallbackInfo.class);
|
||||
|
||||
mCarrierTextController.updateCarrierText();
|
||||
mTestableLooper.processAllMessages();
|
||||
FakeExecutor.exhaustExecutors(mMainExecutor, mBgExecutor);
|
||||
verify(mCarrierTextCallback).updateCarrierInfo(captor.capture());
|
||||
|
||||
assertFalse("No SIM should be available", captor.getValue().anySimReady);
|
||||
@@ -412,7 +398,7 @@ public class CarrierTextControllerTest extends SysuiTestCase {
|
||||
CarrierTextController.CarrierTextCallbackInfo.class);
|
||||
|
||||
mCarrierTextController.updateCarrierText();
|
||||
mTestableLooper.processAllMessages();
|
||||
FakeExecutor.exhaustExecutors(mMainExecutor, mBgExecutor);
|
||||
verify(mCarrierTextCallback).updateCarrierInfo(captor.capture());
|
||||
|
||||
CarrierTextController.CarrierTextCallbackInfo info = captor.getValue();
|
||||
@@ -438,7 +424,7 @@ public class CarrierTextControllerTest extends SysuiTestCase {
|
||||
CarrierTextController.CarrierTextCallbackInfo.class);
|
||||
|
||||
mCarrierTextController.updateCarrierText();
|
||||
mTestableLooper.processAllMessages();
|
||||
FakeExecutor.exhaustExecutors(mMainExecutor, mBgExecutor);
|
||||
verify(mCarrierTextCallback).updateCarrierInfo(captor.capture());
|
||||
|
||||
assertEquals(TEST_CARRIER + SEPARATOR + TEST_CARRIER,
|
||||
@@ -463,7 +449,7 @@ public class CarrierTextControllerTest extends SysuiTestCase {
|
||||
CarrierTextController.CarrierTextCallbackInfo.class);
|
||||
|
||||
mCarrierTextController.updateCarrierText();
|
||||
mTestableLooper.processAllMessages();
|
||||
FakeExecutor.exhaustExecutors(mMainExecutor, mBgExecutor);
|
||||
verify(mCarrierTextCallback).updateCarrierInfo(captor.capture());
|
||||
|
||||
assertEquals(TEST_CARRIER,
|
||||
@@ -488,7 +474,7 @@ public class CarrierTextControllerTest extends SysuiTestCase {
|
||||
CarrierTextController.CarrierTextCallbackInfo.class);
|
||||
|
||||
mCarrierTextController.updateCarrierText();
|
||||
mTestableLooper.processAllMessages();
|
||||
FakeExecutor.exhaustExecutors(mMainExecutor, mBgExecutor);
|
||||
verify(mCarrierTextCallback).updateCarrierInfo(captor.capture());
|
||||
|
||||
assertEquals(TEST_CARRIER,
|
||||
@@ -514,7 +500,7 @@ public class CarrierTextControllerTest extends SysuiTestCase {
|
||||
CarrierTextController.CarrierTextCallbackInfo.class);
|
||||
|
||||
mCarrierTextController.updateCarrierText();
|
||||
mTestableLooper.processAllMessages();
|
||||
FakeExecutor.exhaustExecutors(mMainExecutor, mBgExecutor);
|
||||
verify(mCarrierTextCallback).updateCarrierInfo(captor.capture());
|
||||
|
||||
assertEquals(TEST_CARRIER + SEPARATOR + TEST_CARRIER,
|
||||
|
||||
@@ -88,6 +88,7 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||
import com.android.systemui.statusbar.FeatureFlags;
|
||||
import com.android.systemui.statusbar.StatusBarState;
|
||||
import com.android.systemui.statusbar.phone.KeyguardBypassController;
|
||||
import com.android.systemui.telephony.TelephonyListenerManager;
|
||||
import com.android.systemui.util.RingerModeTracker;
|
||||
|
||||
import org.junit.After;
|
||||
@@ -163,6 +164,8 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
|
||||
@Mock
|
||||
private AuthController mAuthController;
|
||||
@Mock
|
||||
private TelephonyListenerManager mTelephonyListenerManager;
|
||||
@Mock
|
||||
private FeatureFlags mFeatureFlags;
|
||||
@Captor
|
||||
private ArgumentCaptor<StatusBarStateController.StateListener> mStatusBarStateListenerCaptor;
|
||||
@@ -883,7 +886,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
|
||||
mBroadcastDispatcher, mDumpManager,
|
||||
mRingerModeTracker, mBackgroundExecutor,
|
||||
mStatusBarStateController, mLockPatternUtils,
|
||||
mAuthController, mFeatureFlags);
|
||||
mAuthController, mTelephonyListenerManager, mFeatureFlags);
|
||||
setStrongAuthTracker(KeyguardUpdateMonitorTest.this.mStrongAuthTracker);
|
||||
}
|
||||
|
||||
|
||||
@@ -43,7 +43,6 @@ import android.os.Handler;
|
||||
import android.os.RemoteException;
|
||||
import android.os.UserManager;
|
||||
import android.service.dreams.IDreamManager;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.testing.AndroidTestingRunner;
|
||||
import android.testing.TestableLooper;
|
||||
import android.view.IWindowManager;
|
||||
@@ -75,6 +74,7 @@ import com.android.systemui.statusbar.NotificationShadeDepthController;
|
||||
import com.android.systemui.statusbar.NotificationShadeWindowController;
|
||||
import com.android.systemui.statusbar.policy.ConfigurationController;
|
||||
import com.android.systemui.statusbar.policy.KeyguardStateController;
|
||||
import com.android.systemui.telephony.TelephonyListenerManager;
|
||||
import com.android.systemui.util.RingerModeLiveData;
|
||||
import com.android.systemui.util.RingerModeTracker;
|
||||
import com.android.systemui.util.settings.SecureSettings;
|
||||
@@ -106,7 +106,7 @@ public class GlobalActionsDialogTest extends SysuiTestCase {
|
||||
@Mock private LockPatternUtils mLockPatternUtils;
|
||||
@Mock private BroadcastDispatcher mBroadcastDispatcher;
|
||||
@Mock private ConnectivityManager mConnectivityManager;
|
||||
@Mock private TelephonyManager mTelephonyManager;
|
||||
@Mock private TelephonyListenerManager mTelephonyListenerManager;
|
||||
@Mock private ContentResolver mContentResolver;
|
||||
@Mock private Resources mResources;
|
||||
@Mock private ConfigurationController mConfigurationController;
|
||||
@@ -167,7 +167,7 @@ public class GlobalActionsDialogTest extends SysuiTestCase {
|
||||
mLockPatternUtils,
|
||||
mBroadcastDispatcher,
|
||||
mConnectivityManager,
|
||||
mTelephonyManager,
|
||||
mTelephonyListenerManager,
|
||||
mContentResolver,
|
||||
null,
|
||||
mResources,
|
||||
|
||||
@@ -76,6 +76,7 @@ import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceP
|
||||
import com.android.systemui.statusbar.policy.NetworkController.IconState;
|
||||
import com.android.systemui.statusbar.policy.NetworkController.MobileDataIndicators;
|
||||
import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
|
||||
import com.android.systemui.telephony.TelephonyListenerManager;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
@@ -113,6 +114,7 @@ public class NetworkControllerBaseTest extends SysuiTestCase {
|
||||
protected NetworkScoreManager mMockNsm;
|
||||
protected SubscriptionManager mMockSm;
|
||||
protected TelephonyManager mMockTm;
|
||||
protected TelephonyListenerManager mTelephonyListenerManager;
|
||||
protected BroadcastDispatcher mMockBd;
|
||||
protected Config mConfig;
|
||||
protected CallbackHandler mCallbackHandler;
|
||||
@@ -164,6 +166,7 @@ public class NetworkControllerBaseTest extends SysuiTestCase {
|
||||
mDemoModeController = mock(DemoModeController.class);
|
||||
mMockWm = mock(WifiManager.class);
|
||||
mMockTm = mock(TelephonyManager.class);
|
||||
mTelephonyListenerManager = mock(TelephonyListenerManager.class);
|
||||
mMockSm = mock(SubscriptionManager.class);
|
||||
mMockCm = mock(ConnectivityManager.class);
|
||||
mMockBd = mock(BroadcastDispatcher.class);
|
||||
@@ -213,6 +216,7 @@ public class NetworkControllerBaseTest extends SysuiTestCase {
|
||||
mNetworkController = new NetworkControllerImpl(mContext,
|
||||
mMockCm,
|
||||
mMockTm,
|
||||
mTelephonyListenerManager,
|
||||
mMockWm,
|
||||
mMockNsm,
|
||||
mMockSm,
|
||||
@@ -285,7 +289,8 @@ public class NetworkControllerBaseTest extends SysuiTestCase {
|
||||
protected NetworkControllerImpl setUpNoMobileData() {
|
||||
when(mMockTm.isDataCapable()).thenReturn(false);
|
||||
NetworkControllerImpl networkControllerNoMobile =
|
||||
new NetworkControllerImpl(mContext, mMockCm, mMockTm, mMockWm, mMockNsm, mMockSm,
|
||||
new NetworkControllerImpl(mContext, mMockCm, mMockTm, mTelephonyListenerManager,
|
||||
mMockWm, mMockNsm, mMockSm,
|
||||
mConfig, TestableLooper.get(this).getLooper(), mCallbackHandler,
|
||||
mock(AccessPointControllerImpl.class),
|
||||
mock(DataUsageController.class), mMockSubDefaults,
|
||||
|
||||
@@ -106,7 +106,8 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest {
|
||||
public void test4gDataIcon() {
|
||||
// Switch to showing 4g icon and re-initialize the NetworkController.
|
||||
mConfig.show4gForLte = true;
|
||||
mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockTm, mMockWm,
|
||||
mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockTm,
|
||||
mTelephonyListenerManager, mMockWm,
|
||||
mMockNsm, mMockSm, mConfig, Looper.getMainLooper(), mCallbackHandler,
|
||||
mock(AccessPointControllerImpl.class),
|
||||
mock(DataUsageController.class), mMockSubDefaults,
|
||||
|
||||
@@ -61,8 +61,9 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest {
|
||||
// Turn off mobile network support.
|
||||
when(mMockTm.isDataCapable()).thenReturn(false);
|
||||
// Create a new NetworkController as this is currently handled in constructor.
|
||||
mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockTm, mMockWm,
|
||||
mMockNsm, mMockSm, mConfig, Looper.getMainLooper(), mCallbackHandler,
|
||||
mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockTm,
|
||||
mTelephonyListenerManager, mMockWm, mMockNsm, mMockSm, mConfig,
|
||||
Looper.getMainLooper(), mCallbackHandler,
|
||||
mock(AccessPointControllerImpl.class), mock(DataUsageController.class),
|
||||
mMockSubDefaults, mock(DeviceProvisionedController.class), mMockBd,
|
||||
mDemoModeController);
|
||||
@@ -80,8 +81,9 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest {
|
||||
when(mMockTm.getServiceState()).thenReturn(mServiceState);
|
||||
when(mMockSm.getCompleteActiveSubscriptionInfoList()).thenReturn(Collections.emptyList());
|
||||
|
||||
mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockTm, mMockWm,
|
||||
mMockNsm, mMockSm, mConfig, Looper.getMainLooper(), mCallbackHandler,
|
||||
mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockTm,
|
||||
mTelephonyListenerManager, mMockWm, mMockNsm, mMockSm, mConfig,
|
||||
Looper.getMainLooper(), mCallbackHandler,
|
||||
mock(AccessPointControllerImpl.class), mock(DataUsageController.class),
|
||||
mMockSubDefaults, mock(DeviceProvisionedController.class), mMockBd,
|
||||
mDemoModeController);
|
||||
@@ -147,8 +149,9 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest {
|
||||
// Turn off mobile network support.
|
||||
when(mMockTm.isDataCapable()).thenReturn(false);
|
||||
// Create a new NetworkController as this is currently handled in constructor.
|
||||
mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockTm, mMockWm,
|
||||
mMockNsm, mMockSm, mConfig, Looper.getMainLooper(), mCallbackHandler,
|
||||
mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockTm,
|
||||
mTelephonyListenerManager, mMockWm, mMockNsm, mMockSm, mConfig,
|
||||
Looper.getMainLooper(), mCallbackHandler,
|
||||
mock(AccessPointControllerImpl.class), mock(DataUsageController.class),
|
||||
mMockSubDefaults, mock(DeviceProvisionedController.class), mMockBd,
|
||||
mDemoModeController);
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.systemui.telephony;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.telephony.TelephonyCallback.ActiveDataSubscriptionIdListener;
|
||||
import android.telephony.TelephonyCallback.CallStateListener;
|
||||
import android.telephony.TelephonyCallback.ServiceStateListener;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class TelephonyCallbackTest extends SysuiTestCase {
|
||||
|
||||
private TelephonyCallback mTelephonyCallback = new TelephonyCallback();
|
||||
|
||||
@Test
|
||||
public void testAddListener_ActiveDataSubscriptionIdListener() {
|
||||
assertThat(mTelephonyCallback.hasAnyListeners()).isFalse();
|
||||
mTelephonyCallback.addActiveDataSubscriptionIdListener(subId -> {});
|
||||
assertThat(mTelephonyCallback.hasAnyListeners()).isTrue();
|
||||
mTelephonyCallback.addActiveDataSubscriptionIdListener(subId -> {});
|
||||
assertThat(mTelephonyCallback.hasAnyListeners()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddListener_CallStateListener() {
|
||||
assertThat(mTelephonyCallback.hasAnyListeners()).isFalse();
|
||||
mTelephonyCallback.addCallStateListener(state -> {});
|
||||
assertThat(mTelephonyCallback.hasAnyListeners()).isTrue();
|
||||
mTelephonyCallback.addCallStateListener(state -> {});
|
||||
assertThat(mTelephonyCallback.hasAnyListeners()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddListener_ServiceStateListener() {
|
||||
assertThat(mTelephonyCallback.hasAnyListeners()).isFalse();
|
||||
mTelephonyCallback.addServiceStateListener(serviceState -> {});
|
||||
assertThat(mTelephonyCallback.hasAnyListeners()).isTrue();
|
||||
mTelephonyCallback.addServiceStateListener(serviceState -> {});
|
||||
assertThat(mTelephonyCallback.hasAnyListeners()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveListener_ActiveDataSubscriptionIdListener() {
|
||||
ActiveDataSubscriptionIdListener listener = subId -> {};
|
||||
mTelephonyCallback.addActiveDataSubscriptionIdListener(listener);
|
||||
mTelephonyCallback.addActiveDataSubscriptionIdListener(listener);
|
||||
assertThat(mTelephonyCallback.hasAnyListeners()).isTrue();
|
||||
mTelephonyCallback.removeActiveDataSubscriptionIdListener(listener);
|
||||
assertThat(mTelephonyCallback.hasAnyListeners()).isTrue();
|
||||
mTelephonyCallback.removeActiveDataSubscriptionIdListener(listener);
|
||||
assertThat(mTelephonyCallback.hasAnyListeners()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveListener_CallStateListener() {
|
||||
CallStateListener listener = state -> {};
|
||||
mTelephonyCallback.addCallStateListener(listener);
|
||||
mTelephonyCallback.addCallStateListener(listener);
|
||||
assertThat(mTelephonyCallback.hasAnyListeners()).isTrue();
|
||||
mTelephonyCallback.removeCallStateListener(listener);
|
||||
assertThat(mTelephonyCallback.hasAnyListeners()).isTrue();
|
||||
mTelephonyCallback.removeCallStateListener(listener);
|
||||
assertThat(mTelephonyCallback.hasAnyListeners()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveListener_ServiceStateListener() {
|
||||
ServiceStateListener listener = serviceState -> {};
|
||||
mTelephonyCallback.addServiceStateListener(listener);
|
||||
mTelephonyCallback.addServiceStateListener(listener);
|
||||
assertThat(mTelephonyCallback.hasAnyListeners()).isTrue();
|
||||
mTelephonyCallback.removeServiceStateListener(listener);
|
||||
assertThat(mTelephonyCallback.hasAnyListeners()).isTrue();
|
||||
mTelephonyCallback.removeServiceStateListener(listener);
|
||||
assertThat(mTelephonyCallback.hasAnyListeners()).isFalse();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,209 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.systemui.telephony;
|
||||
|
||||
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.telephony.TelephonyCallback.ActiveDataSubscriptionIdListener;
|
||||
import android.telephony.TelephonyCallback.CallStateListener;
|
||||
import android.telephony.TelephonyCallback.ServiceStateListener;
|
||||
import android.telephony.TelephonyManager;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.util.concurrency.FakeExecutor;
|
||||
import com.android.systemui.util.time.FakeSystemClock;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class TelephonyListenerManagerTest extends SysuiTestCase {
|
||||
|
||||
@Mock
|
||||
private TelephonyManager mTelephonyManager;
|
||||
private FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock());
|
||||
@Mock
|
||||
private TelephonyCallback mTelephonyCallback;
|
||||
|
||||
TelephonyListenerManager mTelephonyListenerManager;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mTelephonyListenerManager = new TelephonyListenerManager(
|
||||
mTelephonyManager, mExecutor, mTelephonyCallback);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddListenerRegisters_ActiveDataSubscriptionIdListener() {
|
||||
when(mTelephonyCallback.hasAnyListeners()).thenReturn(true);
|
||||
mTelephonyListenerManager.addActiveDataSubscriptionIdListener(subId -> {});
|
||||
mTelephonyListenerManager.addActiveDataSubscriptionIdListener(subId -> {});
|
||||
mTelephonyListenerManager.addActiveDataSubscriptionIdListener(subId -> {});
|
||||
mTelephonyListenerManager.addActiveDataSubscriptionIdListener(subId -> {});
|
||||
|
||||
verify(mTelephonyManager, times(1))
|
||||
.registerTelephonyCallback(mExecutor, mTelephonyCallback);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddListenerRegisters_CallStateListener() {
|
||||
when(mTelephonyCallback.hasAnyListeners()).thenReturn(true);
|
||||
mTelephonyListenerManager.addCallStateListener(state -> {});
|
||||
mTelephonyListenerManager.addCallStateListener(state -> {});
|
||||
mTelephonyListenerManager.addCallStateListener(state -> {});
|
||||
mTelephonyListenerManager.addCallStateListener(state -> {});
|
||||
|
||||
verify(mTelephonyManager, times(1))
|
||||
.registerTelephonyCallback(mExecutor, mTelephonyCallback);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddListenerRegisters_ServiceStateListener() {
|
||||
when(mTelephonyCallback.hasAnyListeners()).thenReturn(true);
|
||||
mTelephonyListenerManager.addServiceStateListener(serviceState -> {});
|
||||
mTelephonyListenerManager.addServiceStateListener(serviceState -> {});
|
||||
mTelephonyListenerManager.addServiceStateListener(serviceState -> {});
|
||||
mTelephonyListenerManager.addServiceStateListener(serviceState -> {});
|
||||
|
||||
verify(mTelephonyManager, times(1))
|
||||
.registerTelephonyCallback(mExecutor, mTelephonyCallback);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddListenerRegisters_mixed() {
|
||||
when(mTelephonyCallback.hasAnyListeners()).thenReturn(true);
|
||||
mTelephonyListenerManager.addActiveDataSubscriptionIdListener(subId -> {});
|
||||
mTelephonyListenerManager.addCallStateListener(state -> {});
|
||||
mTelephonyListenerManager.addServiceStateListener(serviceState -> {});
|
||||
mTelephonyListenerManager.addActiveDataSubscriptionIdListener(subId -> {});
|
||||
mTelephonyListenerManager.addCallStateListener(state -> {});
|
||||
mTelephonyListenerManager.addServiceStateListener(serviceState -> {});
|
||||
|
||||
verify(mTelephonyManager, times(1))
|
||||
.registerTelephonyCallback(mExecutor, mTelephonyCallback);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveListenerUnregisters_ActiveDataSubscriptionIdListener() {
|
||||
when(mTelephonyCallback.hasAnyListeners()).thenReturn(true);
|
||||
ActiveDataSubscriptionIdListener mListener = subId -> { };
|
||||
|
||||
// Need to add one to actually register
|
||||
mTelephonyListenerManager.addActiveDataSubscriptionIdListener(mListener);
|
||||
verify(mTelephonyManager, times(1))
|
||||
.registerTelephonyCallback(mExecutor, mTelephonyCallback);
|
||||
reset(mTelephonyManager);
|
||||
|
||||
when(mTelephonyCallback.hasAnyListeners()).thenReturn(false);
|
||||
mTelephonyListenerManager.removeActiveDataSubscriptionIdListener(mListener);
|
||||
mTelephonyListenerManager.removeActiveDataSubscriptionIdListener(mListener);
|
||||
mTelephonyListenerManager.removeActiveDataSubscriptionIdListener(mListener);
|
||||
mTelephonyListenerManager.removeActiveDataSubscriptionIdListener(mListener);
|
||||
verify(mTelephonyManager, times(1))
|
||||
.unregisterTelephonyCallback(mTelephonyCallback);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveListenerUnregisters_CallStateListener() {
|
||||
when(mTelephonyCallback.hasAnyListeners()).thenReturn(true);
|
||||
CallStateListener mListener = state -> { };
|
||||
|
||||
// Need to add one to actually register
|
||||
mTelephonyListenerManager.addCallStateListener(mListener);
|
||||
verify(mTelephonyManager, times(1))
|
||||
.registerTelephonyCallback(mExecutor, mTelephonyCallback);
|
||||
reset(mTelephonyManager);
|
||||
|
||||
when(mTelephonyCallback.hasAnyListeners()).thenReturn(false);
|
||||
mTelephonyListenerManager.removeCallStateListener(mListener);
|
||||
mTelephonyListenerManager.removeCallStateListener(mListener);
|
||||
mTelephonyListenerManager.removeCallStateListener(mListener);
|
||||
mTelephonyListenerManager.removeCallStateListener(mListener);
|
||||
verify(mTelephonyManager, times(1))
|
||||
.unregisterTelephonyCallback(mTelephonyCallback);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveListenerUnregisters_ServiceStateListener() {
|
||||
when(mTelephonyCallback.hasAnyListeners()).thenReturn(true);
|
||||
ServiceStateListener mListener = serviceState -> { };
|
||||
|
||||
// Need to add one to actually register
|
||||
mTelephonyListenerManager.addServiceStateListener(mListener);
|
||||
verify(mTelephonyManager, times(1))
|
||||
.registerTelephonyCallback(mExecutor, mTelephonyCallback);
|
||||
reset(mTelephonyManager);
|
||||
|
||||
when(mTelephonyCallback.hasAnyListeners()).thenReturn(false);
|
||||
mTelephonyListenerManager.removeServiceStateListener(mListener);
|
||||
mTelephonyListenerManager.removeServiceStateListener(mListener);
|
||||
mTelephonyListenerManager.removeServiceStateListener(mListener);
|
||||
mTelephonyListenerManager.removeServiceStateListener(mListener);
|
||||
verify(mTelephonyManager, times(1))
|
||||
.unregisterTelephonyCallback(mTelephonyCallback);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveListenerUnregisters_mixed() {
|
||||
when(mTelephonyCallback.hasAnyListeners()).thenReturn(true);
|
||||
ActiveDataSubscriptionIdListener mListenerA = subId -> { };
|
||||
ServiceStateListener mListenerB = serviceState -> { };
|
||||
CallStateListener mListenerC = state -> { };
|
||||
|
||||
// Need to add one to actually register
|
||||
mTelephonyListenerManager.addActiveDataSubscriptionIdListener(mListenerA);
|
||||
verify(mTelephonyManager, times(1))
|
||||
.registerTelephonyCallback(mExecutor, mTelephonyCallback);
|
||||
reset(mTelephonyManager);
|
||||
|
||||
when(mTelephonyCallback.hasAnyListeners()).thenReturn(false);
|
||||
mTelephonyListenerManager.removeActiveDataSubscriptionIdListener(mListenerA);
|
||||
mTelephonyListenerManager.removeServiceStateListener(mListenerB);
|
||||
mTelephonyListenerManager.removeCallStateListener(mListenerC);
|
||||
mTelephonyListenerManager.removeActiveDataSubscriptionIdListener(mListenerA);
|
||||
mTelephonyListenerManager.removeServiceStateListener(mListenerB);
|
||||
mTelephonyListenerManager.removeCallStateListener(mListenerC);
|
||||
verify(mTelephonyManager, times(1))
|
||||
.unregisterTelephonyCallback(mTelephonyCallback);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddListener_noDoubleRegister() {
|
||||
when(mTelephonyCallback.hasAnyListeners()).thenReturn(true);
|
||||
mTelephonyListenerManager.addActiveDataSubscriptionIdListener(subId -> {});
|
||||
verify(mTelephonyManager, times(1))
|
||||
.registerTelephonyCallback(mExecutor, mTelephonyCallback);
|
||||
|
||||
reset(mTelephonyManager);
|
||||
|
||||
// A second call to add doesn't register another listener.
|
||||
mTelephonyListenerManager.addActiveDataSubscriptionIdListener(subId -> {});
|
||||
verify(mTelephonyManager, never()).registerTelephonyCallback(mExecutor, mTelephonyCallback);
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,7 @@ public class FakeExecutor implements DelayableExecutor {
|
||||
private final FakeSystemClock mClock;
|
||||
private PriorityQueue<QueuedRunnable> mQueuedRunnables = new PriorityQueue<>();
|
||||
private boolean mIgnoreClockUpdates;
|
||||
private boolean mExecuting;
|
||||
|
||||
/**
|
||||
* Initializes a fake executor.
|
||||
@@ -56,7 +57,9 @@ public class FakeExecutor implements DelayableExecutor {
|
||||
*/
|
||||
public boolean runNextReady() {
|
||||
if (!mQueuedRunnables.isEmpty() && mQueuedRunnables.peek().mWhen <= mClock.uptimeMillis()) {
|
||||
mExecuting = true;
|
||||
mQueuedRunnables.poll().mRunnable.run();
|
||||
mExecuting = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -162,6 +165,10 @@ public class FakeExecutor implements DelayableExecutor {
|
||||
executeDelayed(command, 0);
|
||||
}
|
||||
|
||||
public boolean isExecuting() {
|
||||
return mExecuting;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run all Executors in a loop until they all report they have no ready work to do.
|
||||
*
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.systemui.util.concurrency;
|
||||
|
||||
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.assertTrue;
|
||||
@@ -319,6 +321,18 @@ public class FakeExecutorTest extends SysuiTestCase {
|
||||
assertEquals(1, runnable.mRunCount);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsExecuting() {
|
||||
FakeSystemClock clock = new FakeSystemClock();
|
||||
FakeExecutor fakeExecutor = new FakeExecutor(clock);
|
||||
|
||||
Runnable runnable = () -> assertThat(fakeExecutor.isExecuting()).isTrue();
|
||||
|
||||
assertThat(fakeExecutor.isExecuting()).isFalse();
|
||||
fakeExecutor.execute(runnable);
|
||||
assertThat(fakeExecutor.isExecuting()).isFalse();
|
||||
}
|
||||
|
||||
private static class RunnableImpl implements Runnable {
|
||||
int mRunCount;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user