diff options
| author | 2024-08-23 11:03:45 +0100 | |
|---|---|---|
| committer | 2024-08-29 13:39:37 +0100 | |
| commit | 790f3563ef4526feebc3b8ee3ddd937101e8ab68 (patch) | |
| tree | 72b5c050b5f1519cb921ded6ba709beeddbb63b3 | |
| parent | dde5de7103f3c9f01be85e8a3a46232802cc9d48 (diff) | |
Introduce VibrationSession to VibratorManagerService
Introduce new interface to represent a generic vibration session, in
preparation for the support for vendor vibration sessions.
Move Vibration CallerInfo, DebugInfo and Status classes to the new
session, since these concepts will be referring to sessions instead of a
single vibration playback.
Migrate ExternalVibration to use the new interface, preserving the
behavior.
Bug: 345414356
Test: VibratorManagerServiceTest
Flag: EXEMPT refactor
Change-Id: Ic184ad77af7e4fde5fa5458744e7b50c5be0a9d4
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. |