Loading core/proto/android/server/vibrator/vibratormanagerservice.proto +1 −0 Original line number Diff line number Diff line Loading @@ -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 } } Loading services/core/java/com/android/server/pm/BackgroundUserSoundNotifier.java +4 −8 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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"; Loading Loading @@ -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())) { Loading @@ -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)); } Loading services/core/java/com/android/server/vibrator/Vibration.java +1 −0 Original line number Diff line number Diff line Loading @@ -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), Loading services/core/java/com/android/server/vibrator/VibratorManagerService.java +28 −1 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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)) { Loading @@ -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); } } } } }; Loading Loading @@ -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()); Loading Loading @@ -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++) { Loading services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java +28 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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(); Loading Loading
core/proto/android/server/vibrator/vibratormanagerservice.proto +1 −0 Original line number Diff line number Diff line Loading @@ -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 } } Loading
services/core/java/com/android/server/pm/BackgroundUserSoundNotifier.java +4 −8 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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"; Loading Loading @@ -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())) { Loading @@ -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)); } Loading
services/core/java/com/android/server/vibrator/Vibration.java +1 −0 Original line number Diff line number Diff line Loading @@ -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), Loading
services/core/java/com/android/server/vibrator/VibratorManagerService.java +28 −1 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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)) { Loading @@ -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); } } } } }; Loading Loading @@ -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()); Loading Loading @@ -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++) { Loading
services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java +28 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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(); Loading