Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dded37d9 authored by yw.bae's avatar yw.bae Committed by Angela Wang
Browse files

Call AccessibilityManager.startFlashNotificationSequence and...


Call AccessibilityManager.startFlashNotificationSequence and stopFlashNotificationSequence method in Ringer to implement Flash Notification for Call.

Bug: 237628564
Test: atest RingerTest
Change-Id: I7ad3bb2ef231feeb6fc16e852aa7ce27d2034650
Signed-off-by: default avataryw.bae <yw.bae@samsung.com>
Signed-off-by: default avatarAngela Wang <angelala@google.com>
parent c75c5d1a
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -106,6 +106,7 @@ import android.util.Pair;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityManager;
import android.widget.Button;

import com.android.internal.annotations.VisibleForTesting;
@@ -600,7 +601,8 @@ public class CallsManager extends Call.ListenerBase
        mRinger = new Ringer(playerFactory, context, systemSettingsUtil, asyncRingtonePlayer,
                ringtoneFactory, systemVibrator,
                new Ringer.VibrationEffectProxy(), mInCallController,
                mContext.getSystemService(NotificationManager.class));
                mContext.getSystemService(NotificationManager.class),
                mContext.getSystemService(AccessibilityManager.class));
        mCallRecordingTonePlayer = new CallRecordingTonePlayer(mContext, audioManager,
                mTimeoutsAdapter, mLock);
        mCallAudioManager = new CallAudioManager(callAudioRouteStateMachine,
+2 −0
Original line number Diff line number Diff line
@@ -214,6 +214,8 @@ public class LogUtils {
        public static final String SET_VOIP_MODE = "SET_VOIP_MODE";
        public static final String STATE_TIMEOUT = "STATE_TIMEOUT";
        public static final String ICS_EXTRAS_CHANGED = "ICS_EXTRAS_CHANGED";
        public static final String FLASH_NOTIFICATION_START = "FLASH_NOTIFICATION_START";
        public static final String FLASH_NOTIFICATION_STOP = "FLASH_NOTIFICATION_STOP";

        public static class Timings {
            public static final String ACCEPT_TIMING = "accept";
+20 −2
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ import android.os.VibrationEffect;
import android.os.Vibrator;
import android.telecom.Log;
import android.telecom.TelecomManager;
import android.view.accessibility.AccessibilityManager;

import com.android.internal.annotations.VisibleForTesting;
import com.android.server.telecom.LogUtils.EventTimer;
@@ -161,6 +162,7 @@ public class Ringer {
    private RingtoneFactory mRingtoneFactory;
    private AudioManager mAudioManager;
    private NotificationManager mNotificationManager;
    private AccessibilityManager mAccessibilityManager;

    /**
     * Call objects that are ringing, vibrating or call-waiting. These are used only for logging
@@ -194,7 +196,8 @@ public class Ringer {
            Vibrator vibrator,
            VibrationEffectProxy vibrationEffectProxy,
            InCallController inCallController,
            NotificationManager notificationManager) {
            NotificationManager notificationManager,
            AccessibilityManager accessibilityManager) {

        mLock = new Object();
        mSystemSettingsUtil = systemSettingsUtil;
@@ -208,6 +211,7 @@ public class Ringer {
        mInCallController = inCallController;
        mVibrationEffectProxy = vibrationEffectProxy;
        mNotificationManager = notificationManager;
        mAccessibilityManager = accessibilityManager;

        if (mContext.getResources().getBoolean(R.bool.use_simple_vibration_pattern)) {
            mDefaultVibrationEffect = mVibrationEffectProxy.createWaveform(SIMPLE_VIBRATION_PATTERN,
@@ -261,7 +265,7 @@ public class Ringer {
            attributes = ringerAttributesFuture.get(
                    RINGER_ATTRIBUTES_TIMEOUT, TimeUnit.MILLISECONDS);
        } catch (ExecutionException | InterruptedException | TimeoutException e) {
            // Keep attributs as null
            // Keep attributes as null
            Log.i(this, "getAttributes error: " + e);
        }

@@ -290,6 +294,13 @@ public class Ringer {

        stopCallWaiting();

        final boolean shouldFlash = attributes.shouldRingForContact();
        if (mAccessibilityManager != null && shouldFlash) {
            Log.addEvent(foregroundCall, LogUtils.Events.FLASH_NOTIFICATION_START);
            getHandler().post(() -> mAccessibilityManager.startFlashNotificationSequence(mContext,
                    AccessibilityManager.FLASH_REASON_CALL));
        }

        // Determine if the settings and DND mode indicate that the vibrator can be used right now.
        final boolean isVibratorEnabled =
            isVibratorEnabled(mContext, attributes.shouldRingForContact());
@@ -427,6 +438,7 @@ public class Ringer {
                    "hasVibrator=%b, userRequestsVibrate=%b, ringerMode=%d, isVibrating=%b",
                    mVibrator.hasVibrator(), mSystemSettingsUtil.isRingVibrationEnabled(mContext),
                    mAudioManager.getRingerMode(), mIsVibrating);
                mVibratingCall = foregroundCall;
                mIsVibrating = true;
                mVibrator.vibrate(effect, VIBRATION_ATTRIBUTES);
                Log.i(this, "start vibration.");
@@ -499,6 +511,12 @@ public class Ringer {
    }

    public void stopRinging() {
        final Call foregroundCall = mRingingCall != null ? mRingingCall : mVibratingCall;
        if (mAccessibilityManager != null) {
            Log.addEvent(foregroundCall, LogUtils.Events.FLASH_NOTIFICATION_STOP);
            getHandler().post(() -> mAccessibilityManager.stopFlashNotificationSequence(mContext));
        }

        synchronized (mLock) {
            if (mRingingCall != null) {
                Log.addEvent(mRingingCall, LogUtils.Events.STOP_RINGER);
+6 −0
Original line number Diff line number Diff line
@@ -75,6 +75,7 @@ import android.telephony.TelephonyManager;
import android.telephony.TelephonyRegistryManager;
import android.test.mock.MockContext;
import android.util.DisplayMetrics;
import android.view.accessibility.AccessibilityManager;

import java.io.File;
import java.io.IOException;
@@ -235,6 +236,8 @@ public class ComponentContextFixture implements TestFixture<Context> {
                    return mPermissionCheckerManager;
                case Context.SENSOR_PRIVACY_SERVICE:
                    return mSensorPrivacyManager;
                case Context.ACCESSIBILITY_SERVICE:
                    return mAccessibilityManager;
                default:
                    return null;
            }
@@ -268,6 +271,8 @@ public class ComponentContextFixture implements TestFixture<Context> {
                return Context.SENSOR_PRIVACY_SERVICE;
            } else if (svcClass == NotificationManager.class) {
                return Context.NOTIFICATION_SERVICE;
            } else if (svcClass == AccessibilityManager.class) {
                return Context.ACCESSIBILITY_SERVICE;
            }
            throw new UnsupportedOperationException();
        }
@@ -560,6 +565,7 @@ public class ComponentContextFixture implements TestFixture<Context> {
    private final LocationManager mLocationManager = mock(LocationManager.class);
    private final AppOpsManager mAppOpsManager = mock(AppOpsManager.class);
    private final NotificationManager mNotificationManager = mock(NotificationManager.class);
    private final AccessibilityManager mAccessibilityManager = mock(AccessibilityManager.class);
    private final UserManager mUserManager = mock(UserManager.class);
    private final StatusBarManager mStatusBarManager = mock(StatusBarManager.class);
    private SubscriptionManager mSubscriptionManager = mock(SubscriptionManager.class);
+58 −12
Original line number Diff line number Diff line
@@ -50,6 +50,7 @@ import android.os.Vibrator;
import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
import android.test.suitebuilder.annotation.SmallTest;
import android.view.accessibility.AccessibilityManager;

import com.android.server.telecom.AsyncRingtonePlayer;
import com.android.server.telecom.Call;
@@ -149,12 +150,13 @@ public class RingerTest extends TelecomTestCase {
    @Mock Vibrator mockVibrator;
    @Mock InCallController mockInCallController;
    @Mock NotificationManager mockNotificationManager;
    @Mock AccessibilityManager mockAccessibilityManager;

    @Spy Ringer.VibrationEffectProxy spyVibrationEffectProxy;

    @Mock InCallTonePlayer mockTonePlayer;
    @Mock Call mockCall1;
    @Mock Call mockCall2;
    @Mock NotificationManager mNotificationManager;

    private static final PhoneAccountHandle PA_HANDLE =
            new PhoneAccountHandle(new ComponentName("pa_pkg", "pa_cls"),
@@ -174,26 +176,22 @@ public class RingerTest extends TelecomTestCase {
            return new UriVibrationEffect(ringtoneUriForEffect);
        }).when(spyVibrationEffectProxy).get(any(), any());
        when(mockPlayerFactory.createPlayer(anyInt())).thenReturn(mockTonePlayer);
        mockAudioManager =
                (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
        mNotificationManager = mContext.getSystemService(NotificationManager.class);

        mockAudioManager = mContext.getSystemService(AudioManager.class);
        when(mockAudioManager.getRingerMode()).thenReturn(AudioManager.RINGER_MODE_NORMAL);
        when(mockSystemSettingsUtil.isHapticPlaybackSupported(any(Context.class))).thenReturn(true);
        mockNotificationManager =
                (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
        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, mNotificationManager);
                mockInCallController, mockNotificationManager, mockAccessibilityManager);
        when(mockCall1.getState()).thenReturn(CallState.RINGING);
        when(mockCall2.getState()).thenReturn(CallState.RINGING);
        when(mockCall1.getUserHandleFromTargetPhoneAccount()).thenReturn(PA_HANDLE.getUserHandle());
        when(mockCall2.getUserHandleFromTargetPhoneAccount()).thenReturn(PA_HANDLE.getUserHandle());
        mRingerUnderTest.setBlockOnRingingFuture(mRingCompletionFuture);
        mRingerUnderTest.setNotificationManager(mockNotificationManager);
    }

    @Override
@@ -522,8 +520,9 @@ public class RingerTest extends TelecomTestCase {
        when(mockCall1.wasDndCheckComputedForCall()).thenReturn(false);
        when(mockCall1.getHandle()).thenReturn(Uri.parse(""));

        when(mContext.getSystemService(NotificationManager.class)).thenReturn(mNotificationManager);
        when(mNotificationManager.matchesCallFilter(any(Bundle.class))).thenReturn(false);
        when(mContext.getSystemService(NotificationManager.class)).thenReturn(
                mockNotificationManager);
        when(mockNotificationManager.matchesCallFilter(any(Bundle.class))).thenReturn(false);

        // THEN
        assertFalse(mRingerUnderTest.shouldRingForContact(mockCall1));
@@ -541,13 +540,60 @@ public class RingerTest extends TelecomTestCase {
        // WHEN
        when(mockCall1.wasDndCheckComputedForCall()).thenReturn(false);
        when(mockCall1.getHandle()).thenReturn(Uri.parse(""));
        when(mNotificationManager.matchesCallFilter(any(Bundle.class))).thenReturn(true);
        when(mockNotificationManager.matchesCallFilter(any(Bundle.class))).thenReturn(true);

        // THEN
        assertTrue(mRingerUnderTest.shouldRingForContact(mockCall1));
        verify(mockCall1, atLeastOnce()).setCallIsSuppressedByDoNotDisturb(false);
    }

    @Test
    public void testNoFlashNotificationWhenCallSuppressed() {
        ensureRingtoneMocked();
        // Start call waiting to make sure that it doesn't stop when we start ringing
        mRingerUnderTest.startCallWaiting(mockCall1);
        when(mockCall2.wasDndCheckComputedForCall()).thenReturn(false);
        when(mockCall2.getHandle()).thenReturn(Uri.parse(""));
        when(mockNotificationManager.matchesCallFilter(any(Bundle.class))).thenReturn(false);

        assertFalse(mRingerUnderTest.shouldRingForContact(mockCall2));
        assertFalse(mRingerUnderTest.startRinging(mockCall2, false));
        verify(mockAccessibilityManager, never())
                .startFlashNotificationSequence(any(Context.class), anyInt());
    }

    @Test
    public void testStartFlashNotificationWhenRingStarts()  {
        ensureRingtoneMocked();
        // Start call waiting to make sure that it doesn't stop when we start ringing
        mRingerUnderTest.startCallWaiting(mockCall1);
        when(mockCall2.wasDndCheckComputedForCall()).thenReturn(false);
        when(mockCall2.getHandle()).thenReturn(Uri.parse(""));
        when(mockNotificationManager.matchesCallFilter(any(Bundle.class))).thenReturn(true);

        assertTrue(mRingerUnderTest.shouldRingForContact(mockCall2));
        assertTrue(mRingerUnderTest.startRinging(mockCall2, false));
        verify(mockAccessibilityManager, atLeastOnce())
                .startFlashNotificationSequence(any(Context.class), anyInt());
    }

    @Test
    public void testStopFlashNotificationWhenRingStops() {
        ensureRingtoneMocked();
        // Start call waiting to make sure that it doesn't stop when we start ringing
        mRingerUnderTest.startCallWaiting(mockCall1);
        when(mockCall2.wasDndCheckComputedForCall()).thenReturn(false);
        when(mockCall2.getHandle()).thenReturn(Uri.parse(""));
        when(mockNotificationManager.matchesCallFilter(any(Bundle.class))).thenReturn(true);

        assertTrue(mRingerUnderTest.shouldRingForContact(mockCall2));
        assertTrue(mRingerUnderTest.startRinging(mockCall2, false));
        mRingerUnderTest.stopRinging();
        verify(mockAccessibilityManager, atLeastOnce())
                .stopFlashNotificationSequence(any(Context.class));

    }

    private void ensureRingerIsAudible() {
        when(mockAudioManager.getRingerMode()).thenReturn(AudioManager.RINGER_MODE_NORMAL);
        when(mockAudioManager.getStreamVolume(AudioManager.STREAM_RING)).thenReturn(100);