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

Commit 9ef63a07 authored by Tetiana Meronyk's avatar Tetiana Meronyk
Browse files

Stop vibration when FG user requests to mute BG user sound

Add broadcast receiver in VibratorManagerService to handle stopping vibration on ACTION_MUTE_SOUND.

Bug: 351794686
Test: manual
Flag: android.multiuser.add_ui_for_sounds_from_background_users
Change-Id: I6b2fe9f80794f2f3eaf650c84ac2d3c81b7aa882
parent f53437f6
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -147,6 +147,7 @@ message VibrationProto {
        IGNORED_ON_WIRELESS_CHARGER = 27;
        IGNORED_MISSING_PERMISSION = 28;
        CANCELLED_BY_APP_OPS = 29;
        CANCELLED_BY_FOREGROUND_USER = 30;
        reserved 17; // prev IGNORED_UNKNOWN_VIBRATION
    }
}
+4 −8
Original line number Diff line number Diff line
@@ -37,7 +37,6 @@ import android.os.Looper;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.Vibrator;
import android.util.Log;

import com.android.internal.R;
@@ -47,9 +46,9 @@ public class BackgroundUserSoundNotifier {

    private static final boolean DEBUG = false;
    private static final String LOG_TAG = BackgroundUserSoundNotifier.class.getSimpleName();
    public static final String BUSN_CHANNEL_ID = "bg_user_sound_channel";
    public static final String BUSN_CHANNEL_NAME = "BackgroundUserSound";
    private static final String ACTION_MUTE_SOUND = "com.android.server.ACTION_MUTE_BG_USER";
    private static final String BUSN_CHANNEL_ID = "bg_user_sound_channel";
    private static final String BUSN_CHANNEL_NAME = "BackgroundUserSound";
    public static final String ACTION_MUTE_SOUND = "com.android.server.ACTION_MUTE_BG_USER";
    private static final String EXTRA_NOTIFICATION_ID = "com.android.server.EXTRA_CLIENT_UID";
    private static final String EXTRA_CURRENT_USER_ID = "com.android.server.EXTRA_CURRENT_USER_ID";
    private static final String ACTION_SWITCH_USER = "com.android.server.ACTION_SWITCH_TO_USER";
@@ -144,6 +143,7 @@ public class BackgroundUserSoundNotifier {
                                    -1) + "  current user id " + intent.getIntExtra(
                                    EXTRA_CURRENT_USER_ID, -1));
                }
                mUserWithNotification = -1;
                mNotificationManager.cancelAsUser(LOG_TAG, notificationId,
                        UserHandle.of(intent.getIntExtra(EXTRA_CURRENT_USER_ID, -1)));
                if (ACTION_MUTE_SOUND.equals(intent.getAction())) {
@@ -159,10 +159,6 @@ public class BackgroundUserSoundNotifier {
                            }
                        }
                    }
                    Vibrator vibrator = mSystemUserContext.getSystemService(Vibrator.class);
                    if (vibrator != null && vibrator.isVibrating()) {
                        vibrator.cancel();
                    }
                } else if (ACTION_SWITCH_USER.equals(intent.getAction())) {
                    service.switchUser(intent.getIntExtra(Intent.EXTRA_USER_ID, -1));
                }
+1 −0
Original line number Diff line number Diff line
@@ -67,6 +67,7 @@ abstract class Vibration {
        CANCELLED_BY_SCREEN_OFF(VibrationProto.CANCELLED_BY_SCREEN_OFF),
        CANCELLED_BY_SETTINGS_UPDATE(VibrationProto.CANCELLED_BY_SETTINGS_UPDATE),
        CANCELLED_BY_USER(VibrationProto.CANCELLED_BY_USER),
        CANCELLED_BY_FOREGROUND_USER(VibrationProto.CANCELLED_BY_FOREGROUND_USER),
        CANCELLED_BY_UNKNOWN_REASON(VibrationProto.CANCELLED_BY_UNKNOWN_REASON),
        CANCELLED_SUPERSEDED(VibrationProto.CANCELLED_SUPERSEDED),
        CANCELLED_BY_APP_OPS(VibrationProto.CANCELLED_BY_APP_OPS),
+28 −1
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.server.vibrator;

import static android.os.VibrationAttributes.USAGE_CLASS_ALARM;
import static android.os.VibrationEffect.VibrationParameter.targetAmplitude;
import static android.os.VibrationEffect.VibrationParameter.targetFrequency;

@@ -73,6 +74,7 @@ import com.android.internal.app.IBatteryStats;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.FrameworkStatsLog;
import com.android.server.SystemService;
import com.android.server.pm.BackgroundUserSoundNotifier;

import libcore.util.NativeAllocationRegistry;

@@ -173,7 +175,8 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
    @GuardedBy("mLock")
    @Nullable private HapticFeedbackVibrationProvider mHapticFeedbackVibrationProvider;

    private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
    @VisibleForTesting
    BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
@@ -190,6 +193,19 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
                                /* immediate= */ false);
                    }
                }
            } else if (android.multiuser.Flags.addUiForSoundsFromBackgroundUsers()
                    && intent.getAction().equals(BackgroundUserSoundNotifier.ACTION_MUTE_SOUND)) {
                synchronized (mLock) {
                    if (shouldCancelOnFgUserRequest(mNextVibration)) {
                        clearNextVibrationLocked(new Vibration.EndInfo(
                                Vibration.Status.CANCELLED_BY_FOREGROUND_USER));
                    }
                    if (shouldCancelOnFgUserRequest(mCurrentVibration)) {
                        mCurrentVibration.notifyCancelled(new Vibration.EndInfo(
                                        Vibration.Status.CANCELLED_BY_FOREGROUND_USER),
                                /* immediate= */ false);
                    }
                }
            }
        }
    };
