diff --git a/core/java/android/os/VibrationAttributes.java b/core/java/android/os/VibrationAttributes.java index 9612ca6addcd8..58315736f37f0 100644 --- a/core/java/android/os/VibrationAttributes.java +++ b/core/java/android/os/VibrationAttributes.java @@ -136,7 +136,7 @@ public final class VibrationAttributes implements Parcelable { /** * @hide */ - @IntDef(prefix = { "FLAG_" }, value = { + @IntDef(prefix = { "FLAG_" }, flag = true, value = { FLAG_BYPASS_INTERRUPTION_POLICY, }) @Retention(RetentionPolicy.SOURCE) @@ -162,7 +162,8 @@ public final class VibrationAttributes implements Parcelable { private final int mFlags; private final int mOriginalAudioUsage; - private VibrationAttributes(int usage, int audioUsage, int flags) { + private VibrationAttributes(@Usage int usage, @AudioAttributes.AttributeUsage int audioUsage, + @Flag int flags) { mUsage = usage; mOriginalAudioUsage = audioUsage; mFlags = flags & FLAG_ALL_SUPPORTED; @@ -172,6 +173,7 @@ public final class VibrationAttributes implements Parcelable { * Return the vibration usage class. * @return USAGE_CLASS_ALARM, USAGE_CLASS_FEEDBACK or USAGE_CLASS_UNKNOWN */ + @UsageClass public int getUsageClass() { return mUsage & USAGE_CLASS_MASK; } @@ -180,6 +182,7 @@ public final class VibrationAttributes implements Parcelable { * Return the vibration usage. * @return one of the values that can be set in {@link Builder#setUsage(int)} */ + @Usage public int getUsage() { return mUsage; } @@ -188,6 +191,7 @@ public final class VibrationAttributes implements Parcelable { * Return the flags. * @return a combined mask of all flags */ + @Flag public int getFlags() { return mFlags; } @@ -196,7 +200,7 @@ public final class VibrationAttributes implements Parcelable { * Check whether a flag is set * @return true if a flag is set and false otherwise */ - public boolean isFlagSet(int flag) { + public boolean isFlagSet(@Flag int flag) { return (mFlags & flag) > 0; } @@ -206,6 +210,7 @@ public final class VibrationAttributes implements Parcelable { * @hide */ @TestApi + @AudioAttributes.AttributeUsage public int getAudioUsage() { if (mOriginalAudioUsage != AudioAttributes.USAGE_UNKNOWN) { // Return same audio usage set in the Builder. @@ -292,7 +297,7 @@ public final class VibrationAttributes implements Parcelable { } /** @hide */ - public static String usageToString(int usage) { + public static String usageToString(@Usage int usage) { switch (usage) { case USAGE_UNKNOWN: return "UNKNOWN"; @@ -419,7 +424,7 @@ public final class VibrationAttributes implements Parcelable { * {@link VibrationAttributes#USAGE_MEDIA}. * @return the same Builder instance. */ - public @NonNull Builder setUsage(int usage) { + public @NonNull Builder setUsage(@Usage int usage) { mOriginalAudioUsage = AudioAttributes.USAGE_UNKNOWN; mUsage = usage; return this; @@ -431,7 +436,7 @@ public final class VibrationAttributes implements Parcelable { * @param mask Bit range that should be changed. * @return the same Builder instance. */ - public @NonNull Builder setFlags(int flags, int mask) { + public @NonNull Builder setFlags(@Flag int flags, int mask) { mask &= FLAG_ALL_SUPPORTED; mFlags = (mFlags & ~mask) | (flags & mask); return this; diff --git a/services/core/java/com/android/server/vibrator/Vibration.java b/services/core/java/com/android/server/vibrator/Vibration.java index ddac9cd84d054..1d6e1585872dc 100644 --- a/services/core/java/com/android/server/vibrator/Vibration.java +++ b/services/core/java/com/android/server/vibrator/Vibration.java @@ -53,13 +53,13 @@ final class Vibration { IGNORED, IGNORED_APP_OPS, IGNORED_BACKGROUND, - IGNORED_RINGTONE, IGNORED_UNKNOWN_VIBRATION, IGNORED_UNSUPPORTED, IGNORED_FOR_ALARM, IGNORED_FOR_EXTERNAL, IGNORED_FOR_ONGOING, IGNORED_FOR_POWER, + IGNORED_FOR_RINGER_MODE, IGNORED_FOR_SETTINGS, IGNORED_SUPERSEDED, } diff --git a/services/core/java/com/android/server/vibrator/VibrationSettings.java b/services/core/java/com/android/server/vibrator/VibrationSettings.java index f82f99d6a2536..1ee115dd28f28 100644 --- a/services/core/java/com/android/server/vibrator/VibrationSettings.java +++ b/services/core/java/com/android/server/vibrator/VibrationSettings.java @@ -53,12 +53,44 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.server.LocalServices; import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; import java.util.List; +import java.util.Set; /** Controls all the system settings related to vibration. */ final class VibrationSettings { private static final String TAG = "VibrationSettings"; + /** + * Set of usages allowed for vibrations from background processes. + * + *
Some examples are notification, ringtone or alarm vibrations, that are allowed to vibrate
+ * unexpectedly as they are meant to grab the user's attention. Hardware feedback and physical
+ * emulation are also supported, as the trigger process might still be in the background when
+ * the user interaction wakes the device.
+ */
+ private static final Set Some examples are ringtone or alarm vibrations, that have high priority and should vibrate
+ * even when the device is saving battery.
+ */
+ private static final Set This checks the current {@link AudioManager#getRingerModeInternal()} against user settings
- * for ringtone usage only. All other usages are allowed independently of ringer mode.
- */
- public boolean shouldVibrateForRingerMode(int usageHint) {
- if (usageHint != USAGE_RINGTONE) {
- return true;
- }
- synchronized (mLock) {
- if (mAudioManager == null) {
- return false;
- }
- int ringerMode = mAudioManager.getRingerModeInternal();
- if (mVibrateWhenRinging) {
- return ringerMode != AudioManager.RINGER_MODE_SILENT;
- } else if (mApplyRampingRinger) {
- return ringerMode != AudioManager.RINGER_MODE_SILENT;
- } else {
- return ringerMode == AudioManager.RINGER_MODE_VIBRATE;
- }
- }
- }
-
- /**
- * Returns {@code true} if this vibration is allowed for given {@code uid}.
- *
- * This checks if the user is aware of this foreground process, or if the vibration usage is
- * allowed to play in the background (i.e. it's a notification, ringtone or alarm vibration).
- */
- public boolean shouldVibrateForUid(int uid, int usageHint) {
- return mUidObserver.isUidForeground(uid) || isClassAlarm(usageHint);
- }
-
- /**
- * Returns {@code true} if this vibration is allowed for current power mode state.
- *
- * This checks if the device is in battery saver mode, in which case only alarm, ringtone and
- * {@link VibrationAttributes#USAGE_COMMUNICATION_REQUEST} usages are allowed to vibrate.
- */
- public boolean shouldVibrateForPowerMode(int usageHint) {
- synchronized (mLock) {
- return !mLowPowerMode || usageHint == USAGE_RINGTONE || usageHint == USAGE_ALARM
- || usageHint == USAGE_COMMUNICATION_REQUEST;
- }
- }
-
/** Return {@code true} if input devices should vibrate instead of this device. */
public boolean shouldVibrateInputDevices() {
return mVibrateInputDevices;
}
- /** Return {@code true} if setting for {@link Settings.Global#ZEN_MODE} is not OFF. */
- public boolean isInZenMode() {
- return mZenMode != Settings.Global.ZEN_MODE_OFF;
+ /**
+ * Check if given vibration should be ignored by the service.
+ *
+ * @return One of Vibration.Status.IGNORED_* values if the vibration should be ignored,
+ * null otherwise.
+ */
+ @Nullable
+ public Vibration.Status shouldIgnoreVibration(int uid, VibrationAttributes attrs) {
+ final int usage = attrs.getUsage();
+ synchronized (mLock) {
+ if (!mUidObserver.isUidForeground(uid)
+ && !BACKGROUND_PROCESS_USAGE_ALLOWLIST.contains(usage)) {
+ return Vibration.Status.IGNORED_BACKGROUND;
+ }
+
+ if (mBatterySaverMode && !BATTERY_SAVER_USAGE_ALLOWLIST.contains(usage)) {
+ return Vibration.Status.IGNORED_FOR_POWER;
+ }
+
+ int intensity = getCurrentIntensity(usage);
+ if (intensity == Vibrator.VIBRATION_INTENSITY_OFF) {
+ return Vibration.Status.IGNORED_FOR_SETTINGS;
+ }
+
+ if (!shouldVibrateForRingerModeLocked(usage)) {
+ return Vibration.Status.IGNORED_FOR_RINGER_MODE;
+ }
+ }
+ return null;
}
- private static boolean isClassAlarm(int usageHint) {
- return (usageHint & VibrationAttributes.USAGE_CLASS_MASK)
- == VibrationAttributes.USAGE_CLASS_ALARM;
+ /**
+ * Return {@code true} if the device should vibrate for current ringer mode.
+ *
+ * This checks the current {@link AudioManager#getRingerModeInternal()} against user settings
+ * for touch and ringtone usages only. All other usages are allowed by this method.
+ */
+ @GuardedBy("mLock")
+ private boolean shouldVibrateForRingerModeLocked(int usageHint) {
+ // If audio manager was not loaded yet then assume most restrictive mode.
+ int ringerMode = (mAudioManager == null)
+ ? AudioManager.RINGER_MODE_SILENT
+ : mAudioManager.getRingerModeInternal();
+
+ switch (usageHint) {
+ case USAGE_TOUCH:
+ // Touch feedback disabled when phone is on silent mode.
+ return ringerMode != AudioManager.RINGER_MODE_SILENT;
+ case USAGE_RINGTONE:
+ switch (ringerMode) {
+ case AudioManager.RINGER_MODE_SILENT:
+ return false;
+ case AudioManager.RINGER_MODE_VIBRATE:
+ return true;
+ default:
+ // Ringtone vibrations also depend on 2 other settings:
+ return mVibrateWhenRinging || mApplyRampingRinger;
+ }
+ default:
+ // All other usages ignore ringer mode settings.
+ return true;
+ }
}
/** Updates all vibration settings and triggers registered listeners. */
- public void updateSettings() {
+ @VisibleForTesting
+ void updateSettings() {
synchronized (mLock) {
mVibrateWhenRinging = getSystemSetting(Settings.System.VIBRATE_WHEN_RINGING, 0) != 0;
mApplyRampingRinger = getSystemSetting(Settings.System.APPLY_RAMPING_RINGER, 0) != 0;
@@ -378,7 +414,6 @@ final class VibrationSettings {
mRingIntensity = getSystemSetting(Settings.System.RING_VIBRATION_INTENSITY,
getDefaultIntensity(USAGE_RINGTONE));
mVibrateInputDevices = getSystemSetting(Settings.System.VIBRATE_INPUT_DEVICES, 0) > 0;
- mZenMode = getGlobalSetting(Settings.Global.ZEN_MODE, Settings.Global.ZEN_MODE_OFF);
}
notifyListeners();
}
@@ -399,31 +434,33 @@ final class VibrationSettings {
@Override
public String toString() {
- return "VibrationSettings{"
- + "mVibrateInputDevices=" + mVibrateInputDevices
- + ", mVibrateWhenRinging=" + mVibrateWhenRinging
- + ", mApplyRampingRinger=" + mApplyRampingRinger
- + ", mLowPowerMode=" + mLowPowerMode
- + ", mZenMode=" + Settings.Global.zenModeToString(mZenMode)
- + ", mProcStatesCache=" + mUidObserver.mProcStatesCache
- + ", mHapticChannelMaxVibrationAmplitude=" + getHapticChannelMaxVibrationAmplitude()
- + ", mRampStepDuration=" + mRampStepDuration
- + ", mRampDownDuration=" + mRampDownDuration
- + ", mHardwareHapticFeedbackIntensity="
- + intensityToString(getCurrentIntensity(USAGE_HARDWARE_FEEDBACK))
- + ", mHapticFeedbackIntensity="
- + intensityToString(getCurrentIntensity(USAGE_TOUCH))
- + ", mHapticFeedbackDefaultIntensity="
- + intensityToString(getDefaultIntensity(USAGE_TOUCH))
- + ", mNotificationIntensity="
- + intensityToString(getCurrentIntensity(USAGE_NOTIFICATION))
- + ", mNotificationDefaultIntensity="
- + intensityToString(getDefaultIntensity(USAGE_NOTIFICATION))
- + ", mRingIntensity="
- + intensityToString(getCurrentIntensity(USAGE_RINGTONE))
- + ", mRingDefaultIntensity="
- + intensityToString(getDefaultIntensity(USAGE_RINGTONE))
- + '}';
+ synchronized (mLock) {
+ return "VibrationSettings{"
+ + "mVibrateInputDevices=" + mVibrateInputDevices
+ + ", mVibrateWhenRinging=" + mVibrateWhenRinging
+ + ", mApplyRampingRinger=" + mApplyRampingRinger
+ + ", mBatterySaverMode=" + mBatterySaverMode
+ + ", mProcStatesCache=" + mUidObserver.mProcStatesCache
+ + ", mHapticChannelMaxVibrationAmplitude="
+ + getHapticChannelMaxVibrationAmplitude()
+ + ", mRampStepDuration=" + mRampStepDuration
+ + ", mRampDownDuration=" + mRampDownDuration
+ + ", mHardwareHapticFeedbackIntensity="
+ + intensityToString(getCurrentIntensity(USAGE_HARDWARE_FEEDBACK))
+ + ", mHapticFeedbackIntensity="
+ + intensityToString(getCurrentIntensity(USAGE_TOUCH))
+ + ", mHapticFeedbackDefaultIntensity="
+ + intensityToString(getDefaultIntensity(USAGE_TOUCH))
+ + ", mNotificationIntensity="
+ + intensityToString(getCurrentIntensity(USAGE_NOTIFICATION))
+ + ", mNotificationDefaultIntensity="
+ + intensityToString(getDefaultIntensity(USAGE_NOTIFICATION))
+ + ", mRingIntensity="
+ + intensityToString(getCurrentIntensity(USAGE_RINGTONE))
+ + ", mRingDefaultIntensity="
+ + intensityToString(getDefaultIntensity(USAGE_RINGTONE))
+ + '}';
+ }
}
/** Write current settings into given {@link ProtoOutputStream}. */
@@ -480,10 +517,6 @@ final class VibrationSettings {
settingName, defaultValue, UserHandle.USER_CURRENT);
}
- private int getGlobalSetting(String settingName, int defaultValue) {
- return Settings.Global.getInt(mContext.getContentResolver(), settingName, defaultValue);
- }
-
private void registerSettingsObserver(Uri settingUri) {
mContext.getContentResolver().registerContentObserver(
settingUri, /* notifyForDescendants= */ true, mSettingObserver,
diff --git a/services/core/java/com/android/server/vibrator/VibratorManagerService.java b/services/core/java/com/android/server/vibrator/VibratorManagerService.java
index 97172015f9f0c..478e86e5f7107 100644
--- a/services/core/java/com/android/server/vibrator/VibratorManagerService.java
+++ b/services/core/java/com/android/server/vibrator/VibratorManagerService.java
@@ -46,7 +46,6 @@ import android.os.ShellCommand;
import android.os.Trace;
import android.os.VibrationAttributes;
import android.os.VibrationEffect;
-import android.os.Vibrator;
import android.os.VibratorInfo;
import android.os.vibrator.PrebakedSegment;
import android.os.vibrator.VibrationEffectSegment;
@@ -394,13 +393,13 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
if (DEBUG) {
Slog.d(TAG, "Starting vibrate for vibration " + vib.id);
}
- Vibration.Status ignoreStatus = shouldIgnoreVibrationLocked(vib);
- if (ignoreStatus != null) {
- endVibrationLocked(vib, ignoreStatus);
- return vib;
+ Vibration.Status ignoreStatus = shouldIgnoreVibrationLocked(
+ vib.uid, vib.opPkg, vib.attrs);
+
+ if (ignoreStatus == null) {
+ ignoreStatus = shouldIgnoreVibrationForOngoingLocked(vib);
}
- ignoreStatus = shouldIgnoreVibrationForCurrentLocked(vib);
if (ignoreStatus != null) {
endVibrationLocked(vib, ignoreStatus);
return vib;
@@ -453,8 +452,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
&& shouldCancelVibration(
mCurrentExternalVibration.externalVibration.getVibrationAttributes(),
usageFilter)) {
- mCurrentExternalVibration.end(Vibration.Status.CANCELLED);
- mVibratorManagerRecords.record(mCurrentExternalVibration);
+ endVibrationLocked(mCurrentExternalVibration, Vibration.Status.CANCELLED);
mCurrentExternalVibration.externalVibration.mute();
mCurrentExternalVibration = null;
setExternalControl(false);
@@ -482,15 +480,76 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
}
try {
if (isDumpProto) {
- mVibratorManagerRecords.dumpProto(fd);
+ dumpProto(fd);
} else {
- mVibratorManagerRecords.dumpText(pw);
+ dumpText(pw);
}
} finally {
Binder.restoreCallingIdentity(ident);
}
}
+ private void dumpText(PrintWriter pw) {
+ if (DEBUG) {
+ Slog.d(TAG, "Dumping vibrator manager service to text...");
+ }
+ synchronized (mLock) {
+ pw.println("Vibrator Manager Service:");
+ pw.println(" mVibrationSettings:");
+ pw.println(" " + mVibrationSettings);
+ pw.println();
+ pw.println(" mVibratorControllers:");
+ for (int i = 0; i < mVibrators.size(); i++) {
+ pw.println(" " + mVibrators.valueAt(i));
+ }
+ pw.println();
+ pw.println(" mCurrentVibration:");
+ pw.println(" " + (mCurrentVibration == null
+ ? null : mCurrentVibration.getVibration().getDebugInfo()));
+ pw.println();
+ pw.println(" mNextVibration:");
+ pw.println(" " + (mNextVibration == null
+ ? null : mNextVibration.getVibration().getDebugInfo()));
+ pw.println();
+ pw.println(" mCurrentExternalVibration:");
+ pw.println(" " + (mCurrentExternalVibration == null
+ ? null : mCurrentExternalVibration.getDebugInfo()));
+ pw.println();
+ }
+ mVibratorManagerRecords.dumpText(pw);
+ }
+
+ synchronized void dumpProto(FileDescriptor fd) {
+ final ProtoOutputStream proto = new ProtoOutputStream(fd);
+ if (DEBUG) {
+ Slog.d(TAG, "Dumping vibrator manager service to proto...");
+ }
+ synchronized (mLock) {
+ mVibrationSettings.dumpProto(proto);
+ if (mCurrentVibration != null) {
+ mCurrentVibration.getVibration().getDebugInfo().dumpProto(proto,
+ VibratorManagerServiceDumpProto.CURRENT_VIBRATION);
+ }
+ if (mCurrentExternalVibration != null) {
+ mCurrentExternalVibration.getDebugInfo().dumpProto(proto,
+ VibratorManagerServiceDumpProto.CURRENT_EXTERNAL_VIBRATION);
+ }
+
+ boolean isVibrating = false;
+ boolean isUnderExternalControl = false;
+ for (int i = 0; i < mVibrators.size(); i++) {
+ proto.write(VibratorManagerServiceDumpProto.VIBRATOR_IDS, mVibrators.keyAt(i));
+ isVibrating |= mVibrators.valueAt(i).isVibrating();
+ isUnderExternalControl |= mVibrators.valueAt(i).isUnderExternalControl();
+ }
+ proto.write(VibratorManagerServiceDumpProto.IS_VIBRATING, isVibrating);
+ proto.write(VibratorManagerServiceDumpProto.VIBRATOR_UNDER_EXTERNAL_CONTROL,
+ isUnderExternalControl);
+ }
+ mVibratorManagerRecords.dumpProto(proto);
+ proto.flush();
+ }
+
@Override
public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
String[] args, ShellCallback cb, ResultReceiver resultReceiver) {
@@ -515,8 +574,15 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
return;
}
- if (inputDevicesChanged || !mVibrationSettings.shouldVibrateForPowerMode(
- mCurrentVibration.getVibration().attrs.getUsage())) {
+ Vibration vib = mCurrentVibration.getVibration();
+ Vibration.Status ignoreStatus = shouldIgnoreVibrationLocked(
+ vib.uid, vib.opPkg, vib.attrs);
+
+ if (inputDevicesChanged || (ignoreStatus != null)) {
+ if (DEBUG) {
+ Slog.d(TAG, "Canceling vibration because settings changed: "
+ + (inputDevicesChanged ? "input devices changed" : ignoreStatus));
+ }
mCurrentVibration.cancel();
}
}
@@ -602,15 +668,56 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
@GuardedBy("mLock")
private void endVibrationLocked(Vibration vib, Vibration.Status status) {
vib.end(status);
+ logVibrationStatus(vib.uid, vib.attrs, status);
mVibratorManagerRecords.record(vib);
}
@GuardedBy("mLock")
private void endVibrationLocked(ExternalVibrationHolder vib, Vibration.Status status) {
vib.end(status);
+ logVibrationStatus(vib.externalVibration.getUid(),
+ vib.externalVibration.getVibrationAttributes(), status);
mVibratorManagerRecords.record(vib);
}
+ private void logVibrationStatus(int uid, VibrationAttributes attrs, Vibration.Status status) {
+ switch (status) {
+ case IGNORED_BACKGROUND:
+ Slog.e(TAG, "Ignoring incoming vibration as process with"
+ + " uid= " + uid + " is background," + " attrs= " + attrs);
+ break;
+ case IGNORED_ERROR_APP_OPS:
+ Slog.w(TAG, "Would be an error: vibrate from uid " + uid);
+ break;
+ case IGNORED_FOR_ALARM:
+ if (DEBUG) {
+ Slog.d(TAG, "Ignoring incoming vibration in favor of alarm vibration");
+ }
+ break;
+ case IGNORED_FOR_EXTERNAL:
+ if (DEBUG) {
+ Slog.d(TAG, "Ignoring incoming vibration for current external vibration");
+ }
+ break;
+ case IGNORED_FOR_ONGOING:
+ if (DEBUG) {
+ Slog.d(TAG, "Ignoring incoming vibration in favor of repeating vibration");
+ }
+ break;
+ case IGNORED_FOR_RINGER_MODE:
+ if (DEBUG) {
+ Slog.d(TAG, "Ignoring incoming vibration because of ringer mode, attrs="
+ + attrs);
+ }
+ break;
+ default:
+ if (DEBUG) {
+ Slog.d(TAG, "Vibration for uid=" + uid + " and with attrs=" + attrs
+ + " ended with status " + status);
+ }
+ }
+ }
+
@GuardedBy("mLock")
private void reportFinishedVibrationLocked(Vibration.Status status) {
Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "reportFinishVibrationLocked");
@@ -651,32 +758,36 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
}
/**
- * Check if given vibration should be ignored in favour of one of the vibrations currently
- * running on the same vibrators.
+ * Check if given vibration should be ignored by this service because of the ongoing vibration.
*
- * @return One of Vibration.Status.IGNORED_* values if the vibration should be ignored.
+ * @return One of Vibration.Status.IGNORED_* values if the vibration should be ignored, null
+ * otherwise.
*/
@GuardedBy("mLock")
@Nullable
- private Vibration.Status shouldIgnoreVibrationForCurrentLocked(Vibration vibration) {
- if (vibration.isRepeating()) {
- // Repeating vibrations always take precedence.
+ private Vibration.Status shouldIgnoreVibrationForOngoingLocked(Vibration vib) {
+ if (mCurrentExternalVibration != null) {
+ // If something has external control of the vibrator, assume that it's more important.
+ return Vibration.Status.IGNORED_FOR_EXTERNAL;
+ }
+
+ if (mCurrentVibration == null || vib.isRepeating()) {
+ // Incoming repeating vibrations always take precedence over ongoing vibrations.
return null;
}
- if (mCurrentVibration != null && !mCurrentVibration.getVibration().hasEnded()) {
- if (mCurrentVibration.getVibration().attrs.getUsage()
- == VibrationAttributes.USAGE_ALARM) {
- if (DEBUG) {
- Slog.d(TAG, "Ignoring incoming vibration in favor of alarm vibration");
- }
- return Vibration.Status.IGNORED_FOR_ALARM;
- }
- if (mCurrentVibration.getVibration().isRepeating()) {
- if (DEBUG) {
- Slog.d(TAG, "Ignoring incoming vibration in favor of repeating vibration");
- }
- return Vibration.Status.IGNORED_FOR_ONGOING;
- }
+
+ Vibration currentVibration = mCurrentVibration.getVibration();
+ if (currentVibration.hasEnded()) {
+ // Current vibration is finishing up, it should not block incoming vibrations.
+ return null;
+ }
+
+ if (currentVibration.attrs.getUsage() == VibrationAttributes.USAGE_ALARM) {
+ return Vibration.Status.IGNORED_FOR_ALARM;
+ }
+
+ if (currentVibration.isRepeating()) {
+ return Vibration.Status.IGNORED_FOR_ONGOING;
}
return null;
}
@@ -684,57 +795,16 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
/**
* Check if given vibration should be ignored by this service.
*
- * @return One of Vibration.Status.IGNORED_* values if the vibration should be ignored.
- * @see #shouldIgnoreVibrationLocked(int, String, VibrationAttributes)
- */
- @GuardedBy("mLock")
- @Nullable
- private Vibration.Status shouldIgnoreVibrationLocked(Vibration vib) {
- // If something has external control of the vibrator, assume that it's more important.
- if (mCurrentExternalVibration != null) {
- if (DEBUG) {
- Slog.d(TAG, "Ignoring incoming vibration for current external vibration");
- }
- return Vibration.Status.IGNORED_FOR_EXTERNAL;
- }
-
- if (!mVibrationSettings.shouldVibrateForUid(vib.uid, vib.attrs.getUsage())) {
- Slog.e(TAG, "Ignoring incoming vibration as process with"
- + " uid= " + vib.uid + " is background,"
- + " attrs= " + vib.attrs);
- return Vibration.Status.IGNORED_BACKGROUND;
- }
-
- return shouldIgnoreVibrationLocked(vib.uid, vib.opPkg, vib.attrs);
- }
-
- /**
- * Check if a vibration with given {@code uid}, {@code opPkg} and {@code attrs} should be
- * ignored by this service.
- *
- * @param uid The user id of this vibration
- * @param opPkg The package name of this vibration
- * @param attrs The attributes of this vibration
- * @return One of Vibration.Status.IGNORED_* values if the vibration should be ignored.
+ * @return One of Vibration.Status.IGNORED_* values if the vibration should be ignored, null
+ * otherwise.
*/
@GuardedBy("mLock")
@Nullable
private Vibration.Status shouldIgnoreVibrationLocked(int uid, String opPkg,
VibrationAttributes attrs) {
- if (!mVibrationSettings.shouldVibrateForPowerMode(attrs.getUsage())) {
- return Vibration.Status.IGNORED_FOR_POWER;
- }
-
- int intensity = mVibrationSettings.getCurrentIntensity(attrs.getUsage());
- if (intensity == Vibrator.VIBRATION_INTENSITY_OFF) {
- return Vibration.Status.IGNORED_FOR_SETTINGS;
- }
-
- if (!mVibrationSettings.shouldVibrateForRingerMode(attrs.getUsage())) {
- if (DEBUG) {
- Slog.e(TAG, "Vibrate ignored, not vibrating for ringtones");
- }
- return Vibration.Status.IGNORED_RINGTONE;
+ Vibration.Status statusFromSettings = mVibrationSettings.shouldIgnoreVibration(uid, attrs);
+ if (statusFromSettings != null) {
+ return statusFromSettings;
}
int mode = checkAppOpModeLocked(uid, opPkg, attrs);
@@ -742,7 +812,6 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
if (mode == AppOpsManager.MODE_ERRORED) {
// We might be getting calls from within system_server, so we don't actually
// want to throw a SecurityException here.
- Slog.w(TAG, "Would be an error: vibrate from uid " + uid);
return Vibration.Status.IGNORED_ERROR_APP_OPS;
} else {
return Vibration.Status.IGNORED_APP_OPS;
@@ -1236,21 +1305,18 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
}
/** Keep records of vibrations played and provide debug information for this service. */
- private final class VibratorManagerRecords {
- @GuardedBy("mLock")
+ private static final class VibratorManagerRecords {
private final SparseArray