diff options
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. |