@@ -299,6 +315,9 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {

        IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_SCREEN_OFF);
        if (android.multiuser.Flags.addUiForSoundsFromBackgroundUsers()) {
            filter.addAction(BackgroundUserSoundNotifier.ACTION_MUTE_SOUND);
        }
        context.registerReceiver(mIntentReceiver, filter, Context.RECEIVER_NOT_EXPORTED);

        injector.addService(EXTERNAL_VIBRATOR_SERVICE, new ExternalVibratorService());
@@ -1422,6 +1441,14 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
                != AppOpsManager.MODE_ALLOWED;
    }

    @GuardedBy("mLock")
    private boolean shouldCancelOnFgUserRequest(@Nullable VibrationStepConductor conductor) {
        if (conductor == null) {
            return false;
        }
        return conductor.getVibration().callerInfo.attrs.getUsageClass() == USAGE_CLASS_ALARM;
    }

    @GuardedBy("mLock")
    private void onAllVibratorsLocked(Consumer<VibratorController> consumer) {
        for (int i = 0; i < mVibrators.size(); i++) {
+28 −0
Original line number Diff line number Diff line
@@ -47,6 +47,7 @@ import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
import android.content.res.Resources;
@@ -103,6 +104,7 @@ import com.android.internal.util.test.FakeSettingsProvider;
import com.android.internal.util.test.FakeSettingsProviderRule;
import com.android.server.LocalServices;
import com.android.server.companion.virtual.VirtualDeviceManagerInternal;
import com.android.server.pm.BackgroundUserSoundNotifier;

import org.junit.After;
import org.junit.Before;
@@ -808,6 +810,32 @@ public class VibratorManagerServiceTest {
                touchMetrics.status);
    }

    @Test
    @RequiresFlagsEnabled(android.multiuser.Flags.FLAG_ADD_UI_FOR_SOUNDS_FROM_BACKGROUND_USERS)
    public void vibrate_thenFgUserRequestsMute_getsCancelled() throws Throwable {
        mockVibrators(1);
        VibratorManagerService service = createSystemReadyService();

        var vib = vibrate(service,
                VibrationEffect.createWaveform(new long[]{100, 100, 100, 100}, 0), ALARM_ATTRS);

        assertTrue(waitUntil(s -> s.isVibrating(1), service, TEST_TIMEOUT_MILLIS));


        service.mIntentReceiver.onReceive(mContextSpy, new Intent(
                BackgroundUserSoundNotifier.ACTION_MUTE_SOUND));

        assertTrue(waitUntil(s -> vib.hasEnded(), service, TEST_TIMEOUT_MILLIS));

        var statsInfoCaptor = ArgumentCaptor.forClass(VibrationStats.StatsInfo.class);
        verify(mVibratorFrameworkStatsLoggerMock, timeout(TEST_TIMEOUT_MILLIS))
                .writeVibrationReportedAsync(statsInfoCaptor.capture());

        VibrationStats.StatsInfo touchMetrics = statsInfoCaptor.getAllValues().get(0);
        assertEquals(Vibration.Status.CANCELLED_BY_FOREGROUND_USER.getProtoEnumValue(),
                touchMetrics.status);
    }

    @Test
    public void vibrate_withVibrationAttributes_usesCorrespondingAudioUsageInAppOpsManager() {
        VibratorManagerService service = createSystemReadyService();