summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/vibrator/ExternalVibrationSession.java146
-rw-r--r--services/core/java/com/android/server/vibrator/HalVibration.java38
-rw-r--r--services/core/java/com/android/server/vibrator/InputDeviceDelegate.java3
-rw-r--r--services/core/java/com/android/server/vibrator/Vibration.java185
-rw-r--r--services/core/java/com/android/server/vibrator/VibrationSession.java208
-rw-r--r--services/core/java/com/android/server/vibrator/VibrationSettings.java28
-rw-r--r--services/core/java/com/android/server/vibrator/VibrationStats.java6
-rw-r--r--services/core/java/com/android/server/vibrator/VibrationStepConductor.java11
-rw-r--r--services/core/java/com/android/server/vibrator/VibrationThread.java5
-rw-r--r--services/core/java/com/android/server/vibrator/VibratorControlService.java4
-rw-r--r--services/core/java/com/android/server/vibrator/VibratorManagerService.java342
-rw-r--r--services/tests/vibrator/src/com/android/server/vibrator/InputDeviceDelegateTest.java6
-rw-r--r--services/tests/vibrator/src/com/android/server/vibrator/VibrationSessionTest.java (renamed from services/tests/vibrator/src/com/android/server/vibrator/VibrationTest.java)8
-rw-r--r--services/tests/vibrator/src/com/android/server/vibrator/VibrationSettingsTest.java57
-rw-r--r--services/tests/vibrator/src/com/android/server/vibrator/VibrationThreadTest.java173
-rw-r--r--services/tests/vibrator/src/com/android/server/vibrator/VibratorFrameworkStatsLoggerTest.java5
-rw-r--r--services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java258
17 files changed, 898 insertions, 585 deletions
diff --git a/services/core/java/com/android/server/vibrator/ExternalVibrationSession.java b/services/core/java/com/android/server/vibrator/ExternalVibrationSession.java
new file mode 100644
index 000000000000..b4d3862431f1
--- /dev/null
+++ b/services/core/java/com/android/server/vibrator/ExternalVibrationSession.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.vibrator;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.os.ExternalVibration;
+import android.os.ExternalVibrationScale;
+import android.os.IBinder;
+import android.os.VibrationAttributes;
+import android.os.vibrator.Flags;
+
+import com.android.internal.util.FrameworkStatsLog;
+
+/**
+ * A vibration session holding a single {@link ExternalVibration} request.
+ */
+final class ExternalVibrationSession extends Vibration
+ implements VibrationSession, IBinder.DeathRecipient {
+
+ private final ExternalVibration mExternalVibration;
+ private final ExternalVibrationScale mScale = new ExternalVibrationScale();
+
+ @Nullable
+ private Runnable mBinderDeathCallback;
+
+ ExternalVibrationSession(ExternalVibration externalVibration) {
+ super(externalVibration.getToken(), new CallerInfo(
+ externalVibration.getVibrationAttributes(), externalVibration.getUid(),
+ // TODO(b/249785241): Find a way to link ExternalVibration to a VirtualDevice
+ // instead of using DEVICE_ID_INVALID here and relying on the UID checks.
+ Context.DEVICE_ID_INVALID, externalVibration.getPackage(), null));
+ mExternalVibration = externalVibration;
+ }
+
+ public ExternalVibrationScale getScale() {
+ return mScale;
+ }
+
+ @Override
+ public CallerInfo getCallerInfo() {
+ return callerInfo;
+ }
+
+ @Override
+ public VibrationSession.DebugInfo getDebugInfo() {
+ return new Vibration.DebugInfoImpl(getStatus(), stats, /* playedEffect= */ null,
+ /* originalEffect= */ null, mScale.scaleLevel, mScale.adaptiveHapticsScale,
+ callerInfo);
+ }
+
+ @Override
+ public VibrationStats.StatsInfo getStatsInfo(long completionUptimeMillis) {
+ return new VibrationStats.StatsInfo(
+ mExternalVibration.getUid(),
+ FrameworkStatsLog.VIBRATION_REPORTED__VIBRATION_TYPE__EXTERNAL,
+ mExternalVibration.getVibrationAttributes().getUsage(), getStatus(), stats,
+ completionUptimeMillis);
+ }
+
+ @Override
+ public boolean isRepeating() {
+ // We don't currently know if the external vibration is repeating, so we just use a
+ // heuristic based on the usage. Ideally this would be propagated in the ExternalVibration.
+ int usage = mExternalVibration.getVibrationAttributes().getUsage();
+ return usage == VibrationAttributes.USAGE_RINGTONE
+ || usage == VibrationAttributes.USAGE_ALARM;
+ }
+
+ @Override
+ public void linkToDeath(Runnable callback) {
+ synchronized (this) {
+ mBinderDeathCallback = callback;
+ }
+ mExternalVibration.linkToDeath(this);
+ }
+
+ @Override
+ public void unlinkToDeath() {
+ mExternalVibration.unlinkToDeath(this);
+ synchronized (this) {
+ mBinderDeathCallback = null;
+ }
+ }
+
+ @Override
+ public void binderDied() {
+ synchronized (this) {
+ if (mBinderDeathCallback != null) {
+ mBinderDeathCallback.run();
+ }
+ }
+ }
+
+ @Override
+ void end(EndInfo endInfo) {
+ super.end(endInfo);
+ if (stats.hasStarted()) {
+ // External vibration doesn't have feedback from total time the vibrator was playing
+ // with non-zero amplitude, so we use the duration between start and end times of
+ // the vibration as the time the vibrator was ON, since the haptic channels are
+ // open for this duration and can receive vibration waveform data.
+ stats.reportVibratorOn(stats.getEndUptimeMillis() - stats.getStartUptimeMillis());
+ }
+ }
+
+ @Override
+ public void notifyEnded() {
+ // Notify external client that this vibration should stop sending data to the vibrator.
+ mExternalVibration.mute();
+ }
+
+ boolean isHoldingSameVibration(ExternalVibration vib) {
+ return mExternalVibration.equals(vib);
+ }
+
+ void muteScale() {
+ mScale.scaleLevel = ExternalVibrationScale.ScaleLevel.SCALE_MUTE;
+ if (Flags.hapticsScaleV2Enabled()) {
+ mScale.scaleFactor = 0;
+ }
+ }
+
+ void scale(VibrationScaler scaler, int usage) {
+ mScale.scaleLevel = scaler.getScaleLevel(usage);
+ if (Flags.hapticsScaleV2Enabled()) {
+ mScale.scaleFactor = scaler.getScaleFactor(usage);
+ }
+ mScale.adaptiveHapticsScale = scaler.getAdaptiveHapticsScale(usage);
+ stats.reportAdaptiveScale(mScale.adaptiveHapticsScale);
+ }
+}
diff --git a/services/core/java/com/android/server/vibrator/HalVibration.java b/services/core/java/com/android/server/vibrator/HalVibration.java
index fe0cf5909970..ea4bd0182ea3 100644
--- a/services/core/java/com/android/server/vibrator/HalVibration.java
+++ b/services/core/java/com/android/server/vibrator/HalVibration.java
@@ -51,37 +51,22 @@ final class HalVibration extends Vibration {
@NonNull
private volatile CombinedVibration mEffectToPlay;
- /** Vibration status. */
- private Vibration.Status mStatus;
-
/** Reported scale values applied to the vibration effects. */
private int mScaleLevel;
private float mAdaptiveScale;
HalVibration(@NonNull IBinder token, @NonNull CombinedVibration effect,
- @NonNull CallerInfo callerInfo) {
+ @NonNull VibrationSession.CallerInfo callerInfo) {
super(token, callerInfo);
mOriginalEffect = effect;
mEffectToPlay = effect;
- mStatus = Vibration.Status.RUNNING;
mScaleLevel = VibrationScaler.SCALE_NONE;
mAdaptiveScale = VibrationScaler.ADAPTIVE_SCALE_NONE;
}
- /**
- * Set the {@link Status} of this vibration and reports the current system time as this
- * vibration end time, for debugging purposes.
- *
- * <p>This method will only accept given value if the current status is {@link
- * Status#RUNNING}.
- */
- public void end(EndInfo info) {
- if (hasEnded()) {
- // Vibration already ended, keep first ending status set and ignore this one.
- return;
- }
- mStatus = info.status;
- stats.reportEnded(info.endedBy);
+ @Override
+ public void end(EndInfo endInfo) {
+ super.end(endInfo);
mCompletionLatch.countDown();
}
@@ -144,11 +129,6 @@ final class HalVibration extends Vibration {
// No need to update fallback effects, they are already configured per device.
}
- /** Return true is current status is different from {@link Status#RUNNING}. */
- public boolean hasEnded() {
- return mStatus != Status.RUNNING;
- }
-
@Override
public boolean isRepeating() {
return mOriginalEffect.getDuration() == Long.MAX_VALUE;
@@ -159,16 +139,16 @@ final class HalVibration extends Vibration {
return mEffectToPlay;
}
- /** Return {@link Vibration.DebugInfo} with read-only debug information about this vibration. */
- public Vibration.DebugInfo getDebugInfo() {
+ @Override
+ public VibrationSession.DebugInfo getDebugInfo() {
// Clear the original effect if it's the same as the effect that was played, for simplicity
CombinedVibration originalEffect =
Objects.equals(mOriginalEffect, mEffectToPlay) ? null : mOriginalEffect;
- return new Vibration.DebugInfo(mStatus, stats, mEffectToPlay, originalEffect,
+ return new Vibration.DebugInfoImpl(getStatus(), stats, mEffectToPlay, originalEffect,
mScaleLevel, mAdaptiveScale, callerInfo);
}
- /** Return {@link VibrationStats.StatsInfo} with read-only metrics about this vibration. */
+ @Override
public VibrationStats.StatsInfo getStatsInfo(long completionUptimeMillis) {
int vibrationType = mEffectToPlay.hasVendorEffects()
? FrameworkStatsLog.VIBRATION_REPORTED__VIBRATION_TYPE__VENDOR
@@ -176,7 +156,7 @@ final class HalVibration extends Vibration {
? FrameworkStatsLog.VIBRATION_REPORTED__VIBRATION_TYPE__REPEATED
: FrameworkStatsLog.VIBRATION_REPORTED__VIBRATION_TYPE__SINGLE;
return new VibrationStats.StatsInfo(
- callerInfo.uid, vibrationType, callerInfo.attrs.getUsage(), mStatus,
+ callerInfo.uid, vibrationType, callerInfo.attrs.getUsage(), getStatus(),
stats, completionUptimeMillis);
}
diff --git a/services/core/java/com/android/server/vibrator/InputDeviceDelegate.java b/services/core/java/com/android/server/vibrator/InputDeviceDelegate.java
index 4e58b9a35243..83e05f4eff9f 100644
--- a/services/core/java/com/android/server/vibrator/InputDeviceDelegate.java
+++ b/services/core/java/com/android/server/vibrator/InputDeviceDelegate.java
@@ -26,6 +26,7 @@ import android.util.SparseArray;
import android.view.InputDevice;
import com.android.internal.annotations.GuardedBy;
+import com.android.server.vibrator.VibrationSession.CallerInfo;
/** Delegates vibrations to all connected {@link InputDevice} with one or more vibrators. */
final class InputDeviceDelegate implements InputManager.InputDeviceListener {
@@ -93,7 +94,7 @@ final class InputDeviceDelegate implements InputManager.InputDeviceListener {
*
* @return {@link #isAvailable()}
*/
- public boolean vibrateIfAvailable(Vibration.CallerInfo callerInfo, CombinedVibration effect) {
+ public boolean vibrateIfAvailable(CallerInfo callerInfo, CombinedVibration effect) {
synchronized (mLock) {
for (int i = 0; i < mInputDeviceVibrators.size(); i++) {
mInputDeviceVibrators.valueAt(i).vibrate(callerInfo.uid, callerInfo.opPkg, effect,
diff --git a/services/core/java/com/android/server/vibrator/Vibration.java b/services/core/java/com/android/server/vibrator/Vibration.java
index aa4b9f3e9d7d..9a0479337471 100644
--- a/services/core/java/com/android/server/vibrator/Vibration.java
+++ b/services/core/java/com/android/server/vibrator/Vibration.java
@@ -31,7 +31,6 @@ import android.os.vibrator.VibrationEffectSegment;
import android.util.IndentingPrintWriter;
import android.util.proto.ProtoOutputStream;
-import java.io.PrintWriter;
import java.time.Instant;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
@@ -52,131 +51,69 @@ abstract class Vibration {
private static final AtomicInteger sNextVibrationId = new AtomicInteger(1); // 0 = no callback
public final long id;
- public final CallerInfo callerInfo;
+ public final VibrationSession.CallerInfo callerInfo;
public final VibrationStats stats = new VibrationStats();
public final IBinder callerToken;
- /** Vibration status with reference to values from vibratormanagerservice.proto for logging. */
- enum Status {
- UNKNOWN(VibrationProto.UNKNOWN),
- RUNNING(VibrationProto.RUNNING),
- FINISHED(VibrationProto.FINISHED),
- FINISHED_UNEXPECTED(VibrationProto.FINISHED_UNEXPECTED),
- FORWARDED_TO_INPUT_DEVICES(VibrationProto.FORWARDED_TO_INPUT_DEVICES),
- CANCELLED_BINDER_DIED(VibrationProto.CANCELLED_BINDER_DIED),
- 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),
- IGNORED_ERROR_APP_OPS(VibrationProto.IGNORED_ERROR_APP_OPS),
- IGNORED_ERROR_CANCELLING(VibrationProto.IGNORED_ERROR_CANCELLING),
- IGNORED_ERROR_SCHEDULING(VibrationProto.IGNORED_ERROR_SCHEDULING),
- IGNORED_ERROR_TOKEN(VibrationProto.IGNORED_ERROR_TOKEN),
- IGNORED_APP_OPS(VibrationProto.IGNORED_APP_OPS),
- IGNORED_BACKGROUND(VibrationProto.IGNORED_BACKGROUND),
- IGNORED_MISSING_PERMISSION(VibrationProto.IGNORED_MISSING_PERMISSION),
- IGNORED_UNSUPPORTED(VibrationProto.IGNORED_UNSUPPORTED),
- IGNORED_FOR_EXTERNAL(VibrationProto.IGNORED_FOR_EXTERNAL),
- IGNORED_FOR_HIGHER_IMPORTANCE(VibrationProto.IGNORED_FOR_HIGHER_IMPORTANCE),
- IGNORED_FOR_ONGOING(VibrationProto.IGNORED_FOR_ONGOING),
- IGNORED_FOR_POWER(VibrationProto.IGNORED_FOR_POWER),
- IGNORED_FOR_RINGER_MODE(VibrationProto.IGNORED_FOR_RINGER_MODE),
- IGNORED_FOR_SETTINGS(VibrationProto.IGNORED_FOR_SETTINGS),
- IGNORED_SUPERSEDED(VibrationProto.IGNORED_SUPERSEDED),
- IGNORED_FROM_VIRTUAL_DEVICE(VibrationProto.IGNORED_FROM_VIRTUAL_DEVICE),
- IGNORED_ON_WIRELESS_CHARGER(VibrationProto.IGNORED_ON_WIRELESS_CHARGER);
-
- private final int mProtoEnumValue;
-
- Status(int value) {
- mProtoEnumValue = value;
- }
-
- public int getProtoEnumValue() {
- return mProtoEnumValue;
- }
- }
+ private VibrationSession.Status mStatus;
- Vibration(@NonNull IBinder token, @NonNull CallerInfo callerInfo) {
+ Vibration(@NonNull IBinder token, @NonNull VibrationSession.CallerInfo callerInfo) {
Objects.requireNonNull(token);
Objects.requireNonNull(callerInfo);
+ mStatus = VibrationSession.Status.RUNNING;
this.id = sNextVibrationId.getAndIncrement();
this.callerToken = token;
this.callerInfo = callerInfo;
}
- /** Return true if vibration is a repeating vibration. */
- abstract boolean isRepeating();
+ VibrationSession.Status getStatus() {
+ return mStatus;
+ }
+
+ /** Return true is current status is different from {@link VibrationSession.Status#RUNNING}. */
+ boolean hasEnded() {
+ return mStatus != VibrationSession.Status.RUNNING;
+ }
/**
- * Holds lightweight immutable info on the process that triggered the vibration. This data
- * could potentially be kept in memory for a long time for bugreport dumpsys operations.
+ * Set the {@link VibrationSession} of this vibration and reports the current system time as
+ * this vibration end time, for debugging purposes.
*
- * Since CallerInfo can be kept in memory for a long time, it shouldn't hold any references to
- * potentially expensive or resource-linked objects, such as {@link IBinder}.
+ * <p>This method will only accept given value if the current status is {@link
+ * VibrationSession.Status#RUNNING}.
*/
- static final class CallerInfo {
- public final VibrationAttributes attrs;
- public final int uid;
- public final int deviceId;
- public final String opPkg;
- public final String reason;
-
- CallerInfo(@NonNull VibrationAttributes attrs, int uid, int deviceId, String opPkg,
- String reason) {
- Objects.requireNonNull(attrs);
- this.attrs = attrs;
- this.uid = uid;
- this.deviceId = deviceId;
- this.opPkg = opPkg;
- this.reason = reason;
+ void end(Vibration.EndInfo endInfo) {
+ if (hasEnded()) {
+ // Vibration already ended, keep first ending status set and ignore this one.
+ return;
}
+ mStatus = endInfo.status;
+ stats.reportEnded(endInfo.endedBy);
+ }
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (!(o instanceof CallerInfo)) return false;
- CallerInfo that = (CallerInfo) o;
- return Objects.equals(attrs, that.attrs)
- && uid == that.uid
- && deviceId == that.deviceId
- && Objects.equals(opPkg, that.opPkg)
- && Objects.equals(reason, that.reason);
- }
+ /** Return true if vibration is a repeating vibration. */
+ abstract boolean isRepeating();
- @Override
- public int hashCode() {
- return Objects.hash(attrs, uid, deviceId, opPkg, reason);
- }
+ /** Return {@link VibrationSession.DebugInfo} with read-only debug data about this vibration. */
+ abstract VibrationSession.DebugInfo getDebugInfo();
- @Override
- public String toString() {
- return "CallerInfo{"
- + " uid=" + uid
- + ", opPkg=" + opPkg
- + ", deviceId=" + deviceId
- + ", attrs=" + attrs
- + ", reason=" + reason
- + '}';
- }
- }
+ /** Return {@link VibrationStats.StatsInfo} with read-only metrics about this vibration. */
+ abstract VibrationStats.StatsInfo getStatsInfo(long completionUptimeMillis);
/** Immutable info passed as a signal to end a vibration. */
static final class EndInfo {
- /** The {@link Status} to be set to the vibration when it ends with this info. */
+ /** The vibration status to be set when it ends with this info. */
@NonNull
- public final Status status;
+ public final VibrationSession.Status status;
/** Info about the process that ended the vibration. */
- public final CallerInfo endedBy;
+ public final VibrationSession.CallerInfo endedBy;
- EndInfo(@NonNull Vibration.Status status) {
+ EndInfo(@NonNull VibrationSession.Status status) {
this(status, null);
}
- EndInfo(@NonNull Vibration.Status status, @Nullable CallerInfo endedBy) {
+ EndInfo(@NonNull VibrationSession.Status status,
+ @Nullable VibrationSession.CallerInfo endedBy) {
this.status = status;
this.endedBy = endedBy;
}
@@ -211,10 +148,10 @@ abstract class Vibration {
* Since DebugInfo can be kept in memory for a long time, it shouldn't hold any references to
* potentially expensive or resource-linked objects, such as {@link IBinder}.
*/
- static final class DebugInfo {
- final Status mStatus;
+ static final class DebugInfoImpl implements VibrationSession.DebugInfo {
+ final VibrationSession.Status mStatus;
final long mCreateTime;
- final CallerInfo mCallerInfo;
+ final VibrationSession.CallerInfo mCallerInfo;
@Nullable
final CombinedVibration mPlayedEffect;
@@ -226,9 +163,10 @@ abstract class Vibration {
private final int mScaleLevel;
private final float mAdaptiveScale;
- DebugInfo(Status status, VibrationStats stats, @Nullable CombinedVibration playedEffect,
+ DebugInfoImpl(VibrationSession.Status status, VibrationStats stats,
+ @Nullable CombinedVibration playedEffect,
@Nullable CombinedVibration originalEffect, int scaleLevel,
- float adaptiveScale, @NonNull CallerInfo callerInfo) {
+ float adaptiveScale, @NonNull VibrationSession.CallerInfo callerInfo) {
Objects.requireNonNull(callerInfo);
mCreateTime = stats.getCreateTimeDebug();
mStartTime = stats.getStartTimeDebug();
@@ -243,6 +181,27 @@ abstract class Vibration {
}
@Override
+ public VibrationSession.Status getStatus() {
+ return mStatus;
+ }
+
+ @Override
+ public long getCreateUptimeMillis() {
+ return mCreateTime;
+ }
+
+ @Override
+ public VibrationSession.CallerInfo getCallerInfo() {
+ return mCallerInfo;
+ }
+
+ @Nullable
+ @Override
+ public Object getDumpAggregationKey() {
+ return mPlayedEffect;
+ }
+
+ @Override
public String toString() {
return "createTime: " + formatTime(mCreateTime, /*includeDate=*/ true)
+ ", startTime: " + formatTime(mStartTime, /*includeDate=*/ true)
@@ -257,17 +216,13 @@ abstract class Vibration {
+ ", callerInfo: " + mCallerInfo;
}
- void logMetrics(VibratorFrameworkStatsLogger statsLogger) {
+ @Override
+ public void logMetrics(VibratorFrameworkStatsLogger statsLogger) {
statsLogger.logVibrationAdaptiveHapticScale(mCallerInfo.uid, mAdaptiveScale);
}
- /**
- * Write this info in a compact way into given {@link PrintWriter}.
- *
- * <p>This is used by dumpsys to log multiple vibration records in single lines that are
- * easy to skim through by the sorted created time.
- */
- void dumpCompact(IndentingPrintWriter pw) {
+ @Override
+ public void dumpCompact(IndentingPrintWriter pw) {
boolean isExternalVibration = mPlayedEffect == null;
String timingsStr = String.format(Locale.ROOT,
"%s | %8s | %20s | duration: %5dms | start: %12s | end: %12s",
@@ -299,8 +254,8 @@ abstract class Vibration {
pw.println(timingsStr + paramStr + audioUsageStr + callerStr + effectStr);
}
- /** Write this info into given {@link PrintWriter}. */
- void dump(IndentingPrintWriter pw) {
+ @Override
+ public void dump(IndentingPrintWriter pw) {
pw.println("Vibration:");
pw.increaseIndent();
pw.println("status = " + mStatus.name().toLowerCase(Locale.ROOT));
@@ -317,8 +272,8 @@ abstract class Vibration {
pw.decreaseIndent();
}
- /** Write this info into given {@code fieldId} on {@link ProtoOutputStream}. */
- void dump(ProtoOutputStream proto, long fieldId) {
+ @Override
+ public void dump(ProtoOutputStream proto, long fieldId) {
final long token = proto.start(fieldId);
proto.write(VibrationProto.START_TIME, mStartTime);
proto.write(VibrationProto.END_TIME, mEndTime);
diff --git a/services/core/java/com/android/server/vibrator/VibrationSession.java b/services/core/java/com/android/server/vibrator/VibrationSession.java
new file mode 100644
index 000000000000..5640b49b28d8
--- /dev/null
+++ b/services/core/java/com/android/server/vibrator/VibrationSession.java
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.vibrator;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.CombinedVibration;
+import android.os.IBinder;
+import android.os.VibrationAttributes;
+import android.util.IndentingPrintWriter;
+import android.util.proto.ProtoOutputStream;
+
+import java.io.PrintWriter;
+import java.util.Objects;
+
+/**
+ * Represents a generic vibration session that plays one or more vibration requests.
+ *
+ * <p>This might represent:
+ *
+ * <ol>
+ * <li>A single {@link CombinedVibration} playback.
+ * <li>An {@link android.os.ExternalVibration} playback.
+ * </ol>
+ */
+interface VibrationSession {
+
+ /** Returns data about the client app that triggered this vibration session. */
+ CallerInfo getCallerInfo();
+
+ /** Returns debug data for logging and metric reports. */
+ DebugInfo getDebugInfo();
+
+ /**
+ * Links this session to the app process death with given callback to handle it.
+ *
+ * <p>This can be used by the service to end the vibration session when the app process dies.
+ */
+ void linkToDeath(Runnable callback);
+
+ /** Removes link to the app process death. */
+ void unlinkToDeath();
+
+ /** Notify the session end was requested, which might be acted upon asynchronously. */
+ void notifyEnded();
+
+ /**
+ * Session status with reference to values from vibratormanagerservice.proto for logging.
+ */
+ enum Status {
+ UNKNOWN(VibrationProto.UNKNOWN),
+ RUNNING(VibrationProto.RUNNING),
+ FINISHED(VibrationProto.FINISHED),
+ FINISHED_UNEXPECTED(VibrationProto.FINISHED_UNEXPECTED),
+ FORWARDED_TO_INPUT_DEVICES(VibrationProto.FORWARDED_TO_INPUT_DEVICES),
+ CANCELLED_BINDER_DIED(VibrationProto.CANCELLED_BINDER_DIED),
+ 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),
+ IGNORED_ERROR_APP_OPS(VibrationProto.IGNORED_ERROR_APP_OPS),
+ IGNORED_ERROR_CANCELLING(VibrationProto.IGNORED_ERROR_CANCELLING),
+ IGNORED_ERROR_SCHEDULING(VibrationProto.IGNORED_ERROR_SCHEDULING),
+ IGNORED_ERROR_TOKEN(VibrationProto.IGNORED_ERROR_TOKEN),
+ IGNORED_APP_OPS(VibrationProto.IGNORED_APP_OPS),
+ IGNORED_BACKGROUND(VibrationProto.IGNORED_BACKGROUND),
+ IGNORED_MISSING_PERMISSION(VibrationProto.IGNORED_MISSING_PERMISSION),
+ IGNORED_UNSUPPORTED(VibrationProto.IGNORED_UNSUPPORTED),
+ IGNORED_FOR_EXTERNAL(VibrationProto.IGNORED_FOR_EXTERNAL),
+ IGNORED_FOR_HIGHER_IMPORTANCE(VibrationProto.IGNORED_FOR_HIGHER_IMPORTANCE),
+ IGNORED_FOR_ONGOING(VibrationProto.IGNORED_FOR_ONGOING),
+ IGNORED_FOR_POWER(VibrationProto.IGNORED_FOR_POWER),
+ IGNORED_FOR_RINGER_MODE(VibrationProto.IGNORED_FOR_RINGER_MODE),
+ IGNORED_FOR_SETTINGS(VibrationProto.IGNORED_FOR_SETTINGS),
+ IGNORED_SUPERSEDED(VibrationProto.IGNORED_SUPERSEDED),
+ IGNORED_FROM_VIRTUAL_DEVICE(VibrationProto.IGNORED_FROM_VIRTUAL_DEVICE),
+ IGNORED_ON_WIRELESS_CHARGER(VibrationProto.IGNORED_ON_WIRELESS_CHARGER);
+
+ private final int mProtoEnumValue;
+
+ Status(int value) {
+ mProtoEnumValue = value;
+ }
+
+ public int getProtoEnumValue() {
+ return mProtoEnumValue;
+ }
+ }
+
+ /**
+ * Holds lightweight immutable info on the process that triggered the vibration session.
+ *
+ * <p>This data could potentially be kept in memory for a long time for bugreport dumpsys
+ * operations. It shouldn't hold any references to potentially expensive or resource-linked
+ * objects, such as {@link IBinder}.
+ */
+ final class CallerInfo {
+ public final VibrationAttributes attrs;
+ public final int uid;
+ public final int deviceId;
+ public final String opPkg;
+ public final String reason;
+
+ CallerInfo(@NonNull VibrationAttributes attrs, int uid, int deviceId, String opPkg,
+ String reason) {
+ Objects.requireNonNull(attrs);
+ this.attrs = attrs;
+ this.uid = uid;
+ this.deviceId = deviceId;
+ this.opPkg = opPkg;
+ this.reason = reason;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof CallerInfo)) return false;
+ CallerInfo that = (CallerInfo) o;
+ return Objects.equals(attrs, that.attrs)
+ && uid == that.uid
+ && deviceId == that.deviceId
+ && Objects.equals(opPkg, that.opPkg)
+ && Objects.equals(reason, that.reason);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(attrs, uid, deviceId, opPkg, reason);
+ }
+
+ @Override
+ public String toString() {
+ return "CallerInfo{"
+ + " uid=" + uid
+ + ", opPkg=" + opPkg
+ + ", deviceId=" + deviceId
+ + ", attrs=" + attrs
+ + ", reason=" + reason
+ + '}';
+ }
+ }
+
+ /**
+ * Interface for lightweight debug information about the vibration session for debugging.
+ *
+ * <p>This data could potentially be kept in memory for a long time for bugreport dumpsys
+ * operations. It shouldn't hold any references to potentially expensive or resource-linked
+ * objects, such as {@link IBinder}.
+ */
+ interface DebugInfo {
+
+ /** Return the vibration session status. */
+ Status getStatus();
+
+ /** Returns the session creation time from {@link android.os.SystemClock#uptimeMillis()}. */
+ long getCreateUptimeMillis();
+
+ /** Returns information about the process that created the session. */
+ CallerInfo getCallerInfo();
+
+ /**
+ * Returns the aggregation key for log records.
+ *
+ * <p>This is used to aggregate similar vibration sessions triggered in quick succession
+ * (e.g. multiple keyboard vibrations when the user is typing).
+ *
+ * <p>This does not need to include data from {@link CallerInfo} or {@link Status}.
+ *
+ * @see GroupedAggregatedLogRecords
+ */
+ @Nullable
+ Object getDumpAggregationKey();
+
+ /** Logs vibration session fields for metric reports. */
+ void logMetrics(VibratorFrameworkStatsLogger statsLogger);
+
+ /** Write this info into given {@code fieldId} on {@link ProtoOutputStream}. */
+ void dump(ProtoOutputStream proto, long fieldId);
+
+ /** Write this info into given {@link PrintWriter}. */
+ void dump(IndentingPrintWriter pw);
+
+ /**
+ * Write this info in a compact way into given {@link PrintWriter}.
+ *
+ * <p>This is used by dumpsys to log multiple records in single lines that are easy to skim
+ * through by the sorted created time.
+ */
+ void dumpCompact(IndentingPrintWriter pw);
+ }
+}
diff --git a/services/core/java/com/android/server/vibrator/VibrationSettings.java b/services/core/java/com/android/server/vibrator/VibrationSettings.java
index 0d6778c18759..69cdcf47680d 100644
--- a/services/core/java/com/android/server/vibrator/VibrationSettings.java
+++ b/services/core/java/com/android/server/vibrator/VibrationSettings.java
@@ -66,6 +66,8 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.LocalServices;
import com.android.server.companion.virtual.VirtualDeviceManagerInternal;
+import com.android.server.vibrator.VibrationSession.CallerInfo;
+import com.android.server.vibrator.VibrationSession.Status;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -416,46 +418,46 @@ final class VibrationSettings {
/**
* Check if given vibration should be ignored by the service.
*
- * @return One of Vibration.Status.IGNORED_* values if the vibration should be ignored,
+ * @return One of VibrationSession.Status.IGNORED_* values if the vibration should be ignored,
* null otherwise.
*/
@Nullable
- public Vibration.Status shouldIgnoreVibration(@NonNull Vibration.CallerInfo callerInfo) {
+ public Status shouldIgnoreVibration(@NonNull CallerInfo callerInfo) {
final int usage = callerInfo.attrs.getUsage();
synchronized (mLock) {
if (!mUidObserver.isUidForeground(callerInfo.uid)
&& !BACKGROUND_PROCESS_USAGE_ALLOWLIST.contains(usage)) {
- return Vibration.Status.IGNORED_BACKGROUND;
+ return Status.IGNORED_BACKGROUND;
}
if (callerInfo.deviceId != Context.DEVICE_ID_DEFAULT
&& callerInfo.deviceId != Context.DEVICE_ID_INVALID) {
- return Vibration.Status.IGNORED_FROM_VIRTUAL_DEVICE;
+ return Status.IGNORED_FROM_VIRTUAL_DEVICE;
}
if (callerInfo.deviceId == Context.DEVICE_ID_INVALID
&& isAppRunningOnAnyVirtualDevice(callerInfo.uid)) {
- return Vibration.Status.IGNORED_FROM_VIRTUAL_DEVICE;
+ return Status.IGNORED_FROM_VIRTUAL_DEVICE;
}
if (mBatterySaverMode && !BATTERY_SAVER_USAGE_ALLOWLIST.contains(usage)) {
- return Vibration.Status.IGNORED_FOR_POWER;
+ return Status.IGNORED_FOR_POWER;
}
if (!callerInfo.attrs.isFlagSet(
VibrationAttributes.FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF)
&& !shouldVibrateForUserSetting(callerInfo)) {
- return Vibration.Status.IGNORED_FOR_SETTINGS;
+ return Status.IGNORED_FOR_SETTINGS;
}
if (!callerInfo.attrs.isFlagSet(VibrationAttributes.FLAG_BYPASS_INTERRUPTION_POLICY)) {
if (!shouldVibrateForRingerModeLocked(usage)) {
- return Vibration.Status.IGNORED_FOR_RINGER_MODE;
+ return Status.IGNORED_FOR_RINGER_MODE;
}
}
if (mVibrationConfig.ignoreVibrationsOnWirelessCharger() && mOnWirelessCharger) {
- return Vibration.Status.IGNORED_ON_WIRELESS_CHARGER;
+ return Status.IGNORED_ON_WIRELESS_CHARGER;
}
}
return null;
@@ -471,7 +473,7 @@ final class VibrationSettings {
*
* @return true if the vibration should be cancelled when the screen goes off, false otherwise.
*/
- public boolean shouldCancelVibrationOnScreenOff(@NonNull Vibration.CallerInfo callerInfo,
+ public boolean shouldCancelVibrationOnScreenOff(@NonNull CallerInfo callerInfo,
long vibrationStartUptimeMillis) {
PowerManagerInternal pm;
synchronized (mLock) {
@@ -483,8 +485,8 @@ final class VibrationSettings {
// ignored here and not cancel a vibration, and those are usually triggered by timeout
// or inactivity, so it's unlikely that it will override a more active goToSleep reason.
PowerManager.SleepData sleepData = pm.getLastGoToSleep();
- if ((sleepData.goToSleepUptimeMillis < vibrationStartUptimeMillis)
- || POWER_MANAGER_SLEEP_REASON_ALLOWLIST.contains(sleepData.goToSleepReason)) {
+ if (sleepData != null && (sleepData.goToSleepUptimeMillis < vibrationStartUptimeMillis
+ || POWER_MANAGER_SLEEP_REASON_ALLOWLIST.contains(sleepData.goToSleepReason))) {
// Ignore screen off events triggered before the vibration started, and all
// automatic "go to sleep" events from allowlist.
Slog.d(TAG, "Ignoring screen off event triggered at uptime "
@@ -522,7 +524,7 @@ final class VibrationSettings {
* {@code false} to ignore the vibration.
*/
@GuardedBy("mLock")
- private boolean shouldVibrateForUserSetting(Vibration.CallerInfo callerInfo) {
+ private boolean shouldVibrateForUserSetting(CallerInfo callerInfo) {
final int usage = callerInfo.attrs.getUsage();
if (!mVibrateOn && (VIBRATE_ON_DISABLED_USAGE_ALLOWED != usage)) {
// Main setting disabled.
diff --git a/services/core/java/com/android/server/vibrator/VibrationStats.java b/services/core/java/com/android/server/vibrator/VibrationStats.java
index 8179d6aea9ca..fc0c6e7bf05e 100644
--- a/services/core/java/com/android/server/vibrator/VibrationStats.java
+++ b/services/core/java/com/android/server/vibrator/VibrationStats.java
@@ -166,7 +166,7 @@ final class VibrationStats {
* @return true if the status was accepted. This method will only accept given values if
* the end timestamp was never set.
*/
- boolean reportEnded(@Nullable Vibration.CallerInfo endedBy) {
+ boolean reportEnded(@Nullable VibrationSession.CallerInfo endedBy) {
if (hasEnded()) {
// Vibration already ended, keep first ending stats set and ignore this one.
return false;
@@ -187,7 +187,7 @@ final class VibrationStats {
* <p>This method will only accept the first value as the one that was interrupted by this
* vibration, and will ignore all successive calls.
*/
- void reportInterruptedAnotherVibration(@NonNull Vibration.CallerInfo callerInfo) {
+ void reportInterruptedAnotherVibration(@NonNull VibrationSession.CallerInfo callerInfo) {
if (mInterruptedUsage < 0) {
mInterruptedUsage = callerInfo.attrs.getUsage();
}
@@ -330,7 +330,7 @@ final class VibrationStats {
public final int[] halUnsupportedEffectsUsed;
private boolean mIsWritten;
- StatsInfo(int uid, int vibrationType, int usage, Vibration.Status status,
+ StatsInfo(int uid, int vibrationType, int usage, VibrationSession.Status status,
VibrationStats stats, long completionUptimeMillis) {
this.uid = uid;
this.vibrationType = vibrationType;
diff --git a/services/core/java/com/android/server/vibrator/VibrationStepConductor.java b/services/core/java/com/android/server/vibrator/VibrationStepConductor.java
index 7152844cc772..5137d1938332 100644
--- a/services/core/java/com/android/server/vibrator/VibrationStepConductor.java
+++ b/services/core/java/com/android/server/vibrator/VibrationStepConductor.java
@@ -32,6 +32,7 @@ import android.util.Slog;
import android.util.SparseArray;
import com.android.internal.annotations.GuardedBy;
+import com.android.server.vibrator.VibrationSession.Status;
import java.util.ArrayList;
import java.util.Iterator;
@@ -217,7 +218,7 @@ final class VibrationStepConductor implements IBinder.DeathRecipient {
}
/**
- * Calculate the {@link Vibration.Status} based on the current queue state and the expected
+ * Calculate the {@link Vibration.EndInfo} based on the current queue state and the expected
* number of {@link StartSequentialEffectStep} to be played.
*/
@Nullable
@@ -235,10 +236,10 @@ final class VibrationStepConductor implements IBinder.DeathRecipient {
}
// No pending steps, and something happened.
if (mSuccessfulVibratorOnSteps > 0) {
- return new Vibration.EndInfo(Vibration.Status.FINISHED);
+ return new Vibration.EndInfo(Status.FINISHED);
}
// If no step was able to turn the vibrator ON successfully.
- return new Vibration.EndInfo(Vibration.Status.IGNORED_UNSUPPORTED);
+ return new Vibration.EndInfo(Status.IGNORED_UNSUPPORTED);
}
/**
@@ -352,7 +353,7 @@ final class VibrationStepConductor implements IBinder.DeathRecipient {
if (DEBUG) {
Slog.d(TAG, "Binder died, cancelling vibration...");
}
- notifyCancelled(new Vibration.EndInfo(Vibration.Status.CANCELLED_BINDER_DIED),
+ notifyCancelled(new Vibration.EndInfo(Status.CANCELLED_BINDER_DIED),
/* immediate= */ false);
}
@@ -377,7 +378,7 @@ final class VibrationStepConductor implements IBinder.DeathRecipient {
if ((cancelInfo == null) || !cancelInfo.status.name().startsWith("CANCEL")) {
Slog.w(TAG, "Vibration cancel requested with bad signal=" + cancelInfo
+ ", using CANCELLED_UNKNOWN_REASON to ensure cancellation.");
- cancelInfo = new Vibration.EndInfo(Vibration.Status.CANCELLED_BY_UNKNOWN_REASON);
+ cancelInfo = new Vibration.EndInfo(Status.CANCELLED_BY_UNKNOWN_REASON);
}
synchronized (mLock) {
if ((immediate && mSignalCancelImmediate) || (mSignalCancel != null)) {
diff --git a/services/core/java/com/android/server/vibrator/VibrationThread.java b/services/core/java/com/android/server/vibrator/VibrationThread.java
index cfb4c74fcbfc..ab4a4d8fc08d 100644
--- a/services/core/java/com/android/server/vibrator/VibrationThread.java
+++ b/services/core/java/com/android/server/vibrator/VibrationThread.java
@@ -29,6 +29,7 @@ import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.vibrator.VibrationSession.Status;
import java.util.NoSuchElementException;
import java.util.Objects;
@@ -240,7 +241,7 @@ final class VibrationThread extends Thread {
runCurrentVibrationWithWakeLockAndDeathLink();
} finally {
clientVibrationCompleteIfNotAlready(
- new Vibration.EndInfo(Vibration.Status.FINISHED_UNEXPECTED));
+ new Vibration.EndInfo(Status.FINISHED_UNEXPECTED));
}
} finally {
mWakeLock.release();
@@ -259,7 +260,7 @@ final class VibrationThread extends Thread {
} catch (RemoteException e) {
Slog.e(TAG, "Error linking vibration to token death", e);
clientVibrationCompleteIfNotAlready(
- new Vibration.EndInfo(Vibration.Status.IGNORED_ERROR_TOKEN));
+ new Vibration.EndInfo(Status.IGNORED_ERROR_TOKEN));
return;
}
// Ensure that the unlink always occurs now.
diff --git a/services/core/java/com/android/server/vibrator/VibratorControlService.java b/services/core/java/com/android/server/vibrator/VibratorControlService.java
index de5e662f2a71..3a814cd80836 100644
--- a/services/core/java/com/android/server/vibrator/VibratorControlService.java
+++ b/services/core/java/com/android/server/vibrator/VibratorControlService.java
@@ -559,8 +559,8 @@ final class VibratorControlService extends IVibratorControlService.Stub {
}
/**
- * Record for a single {@link Vibration.DebugInfo}, that can be grouped by usage and aggregated
- * by UID, {@link VibrationAttributes} and {@link VibrationEffect}.
+ * Record for a single {@link VibrationSession.DebugInfo}, that can be grouped by usage and
+ * aggregated by UID, {@link VibrationAttributes} and {@link VibrationEffect}.
*/
private static final class VibrationScaleParamRecord
implements GroupedAggregatedLogRecords.SingleLogRecord {
diff --git a/services/core/java/com/android/server/vibrator/VibratorManagerService.java b/services/core/java/com/android/server/vibrator/VibratorManagerService.java
index c143bebdd4a5..799934af54c0 100644
--- a/services/core/java/com/android/server/vibrator/VibratorManagerService.java
+++ b/services/core/java/com/android/server/vibrator/VibratorManagerService.java
@@ -73,9 +73,11 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
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 com.android.server.vibrator.VibrationSession.CallerInfo;
+import com.android.server.vibrator.VibrationSession.DebugInfo;
+import com.android.server.vibrator.VibrationSession.Status;
import libcore.util.NativeAllocationRegistry;
@@ -160,11 +162,12 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
@GuardedBy("mLock")
private VibrationStepConductor mNextVibration;
@GuardedBy("mLock")
- private ExternalVibrationHolder mCurrentExternalVibration;
+ private ExternalVibrationSession mCurrentExternalVibration;
@GuardedBy("mLock")
private boolean mServiceReady;
- private final VibrationSettings mVibrationSettings;
+ @VisibleForTesting
+ final VibrationSettings mVibrationSettings;
private final VibrationScaler mVibrationScaler;
private final VibratorControlService mVibratorControlService;
private final InputDeviceDelegate mInputDeviceDelegate;
@@ -184,13 +187,12 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
// When the system is entering a non-interactive state, we want to cancel
// vibrations in case a misbehaving app has abandoned them.
if (shouldCancelOnScreenOffLocked(mNextVibration)) {
- clearNextVibrationLocked(
- new Vibration.EndInfo(Vibration.Status.CANCELLED_BY_SCREEN_OFF));
+ clearNextVibrationLocked(new Vibration.EndInfo(
+ Status.CANCELLED_BY_SCREEN_OFF));
}
if (shouldCancelOnScreenOffLocked(mCurrentVibration)) {
- mCurrentVibration.notifyCancelled(
- new Vibration.EndInfo(Vibration.Status.CANCELLED_BY_SCREEN_OFF),
- /* immediate= */ false);
+ mCurrentVibration.notifyCancelled(new Vibration.EndInfo(
+ Status.CANCELLED_BY_SCREEN_OFF), /* immediate= */ false);
}
}
} else if (android.multiuser.Flags.addUiForSoundsFromBackgroundUsers()
@@ -198,12 +200,11 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
synchronized (mLock) {
if (shouldCancelOnFgUserRequest(mNextVibration)) {
clearNextVibrationLocked(new Vibration.EndInfo(
- Vibration.Status.CANCELLED_BY_FOREGROUND_USER));
+ Status.CANCELLED_BY_FOREGROUND_USER));
}
if (shouldCancelOnFgUserRequest(mCurrentVibration)) {
mCurrentVibration.notifyCancelled(new Vibration.EndInfo(
- Vibration.Status.CANCELLED_BY_FOREGROUND_USER),
- /* immediate= */ false);
+ Status.CANCELLED_BY_FOREGROUND_USER), /* immediate= */ false);
}
}
}
@@ -220,12 +221,12 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
}
synchronized (mLock) {
if (shouldCancelAppOpModeChangedLocked(mNextVibration)) {
- clearNextVibrationLocked(
- new Vibration.EndInfo(Vibration.Status.CANCELLED_BY_APP_OPS));
+ clearNextVibrationLocked(new Vibration.EndInfo(
+ Status.CANCELLED_BY_APP_OPS));
}
if (shouldCancelAppOpModeChangedLocked(mCurrentVibration)) {
mCurrentVibration.notifyCancelled(new Vibration.EndInfo(
- Vibration.Status.CANCELLED_BY_APP_OPS), /* immediate= */ false);
+ Status.CANCELLED_BY_APP_OPS), /* immediate= */ false);
}
}
}
@@ -441,8 +442,8 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
return false;
}
AlwaysOnVibration alwaysOnVibration = new AlwaysOnVibration(alwaysOnId,
- new Vibration.CallerInfo(attrs, uid, Context.DEVICE_ID_DEFAULT, opPkg,
- null), effects);
+ new CallerInfo(attrs, uid, Context.DEVICE_ID_DEFAULT, opPkg, null),
+ effects);
mAlwaysOnEffects.put(alwaysOnId, alwaysOnVibration);
updateAlwaysOnLocked(alwaysOnVibration);
}
@@ -490,8 +491,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
// Make sure we report the constant id in the requested haptic feedback reason.
reason = "performHapticFeedback(constant=" + constant + "): " + reason;
HapticFeedbackVibrationProvider hapticVibrationProvider = getHapticVibrationProvider();
- Vibration.Status ignoreStatus = shouldIgnoreHapticFeedback(constant, reason,
- hapticVibrationProvider);
+ Status ignoreStatus = shouldIgnoreHapticFeedback(constant, reason, hapticVibrationProvider);
if (ignoreStatus != null) {
logAndRecordPerformHapticFeedbackAttempt(uid, deviceId, opPkg, reason, ignoreStatus);
return null;
@@ -516,8 +516,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
reason = "performHapticFeedbackForInputDevice(constant=" + constant + ", inputDeviceId="
+ inputDeviceId + ", inputSource=" + inputSource + "): " + reason;
HapticFeedbackVibrationProvider hapticVibrationProvider = getHapticVibrationProvider();
- Vibration.Status ignoreStatus = shouldIgnoreHapticFeedback(constant, reason,
- hapticVibrationProvider);
+ Status ignoreStatus = shouldIgnoreHapticFeedback(constant, reason, hapticVibrationProvider);
if (ignoreStatus != null) {
logAndRecordPerformHapticFeedbackAttempt(uid, deviceId, opPkg, reason, ignoreStatus);
return null;
@@ -533,7 +532,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
VibrationAttributes attrs) {
if (effect == null) {
logAndRecordPerformHapticFeedbackAttempt(uid, deviceId, opPkg, reason,
- Vibration.Status.IGNORED_UNSUPPORTED);
+ Status.IGNORED_UNSUPPORTED);
Slog.w(TAG,
"performHapticFeedbackWithEffect; vibration absent for constant " + constant);
return null;
@@ -578,23 +577,21 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
private HalVibration vibrateInternal(int uid, int deviceId, String opPkg,
@NonNull CombinedVibration effect, @NonNull VibrationAttributes attrs,
String reason, IBinder token) {
- Vibration.CallerInfo callerInfo =
- new Vibration.CallerInfo(attrs, uid, deviceId, opPkg, reason);
+ CallerInfo callerInfo = new CallerInfo(attrs, uid, deviceId, opPkg, reason);
if (token == null) {
Slog.e(TAG, "token must not be null");
- logAndRecordVibrationAttempt(effect, callerInfo, Vibration.Status.IGNORED_ERROR_TOKEN);
+ logAndRecordVibrationAttempt(effect, callerInfo, Status.IGNORED_ERROR_TOKEN);
return null;
}
if (effect.hasVendorEffects()
&& !hasPermission(android.Manifest.permission.VIBRATE_VENDOR_EFFECTS)) {
Slog.e(TAG, "vibrate; no permission for vendor effects");
- logAndRecordVibrationAttempt(effect, callerInfo,
- Vibration.Status.IGNORED_MISSING_PERMISSION);
+ logAndRecordVibrationAttempt(effect, callerInfo, Status.IGNORED_MISSING_PERMISSION);
return null;
}
enforceUpdateAppOpsStatsPermission(uid);
if (!isEffectValid(effect)) {
- logAndRecordVibrationAttempt(effect, callerInfo, Vibration.Status.IGNORED_UNSUPPORTED);
+ logAndRecordVibrationAttempt(effect, callerInfo, Status.IGNORED_UNSUPPORTED);
return null;
}
// Create Vibration.Stats as close to the received request as possible, for tracking.
@@ -625,11 +622,11 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
final long ident = Binder.clearCallingIdentity();
try {
if (mCurrentExternalVibration != null) {
- mCurrentExternalVibration.mute();
+ mCurrentExternalVibration.notifyEnded();
vib.stats.reportInterruptedAnotherVibration(
mCurrentExternalVibration.callerInfo);
endExternalVibrateLocked(
- new Vibration.EndInfo(Vibration.Status.CANCELLED_SUPERSEDED,
+ new Vibration.EndInfo(Status.CANCELLED_SUPERSEDED,
vib.callerInfo),
/* continueExternalControl= */ false);
} else if (mCurrentVibration != null) {
@@ -645,7 +642,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
vib.stats.reportInterruptedAnotherVibration(
mCurrentVibration.getVibration().callerInfo);
mCurrentVibration.notifyCancelled(
- new Vibration.EndInfo(Vibration.Status.CANCELLED_SUPERSEDED,
+ new Vibration.EndInfo(Status.CANCELLED_SUPERSEDED,
vib.callerInfo),
/* immediate= */ false);
}
@@ -677,7 +674,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
Slog.d(TAG, "Canceling vibration");
}
Vibration.EndInfo cancelledByUserInfo =
- new Vibration.EndInfo(Vibration.Status.CANCELLED_BY_USER);
+ new Vibration.EndInfo(Status.CANCELLED_BY_USER);
final long ident = Binder.clearCallingIdentity();
try {
if (mNextVibration != null
@@ -693,9 +690,9 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
}
if (mCurrentExternalVibration != null
&& shouldCancelVibration(
- mCurrentExternalVibration.externalVibration.getVibrationAttributes(),
+ mCurrentExternalVibration.getCallerInfo().attrs,
usageFilter)) {
- mCurrentExternalVibration.mute();
+ mCurrentExternalVibration.notifyEnded();
endExternalVibrateLocked(
cancelledByUserInfo, /* continueExternalControl= */ false);
}
@@ -860,7 +857,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
: vibrationEndInfo.status));
}
mCurrentVibration.notifyCancelled(
- new Vibration.EndInfo(Vibration.Status.CANCELLED_BY_SETTINGS_UPDATE),
+ new Vibration.EndInfo(Status.CANCELLED_BY_SETTINGS_UPDATE),
/* immediate= */ false);
}
}
@@ -911,7 +908,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
// Note that we don't consider pipelining here, because new pipelined ones should
// replace pending non-executing pipelined ones anyway.
clearNextVibrationLocked(
- new Vibration.EndInfo(Vibration.Status.IGNORED_SUPERSEDED, vib.callerInfo));
+ new Vibration.EndInfo(Status.IGNORED_SUPERSEDED, vib.callerInfo));
mNextVibration = conductor;
return null;
} finally {
@@ -934,15 +931,15 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
if (!mVibrationThread.runVibrationOnVibrationThread(mCurrentVibration)) {
// Shouldn't happen. The method call already logs a wtf.
mCurrentVibration = null; // Aborted.
- return new Vibration.EndInfo(Vibration.Status.IGNORED_ERROR_SCHEDULING);
+ return new Vibration.EndInfo(Status.IGNORED_ERROR_SCHEDULING);
}
return null;
case AppOpsManager.MODE_ERRORED:
Slog.w(TAG, "Start AppOpsManager operation errored for uid "
+ vib.callerInfo.uid);
- return new Vibration.EndInfo(Vibration.Status.IGNORED_ERROR_APP_OPS);
+ return new Vibration.EndInfo(Status.IGNORED_ERROR_APP_OPS);
default:
- return new Vibration.EndInfo(Vibration.Status.IGNORED_APP_OPS);
+ return new Vibration.EndInfo(Status.IGNORED_APP_OPS);
}
} finally {
Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
@@ -950,7 +947,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
}
@GuardedBy("mLock")
- private void endVibrationLocked(HalVibration vib, Vibration.EndInfo vibrationEndInfo,
+ private void endVibrationLocked(Vibration vib, Vibration.EndInfo vibrationEndInfo,
boolean shouldWriteStats) {
vib.end(vibrationEndInfo);
logAndRecordVibration(vib.getDebugInfo());
@@ -960,15 +957,6 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
}
}
- @GuardedBy("mLock")
- private void endVibrationAndWriteStatsLocked(ExternalVibrationHolder vib,
- Vibration.EndInfo vibrationEndInfo) {
- vib.end(vibrationEndInfo);
- logAndRecordVibration(vib.getDebugInfo());
- mFrameworkStatsLogger.writeVibrationReportedAsync(
- vib.getStatsInfo(/* completionUptimeMillis= */ SystemClock.uptimeMillis()));
- }
-
private VibrationStepConductor createVibrationStepConductor(HalVibration vib) {
CompletableFuture<Void> requestVibrationParamsFuture = null;
@@ -990,33 +978,32 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
vib.scaleEffects(mVibrationScaler);
mInputDeviceDelegate.vibrateIfAvailable(vib.callerInfo, vib.getEffectToPlay());
- return new Vibration.EndInfo(Vibration.Status.FORWARDED_TO_INPUT_DEVICES);
+ return new Vibration.EndInfo(Status.FORWARDED_TO_INPUT_DEVICES);
}
private void logAndRecordPerformHapticFeedbackAttempt(int uid, int deviceId, String opPkg,
- String reason, Vibration.Status status) {
- Vibration.CallerInfo callerInfo = new Vibration.CallerInfo(
+ String reason, Status status) {
+ CallerInfo callerInfo = new CallerInfo(
VibrationAttributes.createForUsage(VibrationAttributes.USAGE_UNKNOWN),
uid, deviceId, opPkg, reason);
logAndRecordVibrationAttempt(/* effect= */ null, callerInfo, status);
}
private void logAndRecordVibrationAttempt(@Nullable CombinedVibration effect,
- Vibration.CallerInfo callerInfo, Vibration.Status status) {
+ CallerInfo callerInfo, Status status) {
logAndRecordVibration(
- new Vibration.DebugInfo(status, new VibrationStats(),
+ new Vibration.DebugInfoImpl(status, new VibrationStats(),
effect, /* originalEffect= */ null, VibrationScaler.SCALE_NONE,
VibrationScaler.ADAPTIVE_SCALE_NONE, callerInfo));
}
- private void logAndRecordVibration(Vibration.DebugInfo info) {
+ private void logAndRecordVibration(DebugInfo info) {
info.logMetrics(mFrameworkStatsLogger);
- logVibrationStatus(info.mCallerInfo.uid, info.mCallerInfo.attrs, info.mStatus);
+ logVibrationStatus(info.getCallerInfo().uid, info.getCallerInfo().attrs, info.getStatus());
mVibratorManagerRecords.record(info);
}
- private void logVibrationStatus(int uid, VibrationAttributes attrs,
- Vibration.Status status) {
+ private void logVibrationStatus(int uid, VibrationAttributes attrs, Status status) {
switch (status) {
case IGNORED_BACKGROUND:
Slog.e(TAG, "Ignoring incoming vibration as process with"
@@ -1161,15 +1148,14 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
if (ongoingVibrationImportance > newVibrationImportance) {
// Existing vibration has higher importance and should not be cancelled.
- return new Vibration.EndInfo(Vibration.Status.IGNORED_FOR_HIGHER_IMPORTANCE,
+ return new Vibration.EndInfo(Status.IGNORED_FOR_HIGHER_IMPORTANCE,
ongoingVibration.callerInfo);
}
// Same importance, use repeating as a tiebreaker.
if (ongoingVibration.isRepeating() && !newVibration.isRepeating()) {
// Ongoing vibration is repeating and new one is not, give priority to ongoing
- return new Vibration.EndInfo(Vibration.Status.IGNORED_FOR_ONGOING,
- ongoingVibration.callerInfo);
+ return new Vibration.EndInfo(Status.IGNORED_FOR_ONGOING, ongoingVibration.callerInfo);
}
// New vibration is repeating or this is a complete tie between them,
// give priority to new vibration.
@@ -1220,8 +1206,8 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
*/
@GuardedBy("mLock")
@Nullable
- private Vibration.EndInfo shouldIgnoreVibrationLocked(Vibration.CallerInfo callerInfo) {
- Vibration.Status statusFromSettings = mVibrationSettings.shouldIgnoreVibration(callerInfo);
+ private Vibration.EndInfo shouldIgnoreVibrationLocked(CallerInfo callerInfo) {
+ Status statusFromSettings = mVibrationSettings.shouldIgnoreVibration(callerInfo);
if (statusFromSettings != null) {
return new Vibration.EndInfo(statusFromSettings);
}
@@ -1231,9 +1217,9 @@ 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.
- return new Vibration.EndInfo(Vibration.Status.IGNORED_ERROR_APP_OPS);
+ return new Vibration.EndInfo(Status.IGNORED_ERROR_APP_OPS);
} else {
- return new Vibration.EndInfo(Vibration.Status.IGNORED_APP_OPS);
+ return new Vibration.EndInfo(Status.IGNORED_APP_OPS);
}
}
@@ -1241,16 +1227,16 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
}
@Nullable
- private Vibration.Status shouldIgnoreHapticFeedback(int constant, String reason,
+ private Status shouldIgnoreHapticFeedback(int constant, String reason,
HapticFeedbackVibrationProvider hapticVibrationProvider) {
if (hapticVibrationProvider == null) {
Slog.e(TAG, reason + "; haptic vibration provider not ready.");
- return Vibration.Status.IGNORED_ERROR_SCHEDULING;
+ return Status.IGNORED_ERROR_SCHEDULING;
}
if (hapticVibrationProvider.isRestrictedHapticFeedback(constant)
&& !hasPermission(android.Manifest.permission.VIBRATE_SYSTEM_CONSTANTS)) {
Slog.w(TAG, reason + "; no permission for system constant " + constant);
- return Vibration.Status.IGNORED_MISSING_PERMISSION;
+ return Status.IGNORED_MISSING_PERMISSION;
}
return null;
}
@@ -1291,7 +1277,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
* {@code attrs}. This will return one of the AppOpsManager.MODE_*.
*/
@GuardedBy("mLock")
- private int checkAppOpModeLocked(Vibration.CallerInfo callerInfo) {
+ private int checkAppOpModeLocked(CallerInfo callerInfo) {
int mode = mAppOps.checkAudioOpNoThrow(AppOpsManager.OP_VIBRATE,
callerInfo.attrs.getAudioUsage(), callerInfo.uid, callerInfo.opPkg);
int fixedMode = fixupAppOpModeLocked(mode, callerInfo.attrs);
@@ -1306,7 +1292,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
/** Start an operation in {@link AppOpsManager}, if allowed. */
@GuardedBy("mLock")
- private int startAppOpModeLocked(Vibration.CallerInfo callerInfo) {
+ private int startAppOpModeLocked(CallerInfo callerInfo) {
return fixupAppOpModeLocked(
mAppOps.startOpNoThrow(AppOpsManager.OP_VIBRATE, callerInfo.uid, callerInfo.opPkg),
callerInfo.attrs);
@@ -1317,7 +1303,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
* operation with same uid was previously started.
*/
@GuardedBy("mLock")
- private void finishAppOpModeLocked(Vibration.CallerInfo callerInfo) {
+ private void finishAppOpModeLocked(CallerInfo callerInfo) {
mAppOps.finishOp(AppOpsManager.OP_VIBRATE, callerInfo.uid, callerInfo.opPkg);
}
@@ -1735,10 +1721,10 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
*/
private static final class AlwaysOnVibration {
public final int alwaysOnId;
- public final Vibration.CallerInfo callerInfo;
+ public final CallerInfo callerInfo;
public final SparseArray<PrebakedSegment> effects;
- AlwaysOnVibration(int alwaysOnId, Vibration.CallerInfo callerInfo,
+ AlwaysOnVibration(int alwaysOnId, CallerInfo callerInfo,
SparseArray<PrebakedSegment> effects) {
this.alwaysOnId = alwaysOnId;
this.callerInfo = callerInfo;
@@ -1746,113 +1732,6 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
}
}
- /** Holder for a {@link ExternalVibration}. */
- private final class ExternalVibrationHolder extends Vibration implements
- IBinder.DeathRecipient {
-
- public final ExternalVibration externalVibration;
- public final ExternalVibrationScale scale = new ExternalVibrationScale();
-
- private Vibration.Status mStatus;
-
- private ExternalVibrationHolder(ExternalVibration externalVibration) {
- super(externalVibration.getToken(), new Vibration.CallerInfo(
- externalVibration.getVibrationAttributes(), externalVibration.getUid(),
- // TODO(b/249785241): Find a way to link ExternalVibration to a VirtualDevice
- // instead of using DEVICE_ID_INVALID here and relying on the UID checks.
- Context.DEVICE_ID_INVALID, externalVibration.getPackage(), null));
- this.externalVibration = externalVibration;
- mStatus = Vibration.Status.RUNNING;
- }
-
- public void muteScale() {
- scale.scaleLevel = ExternalVibrationScale.ScaleLevel.SCALE_MUTE;
- if (Flags.hapticsScaleV2Enabled()) {
- scale.scaleFactor = 0;
- }
- }
-
- public void scale(VibrationScaler scaler, int usage) {
- scale.scaleLevel = scaler.getScaleLevel(usage);
- if (Flags.hapticsScaleV2Enabled()) {
- scale.scaleFactor = scaler.getScaleFactor(usage);
- }
- scale.adaptiveHapticsScale = scaler.getAdaptiveHapticsScale(usage);
- stats.reportAdaptiveScale(scale.adaptiveHapticsScale);
- }
-
- public void mute() {
- externalVibration.mute();
- }
-
- public void linkToDeath() {
- externalVibration.linkToDeath(this);
- }
-
- public void unlinkToDeath() {
- externalVibration.unlinkToDeath(this);
- }
-
- public boolean isHoldingSameVibration(ExternalVibration externalVibration) {
- return this.externalVibration.equals(externalVibration);
- }
-
- public void end(Vibration.EndInfo info) {
- if (mStatus != Vibration.Status.RUNNING) {
- // Already ended, ignore this call
- return;
- }
- mStatus = info.status;
- stats.reportEnded(info.endedBy);
-
- if (stats.hasStarted()) {
- // External vibration doesn't have feedback from total time the vibrator was playing
- // with non-zero amplitude, so we use the duration between start and end times of
- // the vibration as the time the vibrator was ON, since the haptic channels are
- // open for this duration and can receive vibration waveform data.
- stats.reportVibratorOn(
- stats.getEndUptimeMillis() - stats.getStartUptimeMillis());
- }
- }
-
- public void binderDied() {
- synchronized (mLock) {
- if (mCurrentExternalVibration != null) {
- if (DEBUG) {
- Slog.d(TAG, "External vibration finished because binder died");
- }
- endExternalVibrateLocked(
- new Vibration.EndInfo(Vibration.Status.CANCELLED_BINDER_DIED),
- /* continueExternalControl= */ false);
- }
- }
- }
-
- public Vibration.DebugInfo getDebugInfo() {
- return new Vibration.DebugInfo(mStatus, stats, /* playedEffect= */ null,
- /* originalEffect= */ null, scale.scaleLevel, scale.adaptiveHapticsScale,
- callerInfo);
- }
-
- public VibrationStats.StatsInfo getStatsInfo(long completionUptimeMillis) {
- return new VibrationStats.StatsInfo(
- externalVibration.getUid(),
- FrameworkStatsLog.VIBRATION_REPORTED__VIBRATION_TYPE__EXTERNAL,
- externalVibration.getVibrationAttributes().getUsage(), mStatus, stats,
- completionUptimeMillis);
- }
-
- @Override
- boolean isRepeating() {
- // We don't currently know if the external vibration is repeating, so we just use a
- // heuristic based on the usage. Ideally this would be propagated in the
- // ExternalVibration.
- int usage = externalVibration.getVibrationAttributes().getUsage();
- return usage == VibrationAttributes.USAGE_RINGTONE
- || usage == VibrationAttributes.USAGE_ALARM;
- }
- }
-
/** Wrapper around the static-native methods of {@link VibratorManagerService} for tests. */
@VisibleForTesting
public static class NativeWrapper {
@@ -1912,7 +1791,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
new VibrationRecords(recentVibrationSizeLimit, /* aggregationTimeLimit= */ 0);
}
- synchronized void record(Vibration.DebugInfo info) {
+ synchronized void record(DebugInfo info) {
GroupedAggregatedLogRecords.AggregatedLogRecord<VibrationRecord> droppedRecord =
mRecentVibrations.add(new VibrationRecord(info));
if (droppedRecord != null) {
@@ -1969,25 +1848,25 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
}
/**
- * Record for a single {@link Vibration.DebugInfo}, that can be grouped by usage and aggregated
- * by UID, {@link VibrationAttributes} and {@link VibrationEffect}.
+ * Record for a single {@link DebugInfo}, that can be grouped by usage and aggregated by UID,
+ * {@link VibrationAttributes} and {@link CombinedVibration}.
*/
private static final class VibrationRecord
implements GroupedAggregatedLogRecords.SingleLogRecord {
- private final Vibration.DebugInfo mInfo;
+ private final DebugInfo mInfo;
- VibrationRecord(Vibration.DebugInfo info) {
+ VibrationRecord(DebugInfo info) {
mInfo = info;
}
@Override
public int getGroupKey() {
- return mInfo.mCallerInfo.attrs.getUsage();
+ return mInfo.getCallerInfo().attrs.getUsage();
}
@Override
public long getCreateUptimeMs() {
- return mInfo.mCreateTime;
+ return mInfo.getCreateUptimeMillis();
}
@Override
@@ -1995,10 +1874,10 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
if (!(record instanceof VibrationRecord)) {
return false;
}
- Vibration.DebugInfo info = ((VibrationRecord) record).mInfo;
- return mInfo.mCallerInfo.uid == info.mCallerInfo.uid
- && Objects.equals(mInfo.mCallerInfo.attrs, info.mCallerInfo.attrs)
- && Objects.equals(mInfo.mPlayedEffect, info.mPlayedEffect);
+ DebugInfo info = ((VibrationRecord) record).mInfo;
+ return mInfo.getCallerInfo().uid == info.getCallerInfo().uid
+ && Objects.equals(mInfo.getCallerInfo().attrs, info.getCallerInfo().attrs)
+ && Objects.equals(mInfo.getDumpAggregationKey(), info.getDumpAggregationKey());
}
@Override
@@ -2048,7 +1927,8 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
setExternalControl(false, mCurrentExternalVibration.stats);
}
// The external control was turned off, end it and report metrics right away.
- endVibrationAndWriteStatsLocked(mCurrentExternalVibration, vibrationEndInfo);
+ endVibrationLocked(mCurrentExternalVibration, vibrationEndInfo,
+ /* shouldWriteStats= */ true);
mCurrentExternalVibration = null;
} finally {
Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
@@ -2108,17 +1988,18 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
@Override
public ExternalVibrationScale onExternalVibrationStart(ExternalVibration vib) {
// Create Vibration.Stats as close to the received request as possible, for tracking.
- ExternalVibrationHolder vibHolder = new ExternalVibrationHolder(vib);
+ ExternalVibrationSession externalVibration = new ExternalVibrationSession(vib);
// Mute the request until we run all the checks and accept the vibration.
- vibHolder.muteScale();
+ externalVibration.muteScale();
boolean alreadyUnderExternalControl = false;
boolean waitForCompletion = false;
synchronized (mLock) {
if (!hasExternalControlCapability()) {
- endVibrationAndWriteStatsLocked(vibHolder,
- new Vibration.EndInfo(Vibration.Status.IGNORED_UNSUPPORTED));
- return vibHolder.scale;
+ endVibrationLocked(externalVibration,
+ new Vibration.EndInfo(Status.IGNORED_UNSUPPORTED),
+ /* shouldWriteStats= */ true);
+ return externalVibration.getScale();
}
if (ActivityManager.checkComponentPermission(android.Manifest.permission.VIBRATE,
@@ -2127,44 +2008,46 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
Slog.w(TAG, "pkg=" + vib.getPackage() + ", uid=" + vib.getUid()
+ " tried to play externally controlled vibration"
+ " without VIBRATE permission, ignoring.");
- endVibrationAndWriteStatsLocked(vibHolder,
- new Vibration.EndInfo(Vibration.Status.IGNORED_MISSING_PERMISSION));
- return vibHolder.scale;
+ endVibrationLocked(externalVibration,
+ new Vibration.EndInfo(Status.IGNORED_MISSING_PERMISSION),
+ /* shouldWriteStats= */ true);
+ return externalVibration.getScale();
}
Vibration.EndInfo vibrationEndInfo = shouldIgnoreVibrationLocked(
- vibHolder.callerInfo);
+ externalVibration.callerInfo);
if (vibrationEndInfo == null
&& mCurrentExternalVibration != null
&& mCurrentExternalVibration.isHoldingSameVibration(vib)) {
// We are already playing this external vibration, so we can return the same
// scale calculated in the previous call to this method.
- return mCurrentExternalVibration.scale;
+ return mCurrentExternalVibration.getScale();
}
if (vibrationEndInfo == null) {
// Check if ongoing vibration is more important than this vibration.
- vibrationEndInfo = shouldIgnoreVibrationForOngoingLocked(vibHolder);
+ vibrationEndInfo = shouldIgnoreVibrationForOngoingLocked(externalVibration);
}
if (vibrationEndInfo != null) {
- endVibrationAndWriteStatsLocked(vibHolder, vibrationEndInfo);
- return vibHolder.scale;
+ endVibrationLocked(externalVibration, vibrationEndInfo,
+ /* shouldWriteStats= */ true);
+ return externalVibration.getScale();
}
if (mCurrentExternalVibration == null) {
// If we're not under external control right now, then cancel any normal
// vibration that may be playing and ready the vibrator for external control.
if (mCurrentVibration != null) {
- vibHolder.stats.reportInterruptedAnotherVibration(
+ externalVibration.stats.reportInterruptedAnotherVibration(
mCurrentVibration.getVibration().callerInfo);
clearNextVibrationLocked(
- new Vibration.EndInfo(Vibration.Status.IGNORED_FOR_EXTERNAL,
- vibHolder.callerInfo));
+ new Vibration.EndInfo(Status.IGNORED_FOR_EXTERNAL,
+ externalVibration.callerInfo));
mCurrentVibration.notifyCancelled(
- new Vibration.EndInfo(Vibration.Status.CANCELLED_SUPERSEDED,
- vibHolder.callerInfo),
+ new Vibration.EndInfo(Status.CANCELLED_SUPERSEDED,
+ externalVibration.callerInfo),
/* immediate= */ true);
waitForCompletion = true;
}
@@ -2178,12 +2061,12 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
// Note that this doesn't support multiple concurrent external controls, as we
// would need to mute the old one still if it came from a different controller.
alreadyUnderExternalControl = true;
- mCurrentExternalVibration.mute();
- vibHolder.stats.reportInterruptedAnotherVibration(
+ mCurrentExternalVibration.notifyEnded();
+ externalVibration.stats.reportInterruptedAnotherVibration(
mCurrentExternalVibration.callerInfo);
endExternalVibrateLocked(
- new Vibration.EndInfo(Vibration.Status.CANCELLED_SUPERSEDED,
- vibHolder.callerInfo),
+ new Vibration.EndInfo(Status.CANCELLED_SUPERSEDED,
+ externalVibration.callerInfo),
/* continueExternalControl= */ true);
}
@@ -2195,9 +2078,9 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
mVibrationSettings.update();
}
- mCurrentExternalVibration = vibHolder;
- vibHolder.linkToDeath();
- vibHolder.scale(mVibrationScaler, attrs.getUsage());
+ mCurrentExternalVibration = externalVibration;
+ externalVibration.linkToDeath(this::onExternalVibrationBinderDied);
+ externalVibration.scale(mVibrationScaler, attrs.getUsage());
}
if (waitForCompletion) {
@@ -2206,27 +2089,27 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
synchronized (mLock) {
// Trigger endExternalVibrateLocked to unlink to death recipient.
endExternalVibrateLocked(
- new Vibration.EndInfo(Vibration.Status.IGNORED_ERROR_CANCELLING),
+ new Vibration.EndInfo(Status.IGNORED_ERROR_CANCELLING),
/* continueExternalControl= */ false);
// Mute the request, vibration will be ignored.
- vibHolder.muteScale();
+ externalVibration.muteScale();
}
- return vibHolder.scale;
+ return externalVibration.getScale();
}
}
if (!alreadyUnderExternalControl) {
if (DEBUG) {
Slog.d(TAG, "Vibrator going under external control.");
}
- setExternalControl(true, vibHolder.stats);
+ setExternalControl(true, externalVibration.stats);
}
if (DEBUG) {
Slog.d(TAG, "Playing external vibration: " + vib);
}
// Vibrator will start receiving data from external channels after this point.
// Report current time as the vibration start time, for debugging.
- vibHolder.stats.reportStarted();
- return vibHolder.scale;
+ externalVibration.stats.reportStarted();
+ return externalVibration.getScale();
}
@Override
@@ -2238,7 +2121,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
Slog.d(TAG, "Stopping external vibration: " + vib);
}
endExternalVibrateLocked(
- new Vibration.EndInfo(Vibration.Status.FINISHED),
+ new Vibration.EndInfo(Status.FINISHED),
/* continueExternalControl= */ false);
}
}
@@ -2252,6 +2135,19 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
}
return false;
}
+
+ private void onExternalVibrationBinderDied() {
+ synchronized (mLock) {
+ if (mCurrentExternalVibration != null) {
+ if (DEBUG) {
+ Slog.d(TAG, "External vibration finished because binder died");
+ }
+ endExternalVibrateLocked(
+ new Vibration.EndInfo(Status.CANCELLED_BINDER_DIED),
+ /* continueExternalControl= */ false);
+ }
+ }
+ }
}
/** Provide limited functionality from {@link VibratorManagerService} as shell commands. */
diff --git a/services/tests/vibrator/src/com/android/server/vibrator/InputDeviceDelegateTest.java b/services/tests/vibrator/src/com/android/server/vibrator/InputDeviceDelegateTest.java
index f3ecfcc933b4..66788b6d2444 100644
--- a/services/tests/vibrator/src/com/android/server/vibrator/InputDeviceDelegateTest.java
+++ b/services/tests/vibrator/src/com/android/server/vibrator/InputDeviceDelegateTest.java
@@ -45,6 +45,8 @@ import android.view.InputDevice;
import androidx.test.InstrumentationRegistry;
+import com.android.server.vibrator.VibrationSession.CallerInfo;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
@@ -262,7 +264,7 @@ public class InputDeviceDelegateTest {
public void vibrateIfAvailable_withNoInputDevice_returnsFalse() {
assertFalse(mInputDeviceDelegate.isAvailable());
assertFalse(mInputDeviceDelegate.vibrateIfAvailable(
- new Vibration.CallerInfo(VIBRATION_ATTRIBUTES, UID, -1, PACKAGE_NAME, REASON),
+ new CallerInfo(VIBRATION_ATTRIBUTES, UID, -1, PACKAGE_NAME, REASON),
SYNCED_EFFECT));
}
@@ -277,7 +279,7 @@ public class InputDeviceDelegateTest {
mInputDeviceDelegate.updateInputDeviceVibrators(/* vibrateInputDevices= */ true);
assertTrue(mInputDeviceDelegate.vibrateIfAvailable(
- new Vibration.CallerInfo(VIBRATION_ATTRIBUTES, UID, -1, PACKAGE_NAME, REASON),
+ new CallerInfo(VIBRATION_ATTRIBUTES, UID, -1, PACKAGE_NAME, REASON),
SYNCED_EFFECT));
verify(mIInputManagerMock).vibrateCombined(eq(1), same(SYNCED_EFFECT), any());
verify(mIInputManagerMock).vibrateCombined(eq(2), same(SYNCED_EFFECT), any());
diff --git a/services/tests/vibrator/src/com/android/server/vibrator/VibrationTest.java b/services/tests/vibrator/src/com/android/server/vibrator/VibrationSessionTest.java
index 84f8412fb4b5..f69d1c42eb14 100644
--- a/services/tests/vibrator/src/com/android/server/vibrator/VibrationTest.java
+++ b/services/tests/vibrator/src/com/android/server/vibrator/VibrationSessionTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,13 +24,13 @@ import org.junit.Test;
import java.util.Arrays;
-public class VibrationTest {
+public class VibrationSessionTest {
@Test
public void status_hasUniqueProtoEnumValues() {
assertThat(
- Arrays.stream(Vibration.Status.values())
- .map(Vibration.Status::getProtoEnumValue)
+ Arrays.stream(VibrationSession.Status.values())
+ .map(VibrationSession.Status::getProtoEnumValue)
.collect(toList()))
.containsNoDuplicates();
}
diff --git a/services/tests/vibrator/src/com/android/server/vibrator/VibrationSettingsTest.java b/services/tests/vibrator/src/com/android/server/vibrator/VibrationSettingsTest.java
index 38cd49daf99d..c7a136ad0f9f 100644
--- a/services/tests/vibrator/src/com/android/server/vibrator/VibrationSettingsTest.java
+++ b/services/tests/vibrator/src/com/android/server/vibrator/VibrationSettingsTest.java
@@ -81,6 +81,8 @@ 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.vibrator.VibrationSession.CallerInfo;
+import com.android.server.vibrator.VibrationSession.Status;
import org.junit.After;
import org.junit.Before;
@@ -292,7 +294,7 @@ public class VibrationSettingsTest {
if (expectedAllowedVibrations.contains(usage)) {
assertVibrationNotIgnoredForUsage(usage);
} else {
- assertVibrationIgnoredForUsage(usage, Vibration.Status.IGNORED_BACKGROUND);
+ assertVibrationIgnoredForUsage(usage, Status.IGNORED_BACKGROUND);
}
}
}
@@ -350,7 +352,7 @@ public class VibrationSettingsTest {
createSystemReadyVibrationSettings();
for (int usage : ALL_USAGES) {
- assertVibrationIgnoredForUsage(usage, Vibration.Status.IGNORED_ON_WIRELESS_CHARGER);
+ assertVibrationIgnoredForUsage(usage, Status.IGNORED_ON_WIRELESS_CHARGER);
}
}
@@ -365,7 +367,7 @@ public class VibrationSettingsTest {
mRegisteredBatteryBroadcastReceiver.onReceive(mContextSpy, wirelessChargingIntent);
for (int usage : ALL_USAGES) {
- assertVibrationIgnoredForUsage(usage, Vibration.Status.IGNORED_ON_WIRELESS_CHARGER);
+ assertVibrationIgnoredForUsage(usage, Status.IGNORED_ON_WIRELESS_CHARGER);
}
}
@@ -377,7 +379,7 @@ public class VibrationSettingsTest {
createSystemReadyVibrationSettings();
// Check that initially, all usages are ignored due to the wireless charging.
for (int usage : ALL_USAGES) {
- assertVibrationIgnoredForUsage(usage, Vibration.Status.IGNORED_ON_WIRELESS_CHARGER);
+ assertVibrationIgnoredForUsage(usage, Status.IGNORED_ON_WIRELESS_CHARGER);
}
Intent nonWirelessChargingIntent = getBatteryChangedIntent(BATTERY_PLUGGED_USB);
@@ -404,7 +406,7 @@ public class VibrationSettingsTest {
if (expectedAllowedVibrations.contains(usage)) {
assertVibrationNotIgnoredForUsage(usage);
} else {
- assertVibrationIgnoredForUsage(usage, Vibration.Status.IGNORED_FOR_POWER);
+ assertVibrationIgnoredForUsage(usage, Status.IGNORED_FOR_POWER);
}
}
}
@@ -426,7 +428,7 @@ public class VibrationSettingsTest {
for (int usage : ALL_USAGES) {
if (usage == USAGE_RINGTONE || usage == USAGE_NOTIFICATION) {
- assertVibrationIgnoredForUsage(usage, Vibration.Status.IGNORED_FOR_RINGER_MODE);
+ assertVibrationIgnoredForUsage(usage, Status.IGNORED_FOR_RINGER_MODE);
} else {
assertVibrationNotIgnoredForUsage(usage);
}
@@ -470,7 +472,7 @@ public class VibrationSettingsTest {
if (usage == USAGE_ACCESSIBILITY) {
assertVibrationNotIgnoredForUsage(usage);
} else {
- assertVibrationIgnoredForUsage(usage, Vibration.Status.IGNORED_FOR_SETTINGS);
+ assertVibrationIgnoredForUsage(usage, Status.IGNORED_FOR_SETTINGS);
}
assertVibrationNotIgnoredForUsageAndFlags(usage,
VibrationAttributes.FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF);
@@ -512,7 +514,7 @@ public class VibrationSettingsTest {
for (int usage : ALL_USAGES) {
if (usage == USAGE_TOUCH) {
- assertVibrationIgnoredForUsage(usage, Vibration.Status.IGNORED_FOR_SETTINGS);
+ assertVibrationIgnoredForUsage(usage, Status.IGNORED_FOR_SETTINGS);
} else {
assertVibrationNotIgnoredForUsage(usage);
}
@@ -527,7 +529,7 @@ public class VibrationSettingsTest {
for (int usage : ALL_USAGES) {
if (usage == USAGE_TOUCH || usage == USAGE_IME_FEEDBACK) {
- assertVibrationIgnoredForUsage(usage, Vibration.Status.IGNORED_FOR_SETTINGS);
+ assertVibrationIgnoredForUsage(usage, Status.IGNORED_FOR_SETTINGS);
} else {
assertVibrationNotIgnoredForUsage(usage);
}
@@ -542,7 +544,7 @@ public class VibrationSettingsTest {
for (int usage : ALL_USAGES) {
if (usage == USAGE_HARDWARE_FEEDBACK || usage == USAGE_PHYSICAL_EMULATION) {
- assertVibrationIgnoredForUsage(usage, Vibration.Status.IGNORED_FOR_SETTINGS);
+ assertVibrationIgnoredForUsage(usage, Status.IGNORED_FOR_SETTINGS);
} else {
assertVibrationNotIgnoredForUsage(usage);
}
@@ -557,7 +559,7 @@ public class VibrationSettingsTest {
for (int usage : ALL_USAGES) {
if (usage == USAGE_NOTIFICATION) {
- assertVibrationIgnoredForUsage(usage, Vibration.Status.IGNORED_FOR_SETTINGS);
+ assertVibrationIgnoredForUsage(usage, Status.IGNORED_FOR_SETTINGS);
} else {
assertVibrationNotIgnoredForUsage(usage);
}
@@ -574,7 +576,7 @@ public class VibrationSettingsTest {
for (int usage : ALL_USAGES) {
if (usage == USAGE_RINGTONE) {
- assertVibrationIgnoredForUsage(usage, Vibration.Status.IGNORED_FOR_SETTINGS);
+ assertVibrationIgnoredForUsage(usage, Status.IGNORED_FOR_SETTINGS);
} else {
assertVibrationNotIgnoredForUsage(usage);
}
@@ -597,7 +599,7 @@ public class VibrationSettingsTest {
mVibrationSettings.mSettingChangeReceiver.onReceive(mContextSpy,
new Intent(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION));
- assertVibrationIgnoredForUsage(USAGE_RINGTONE, Vibration.Status.IGNORED_FOR_RINGER_MODE);
+ assertVibrationIgnoredForUsage(USAGE_RINGTONE, Status.IGNORED_FOR_RINGER_MODE);
}
@Test
@@ -611,7 +613,7 @@ public class VibrationSettingsTest {
new VibrationAttributes.Builder()
.setUsage(USAGE_IME_FEEDBACK)
.build(),
- Vibration.Status.IGNORED_FOR_SETTINGS);
+ Status.IGNORED_FOR_SETTINGS);
// General touch and keyboard touch with bypass flag not ignored.
assertVibrationNotIgnoredForUsage(USAGE_TOUCH);
@@ -629,7 +631,7 @@ public class VibrationSettingsTest {
setUserSetting(Settings.System.KEYBOARD_VIBRATION_ENABLED, 1 /* ON */);
// General touch ignored.
- assertVibrationIgnoredForUsage(USAGE_TOUCH, Vibration.Status.IGNORED_FOR_SETTINGS);
+ assertVibrationIgnoredForUsage(USAGE_TOUCH, Status.IGNORED_FOR_SETTINGS);
// Keyboard touch not ignored.
assertVibrationNotIgnoredForAttributes(
@@ -645,14 +647,14 @@ public class VibrationSettingsTest {
setUserSetting(Settings.System.KEYBOARD_VIBRATION_ENABLED, 1 /* ON */);
// General touch ignored.
- assertVibrationIgnoredForUsage(USAGE_TOUCH, Vibration.Status.IGNORED_FOR_SETTINGS);
+ assertVibrationIgnoredForUsage(USAGE_TOUCH, Status.IGNORED_FOR_SETTINGS);
// Keyboard touch ignored.
assertVibrationIgnoredForAttributes(
new VibrationAttributes.Builder()
.setUsage(USAGE_IME_FEEDBACK)
.build(),
- Vibration.Status.IGNORED_FOR_SETTINGS);
+ Status.IGNORED_FOR_SETTINGS);
}
@Test
@@ -668,7 +670,7 @@ public class VibrationSettingsTest {
// Ignore the vibration when the coming device id represents a virtual device.
for (int usage : ALL_USAGES) {
assertVibrationIgnoredForUsageAndDevice(usage, VIRTUAL_DEVICE_ID,
- Vibration.Status.IGNORED_FROM_VIRTUAL_DEVICE);
+ Status.IGNORED_FROM_VIRTUAL_DEVICE);
}
}
@@ -911,22 +913,21 @@ public class VibrationSettingsTest {
}
private void assertVibrationIgnoredForUsage(@VibrationAttributes.Usage int usage,
- Vibration.Status expectedStatus) {
+ Status expectedStatus) {
assertVibrationIgnoredForUsageAndDevice(usage, Context.DEVICE_ID_DEFAULT, expectedStatus);
}
private void assertVibrationIgnoredForUsageAndDevice(@VibrationAttributes.Usage int usage,
- int deviceId, Vibration.Status expectedStatus) {
- Vibration.CallerInfo callerInfo = new Vibration.CallerInfo(
+ int deviceId, Status expectedStatus) {
+ CallerInfo callerInfo = new CallerInfo(
VibrationAttributes.createForUsage(usage), UID, deviceId, null, null);
assertEquals(errorMessageForUsage(usage), expectedStatus,
mVibrationSettings.shouldIgnoreVibration(callerInfo));
}
private void assertVibrationIgnoredForAttributes(VibrationAttributes attrs,
- Vibration.Status expectedStatus) {
- Vibration.CallerInfo callerInfo = new Vibration.CallerInfo(attrs, UID,
- Context.DEVICE_ID_DEFAULT, null, null);
+ Status expectedStatus) {
+ CallerInfo callerInfo = new CallerInfo(attrs, UID, Context.DEVICE_ID_DEFAULT, null, null);
assertEquals(errorMessageForAttributes(attrs), expectedStatus,
mVibrationSettings.shouldIgnoreVibration(callerInfo));
}
@@ -948,7 +949,7 @@ public class VibrationSettingsTest {
private void assertVibrationNotIgnoredForUsageAndFlagsAndDevice(
@VibrationAttributes.Usage int usage, int deviceId,
@VibrationAttributes.Flag int flags) {
- Vibration.CallerInfo callerInfo = new Vibration.CallerInfo(
+ CallerInfo callerInfo = new CallerInfo(
new VibrationAttributes.Builder().setUsage(usage).setFlags(flags).build(), UID,
deviceId, null, null);
assertNull(errorMessageForUsage(usage),
@@ -956,7 +957,7 @@ public class VibrationSettingsTest {
}
private void assertVibrationNotIgnoredForAttributes(VibrationAttributes attrs) {
- Vibration.CallerInfo callerInfo = new Vibration.CallerInfo(attrs, UID,
+ CallerInfo callerInfo = new CallerInfo(attrs, UID,
Context.DEVICE_ID_DEFAULT, null, null);
assertNull(errorMessageForAttributes(attrs),
mVibrationSettings.shouldIgnoreVibration(callerInfo));
@@ -1017,10 +1018,10 @@ public class VibrationSettingsTest {
new PowerManager.SleepData(sleepTime, reason));
}
- private Vibration.CallerInfo createCallerInfo(int uid, String opPkg,
+ private CallerInfo createCallerInfo(int uid, String opPkg,
@VibrationAttributes.Usage int usage) {
VibrationAttributes attrs = VibrationAttributes.createForUsage(usage);
- return new Vibration.CallerInfo(attrs, uid, VIRTUAL_DEVICE_ID, opPkg, null);
+ return new CallerInfo(attrs, uid, VIRTUAL_DEVICE_ID, opPkg, null);
}
private void setBatteryReceiverRegistrationResult(Intent result) {
diff --git a/services/tests/vibrator/src/com/android/server/vibrator/VibrationThreadTest.java b/services/tests/vibrator/src/com/android/server/vibrator/VibrationThreadTest.java
index bfdaa785a669..31cc50f18299 100644
--- a/services/tests/vibrator/src/com/android/server/vibrator/VibrationThreadTest.java
+++ b/services/tests/vibrator/src/com/android/server/vibrator/VibrationThreadTest.java
@@ -78,6 +78,8 @@ import androidx.test.filters.LargeTest;
import com.android.internal.util.test.FakeSettingsProvider;
import com.android.internal.util.test.FakeSettingsProviderRule;
import com.android.server.LocalServices;
+import com.android.server.vibrator.VibrationSession.CallerInfo;
+import com.android.server.vibrator.VibrationSession.Status;
import org.junit.After;
import org.junit.Before;
@@ -189,7 +191,7 @@ public class VibrationThreadTest {
waitForCompletion();
verify(mControllerCallbacks, never()).onComplete(anyInt(), eq(vibrationId));
- verifyCallbacksTriggered(vibrationId, Vibration.Status.IGNORED_UNSUPPORTED);
+ verifyCallbacksTriggered(vibrationId, Status.IGNORED_UNSUPPORTED);
}
@Test
@@ -202,7 +204,7 @@ public class VibrationThreadTest {
waitForCompletion();
verify(mControllerCallbacks, never()).onComplete(anyInt(), eq(vibrationId));
- verifyCallbacksTriggered(vibrationId, Vibration.Status.IGNORED_UNSUPPORTED);
+ verifyCallbacksTriggered(vibrationId, Status.IGNORED_UNSUPPORTED);
}
@Test
@@ -216,7 +218,7 @@ public class VibrationThreadTest {
verify(mManagerHooks).noteVibratorOn(eq(UID), eq(10L));
verify(mManagerHooks).noteVibratorOff(eq(UID));
verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibrationId));
- verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
+ verifyCallbacksTriggered(vibrationId, Status.FINISHED);
assertFalse(mControllers.get(VIBRATOR_ID).isVibrating());
assertEquals(Arrays.asList(expectedOneShot(10)),
@@ -233,7 +235,7 @@ public class VibrationThreadTest {
verify(mManagerHooks).noteVibratorOn(eq(UID), eq(10L));
verify(mManagerHooks).noteVibratorOff(eq(UID));
verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibrationId));
- verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
+ verifyCallbacksTriggered(vibrationId, Status.FINISHED);
assertFalse(mControllers.get(VIBRATOR_ID).isVibrating());
assertEquals(Arrays.asList(expectedOneShot(10)),
@@ -253,7 +255,7 @@ public class VibrationThreadTest {
verify(mManagerHooks).noteVibratorOn(eq(UID), eq(15L));
verify(mManagerHooks).noteVibratorOff(eq(UID));
verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibrationId));
- verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
+ verifyCallbacksTriggered(vibrationId, Status.FINISHED);
assertFalse(mControllers.get(VIBRATOR_ID).isVibrating());
assertEquals(Arrays.asList(expectedOneShot(15)),
@@ -326,13 +328,10 @@ public class VibrationThreadTest {
assertTrue(mThread.isRunningVibrationId(vibrationId));
assertTrue(mControllers.get(VIBRATOR_ID).isVibrating());
- Vibration.EndInfo cancelVibrationInfo = new Vibration.EndInfo(
- Vibration.Status.CANCELLED_SUPERSEDED, new Vibration.CallerInfo(
- VibrationAttributes.createForUsage(VibrationAttributes.USAGE_ALARM), /* uid= */
- 1, /* deviceId= */ -1, /* opPkg= */ null, /* reason= */ null));
- mVibrationConductor.notifyCancelled(
- cancelVibrationInfo,
- /* immediate= */ false);
+ Vibration.EndInfo cancelVibrationInfo = new Vibration.EndInfo(Status.CANCELLED_SUPERSEDED,
+ new CallerInfo(VibrationAttributes.createForUsage(VibrationAttributes.USAGE_ALARM),
+ /* uid= */ 1, /* deviceId= */ -1, /* opPkg= */ null, /* reason= */ null));
+ mVibrationConductor.notifyCancelled(cancelVibrationInfo, /* immediate= */ false);
waitForCompletion();
assertFalse(mThread.isRunningVibrationId(vibrationId));
@@ -363,11 +362,10 @@ public class VibrationThreadTest {
assertTrue(waitUntil(() -> !fakeVibrator.getAmplitudes().isEmpty(), TEST_TIMEOUT_MILLIS));
mVibrationConductor.notifyCancelled(
- new Vibration.EndInfo(Vibration.Status.CANCELLED_BY_USER),
- /* immediate= */ false);
+ new Vibration.EndInfo(Status.CANCELLED_BY_USER), /* immediate= */ false);
waitForCompletion();
- verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED_BY_USER);
+ verifyCallbacksTriggered(vibrationId, Status.CANCELLED_BY_USER);
assertFalse(mControllers.get(VIBRATOR_ID).isVibrating());
assertEquals(Arrays.asList(expectedOneShot(5000)),
fakeVibrator.getEffectSegments(vibrationId));
@@ -385,7 +383,7 @@ public class VibrationThreadTest {
verify(mManagerHooks).noteVibratorOn(eq(UID), eq(300L));
verify(mManagerHooks).noteVibratorOff(eq(UID));
- verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
+ verifyCallbacksTriggered(vibrationId, Status.FINISHED);
assertThat(mControllers.get(VIBRATOR_ID).isVibrating()).isFalse();
assertThat(mVibratorProviders.get(VIBRATOR_ID).getEffectSegments(vibrationId))
@@ -406,7 +404,7 @@ public class VibrationThreadTest {
verify(mManagerHooks).noteVibratorOn(eq(UID), eq(350L));
verify(mManagerHooks).noteVibratorOff(eq(UID));
- verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
+ verifyCallbacksTriggered(vibrationId, Status.FINISHED);
assertThat(mControllers.get(VIBRATOR_ID).isVibrating()).isFalse();
assertThat(mVibratorProviders.get(VIBRATOR_ID).getEffectSegments(vibrationId))
@@ -433,11 +431,10 @@ public class VibrationThreadTest {
assertTrue(waitUntil(() -> fakeVibrator.getEffectSegments(vibrationId).size() >= 5,
5000L + TEST_TIMEOUT_MILLIS));
mVibrationConductor.notifyCancelled(
- new Vibration.EndInfo(Vibration.Status.CANCELLED_BY_USER),
- /* immediate= */ false);
+ new Vibration.EndInfo(Status.CANCELLED_BY_USER), /* immediate= */ false);
waitForCompletion();
- verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED_BY_USER);
+ verifyCallbacksTriggered(vibrationId, Status.CANCELLED_BY_USER);
assertThat(mControllers.get(VIBRATOR_ID).isVibrating()).isFalse();
assertThat(mVibratorProviders.get(VIBRATOR_ID).getEffectSegments(vibrationId).subList(0, 5))
@@ -466,12 +463,11 @@ public class VibrationThreadTest {
assertTrue(waitUntil(() -> !fakeVibrator.getEffectSegments(vibrationId).isEmpty(),
TEST_TIMEOUT_MILLIS));
mVibrationConductor.notifyCancelled(
- new Vibration.EndInfo(Vibration.Status.CANCELLED_BY_USER),
- /* immediate= */ false);
+ new Vibration.EndInfo(Status.CANCELLED_BY_USER), /* immediate= */ false);
waitForCompletion();
// PWLE size max was used to generate a single vibrate call with 10 segments.
- verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED_BY_USER);
+ verifyCallbacksTriggered(vibrationId, Status.CANCELLED_BY_USER);
assertFalse(mControllers.get(VIBRATOR_ID).isVibrating());
assertEquals(10, fakeVibrator.getEffectSegments(vibrationId).size());
}
@@ -496,12 +492,11 @@ public class VibrationThreadTest {
assertTrue(waitUntil(() -> !fakeVibrator.getEffectSegments(vibrationId).isEmpty(),
TEST_TIMEOUT_MILLIS));
mVibrationConductor.notifyCancelled(
- new Vibration.EndInfo(Vibration.Status.CANCELLED_BY_SCREEN_OFF),
- /* immediate= */ false);
+ new Vibration.EndInfo(Status.CANCELLED_BY_SCREEN_OFF), /* immediate= */ false);
waitForCompletion();
// Composition size max was used to generate a single vibrate call with 10 primitives.
- verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED_BY_SCREEN_OFF);
+ verifyCallbacksTriggered(vibrationId, Status.CANCELLED_BY_SCREEN_OFF);
assertFalse(mControllers.get(VIBRATOR_ID).isVibrating());
assertEquals(10, fakeVibrator.getEffectSegments(vibrationId).size());
}
@@ -519,11 +514,10 @@ public class VibrationThreadTest {
assertTrue(waitUntil(() -> !fakeVibrator.getAmplitudes().isEmpty(), TEST_TIMEOUT_MILLIS));
mVibrationConductor.notifyCancelled(
- new Vibration.EndInfo(Vibration.Status.CANCELLED_BY_USER),
- /* immediate= */ false);
+ new Vibration.EndInfo(Status.CANCELLED_BY_USER), /* immediate= */ false);
waitForCompletion();
- verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED_BY_USER);
+ verifyCallbacksTriggered(vibrationId, Status.CANCELLED_BY_USER);
assertFalse(mControllers.get(VIBRATOR_ID).isVibrating());
assertEquals(Arrays.asList(expectedOneShot(5550)),
fakeVibrator.getEffectSegments(vibrationId));
@@ -545,11 +539,10 @@ public class VibrationThreadTest {
assertTrue(waitUntil(() -> fakeVibrator.getEffectSegments(vibrationId).size() > 1,
expectedOnDuration + TEST_TIMEOUT_MILLIS));
mVibrationConductor.notifyCancelled(
- new Vibration.EndInfo(Vibration.Status.CANCELLED_BY_USER),
- /* immediate= */ false);
+ new Vibration.EndInfo(Status.CANCELLED_BY_USER), /* immediate= */ false);
waitForCompletion();
- verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED_BY_USER);
+ verifyCallbacksTriggered(vibrationId, Status.CANCELLED_BY_USER);
assertFalse(mControllers.get(VIBRATOR_ID).isVibrating());
List<VibrationEffectSegment> effectSegments = fakeVibrator.getEffectSegments(vibrationId);
// First time, turn vibrator ON for the expected fixed duration.
@@ -584,14 +577,14 @@ public class VibrationThreadTest {
// fail at waitForCompletion(vibrationThread) if the vibration not cancelled immediately.
Thread cancellingThread =
new Thread(() -> mVibrationConductor.notifyCancelled(
- new Vibration.EndInfo(Vibration.Status.CANCELLED_BY_SETTINGS_UPDATE),
+ new Vibration.EndInfo(Status.CANCELLED_BY_SETTINGS_UPDATE),
/* immediate= */ false));
cancellingThread.start();
waitForCompletion(/* timeout= */ 50);
cancellingThread.join();
- verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED_BY_SETTINGS_UPDATE);
+ verifyCallbacksTriggered(vibrationId, Status.CANCELLED_BY_SETTINGS_UPDATE);
assertFalse(mControllers.get(VIBRATOR_ID).isVibrating());
}
@@ -614,14 +607,14 @@ public class VibrationThreadTest {
// fail at waitForCompletion(vibrationThread) if the vibration not cancelled immediately.
Thread cancellingThread =
new Thread(() -> mVibrationConductor.notifyCancelled(
- new Vibration.EndInfo(Vibration.Status.CANCELLED_BY_SETTINGS_UPDATE),
+ new Vibration.EndInfo(Status.CANCELLED_BY_SETTINGS_UPDATE),
/* immediate= */ false));
cancellingThread.start();
waitForCompletion(/* timeout= */ 50);
cancellingThread.join();
- verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED_BY_SETTINGS_UPDATE);
+ verifyCallbacksTriggered(vibrationId, Status.CANCELLED_BY_SETTINGS_UPDATE);
assertFalse(mControllers.get(VIBRATOR_ID).isVibrating());
}
@@ -641,14 +634,14 @@ public class VibrationThreadTest {
// fail at waitForCompletion(vibrationThread) if the vibration not cancelled immediately.
Thread cancellingThread =
new Thread(() -> mVibrationConductor.notifyCancelled(
- new Vibration.EndInfo(Vibration.Status.CANCELLED_BY_SCREEN_OFF),
+ new Vibration.EndInfo(Status.CANCELLED_BY_SCREEN_OFF),
/* immediate= */ false));
cancellingThread.start();
waitForCompletion(/* timeout= */ 50);
cancellingThread.join();
- verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED_BY_SCREEN_OFF);
+ verifyCallbacksTriggered(vibrationId, Status.CANCELLED_BY_SCREEN_OFF);
assertFalse(mControllers.get(VIBRATOR_ID).isVibrating());
}
@@ -663,7 +656,7 @@ public class VibrationThreadTest {
verify(mManagerHooks).noteVibratorOn(eq(UID), eq(20L));
verify(mManagerHooks).noteVibratorOff(eq(UID));
verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibrationId));
- verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
+ verifyCallbacksTriggered(vibrationId, Status.FINISHED);
assertFalse(mControllers.get(VIBRATOR_ID).isVibrating());
assertEquals(Arrays.asList(expectedPrebaked(VibrationEffect.EFFECT_THUD)),
@@ -684,7 +677,7 @@ public class VibrationThreadTest {
verify(mManagerHooks).noteVibratorOn(eq(UID), eq(10L));
verify(mManagerHooks).noteVibratorOff(eq(UID));
verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibrationId));
- verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
+ verifyCallbacksTriggered(vibrationId, Status.FINISHED);
assertFalse(mControllers.get(VIBRATOR_ID).isVibrating());
assertEquals(Arrays.asList(expectedOneShot(10)),
@@ -701,7 +694,7 @@ public class VibrationThreadTest {
verify(mManagerHooks).noteVibratorOn(eq(UID), eq(0L));
verify(mManagerHooks, never()).noteVibratorOff(eq(UID));
verify(mControllerCallbacks, never()).onComplete(eq(VIBRATOR_ID), eq(vibrationId));
- verifyCallbacksTriggered(vibrationId, Vibration.Status.IGNORED_UNSUPPORTED);
+ verifyCallbacksTriggered(vibrationId, Status.IGNORED_UNSUPPORTED);
assertTrue(mVibratorProviders.get(VIBRATOR_ID).getEffectSegments(vibrationId).isEmpty());
}
@@ -718,7 +711,7 @@ public class VibrationThreadTest {
eq(PerformVendorEffectVibratorStep.VENDOR_EFFECT_MAX_DURATION_MS));
verify(mManagerHooks).noteVibratorOff(eq(UID));
verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibrationId));
- verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
+ verifyCallbacksTriggered(vibrationId, Status.FINISHED);
assertThat(mControllers.get(VIBRATOR_ID).isVibrating()).isFalse();
assertThat(mVibratorProviders.get(VIBRATOR_ID).getVendorEffects(vibrationId))
@@ -743,7 +736,7 @@ public class VibrationThreadTest {
verify(mManagerHooks).noteVibratorOn(eq(UID), eq(40L));
verify(mManagerHooks).noteVibratorOff(eq(UID));
verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibrationId));
- verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
+ verifyCallbacksTriggered(vibrationId, Status.FINISHED);
assertFalse(mControllers.get(VIBRATOR_ID).isVibrating());
assertEquals(Arrays.asList(
expectedPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1, 0),
@@ -762,7 +755,7 @@ public class VibrationThreadTest {
verify(mManagerHooks).noteVibratorOn(eq(UID), eq(0L));
verify(mManagerHooks, never()).noteVibratorOff(eq(UID));
verify(mControllerCallbacks, never()).onComplete(eq(VIBRATOR_ID), eq(vibrationId));
- verifyCallbacksTriggered(vibrationId, Vibration.Status.IGNORED_UNSUPPORTED);
+ verifyCallbacksTriggered(vibrationId, Status.IGNORED_UNSUPPORTED);
assertTrue(mVibratorProviders.get(VIBRATOR_ID).getEffectSegments(vibrationId).isEmpty());
}
@@ -784,7 +777,7 @@ public class VibrationThreadTest {
long vibrationId = startThreadAndDispatcher(effect);
waitForCompletion();
- verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
+ verifyCallbacksTriggered(vibrationId, Status.FINISHED);
// Vibrator compose called twice.
verify(mControllerCallbacks, times(2)).onComplete(eq(VIBRATOR_ID), eq(vibrationId));
assertEquals(3, fakeVibrator.getEffectSegments(vibrationId).size());
@@ -824,7 +817,7 @@ public class VibrationThreadTest {
verify(mManagerHooks).noteVibratorOn(eq(UID), eq(10L));
verify(mManagerHooks).noteVibratorOff(eq(UID));
verify(mControllerCallbacks, times(5)).onComplete(eq(VIBRATOR_ID), eq(vibrationId));
- verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
+ verifyCallbacksTriggered(vibrationId, Status.FINISHED);
assertFalse(mControllers.get(VIBRATOR_ID).isVibrating());
assertEquals(Arrays.asList(
expectedOneShot(10),
@@ -865,7 +858,7 @@ public class VibrationThreadTest {
verify(mManagerHooks).noteVibratorOn(eq(UID), anyLong());
verify(mManagerHooks).noteVibratorOff(eq(UID));
verify(mControllerCallbacks, times(4)).onComplete(eq(VIBRATOR_ID), eq(vibrationId));
- verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
+ verifyCallbacksTriggered(vibrationId, Status.FINISHED);
assertFalse(mControllers.get(VIBRATOR_ID).isVibrating());
List<VibrationEffectSegment> segments =
@@ -904,7 +897,7 @@ public class VibrationThreadTest {
verify(mManagerHooks).noteVibratorOn(eq(UID), eq(100L));
verify(mManagerHooks).noteVibratorOff(eq(UID));
verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibrationId));
- verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
+ verifyCallbacksTriggered(vibrationId, Status.FINISHED);
assertFalse(mControllers.get(VIBRATOR_ID).isVibrating());
assertEquals(Arrays.asList(
expectedRamp(/* amplitude= */ 1, /* frequencyHz= */ 150, /* duration= */ 10),
@@ -942,7 +935,7 @@ public class VibrationThreadTest {
long vibrationId = startThreadAndDispatcher(effect);
waitForCompletion();
- verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
+ verifyCallbacksTriggered(vibrationId, Status.FINISHED);
// Vibrator compose called 3 times with 2 segments instead of 2 times with 3 segments.
// Using best split points instead of max-packing PWLEs.
@@ -967,7 +960,7 @@ public class VibrationThreadTest {
waitForCompletion();
assertFalse(mControllers.get(VIBRATOR_ID).isVibrating());
- verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED_BINDER_DIED);
+ verifyCallbacksTriggered(vibrationId, Status.CANCELLED_BINDER_DIED);
}
@Test
@@ -977,7 +970,7 @@ public class VibrationThreadTest {
long vibrationId = startThreadAndDispatcher(VibrationEffect.createOneShot(10, 100));
waitForCompletion();
- verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
+ verifyCallbacksTriggered(vibrationId, Status.FINISHED);
verify(mManagerHooks, never()).prepareSyncedVibration(anyLong(), any());
verify(mManagerHooks, never()).triggerSyncedVibration(anyLong());
verify(mManagerHooks, never()).cancelSyncedVibration();
@@ -998,7 +991,7 @@ public class VibrationThreadTest {
verify(mManagerHooks).noteVibratorOff(eq(UID));
verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibrationId));
verify(mControllerCallbacks, never()).onComplete(eq(2), eq(vibrationId));
- verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
+ verifyCallbacksTriggered(vibrationId, Status.FINISHED);
assertFalse(mControllers.get(VIBRATOR_ID).isVibrating());
assertEquals(Arrays.asList(expectedPrebaked(VibrationEffect.EFFECT_TICK)),
@@ -1022,7 +1015,7 @@ public class VibrationThreadTest {
verify(mControllerCallbacks).onComplete(eq(1), eq(vibrationId));
verify(mControllerCallbacks).onComplete(eq(2), eq(vibrationId));
verify(mControllerCallbacks).onComplete(eq(3), eq(vibrationId));
- verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
+ verifyCallbacksTriggered(vibrationId, Status.FINISHED);
assertFalse(mControllers.get(1).isVibrating());
assertFalse(mControllers.get(2).isVibrating());
assertFalse(mControllers.get(3).isVibrating());
@@ -1065,7 +1058,7 @@ public class VibrationThreadTest {
verify(mControllerCallbacks).onComplete(eq(2), eq(vibrationId));
verify(mControllerCallbacks).onComplete(eq(3), eq(vibrationId));
verify(mControllerCallbacks).onComplete(eq(4), eq(vibrationId));
- verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
+ verifyCallbacksTriggered(vibrationId, Status.FINISHED);
assertFalse(mControllers.get(1).isVibrating());
assertFalse(mControllers.get(2).isVibrating());
assertFalse(mControllers.get(3).isVibrating());
@@ -1117,7 +1110,7 @@ public class VibrationThreadTest {
batteryVerifier.verify(mManagerHooks).noteVibratorOn(eq(UID), eq(20L));
batteryVerifier.verify(mManagerHooks).noteVibratorOff(eq(UID));
- verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
+ verifyCallbacksTriggered(vibrationId, Status.FINISHED);
assertFalse(mControllers.get(1).isVibrating());
assertFalse(mControllers.get(2).isVibrating());
assertFalse(mControllers.get(3).isVibrating());
@@ -1166,7 +1159,7 @@ public class VibrationThreadTest {
verify(mManagerHooks).prepareSyncedVibration(eq(expectedCap), eq(vibratorIds));
verify(mManagerHooks).triggerSyncedVibration(eq(vibrationId));
verify(mManagerHooks, never()).cancelSyncedVibration();
- verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
+ verifyCallbacksTriggered(vibrationId, Status.FINISHED);
VibrationEffectSegment expected = expectedPrimitive(
VibrationEffect.Composition.PRIMITIVE_CLICK, 1, 100);
@@ -1213,7 +1206,7 @@ public class VibrationThreadTest {
verify(mManagerHooks).prepareSyncedVibration(eq(expectedCap), eq(vibratorIds));
verify(mManagerHooks).triggerSyncedVibration(eq(vibrationId));
verify(mManagerHooks, never()).cancelSyncedVibration();
- verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
+ verifyCallbacksTriggered(vibrationId, Status.FINISHED);
}
@Test
@@ -1305,7 +1298,7 @@ public class VibrationThreadTest {
verify(mControllerCallbacks).onComplete(eq(1), eq(vibrationId));
verify(mControllerCallbacks).onComplete(eq(2), eq(vibrationId));
verify(mControllerCallbacks).onComplete(eq(3), eq(vibrationId));
- verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
+ verifyCallbacksTriggered(vibrationId, Status.FINISHED);
assertFalse(mControllers.get(1).isVibrating());
assertFalse(mControllers.get(2).isVibrating());
assertFalse(mControllers.get(3).isVibrating());
@@ -1478,8 +1471,7 @@ public class VibrationThreadTest {
// fail at waitForCompletion(cancellingThread).
Thread cancellingThread = new Thread(
() -> mVibrationConductor.notifyCancelled(
- new Vibration.EndInfo(Vibration.Status.CANCELLED_BY_USER),
- /* immediate= */ false));
+ new Vibration.EndInfo(Status.CANCELLED_BY_USER), /* immediate= */ false));
cancellingThread.start();
// Cancelling the vibration should be fast and return right away, even if the thread is
@@ -1488,7 +1480,7 @@ public class VibrationThreadTest {
// After the vibrator call ends the vibration is cancelled and the vibrator is turned off.
waitForCompletion(/* timeout= */ latency + TEST_TIMEOUT_MILLIS);
- verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED_BY_USER);
+ verifyCallbacksTriggered(vibrationId, Status.CANCELLED_BY_USER);
assertFalse(mControllers.get(VIBRATOR_ID).isVibrating());
}
@@ -1517,14 +1509,14 @@ public class VibrationThreadTest {
// fail at waitForCompletion(vibrationThread) if the vibration not cancelled immediately.
Thread cancellingThread = new Thread(
() -> mVibrationConductor.notifyCancelled(
- new Vibration.EndInfo(Vibration.Status.CANCELLED_BY_SCREEN_OFF),
+ new Vibration.EndInfo(Status.CANCELLED_BY_SCREEN_OFF),
/* immediate= */ false));
cancellingThread.start();
waitForCompletion(/* timeout= */ 50);
cancellingThread.join();
- verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED_BY_SCREEN_OFF);
+ verifyCallbacksTriggered(vibrationId, Status.CANCELLED_BY_SCREEN_OFF);
assertFalse(mControllers.get(1).isVibrating());
assertFalse(mControllers.get(2).isVibrating());
}
@@ -1551,14 +1543,14 @@ public class VibrationThreadTest {
// fail at waitForCompletion(vibrationThread) if the vibration not cancelled immediately.
Thread cancellingThread = new Thread(
() -> mVibrationConductor.notifyCancelled(
- new Vibration.EndInfo(Vibration.Status.CANCELLED_BY_SCREEN_OFF),
+ new Vibration.EndInfo(Status.CANCELLED_BY_SCREEN_OFF),
/* immediate= */ false));
cancellingThread.start();
waitForCompletion(/* timeout= */ 50);
cancellingThread.join();
- verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED_BY_SCREEN_OFF);
+ verifyCallbacksTriggered(vibrationId, Status.CANCELLED_BY_SCREEN_OFF);
assertFalse(mControllers.get(1).isVibrating());
assertFalse(mControllers.get(2).isVibrating());
}
@@ -1585,15 +1577,14 @@ public class VibrationThreadTest {
// fail at waitForCompletion(vibrationThread) if the vibration not cancelled immediately.
Thread cancellingThread = new Thread(
() -> mVibrationConductor.notifyCancelled(
- new Vibration.EndInfo(
- Vibration.Status.CANCELLED_BY_SCREEN_OFF),
+ new Vibration.EndInfo(Status.CANCELLED_BY_SCREEN_OFF),
/* immediate= */ false));
cancellingThread.start();
waitForCompletion(/* timeout= */ 50);
cancellingThread.join();
- verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED_BY_SCREEN_OFF);
+ verifyCallbacksTriggered(vibrationId, Status.CANCELLED_BY_SCREEN_OFF);
assertFalse(mControllers.get(1).isVibrating());
assertFalse(mControllers.get(2).isVibrating());
}
@@ -1612,7 +1603,7 @@ public class VibrationThreadTest {
verify(mVibrationToken).linkToDeath(same(mVibrationConductor), eq(0));
verify(mVibrationToken).unlinkToDeath(same(mVibrationConductor), eq(0));
- verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED_BINDER_DIED);
+ verifyCallbacksTriggered(vibrationId, Status.CANCELLED_BINDER_DIED);
assertFalse(mVibratorProviders.get(VIBRATOR_ID).getEffectSegments(vibrationId).isEmpty());
assertFalse(mControllers.get(VIBRATOR_ID).isVibrating());
}
@@ -1628,7 +1619,7 @@ public class VibrationThreadTest {
waitForCompletion();
verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibrationId));
- verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
+ verifyCallbacksTriggered(vibrationId, Status.FINISHED);
// Duration extended for 5 + 5 + 5 + 15.
assertEquals(Arrays.asList(expectedOneShot(30)),
@@ -1651,7 +1642,7 @@ public class VibrationThreadTest {
// Vibration completed but vibrator not yet released.
verify(mManagerHooks, timeout(TEST_TIMEOUT_MILLIS)).onVibrationCompleted(eq(vibrationId),
- eq(new Vibration.EndInfo(Vibration.Status.FINISHED)));
+ eq(new Vibration.EndInfo(Status.FINISHED)));
verify(mManagerHooks, never()).onVibrationThreadReleased(anyLong());
// Thread still running ramp down.
@@ -1663,13 +1654,12 @@ public class VibrationThreadTest {
// Will stop the ramp down right away.
mVibrationConductor.notifyCancelled(
- new Vibration.EndInfo(Vibration.Status.CANCELLED_BY_SETTINGS_UPDATE),
- /* immediate= */ true);
+ new Vibration.EndInfo(Status.CANCELLED_BY_SETTINGS_UPDATE), /* immediate= */ true);
waitForCompletion();
// Does not cancel already finished vibration, but releases vibrator.
verify(mManagerHooks, never()).onVibrationCompleted(eq(vibrationId),
- eq(new Vibration.EndInfo(Vibration.Status.CANCELLED_BY_SETTINGS_UPDATE)));
+ eq(new Vibration.EndInfo(Status.CANCELLED_BY_SETTINGS_UPDATE)));
verify(mManagerHooks).onVibrationThreadReleased(vibrationId);
}
@@ -1684,11 +1674,10 @@ public class VibrationThreadTest {
assertTrue(waitUntil(() -> mControllers.get(VIBRATOR_ID).isVibrating(),
TEST_TIMEOUT_MILLIS));
mVibrationConductor.notifyCancelled(
- new Vibration.EndInfo(Vibration.Status.CANCELLED_BY_USER),
- /* immediate= */ false);
+ new Vibration.EndInfo(Status.CANCELLED_BY_USER), /* immediate= */ false);
waitForCompletion();
- verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED_BY_USER);
+ verifyCallbacksTriggered(vibrationId, Status.CANCELLED_BY_USER);
// Duration extended for 10000 + 15.
assertEquals(Arrays.asList(expectedOneShot(10_015)),
@@ -1711,7 +1700,7 @@ public class VibrationThreadTest {
waitForCompletion();
verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibrationId));
- verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
+ verifyCallbacksTriggered(vibrationId, Status.FINISHED);
assertEquals(Arrays.asList(expectedPrebaked(VibrationEffect.EFFECT_CLICK)),
mVibratorProviders.get(VIBRATOR_ID).getEffectSegments(vibrationId));
@@ -1729,7 +1718,7 @@ public class VibrationThreadTest {
waitForCompletion();
verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibrationId));
- verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
+ verifyCallbacksTriggered(vibrationId, Status.FINISHED);
assertThat(mVibratorProviders.get(VIBRATOR_ID).getVendorEffects(vibrationId))
.containsExactly(effect)
@@ -1752,7 +1741,7 @@ public class VibrationThreadTest {
waitForCompletion();
verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibrationId));
- verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
+ verifyCallbacksTriggered(vibrationId, Status.FINISHED);
assertEquals(
Arrays.asList(expectedPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1, 0)),
@@ -1779,7 +1768,7 @@ public class VibrationThreadTest {
waitForCompletion();
verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibrationId));
- verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
+ verifyCallbacksTriggered(vibrationId, Status.FINISHED);
assertEquals(Arrays.asList(expectedRamp(0, 1, 150, 150, 1)),
fakeVibrator.getEffectSegments(vibrationId));
@@ -1810,14 +1799,13 @@ public class VibrationThreadTest {
long vibrationId1 = startThreadAndDispatcher(effect1);
waitForCompletion();
verify(mControllerCallbacks).onComplete(VIBRATOR_ID, vibrationId1);
- verifyCallbacksTriggered(vibrationId1, Vibration.Status.FINISHED);
+ verifyCallbacksTriggered(vibrationId1, Status.FINISHED);
long vibrationId2 = startThreadAndDispatcher(effect2);
// Effect2 won't complete on its own. Cancel it after a couple of repeats.
Thread.sleep(150); // More than two TICKs.
mVibrationConductor.notifyCancelled(
- new Vibration.EndInfo(Vibration.Status.CANCELLED_BY_USER),
- /* immediate= */ false);
+ new Vibration.EndInfo(Status.CANCELLED_BY_USER), /* immediate= */ false);
waitForCompletion();
long vibrationId3 = startThreadAndDispatcher(effect3);
@@ -1827,8 +1815,7 @@ public class VibrationThreadTest {
long start4 = System.currentTimeMillis();
long vibrationId4 = startThreadAndDispatcher(effect4);
mVibrationConductor.notifyCancelled(
- new Vibration.EndInfo(Vibration.Status.CANCELLED_BY_SCREEN_OFF),
- /* immediate= */ true);
+ new Vibration.EndInfo(Status.CANCELLED_BY_SCREEN_OFF), /* immediate= */ true);
waitForCompletion();
long duration4 = System.currentTimeMillis() - start4;
@@ -1841,14 +1828,14 @@ public class VibrationThreadTest {
// Effect1
verify(mControllerCallbacks).onComplete(VIBRATOR_ID, vibrationId1);
- verifyCallbacksTriggered(vibrationId1, Vibration.Status.FINISHED);
+ verifyCallbacksTriggered(vibrationId1, Status.FINISHED);
assertEquals(Arrays.asList(expectedPrebaked(VibrationEffect.EFFECT_CLICK)),
fakeVibrator.getEffectSegments(vibrationId1));
// Effect2: repeating, cancelled.
verify(mControllerCallbacks, atLeast(2)).onComplete(VIBRATOR_ID, vibrationId2);
- verifyCallbacksTriggered(vibrationId2, Vibration.Status.CANCELLED_BY_USER);
+ verifyCallbacksTriggered(vibrationId2, Status.CANCELLED_BY_USER);
// The exact count of segments might vary, so just check that there's more than 2 and
// all elements are the same segment.
@@ -1860,13 +1847,13 @@ public class VibrationThreadTest {
// Effect3
verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibrationId3));
- verifyCallbacksTriggered(vibrationId3, Vibration.Status.FINISHED);
+ verifyCallbacksTriggered(vibrationId3, Status.FINISHED);
assertEquals(Arrays.asList(
expectedPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1, 0)),
fakeVibrator.getEffectSegments(vibrationId3));
// Effect4: cancelled quickly.
- verifyCallbacksTriggered(vibrationId4, Vibration.Status.CANCELLED_BY_SCREEN_OFF);
+ verifyCallbacksTriggered(vibrationId4, Status.CANCELLED_BY_SCREEN_OFF);
assertTrue("Tested duration=" + duration4, duration4 < 2000);
// Effect5: played normally after effect4, which may or may not have played.
@@ -1907,7 +1894,7 @@ public class VibrationThreadTest {
.build();
HalVibration vib = new HalVibration(mVibrationToken,
CombinedVibration.createParallel(effect),
- new Vibration.CallerInfo(attrs, UID, DEVICE_ID, PACKAGE_NAME, "reason"));
+ new CallerInfo(attrs, UID, DEVICE_ID, PACKAGE_NAME, "reason"));
return startThreadAndDispatcher(vib, requestVibrationParamsFuture);
}
@@ -1944,7 +1931,7 @@ public class VibrationThreadTest {
private HalVibration createVibration(CombinedVibration effect) {
return new HalVibration(mVibrationToken, effect,
- new Vibration.CallerInfo(ATTRS, UID, DEVICE_ID, PACKAGE_NAME, "reason"));
+ new CallerInfo(ATTRS, UID, DEVICE_ID, PACKAGE_NAME, "reason"));
}
private SparseArray<VibratorController> createVibratorControllers() {
@@ -2007,7 +1994,7 @@ public class VibrationThreadTest {
.collect(Collectors.toList());
}
- private void verifyCallbacksTriggered(long vibrationId, Vibration.Status expectedStatus) {
+ private void verifyCallbacksTriggered(long vibrationId, Status expectedStatus) {
verifyCallbacksTriggered(vibrationId, new Vibration.EndInfo(expectedStatus));
}
diff --git a/services/tests/vibrator/src/com/android/server/vibrator/VibratorFrameworkStatsLoggerTest.java b/services/tests/vibrator/src/com/android/server/vibrator/VibratorFrameworkStatsLoggerTest.java
index 3466bbb26fc8..cd057b619000 100644
--- a/services/tests/vibrator/src/com/android/server/vibrator/VibratorFrameworkStatsLoggerTest.java
+++ b/services/tests/vibrator/src/com/android/server/vibrator/VibratorFrameworkStatsLoggerTest.java
@@ -22,6 +22,8 @@ import static org.junit.Assert.assertTrue;
import android.os.Handler;
import android.os.test.TestLooper;
+import com.android.server.vibrator.VibrationSession.Status;
+
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -113,7 +115,6 @@ public class VibratorFrameworkStatsLoggerTest {
}
private static VibrationStats.StatsInfo newEmptyStatsInfo() {
- return new VibrationStats.StatsInfo(
- 0, 0, 0, Vibration.Status.FINISHED, new VibrationStats(), 0L);
+ return new VibrationStats.StatsInfo(0, 0, 0, Status.FINISHED, new VibrationStats(), 0L);
}
}
diff --git a/services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java b/services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java
index 4afb56265563..4012575cda88 100644
--- a/services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java
+++ b/services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java
@@ -110,6 +110,7 @@ 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 com.android.server.vibrator.VibrationSession.Status;
import org.junit.After;
import org.junit.Before;
@@ -803,8 +804,8 @@ public class VibratorManagerServiceTest {
mockVibrators(1);
VibratorManagerService service = createSystemReadyService();
- var vib = vibrate(service,
- VibrationEffect.createWaveform(new long[]{100, 100, 100, 100}, 0), RINGTONE_ATTRS);
+ HalVibration vib = vibrate(service, VibrationEffect.createWaveform(
+ new long[]{0, TEST_TIMEOUT_MILLIS, TEST_TIMEOUT_MILLIS}, 0), RINGTONE_ATTRS);
assertTrue(waitUntil(s -> s.isVibrating(1), service, TEST_TIMEOUT_MILLIS));
@@ -815,14 +816,80 @@ public class VibratorManagerServiceTest {
service.mAppOpsChangeListener.onOpChanged(AppOpsManager.OP_VIBRATE, null);
assertTrue(waitUntil(s -> vib.hasEnded(), service, TEST_TIMEOUT_MILLIS));
+ assertThat(vib.getStatus()).isEqualTo(Status.CANCELLED_BY_APP_OPS);
+ }
- var statsInfoCaptor = ArgumentCaptor.forClass(VibrationStats.StatsInfo.class);
- verify(mVibratorFrameworkStatsLoggerMock, timeout(TEST_TIMEOUT_MILLIS))
- .writeVibrationReportedAsync(statsInfoCaptor.capture());
+ @Test
+ public void vibrate_thenPowerModeChanges_getsCancelled() throws Exception {
+ mockVibrators(1, 2);
+ VibratorManagerService service = createSystemReadyService();
- VibrationStats.StatsInfo touchMetrics = statsInfoCaptor.getAllValues().get(0);
- assertEquals(Vibration.Status.CANCELLED_BY_APP_OPS.getProtoEnumValue(),
- touchMetrics.status);
+ HalVibration vib = vibrate(service,
+ CombinedVibration.startParallel()
+ .addVibrator(1, VibrationEffect.createOneShot(2 * TEST_TIMEOUT_MILLIS, 100))
+ .combine(),
+ HAPTIC_FEEDBACK_ATTRS);
+
+ // VibrationThread will start this vibration async, so wait until vibration is triggered.
+ assertTrue(waitUntil(s -> s.isVibrating(1), service, TEST_TIMEOUT_MILLIS));
+
+ mRegisteredPowerModeListener.onLowPowerModeChanged(LOW_POWER_STATE);
+
+ assertTrue(waitUntil(s -> vib.hasEnded(), service, TEST_TIMEOUT_MILLIS));
+ assertThat(vib.getStatus()).isEqualTo(Status.CANCELLED_BY_SETTINGS_UPDATE);
+ }
+
+ @Test
+ public void vibrate_thenSettingsRefreshedWithoutChange_doNotCancelVibration() throws Exception {
+ mockVibrators(1);
+ VibratorManagerService service = createSystemReadyService();
+
+ vibrate(service, VibrationEffect.createOneShot(2 * TEST_TIMEOUT_MILLIS, 100),
+ HAPTIC_FEEDBACK_ATTRS);
+
+ // VibrationThread will start this vibration async, so wait until vibration is triggered.
+ assertTrue(waitUntil(s -> s.isVibrating(1), service, TEST_TIMEOUT_MILLIS));
+
+ service.updateServiceState();
+
+ // Vibration is not stopped nearly after updating service.
+ assertFalse(waitUntil(s -> !s.isVibrating(1), service, 50));
+ }
+
+ @Test
+ public void vibrate_thenSettingsChange_getsCancelled() throws Exception {
+ mockVibrators(1);
+ VibratorManagerService service = createSystemReadyService();
+
+ HalVibration vib = vibrate(service,
+ VibrationEffect.createOneShot(2 * TEST_TIMEOUT_MILLIS, 100),
+ HAPTIC_FEEDBACK_ATTRS);
+
+ // VibrationThread will start this vibration async, so wait until vibration is triggered.
+ assertTrue(waitUntil(s -> s.isVibrating(1), service, TEST_TIMEOUT_MILLIS));
+
+ setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, Vibrator.VIBRATION_INTENSITY_OFF);
+ service.mVibrationSettings.mSettingObserver.onChange(false);
+ service.updateServiceState();
+
+ assertTrue(waitUntil(s -> vib.hasEnded(), service, TEST_TIMEOUT_MILLIS));
+ assertThat(vib.getStatus()).isEqualTo(Status.CANCELLED_BY_SETTINGS_UPDATE);
+ }
+
+ @Test
+ public void vibrate_thenScreenTurnsOff_getsCancelled() throws Throwable {
+ mockVibrators(1);
+ VibratorManagerService service = createSystemReadyService();
+
+ HalVibration vib = vibrate(service, VibrationEffect.createWaveform(
+ new long[]{0, TEST_TIMEOUT_MILLIS, TEST_TIMEOUT_MILLIS}, 0), ALARM_ATTRS);
+
+ assertTrue(waitUntil(s -> s.isVibrating(1), service, TEST_TIMEOUT_MILLIS));
+
+ service.mIntentReceiver.onReceive(mContextSpy, new Intent(Intent.ACTION_SCREEN_OFF));
+
+ assertTrue(waitUntil(s -> vib.hasEnded(), service, TEST_TIMEOUT_MILLIS));
+ assertThat(vib.getStatus()).isEqualTo(Status.CANCELLED_BY_SCREEN_OFF);
}
@Test
@@ -831,8 +898,8 @@ public class VibratorManagerServiceTest {
mockVibrators(1);
VibratorManagerService service = createSystemReadyService();
- var vib = vibrate(service,
- VibrationEffect.createWaveform(new long[]{100, 100, 100, 100}, 0), ALARM_ATTRS);
+ HalVibration vib = vibrate(service, VibrationEffect.createWaveform(
+ new long[]{0, TEST_TIMEOUT_MILLIS, TEST_TIMEOUT_MILLIS}, 0), ALARM_ATTRS);
assertTrue(waitUntil(s -> s.isVibrating(1), service, TEST_TIMEOUT_MILLIS));
@@ -841,14 +908,7 @@ public class VibratorManagerServiceTest {
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);
+ assertThat(vib.getStatus()).isEqualTo(Status.CANCELLED_BY_FOREGROUND_USER);
}
@Test
@@ -1314,7 +1374,7 @@ public class VibratorManagerServiceTest {
}
@Test
- public void vibrate_withriggerCallback_finishesVibration() throws Exception {
+ public void vibrate_withTriggerCallback_finishesVibration() throws Exception {
mockCapabilities(IVibratorManager.CAP_SYNC, IVibratorManager.CAP_PREPARE_COMPOSE);
mockVibrators(1, 2);
mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS);
@@ -1947,41 +2007,6 @@ public class VibratorManagerServiceTest {
}
@Test
- public void vibrate_withPowerModeChange_cancelVibrationIfNotAllowed() throws Exception {
- mockVibrators(1, 2);
- VibratorManagerService service = createSystemReadyService();
- vibrate(service,
- CombinedVibration.startParallel()
- .addVibrator(1, VibrationEffect.createOneShot(1000, 100))
- .combine(),
- HAPTIC_FEEDBACK_ATTRS);
-
- // VibrationThread will start this vibration async, so wait until vibration is triggered.
- assertTrue(waitUntil(s -> s.isVibrating(1), service, TEST_TIMEOUT_MILLIS));
-
- mRegisteredPowerModeListener.onLowPowerModeChanged(LOW_POWER_STATE);
-
- // Haptic feedback cancelled on low power mode.
- assertTrue(waitUntil(s -> !s.isVibrating(1), service, TEST_TIMEOUT_MILLIS));
- }
-
- @Test
- public void vibrate_withSettingsChange_doNotCancelVibration() throws Exception {
- mockVibrators(1);
- VibratorManagerService service = createSystemReadyService();
-
- vibrate(service, VibrationEffect.createOneShot(1000, 100), HAPTIC_FEEDBACK_ATTRS);
-
- // VibrationThread will start this vibration async, so wait until vibration is triggered.
- assertTrue(waitUntil(s -> s.isVibrating(1), service, TEST_TIMEOUT_MILLIS));
-
- service.updateServiceState();
-
- // Vibration is not stopped nearly after updating service.
- assertFalse(waitUntil(s -> !s.isVibrating(1), service, 50));
- }
-
- @Test
public void vibrate_ignoreVibrationFromVirtualDevice() throws Exception {
mockVibrators(1);
VibratorManagerService service = createSystemReadyService();
@@ -2475,6 +2500,113 @@ public class VibratorManagerServiceTest {
}
@Test
+ public void onExternalVibration_thenDeniedAppOps_doNotCancelVibration() throws Throwable {
+ mockVibrators(1);
+ mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_EXTERNAL_CONTROL);
+ VibratorManagerService service = createSystemReadyService();
+
+ IExternalVibrationController externalVibrationControllerMock =
+ mock(IExternalVibrationController.class);
+ ExternalVibration externalVibration = new ExternalVibration(UID, PACKAGE_NAME,
+ AUDIO_ALARM_ATTRS, externalVibrationControllerMock, mock(IBinder.class));
+ ExternalVibrationScale scale = mExternalVibratorService.onExternalVibrationStart(
+ externalVibration);
+
+ assertThat(scale.scaleLevel).isNotEqualTo(ExternalVibrationScale.ScaleLevel.SCALE_MUTE);
+
+ when(mAppOpsManagerMock.checkAudioOpNoThrow(eq(AppOpsManager.OP_VIBRATE),
+ eq(AudioAttributes.USAGE_ALARM), anyInt(), anyString()))
+ .thenReturn(AppOpsManager.MODE_IGNORED);
+ service.mAppOpsChangeListener.onOpChanged(AppOpsManager.OP_VIBRATE, null);
+
+ verify(externalVibrationControllerMock, never()).mute();
+ }
+
+ @Test
+ public void onExternalVibration_thenPowerModeChanges_doNotCancelVibration() throws Exception {
+ mockVibrators(1);
+ mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_EXTERNAL_CONTROL);
+ createSystemReadyService();
+
+ IExternalVibrationController externalVibrationControllerMock =
+ mock(IExternalVibrationController.class);
+ ExternalVibration externalVibration = new ExternalVibration(UID, PACKAGE_NAME,
+ AUDIO_ALARM_ATTRS, externalVibrationControllerMock, mock(IBinder.class));
+ ExternalVibrationScale scale = mExternalVibratorService.onExternalVibrationStart(
+ externalVibration);
+
+ assertThat(scale.scaleLevel).isNotEqualTo(ExternalVibrationScale.ScaleLevel.SCALE_MUTE);
+
+ mRegisteredPowerModeListener.onLowPowerModeChanged(LOW_POWER_STATE);
+
+ verify(externalVibrationControllerMock, never()).mute();
+ }
+
+ @Test
+ public void onExternalVibration_thenSettingsChange_doNotCancelVibration() throws Exception {
+ mockVibrators(1);
+ mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_EXTERNAL_CONTROL);
+ VibratorManagerService service = createSystemReadyService();
+
+ IExternalVibrationController externalVibrationControllerMock =
+ mock(IExternalVibrationController.class);
+ ExternalVibration externalVibration = new ExternalVibration(UID, PACKAGE_NAME,
+ AUDIO_ALARM_ATTRS, externalVibrationControllerMock, mock(IBinder.class));
+ ExternalVibrationScale scale = mExternalVibratorService.onExternalVibrationStart(
+ externalVibration);
+
+ assertThat(scale.scaleLevel).isNotEqualTo(ExternalVibrationScale.ScaleLevel.SCALE_MUTE);
+
+ setUserSetting(Settings.System.ALARM_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_OFF);
+ service.mVibrationSettings.mSettingObserver.onChange(false);
+ service.updateServiceState();
+
+ verify(externalVibrationControllerMock, never()).mute();
+ }
+
+ @Test
+ public void onExternalVibration_thenScreenTurnsOff_doNotCancelVibration() throws Throwable {
+ mockVibrators(1);
+ mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_EXTERNAL_CONTROL);
+ VibratorManagerService service = createSystemReadyService();
+
+ IExternalVibrationController externalVibrationControllerMock =
+ mock(IExternalVibrationController.class);
+ ExternalVibration externalVibration = new ExternalVibration(UID, PACKAGE_NAME,
+ AUDIO_ALARM_ATTRS, externalVibrationControllerMock, mock(IBinder.class));
+ ExternalVibrationScale scale = mExternalVibratorService.onExternalVibrationStart(
+ externalVibration);
+
+ assertThat(scale.scaleLevel).isNotEqualTo(ExternalVibrationScale.ScaleLevel.SCALE_MUTE);
+
+ service.mIntentReceiver.onReceive(mContextSpy, new Intent(Intent.ACTION_SCREEN_OFF));
+
+ verify(externalVibrationControllerMock, never()).mute();
+ }
+
+ @Test
+ @RequiresFlagsEnabled(android.multiuser.Flags.FLAG_ADD_UI_FOR_SOUNDS_FROM_BACKGROUND_USERS)
+ public void onExternalVibration_thenFgUserRequestsMute_doNotCancelVibration() throws Throwable {
+ mockVibrators(1);
+ mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_EXTERNAL_CONTROL);
+ VibratorManagerService service = createSystemReadyService();
+
+ IExternalVibrationController externalVibrationControllerMock =
+ mock(IExternalVibrationController.class);
+ ExternalVibration externalVibration = new ExternalVibration(UID, PACKAGE_NAME,
+ AUDIO_ALARM_ATTRS, externalVibrationControllerMock, mock(IBinder.class));
+ ExternalVibrationScale scale = mExternalVibratorService.onExternalVibrationStart(
+ externalVibration);
+
+ assertThat(scale.scaleLevel).isNotEqualTo(ExternalVibrationScale.ScaleLevel.SCALE_MUTE);
+
+ service.mIntentReceiver.onReceive(mContextSpy, new Intent(
+ BackgroundUserSoundNotifier.ACTION_MUTE_SOUND));
+
+ verify(externalVibrationControllerMock, never()).mute();
+ }
+
+ @Test
public void frameworkStats_externalVibration_reportsAllMetrics() throws Exception {
mockVibrators(1);
mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_EXTERNAL_CONTROL);
@@ -2501,7 +2633,7 @@ public class VibratorManagerServiceTest {
assertEquals(FrameworkStatsLog.VIBRATION_REPORTED__VIBRATION_TYPE__EXTERNAL,
statsInfo.vibrationType);
assertEquals(VibrationAttributes.USAGE_ALARM, statsInfo.usage);
- assertEquals(Vibration.Status.FINISHED.getProtoEnumValue(), statsInfo.status);
+ assertEquals(Status.FINISHED.getProtoEnumValue(), statsInfo.status);
assertTrue(statsInfo.totalDurationMillis > 0);
assertTrue(
"Expected vibrator ON for at least 10ms, got " + statsInfo.vibratorOnMillis + "ms",
@@ -2533,7 +2665,7 @@ public class VibratorManagerServiceTest {
assertEquals(FrameworkStatsLog.VIBRATION_REPORTED__VIBRATION_TYPE__SINGLE,
metrics.vibrationType);
assertEquals(VibrationAttributes.USAGE_RINGTONE, metrics.usage);
- assertEquals(Vibration.Status.FINISHED.getProtoEnumValue(), metrics.status);
+ assertEquals(Status.FINISHED.getProtoEnumValue(), metrics.status);
assertTrue("Total duration was too low, " + metrics.totalDurationMillis + "ms",
metrics.totalDurationMillis >= 20);
assertTrue("Vibrator ON duration was too low, " + metrics.vibratorOnMillis + "ms",
@@ -2586,7 +2718,7 @@ public class VibratorManagerServiceTest {
assertEquals(FrameworkStatsLog.VIBRATION_REPORTED__VIBRATION_TYPE__REPEATED,
metrics.vibrationType);
assertEquals(VibrationAttributes.USAGE_RINGTONE, metrics.usage);
- assertEquals(Vibration.Status.CANCELLED_BY_USER.getProtoEnumValue(), metrics.status);
+ assertEquals(Status.CANCELLED_BY_USER.getProtoEnumValue(), metrics.status);
assertTrue("Total duration was too low, " + metrics.totalDurationMillis + "ms",
metrics.totalDurationMillis >= 100);
assertTrue("Vibrator ON duration was too low, " + metrics.vibratorOnMillis + "ms",
@@ -2647,7 +2779,7 @@ public class VibratorManagerServiceTest {
assertEquals(FrameworkStatsLog.VIBRATION_REPORTED__VIBRATION_TYPE__SINGLE,
metrics.vibrationType);
assertEquals(VibrationAttributes.USAGE_ALARM, metrics.usage);
- assertEquals(Vibration.Status.FINISHED.getProtoEnumValue(), metrics.status);
+ assertEquals(Status.FINISHED.getProtoEnumValue(), metrics.status);
// At least 4 effect/primitive played, 20ms each, plus configured fallback.
assertTrue("Total duration was too low, " + metrics.totalDurationMillis + "ms",
@@ -2703,7 +2835,7 @@ public class VibratorManagerServiceTest {
VibrationStats.StatsInfo touchMetrics = argumentCaptor.getAllValues().get(0);
assertEquals(UID, touchMetrics.uid);
assertEquals(VibrationAttributes.USAGE_TOUCH, touchMetrics.usage);
- assertEquals(Vibration.Status.CANCELLED_SUPERSEDED.getProtoEnumValue(),
+ assertEquals(Status.CANCELLED_SUPERSEDED.getProtoEnumValue(),
touchMetrics.status);
assertTrue(touchMetrics.endedBySameUid);
assertEquals(VibrationAttributes.USAGE_ALARM, touchMetrics.endedByUsage);
@@ -2712,7 +2844,7 @@ public class VibratorManagerServiceTest {
VibrationStats.StatsInfo alarmMetrics = argumentCaptor.getAllValues().get(1);
assertEquals(UID, alarmMetrics.uid);
assertEquals(VibrationAttributes.USAGE_ALARM, alarmMetrics.usage);
- assertEquals(Vibration.Status.FINISHED.getProtoEnumValue(), alarmMetrics.status);
+ assertEquals(Status.FINISHED.getProtoEnumValue(), alarmMetrics.status);
assertFalse(alarmMetrics.endedBySameUid);
assertEquals(-1, alarmMetrics.endedByUsage);
assertEquals(VibrationAttributes.USAGE_TOUCH, alarmMetrics.interruptedUsage);
@@ -2742,12 +2874,12 @@ public class VibratorManagerServiceTest {
VibrationStats.StatsInfo touchMetrics = argumentCaptor.getAllValues().get(0);
assertEquals(UID, touchMetrics.uid);
assertEquals(VibrationAttributes.USAGE_TOUCH, touchMetrics.usage);
- assertEquals(Vibration.Status.IGNORED_FOR_POWER.getProtoEnumValue(), touchMetrics.status);
+ assertEquals(Status.IGNORED_FOR_POWER.getProtoEnumValue(), touchMetrics.status);
VibrationStats.StatsInfo ringtoneMetrics = argumentCaptor.getAllValues().get(1);
assertEquals(UID, ringtoneMetrics.uid);
assertEquals(VibrationAttributes.USAGE_RINGTONE, ringtoneMetrics.usage);
- assertEquals(Vibration.Status.IGNORED_FOR_SETTINGS.getProtoEnumValue(),
+ assertEquals(Status.IGNORED_FOR_SETTINGS.getProtoEnumValue(),
ringtoneMetrics.status);
for (VibrationStats.StatsInfo metrics : argumentCaptor.getAllValues()) {
@@ -2814,7 +2946,7 @@ public class VibratorManagerServiceTest {
assertEquals(FrameworkStatsLog.VIBRATION_REPORTED__VIBRATION_TYPE__SINGLE,
metrics.vibrationType);
assertEquals(VibrationAttributes.USAGE_NOTIFICATION, metrics.usage);
- assertEquals(Vibration.Status.FINISHED.getProtoEnumValue(), metrics.status);
+ assertEquals(Status.FINISHED.getProtoEnumValue(), metrics.status);
assertTrue(metrics.totalDurationMillis >= 20);
// vibratorOnMillis accumulates both vibrators, it's 20 for each constant.