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

Commit a9386a2b authored by Wilson Wu's avatar Wilson Wu Committed by Android (Google) Code Review
Browse files

Merge "Refine default vibration behavior for vibrate-only" into main

parents 52a8f077 f7da48f1
Loading
Loading
Loading
Loading
+22 −1
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ import android.content.res.Resources;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.media.Utils;
import android.media.VolumeShaper;
import android.media.audio.Flags;
@@ -431,6 +432,11 @@ public class Ringer {
                    && isVibratorEnabled) {
                Log.i(this, "Muted haptic channels since audio coupled ramping ringer is disabled");
                hapticChannelsMuted = true;
                if (useCustomVibration(foregroundCall)) {
                    Log.i(this,
                            "Not muted haptic channel for customization when apply ramping ringer");
                    hapticChannelsMuted = false;
                }
            } else if (hapticChannelsMuted) {
                Log.i(this,
                        "Muted haptic channels isVibratorEnabled=%s, hapticPlaybackSupported=%s",
@@ -442,7 +448,7 @@ public class Ringer {
            if (!isHapticOnly) {
                ringtoneInfoSupplier = () -> mRingtoneFactory.getRingtone(
                        foregroundCall, mVolumeShaperConfig, finalHapticChannelsMuted);
            } else if (Flags.enableRingtoneHapticsCustomization() && mRingtoneVibrationSupported) {
            } else if (useCustomVibration(foregroundCall)) {
                ringtoneInfoSupplier = () -> mRingtoneFactory.getRingtone(
                        foregroundCall, null, false);
            }
@@ -521,6 +527,21 @@ public class Ringer {
        }
    }

    private boolean useCustomVibration(@NonNull Call foregroundCall) {
        return Flags.enableRingtoneHapticsCustomization() && mRingtoneVibrationSupported
                && hasExplicitVibration(foregroundCall);
    }

    private boolean hasExplicitVibration(@NonNull Call foregroundCall) {
        final Uri ringtoneUri = foregroundCall.getRingtone();
        if (ringtoneUri != null) {
            // TODO(b/399265235) : Avoid this hidden API access for mainline
            return Utils.hasVibration(ringtoneUri);
        }
        return Utils.hasVibration(RingtoneManager.getActualDefaultRingtoneUri(
                mContext, RingtoneManager.TYPE_RINGTONE));
    }

    /**
     * Try to reserve the vibrator for this call, returning false if it's already committed.
     * The vibration will be started by AsyncRingtonePlayer to ensure timing is aligned with the
+63 −15
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import static android.provider.Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeNotNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -46,6 +47,7 @@ import android.content.Context;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.media.VolumeShaper;
import android.media.audio.Flags;
import android.net.Uri;
@@ -65,6 +67,7 @@ import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
import android.util.Pair;

import androidx.test.core.app.ApplicationProvider;
import androidx.test.filters.SmallTest;
import androidx.test.platform.app.InstrumentationRegistry;

@@ -85,6 +88,7 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.Spy;

@@ -846,8 +850,12 @@ public class RingerTest extends TelecomTestCase {
    @Test
    @EnableFlags(Flags.FLAG_ENABLE_RINGTONE_HAPTICS_CUSTOMIZATION)
    public void testNoVibrateForSilentRingtoneIfRingtoneHasVibration() throws Exception {
        final Context context = ApplicationProvider.getApplicationContext();
        Uri defaultRingtoneUri = RingtoneManager.getActualDefaultRingtoneUri(context,
                RingtoneManager.TYPE_RINGTONE);
        assumeNotNull(defaultRingtoneUri);
        Uri FAKE_RINGTONE_VIBRATION_URI =
                FAKE_RINGTONE_URI.buildUpon().appendQueryParameter(
                defaultRingtoneUri.buildUpon().appendQueryParameter(
                        VIBRATION_PARAM, FAKE_VIBRATION_URI.toString()).build();
        Ringtone mockRingtone = mock(Ringtone.class);
        Pair<Uri, Ringtone> ringtoneInfo = new Pair(FAKE_RINGTONE_VIBRATION_URI, mockRingtone);
@@ -856,6 +864,9 @@ public class RingerTest extends TelecomTestCase {
                .thenReturn(ringtoneInfo);
        mComponentContextFixture.putBooleanResource(
                com.android.internal.R.bool.config_ringtoneVibrationSettingsSupported, true);
        try {
            RingtoneManager.setActualDefaultRingtoneUri(context, RingtoneManager.TYPE_RINGTONE,
                    FAKE_RINGTONE_VIBRATION_URI);
            createRingerUnderTest(); // Needed after mock the config.

            mRingerUnderTest.startCallWaiting(mockCall1);
@@ -871,6 +882,43 @@ public class RingerTest extends TelecomTestCase {
            // Skip vibration play in Ringer if a vibration was specified to the ringtone
            verify(mockVibrator, never()).vibrate(any(VibrationEffect.class),
                    any(VibrationAttributes.class));
        } finally {
            // Restore the default ringtone Uri
            RingtoneManager.setActualDefaultRingtoneUri(context, RingtoneManager.TYPE_RINGTONE,
                    defaultRingtoneUri);
        }
    }

    @SmallTest
    @Test
    @EnableFlags(Flags.FLAG_ENABLE_RINGTONE_HAPTICS_CUSTOMIZATION)
    public void testNotMuteHapticChannelWithRampingRinger() throws Exception {
        final Context context = ApplicationProvider.getApplicationContext();
        Uri defaultRingtoneUri = RingtoneManager.getActualDefaultRingtoneUri(context,
                RingtoneManager.TYPE_RINGTONE);
        assumeNotNull(defaultRingtoneUri);
        Uri FAKE_RINGTONE_VIBRATION_URI = defaultRingtoneUri.buildUpon().appendQueryParameter(
                        VIBRATION_PARAM, FAKE_VIBRATION_URI.toString()).build();
        mComponentContextFixture.putBooleanResource(
                com.android.internal.R.bool.config_ringtoneVibrationSettingsSupported, true);
        ArgumentCaptor<Boolean> muteHapticChannelCaptor = ArgumentCaptor.forClass(Boolean.class);
        try {
            RingtoneManager.setActualDefaultRingtoneUri(context, RingtoneManager.TYPE_RINGTONE,
                    FAKE_RINGTONE_VIBRATION_URI);
            createRingerUnderTest(); // Needed after mock the config.
            mRingerUnderTest.startCallWaiting(mockCall1);
            ensureRingerIsAudible();
            enableRampingRinger();
            enableVibrationWhenRinging();
            assertTrue(startRingingAndWaitForAsync(mockCall2, false));
            verify(mockRingtoneFactory, atLeastOnce()).getRingtone(any(Call.class),
                    nullable(VolumeShaper.Configuration.class), muteHapticChannelCaptor.capture());
            assertFalse(muteHapticChannelCaptor.getValue());
        } finally {
            // Restore the default ringtone Uri
            RingtoneManager.setActualDefaultRingtoneUri(context, RingtoneManager.TYPE_RINGTONE,
                    defaultRingtoneUri);
        }
    }

    /**