Vibrate as system instead of as an app
When DND is on, apps aren't allowed to play vibrations on blocked usages. However, we still need to play vibrations for notifications from those apps that meet DND criteria. Previously we accomplished this by passing in the bypass DND flag, however this flag is also being used to bypass camera audio restrictions, which we don't want. So now we'll play vibrations as "android", which is always exception from DND restrictions and isn't exempt from the camera restriction. In order to maintain debugging from bugreports, the package name and uid that we're vibrating for are now included in the vibration reason. Test: BuzzBeepBlinkTest Test: trigger notification vibration Test: trigger notification vibration, DND on, notif allowed Test: fail to trigger notification vibration, DND on, notif intercepted Test: fail to trigger notification vibration, camera is recording video Test: check bugreport output Bug: 171946151 Change-Id: I8958852403827341480351ee0c60a4fd30f5280d (cherry picked from commite13866164b) Merged-In:e13866164b
This commit is contained in:
@@ -7153,15 +7153,7 @@ public class NotificationManagerService extends SystemService {
|
||||
// so need to check the notification still valide for vibrate.
|
||||
synchronized (mNotificationLock) {
|
||||
if (mNotificationsByKey.get(record.getKey()) != null) {
|
||||
// Vibrator checks the appops for the op package, not the caller,
|
||||
// so we need to add the bypass dnd flag to be heard. it's ok to
|
||||
// always add this flag here because we've already checked that we can
|
||||
// bypass dnd
|
||||
AudioAttributes.Builder aab =
|
||||
new AudioAttributes.Builder(record.getAudioAttributes())
|
||||
.setFlags(FLAG_BYPASS_INTERRUPTION_POLICY);
|
||||
mVibrator.vibrate(record.getSbn().getUid(), record.getSbn().getOpPkg(),
|
||||
effect, "Notification (delayed)", aab.build());
|
||||
vibrate(record, effect, true);
|
||||
} else {
|
||||
Slog.e(TAG, "No vibration for canceled notification : "
|
||||
+ record.getKey());
|
||||
@@ -7169,8 +7161,7 @@ public class NotificationManagerService extends SystemService {
|
||||
}
|
||||
}).start();
|
||||
} else {
|
||||
mVibrator.vibrate(record.getSbn().getUid(), record.getSbn().getPackageName(),
|
||||
effect, "Notification", record.getAudioAttributes());
|
||||
vibrate(record, effect, false);
|
||||
}
|
||||
return true;
|
||||
} finally{
|
||||
@@ -7178,6 +7169,16 @@ public class NotificationManagerService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
private void vibrate(NotificationRecord record, VibrationEffect effect, boolean delayed) {
|
||||
// We need to vibrate as "android" so we can breakthrough DND. VibratorManagerService
|
||||
// doesn't have a concept of vibrating on an app's behalf, so add the app information
|
||||
// to the reason so we can still debug from bugreports
|
||||
String reason = "Notification (" + record.getSbn().getOpPkg() + " "
|
||||
+ record.getSbn().getUid() + ") " + (delayed ? "(Delayed)" : "");
|
||||
mVibrator.vibrate(Process.SYSTEM_UID, PackageManagerService.PLATFORM_PACKAGE_NAME,
|
||||
effect, reason, record.getAudioAttributes());
|
||||
}
|
||||
|
||||
private boolean isNotificationForCurrentUser(NotificationRecord record) {
|
||||
final int currentUser;
|
||||
final long token = Binder.clearCallingIdentity();
|
||||
|
||||
@@ -57,6 +57,7 @@ import android.media.AudioAttributes;
|
||||
import android.media.AudioManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Handler;
|
||||
import android.os.Process;
|
||||
import android.os.RemoteException;
|
||||
import android.os.UserHandle;
|
||||
import android.os.VibrationEffect;
|
||||
@@ -77,10 +78,12 @@ import com.android.internal.logging.InstanceIdSequenceFake;
|
||||
import com.android.internal.util.IntPair;
|
||||
import com.android.server.UiServiceTestCase;
|
||||
import com.android.server.lights.LogicalLight;
|
||||
import com.android.server.pm.PackageManagerService;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.ArgumentMatcher;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
@@ -407,12 +410,17 @@ public class BuzzBeepBlinkTest extends UiServiceTestCase {
|
||||
}
|
||||
|
||||
private void verifyVibrate() {
|
||||
ArgumentCaptor<AudioAttributes> captor = ArgumentCaptor.forClass(AudioAttributes.class);
|
||||
verify(mVibrator, times(1)).vibrate(anyInt(), anyString(), argThat(mVibrateOnceMatcher),
|
||||
anyString(), any());
|
||||
anyString(), captor.capture());
|
||||
assertEquals(0, (captor.getValue().getAllFlags()
|
||||
& AudioAttributes.FLAG_BYPASS_INTERRUPTION_POLICY));
|
||||
}
|
||||
|
||||
private void verifyVibrate(int times) {
|
||||
verify(mVibrator, times(times)).vibrate(anyInt(), anyString(), any(), anyString(), any());
|
||||
verify(mVibrator, times(times)).vibrate(eq(Process.SYSTEM_UID),
|
||||
eq(PackageManagerService.PLATFORM_PACKAGE_NAME), any(), anyString(),
|
||||
any(AudioAttributes.class));
|
||||
}
|
||||
|
||||
private void verifyVibrateLooped() {
|
||||
|
||||
Reference in New Issue
Block a user