Refactor dependency on AccessibilityManager.
The class is final, so the attempt to mock it in the Telecom unit tests
was resulting in Mockito just using the actual class. This was causing
test flakes.
To fix this, added a new interface that abstracts out the few methods
from AM that our code actually uses. We mock these in the unit tests and
rely on the real class in production.
Test: Ran all Telecom unit tests to verify no regressions.
Fixes: 270428514
Change-Id: I0e58896640e5ff5c9d7446665ff0ca42cf15597c
diff --git a/src/com/android/server/telecom/CallsManager.java b/src/com/android/server/telecom/CallsManager.java
index 1eb65ad..e9458a4 100644
--- a/src/com/android/server/telecom/CallsManager.java
+++ b/src/com/android/server/telecom/CallsManager.java
@@ -558,7 +558,8 @@
ToastFactory toastFactory,
CallEndpointControllerFactory callEndpointControllerFactory,
CallAnomalyWatchdog callAnomalyWatchdog,
- Executor asyncTaskExecutor) {
+ Executor asyncTaskExecutor,
+ Ringer.AccessibilityManagerAdapter accessibilityManagerAdapter) {
mContext = context;
mLock = lock;
mPhoneNumberUtilsAdapter = phoneNumberUtilsAdapter;
@@ -619,7 +620,7 @@
ringtoneFactory, systemVibrator,
new Ringer.VibrationEffectProxy(), mInCallController,
mContext.getSystemService(NotificationManager.class),
- mContext.getSystemService(AccessibilityManager.class));
+ accessibilityManagerAdapter);
mCallRecordingTonePlayer = new CallRecordingTonePlayer(mContext, audioManager,
mTimeoutsAdapter, mLock);
mCallAudioManager = new CallAudioManager(callAudioRouteStateMachine,
diff --git a/src/com/android/server/telecom/Ringer.java b/src/com/android/server/telecom/Ringer.java
index 171745f..c04cf6b 100644
--- a/src/com/android/server/telecom/Ringer.java
+++ b/src/com/android/server/telecom/Ringer.java
@@ -21,6 +21,7 @@
import static android.provider.CallLog.Calls.USER_MISSED_NO_VIBRATE;
import static android.provider.Settings.Global.ZEN_MODE_OFF;
+import android.annotation.NonNull;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.Person;
@@ -54,20 +55,25 @@
*/
@VisibleForTesting
public class Ringer {
- /**
- * Flag only for local debugging. Do not submit enabled.
- */
- private static final boolean DEBUG_RINGER = false;
-
- public static class VibrationEffectProxy {
- public VibrationEffect createWaveform(long[] timings, int[] amplitudes, int repeat) {
- return VibrationEffect.createWaveform(timings, amplitudes, repeat);
+ public interface AccessibilityManagerAdapter {
+ boolean startFlashNotificationSequence(@NonNull Context context,
+ @AccessibilityManager.FlashNotificationReason int reason);
+ boolean stopFlashNotificationSequence(@NonNull Context context);
}
+ /**
+ * Flag only for local debugging. Do not submit enabled.
+ */
+ private static final boolean DEBUG_RINGER = false;
- public VibrationEffect get(Uri ringtoneUri, Context context) {
- return VibrationEffect.get(ringtoneUri, context);
+ public static class VibrationEffectProxy {
+ public VibrationEffect createWaveform(long[] timings, int[] amplitudes, int repeat) {
+ return VibrationEffect.createWaveform(timings, amplitudes, repeat);
+ }
+
+ public VibrationEffect get(Uri ringtoneUri, Context context) {
+ return VibrationEffect.get(ringtoneUri, context);
+ }
}
- }
@VisibleForTesting
public VibrationEffect mDefaultVibrationEffect;
@@ -162,7 +168,7 @@
private RingtoneFactory mRingtoneFactory;
private AudioManager mAudioManager;
private NotificationManager mNotificationManager;
- private AccessibilityManager mAccessibilityManager;
+ private AccessibilityManagerAdapter mAccessibilityManagerAdapter;
/**
* Call objects that are ringing, vibrating or call-waiting. These are used only for logging
@@ -197,7 +203,7 @@
VibrationEffectProxy vibrationEffectProxy,
InCallController inCallController,
NotificationManager notificationManager,
- AccessibilityManager accessibilityManager) {
+ AccessibilityManagerAdapter accessibilityManagerAdapter) {
mLock = new Object();
mSystemSettingsUtil = systemSettingsUtil;
@@ -211,7 +217,7 @@
mInCallController = inCallController;
mVibrationEffectProxy = vibrationEffectProxy;
mNotificationManager = notificationManager;
- mAccessibilityManager = accessibilityManager;
+ mAccessibilityManagerAdapter = accessibilityManagerAdapter;
if (mContext.getResources().getBoolean(R.bool.use_simple_vibration_pattern)) {
mDefaultVibrationEffect = mVibrationEffectProxy.createWaveform(SIMPLE_VIBRATION_PATTERN,
@@ -295,10 +301,11 @@
stopCallWaiting();
final boolean shouldFlash = attributes.shouldRingForContact();
- if (mAccessibilityManager != null && shouldFlash) {
+ if (mAccessibilityManagerAdapter != null && shouldFlash) {
Log.addEvent(foregroundCall, LogUtils.Events.FLASH_NOTIFICATION_START);
- getHandler().post(() -> mAccessibilityManager.startFlashNotificationSequence(mContext,
- AccessibilityManager.FLASH_REASON_CALL));
+ getHandler().post(() ->
+ mAccessibilityManagerAdapter.startFlashNotificationSequence(mContext,
+ AccessibilityManager.FLASH_REASON_CALL));
}
// Determine if the settings and DND mode indicate that the vibrator can be used right now.
@@ -512,9 +519,10 @@
public void stopRinging() {
final Call foregroundCall = mRingingCall != null ? mRingingCall : mVibratingCall;
- if (mAccessibilityManager != null) {
+ if (mAccessibilityManagerAdapter != null) {
Log.addEvent(foregroundCall, LogUtils.Events.FLASH_NOTIFICATION_STOP);
- getHandler().post(() -> mAccessibilityManager.stopFlashNotificationSequence(mContext));
+ getHandler().post(() ->
+ mAccessibilityManagerAdapter.stopFlashNotificationSequence(mContext));
}
synchronized (mLock) {
diff --git a/src/com/android/server/telecom/TelecomSystem.java b/src/com/android/server/telecom/TelecomSystem.java
index 4d1bca9..f9c2508 100644
--- a/src/com/android/server/telecom/TelecomSystem.java
+++ b/src/com/android/server/telecom/TelecomSystem.java
@@ -31,6 +31,7 @@
import android.telecom.Log;
import android.telecom.PhoneAccountHandle;
import android.telephony.AnomalyReporter;
+import android.view.accessibility.AccessibilityManager;
import android.widget.Toast;
import androidx.annotation.NonNull;
@@ -208,7 +209,8 @@
ClockProxy clockProxy,
RoleManagerAdapter roleManagerAdapter,
ContactsAsyncHelper.Factory contactsAsyncHelperFactory,
- DeviceIdleControllerAdapter deviceIdleControllerAdapter) {
+ DeviceIdleControllerAdapter deviceIdleControllerAdapter,
+ Ringer.AccessibilityManagerAdapter accessibilityManagerAdapter) {
mContext = context.getApplicationContext();
LogUtils.initLogging(mContext);
AnomalyReporter.initialize(mContext);
@@ -332,6 +334,7 @@
CallAnomalyWatchdog callAnomalyWatchdog = new CallAnomalyWatchdog(
Executors.newSingleThreadScheduledExecutor(),
mLock, timeoutsAdapter, clockProxy);
+
mCallsManager = new CallsManager(
mContext,
mLock,
@@ -364,7 +367,8 @@
toastFactory,
callEndpointControllerFactory,
callAnomalyWatchdog,
- Executors.newSingleThreadExecutor());
+ Executors.newSingleThreadExecutor(),
+ accessibilityManagerAdapter);
mIncomingCallNotifier = incomingCallNotifier;
incomingCallNotifier.setCallsManagerProxy(new IncomingCallNotifier.CallsManagerProxy() {
diff --git a/src/com/android/server/telecom/components/TelecomService.java b/src/com/android/server/telecom/components/TelecomService.java
index 9ad0da4..3881154 100644
--- a/src/com/android/server/telecom/components/TelecomService.java
+++ b/src/com/android/server/telecom/components/TelecomService.java
@@ -29,6 +29,7 @@
import android.telecom.Log;
import android.telecom.CallerInfoAsyncQuery;
+import android.view.accessibility.AccessibilityManager;
import com.android.internal.telecom.IInternalServiceRetriever;
import com.android.internal.telecom.ITelecomLoader;
@@ -53,6 +54,7 @@
import com.android.server.telecom.ProximitySensorManagerFactory;
import com.android.server.telecom.InCallWakeLockController;
import com.android.server.telecom.ProximitySensorManager;
+import com.android.server.telecom.Ringer;
import com.android.server.telecom.RoleManagerAdapterImpl;
import com.android.server.telecom.TelecomSystem;
import com.android.server.telecom.TelecomWakeLock;
@@ -191,7 +193,22 @@
new RoleManagerAdapterImpl(context,
(RoleManager) context.getSystemService(Context.ROLE_SERVICE)),
new ContactsAsyncHelper.Factory(),
- internalServiceRetriever.getDeviceIdleController()));
+ internalServiceRetriever.getDeviceIdleController(),
+ new Ringer.AccessibilityManagerAdapter() {
+ @Override
+ public boolean startFlashNotificationSequence(
+ @androidx.annotation.NonNull Context context, int reason) {
+ return context.getSystemService(AccessibilityManager.class)
+ .startFlashNotificationSequence(context, reason);
+ }
+
+ @Override
+ public boolean stopFlashNotificationSequence(
+ @androidx.annotation.NonNull Context context) {
+ return context.getSystemService(AccessibilityManager.class)
+ .stopFlashNotificationSequence(context);
+ }
+ }));
}
}
diff --git a/tests/src/com/android/server/telecom/tests/CallsManagerTest.java b/tests/src/com/android/server/telecom/tests/CallsManagerTest.java
index 9876138..7544dc9 100644
--- a/tests/src/com/android/server/telecom/tests/CallsManagerTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallsManagerTest.java
@@ -106,6 +106,7 @@
import com.android.server.telecom.PhoneNumberUtilsAdapter;
import com.android.server.telecom.ProximitySensorManager;
import com.android.server.telecom.ProximitySensorManagerFactory;
+import com.android.server.telecom.Ringer;
import com.android.server.telecom.RoleManagerAdapter;
import com.android.server.telecom.SystemStateHelper;
import com.android.server.telecom.TelecomSystem;
@@ -235,6 +236,7 @@
@Mock private Toast mToast;
@Mock private CallAnomalyWatchdog mCallAnomalyWatchdog;
@Mock private AnomalyReporterAdapter mAnomalyReporterAdapter;
+ @Mock private Ringer.AccessibilityManagerAdapter mAccessibilityManagerAdapter;
private CallsManager mCallsManager;
@@ -298,7 +300,8 @@
mCallEndpointControllerFactory,
mCallAnomalyWatchdog,
// Just do async tasks synchronously to support testing.
- command -> command.run());
+ command -> command.run(),
+ mAccessibilityManagerAdapter);
when(mPhoneAccountRegistrar.getPhoneAccount(
eq(SELF_MANAGED_HANDLE), any())).thenReturn(SELF_MANAGED_ACCOUNT);
diff --git a/tests/src/com/android/server/telecom/tests/RingerTest.java b/tests/src/com/android/server/telecom/tests/RingerTest.java
index 35eda43..d397910 100644
--- a/tests/src/com/android/server/telecom/tests/RingerTest.java
+++ b/tests/src/com/android/server/telecom/tests/RingerTest.java
@@ -150,7 +150,7 @@
@Mock Vibrator mockVibrator;
@Mock InCallController mockInCallController;
@Mock NotificationManager mockNotificationManager;
- @Mock AccessibilityManager mockAccessibilityManager;
+ @Mock Ringer.AccessibilityManagerAdapter mockAccessibilityManagerAdapter;
@Spy Ringer.VibrationEffectProxy spyVibrationEffectProxy;
@@ -180,13 +180,12 @@
when(mockAudioManager.getRingerMode()).thenReturn(AudioManager.RINGER_MODE_NORMAL);
when(mockSystemSettingsUtil.isHapticPlaybackSupported(any(Context.class))).thenReturn(true);
mockNotificationManager =mContext.getSystemService(NotificationManager.class);
- mockAccessibilityManager = mContext.getSystemService(AccessibilityManager.class);
when(mockTonePlayer.startTone()).thenReturn(true);
when(mockNotificationManager.matchesCallFilter(any(Bundle.class))).thenReturn(true);
when(mockRingtoneFactory.hasHapticChannels(any(Ringtone.class))).thenReturn(false);
mRingerUnderTest = new Ringer(mockPlayerFactory, mContext, mockSystemSettingsUtil,
mockRingtonePlayer, mockRingtoneFactory, mockVibrator, spyVibrationEffectProxy,
- mockInCallController, mockNotificationManager, mockAccessibilityManager);
+ mockInCallController, mockNotificationManager, mockAccessibilityManagerAdapter);
when(mockCall1.getState()).thenReturn(CallState.RINGING);
when(mockCall2.getState()).thenReturn(CallState.RINGING);
when(mockCall1.getUserHandleFromTargetPhoneAccount()).thenReturn(PA_HANDLE.getUserHandle());
@@ -558,7 +557,7 @@
assertFalse(mRingerUnderTest.shouldRingForContact(mockCall2));
assertFalse(mRingerUnderTest.startRinging(mockCall2, false));
- verify(mockAccessibilityManager, never())
+ verify(mockAccessibilityManagerAdapter, never())
.startFlashNotificationSequence(any(Context.class), anyInt());
}
@@ -573,7 +572,7 @@
assertTrue(mRingerUnderTest.shouldRingForContact(mockCall2));
assertTrue(mRingerUnderTest.startRinging(mockCall2, false));
- verify(mockAccessibilityManager, atLeastOnce())
+ verify(mockAccessibilityManagerAdapter, atLeastOnce())
.startFlashNotificationSequence(any(Context.class), anyInt());
}
@@ -589,7 +588,7 @@
assertTrue(mRingerUnderTest.shouldRingForContact(mockCall2));
assertTrue(mRingerUnderTest.startRinging(mockCall2, false));
mRingerUnderTest.stopRinging();
- verify(mockAccessibilityManager, atLeastOnce())
+ verify(mockAccessibilityManagerAdapter, atLeastOnce())
.stopFlashNotificationSequence(any(Context.class));
}
diff --git a/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java b/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
index 2ab3160..7e7235d 100644
--- a/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
+++ b/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
@@ -89,6 +89,7 @@
import com.android.server.telecom.PhoneNumberUtilsAdapterImpl;
import com.android.server.telecom.ProximitySensorManager;
import com.android.server.telecom.ProximitySensorManagerFactory;
+import com.android.server.telecom.Ringer;
import com.android.server.telecom.RoleManagerAdapter;
import com.android.server.telecom.StatusBarNotifier;
import com.android.server.telecom.SystemStateHelper;
@@ -209,6 +210,8 @@
@Mock ToneGenerator mToneGenerator;
@Mock DeviceIdleControllerAdapter mDeviceIdleControllerAdapter;
+ @Mock Ringer.AccessibilityManagerAdapter mAccessibilityManagerAdapter;
+
final ComponentName mInCallServiceComponentNameX =
new ComponentName(
"incall-service-package-X",
@@ -537,7 +540,7 @@
ContactsAsyncHelper.ContentResolverAdapter adapter) {
return new ContactsAsyncHelper(adapter, mHandlerThread.getLooper());
}
- }, mDeviceIdleControllerAdapter);
+ }, mDeviceIdleControllerAdapter, mAccessibilityManagerAdapter);
mComponentContextFixture.setTelecomManager(new TelecomManager(
mComponentContextFixture.getTestDouble(),