Merge "Add CallerInfo to Vibration class."

This commit is contained in:
Ahmad Khalil
2023-02-09 11:01:15 +00:00
committed by Android (Google) Code Review
19 changed files with 384 additions and 334 deletions

View File

@@ -104,6 +104,10 @@ public class ExternalVibration implements Parcelable {
return mAttrs;
}
public IBinder getToken() {
return mToken;
}
public VibrationAttributes getVibrationAttributes() {
return new VibrationAttributes.Builder(mAttrs).build();
}

View File

@@ -126,7 +126,7 @@ abstract class AbstractVibratorStep extends Step {
"Turning off vibrator " + getVibratorId());
}
controller.off();
getVibration().stats().reportVibratorOff();
getVibration().stats.reportVibratorOff();
mPendingVibratorOffDeadline = 0;
}
@@ -136,7 +136,7 @@ abstract class AbstractVibratorStep extends Step {
"Amplitude changed on vibrator " + getVibratorId() + " to " + amplitude);
}
controller.setAmplitude(amplitude);
getVibration().stats().reportSetAmplitude();
getVibration().stats.reportSetAmplitude();
}
/**
@@ -170,7 +170,7 @@ abstract class AbstractVibratorStep extends Step {
// Count the loops that were played.
int loopSize = effectSize - repeatIndex;
int loopSegmentsPlayed = nextSegmentIndex - repeatIndex;
getVibration().stats().reportRepetition(loopSegmentsPlayed / loopSize);
getVibration().stats.reportRepetition(loopSegmentsPlayed / loopSize);
nextSegmentIndex = repeatIndex + ((nextSegmentIndex - effectSize) % loopSize);
}
Step nextStep = conductor.nextVibrateStep(nextStartTime, controller, effect,

View File

@@ -73,7 +73,7 @@ final class ComposePrimitivesVibratorStep extends AbstractVibratorStep {
primitives.toArray(new PrimitiveSegment[primitives.size()]);
long vibratorOnResult = controller.on(primitivesArray, getVibration().id);
handleVibratorOnResult(vibratorOnResult);
getVibration().stats().reportComposePrimitives(vibratorOnResult, primitivesArray);
getVibration().stats.reportComposePrimitives(vibratorOnResult, primitivesArray);
// The next start and off times will be calculated from mVibratorOnResult.
return nextSteps(/* segmentsPlayed= */ primitives.size());

View File

@@ -72,7 +72,7 @@ final class ComposePwleVibratorStep extends AbstractVibratorStep {
RampSegment[] pwlesArray = pwles.toArray(new RampSegment[pwles.size()]);
long vibratorOnResult = controller.on(pwlesArray, getVibration().id);
handleVibratorOnResult(vibratorOnResult);
getVibration().stats().reportComposePwle(vibratorOnResult, pwlesArray);
getVibration().stats.reportComposePwle(vibratorOnResult, pwlesArray);
// The next start and off times will be calculated from mVibratorOnResult.
return nextSteps(/* segmentsPlayed= */ pwles.size());

View File

@@ -51,7 +51,8 @@ final class FinishSequentialEffectStep extends Step {
Slog.d(VibrationThread.TAG,
"FinishSequentialEffectStep for effect #" + startedStep.currentIndex);
}
conductor.vibratorManagerHooks.noteVibratorOff(conductor.getVibration().uid);
conductor.vibratorManagerHooks.noteVibratorOff(
conductor.getVibration().callerInfo.uid);
Step nextStep = startedStep.nextStep();
return nextStep == null ? VibrationStepConductor.EMPTY_STEP_LIST
: Arrays.asList(nextStep);
@@ -68,6 +69,7 @@ final class FinishSequentialEffectStep extends Step {
@Override
public void cancelImmediately() {
conductor.vibratorManagerHooks.noteVibratorOff(conductor.getVibration().uid);
conductor.vibratorManagerHooks.noteVibratorOff(
conductor.getVibration().callerInfo.uid);
}
}

View File

@@ -16,6 +16,7 @@
package com.android.server.vibrator;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.CombinedVibration;
import android.os.IBinder;
@@ -35,13 +36,6 @@ import java.util.function.Function;
*/
final class HalVibration extends Vibration {
public final VibrationAttributes attrs;
public final long id;
public final int uid;
public final int displayId;
public final String opPkg;
public final String reason;
public final IBinder token;
public final SparseArray<VibrationEffect> mFallbacks = new SparseArray<>();
/** The actual effect to be played. */
@@ -58,29 +52,15 @@ final class HalVibration extends Vibration {
/** Vibration status. */
private Vibration.Status mStatus;
/** Vibration runtime stats. */
private final VibrationStats mStats = new VibrationStats();
/** A {@link CountDownLatch} to enable waiting for completion. */
private final CountDownLatch mCompletionLatch = new CountDownLatch(1);
HalVibration(IBinder token, int id, CombinedVibration effect,
VibrationAttributes attrs, int uid, int displayId, String opPkg, String reason) {
this.token = token;
HalVibration(@NonNull IBinder token, CombinedVibration effect, @NonNull CallerInfo callerInfo) {
super(token, callerInfo);
this.mEffect = effect;
this.id = id;
this.attrs = attrs;
this.uid = uid;
this.displayId = displayId;
this.opPkg = opPkg;
this.reason = reason;
mStatus = Vibration.Status.RUNNING;
}
VibrationStats stats() {
return mStats;
}
/**
* Set the {@link Status} of this vibration and reports the current system time as this
* vibration end time, for debugging purposes.
@@ -94,7 +74,7 @@ final class HalVibration extends Vibration {
return;
}
mStatus = info.status;
mStats.reportEnded(info.endedByUid, info.endedByUsage);
stats.reportEnded(info.endedBy);
mCompletionLatch.countDown();
}
@@ -190,8 +170,8 @@ final class HalVibration extends Vibration {
* Return {@link Vibration.DebugInfo} with read-only debug information about this vibration.
*/
public Vibration.DebugInfo getDebugInfo() {
return new Vibration.DebugInfo(mStatus, mStats, mEffect, mOriginalEffect, /* scale= */ 0,
attrs, uid, displayId, opPkg, reason);
return new Vibration.DebugInfo(mStatus, stats, mEffect, mOriginalEffect, /* scale= */ 0,
callerInfo);
}
/** Return {@link VibrationStats.StatsInfo} with read-only metrics about this vibration. */
@@ -200,7 +180,8 @@ final class HalVibration extends Vibration {
? FrameworkStatsLog.VIBRATION_REPORTED__VIBRATION_TYPE__REPEATED
: FrameworkStatsLog.VIBRATION_REPORTED__VIBRATION_TYPE__SINGLE;
return new VibrationStats.StatsInfo(
uid, vibrationType, attrs.getUsage(), mStatus, mStats, completionUptimeMillis);
callerInfo.uid, vibrationType, callerInfo.attrs.getUsage(), mStatus,
stats, completionUptimeMillis);
}
/**
@@ -212,8 +193,9 @@ final class HalVibration extends Vibration {
* pipeline very short vibrations together, regardless of the flag.
*/
public boolean canPipelineWith(HalVibration vib) {
return uid == vib.uid && attrs.isFlagSet(VibrationAttributes.FLAG_PIPELINED_EFFECT)
&& vib.attrs.isFlagSet(VibrationAttributes.FLAG_PIPELINED_EFFECT)
return callerInfo.uid == vib.callerInfo.uid && callerInfo.attrs.isFlagSet(
VibrationAttributes.FLAG_PIPELINED_EFFECT)
&& vib.callerInfo.attrs.isFlagSet(VibrationAttributes.FLAG_PIPELINED_EFFECT)
&& !isRepeating();
}
}

View File

@@ -21,7 +21,6 @@ import android.content.Context;
import android.hardware.input.InputManager;
import android.os.CombinedVibration;
import android.os.Handler;
import android.os.VibrationAttributes;
import android.os.VibratorManager;
import android.util.SparseArray;
import android.view.InputDevice;
@@ -94,11 +93,11 @@ final class InputDeviceDelegate implements InputManager.InputDeviceListener {
*
* @return {@link #isAvailable()}
*/
public boolean vibrateIfAvailable(int uid, String opPkg, CombinedVibration effect,
String reason, VibrationAttributes attrs) {
public boolean vibrateIfAvailable(Vibration.CallerInfo callerInfo, CombinedVibration effect) {
synchronized (mLock) {
for (int i = 0; i < mInputDeviceVibrators.size(); i++) {
mInputDeviceVibrators.valueAt(i).vibrate(uid, opPkg, effect, reason, attrs);
mInputDeviceVibrators.valueAt(i).vibrate(callerInfo.uid, callerInfo.opPkg, effect,
callerInfo.reason, callerInfo.attrs);
}
return mInputDeviceVibrators.size() > 0;
}

View File

@@ -64,7 +64,7 @@ final class PerformPrebakedVibratorStep extends AbstractVibratorStep {
VibrationEffect fallback = getVibration().getFallback(prebaked.getEffectId());
long vibratorOnResult = controller.on(prebaked, getVibration().id);
handleVibratorOnResult(vibratorOnResult);
getVibration().stats().reportPerformEffect(vibratorOnResult, prebaked);
getVibration().stats.reportPerformEffect(vibratorOnResult, prebaked);
if (vibratorOnResult == 0 && prebaked.shouldFallback()
&& (fallback instanceof VibrationEffect.Composed)) {

View File

@@ -161,7 +161,7 @@ final class SetAmplitudeVibratorStep extends AbstractVibratorStep {
}
long vibratorOnResult = controller.on(duration, getVibration().id);
handleVibratorOnResult(vibratorOnResult);
getVibration().stats().reportVibratorOn(vibratorOnResult);
getVibration().stats.reportVibratorOn(vibratorOnResult);
return vibratorOnResult;
}

View File

@@ -93,8 +93,8 @@ final class StartSequentialEffectStep extends Step {
}
mVibratorsOnMaxDuration = startVibrating(effectMapping, nextSteps);
conductor.vibratorManagerHooks.noteVibratorOn(conductor.getVibration().uid,
mVibratorsOnMaxDuration);
conductor.vibratorManagerHooks.noteVibratorOn(
conductor.getVibration().callerInfo.uid, mVibratorsOnMaxDuration);
} finally {
if (mVibratorsOnMaxDuration >= 0) {
// It least one vibrator was started then add a finish step to wait for all
@@ -211,7 +211,8 @@ final class StartSequentialEffectStep extends Step {
// Check if sync was prepared and if any step was accepted by a vibrator,
// otherwise there is nothing to trigger here.
if (hasPrepared && !hasFailed && maxDuration > 0) {
hasTriggered = conductor.vibratorManagerHooks.triggerSyncedVibration(getVibration().id);
hasTriggered = conductor.vibratorManagerHooks.triggerSyncedVibration(
getVibration().id);
hasFailed &= hasTriggered;
}

View File

@@ -19,6 +19,7 @@ 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.os.VibrationEffect;
import android.os.vibrator.PrebakedSegment;
@@ -31,6 +32,7 @@ import android.util.proto.ProtoOutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
/**
* The base class for all vibrations.
@@ -38,6 +40,13 @@ import java.util.Objects;
class Vibration {
private static final SimpleDateFormat DEBUG_DATE_FORMAT =
new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
// Used to generate globally unique vibration ids.
private static final AtomicInteger sNextVibrationId = new AtomicInteger(1); // 0 = no callback
public final long id;
public final 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 {
@@ -80,24 +89,82 @@ class Vibration {
}
}
Vibration(@NonNull IBinder token, @NonNull CallerInfo callerInfo) {
Objects.requireNonNull(token);
Objects.requireNonNull(callerInfo);
this.id = sNextVibrationId.getAndIncrement();
this.callerToken = token;
this.callerInfo = callerInfo;
}
/**
* 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.
*
* 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}.
*/
static final class CallerInfo {
public final VibrationAttributes attrs;
public final int uid;
public final int displayId;
public final String opPkg;
public final String reason;
CallerInfo(@NonNull VibrationAttributes attrs, int uid, int displayId,
String opPkg, String reason) {
Objects.requireNonNull(attrs);
this.attrs = attrs;
this.uid = uid;
this.displayId = displayId;
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
&& displayId == that.displayId
&& Objects.equals(opPkg, that.opPkg)
&& Objects.equals(reason, that.reason);
}
@Override
public int hashCode() {
return Objects.hash(attrs, uid, displayId, opPkg, reason);
}
@Override
public String toString() {
return "CallerInfo{"
+ " attrs=" + attrs
+ ", uid=" + uid
+ ", displayId=" + displayId
+ ", opPkg=" + opPkg
+ ", reason=" + reason
+ '}';
}
}
/** 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. */
@NonNull
public final Status status;
/** The UID that triggered the vibration that ended this, or -1 if undefined. */
public final int endedByUid;
/** The VibrationAttributes.USAGE_* of the vibration that ended this, or -1 if undefined. */
public final int endedByUsage;
/** Info about the process that ended the vibration. */
public final CallerInfo endedBy;
EndInfo(@NonNull Vibration.Status status) {
this(status, /* endedByUid= */ -1, /* endedByUsage= */ -1);
this(status, null);
}
EndInfo(@NonNull Vibration.Status status, int endedByUid, int endedByUsage) {
EndInfo(@NonNull Vibration.Status status, @Nullable CallerInfo endedBy) {
this.status = status;
this.endedByUid = endedByUid;
this.endedByUsage = endedByUsage;
this.endedBy = endedBy;
}
@Override
@@ -105,27 +172,31 @@ class Vibration {
if (this == o) return true;
if (!(o instanceof EndInfo)) return false;
EndInfo that = (EndInfo) o;
return endedByUid == that.endedByUid
&& endedByUsage == that.endedByUsage
return Objects.equals(endedBy, that.endedBy)
&& status == that.status;
}
@Override
public int hashCode() {
return Objects.hash(status, endedByUid, endedByUsage);
return Objects.hash(status, endedBy);
}
@Override
public String toString() {
return "EndInfo{"
+ "status=" + status
+ ", endedByUid=" + endedByUid
+ ", endedByUsage=" + endedByUsage
+ ", endedBy=" + endedBy
+ '}';
}
}
/** Debug information about vibrations. */
/**
* Holds lightweight debug information about the vibration that could potentially be kept in
* memory for a long time for bugreport dumpsys operations.
*
* 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 {
private final long mCreateTime;
private final long mStartTime;
@@ -134,16 +205,13 @@ class Vibration {
private final CombinedVibration mEffect;
private final CombinedVibration mOriginalEffect;
private final float mScale;
private final VibrationAttributes mAttrs;
private final int mUid;
private final int mDisplayId;
private final String mOpPkg;
private final String mReason;
private final CallerInfo mCallerInfo;
private final Status mStatus;
DebugInfo(Status status, VibrationStats stats, @Nullable CombinedVibration effect,
@Nullable CombinedVibration originalEffect, float scale, VibrationAttributes attrs,
int uid, int displayId, String opPkg, String reason) {
@Nullable CombinedVibration originalEffect, float scale,
@NonNull CallerInfo callerInfo) {
Objects.requireNonNull(callerInfo);
mCreateTime = stats.getCreateTimeDebug();
mStartTime = stats.getStartTimeDebug();
mEndTime = stats.getEndTimeDebug();
@@ -151,11 +219,7 @@ class Vibration {
mEffect = effect;
mOriginalEffect = originalEffect;
mScale = scale;
mAttrs = attrs;
mUid = uid;
mDisplayId = displayId;
mOpPkg = opPkg;
mReason = reason;
mCallerInfo = callerInfo;
mStatus = status;
}
@@ -179,16 +243,8 @@ class Vibration {
.append(mOriginalEffect)
.append(", scale: ")
.append(String.format("%.2f", mScale))
.append(", attrs: ")
.append(mAttrs)
.append(", uid: ")
.append(mUid)
.append(", displayId: ")
.append(mDisplayId)
.append(", opPkg: ")
.append(mOpPkg)
.append(", reason: ")
.append(mReason)
.append(", callerInfo: ")
.append(mCallerInfo)
.toString();
}
@@ -201,9 +257,10 @@ class Vibration {
proto.write(VibrationProto.STATUS, mStatus.ordinal());
final long attrsToken = proto.start(VibrationProto.ATTRIBUTES);
proto.write(VibrationAttributesProto.USAGE, mAttrs.getUsage());
proto.write(VibrationAttributesProto.AUDIO_USAGE, mAttrs.getAudioUsage());
proto.write(VibrationAttributesProto.FLAGS, mAttrs.getFlags());
final VibrationAttributes attrs = mCallerInfo.attrs;
proto.write(VibrationAttributesProto.USAGE, attrs.getUsage());
proto.write(VibrationAttributesProto.AUDIO_USAGE, attrs.getAudioUsage());
proto.write(VibrationAttributesProto.FLAGS, attrs.getFlags());
proto.end(attrsToken);
if (mEffect != null) {

View File

@@ -27,6 +27,7 @@ import static android.os.VibrationAttributes.USAGE_RINGTONE;
import static android.os.VibrationAttributes.USAGE_TOUCH;
import static android.os.VibrationAttributes.USAGE_UNKNOWN;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.IUidObserver;
@@ -375,15 +376,15 @@ final class VibrationSettings {
* null otherwise.
*/
@Nullable
public Vibration.Status shouldIgnoreVibration(int uid, int displayId,
VibrationAttributes attrs) {
final int usage = attrs.getUsage();
public Vibration.Status shouldIgnoreVibration(@NonNull Vibration.CallerInfo callerInfo) {
final int usage = callerInfo.attrs.getUsage();
synchronized (mLock) {
if (!mUidObserver.isUidForeground(uid)
if (!mUidObserver.isUidForeground(callerInfo.uid)
&& !BACKGROUND_PROCESS_USAGE_ALLOWLIST.contains(usage)) {
return Vibration.Status.IGNORED_BACKGROUND;
}
if (mVirtualDeviceListener.isAppOrDisplayOnAnyVirtualDevice(uid, displayId)) {
if (mVirtualDeviceListener.isAppOrDisplayOnAnyVirtualDevice(callerInfo.uid,
callerInfo.displayId)) {
return Vibration.Status.IGNORED_FROM_VIRTUAL_DEVICE;
}
@@ -391,7 +392,8 @@ final class VibrationSettings {
return Vibration.Status.IGNORED_FOR_POWER;
}
if (!attrs.isFlagSet(VibrationAttributes.FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF)) {
if (!callerInfo.attrs.isFlagSet(
VibrationAttributes.FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF)) {
if (!mVibrateOn && (VIBRATE_ON_DISABLED_USAGE_ALLOWED != usage)) {
return Vibration.Status.IGNORED_FOR_SETTINGS;
}
@@ -401,7 +403,7 @@ final class VibrationSettings {
}
}
if (!attrs.isFlagSet(VibrationAttributes.FLAG_BYPASS_INTERRUPTION_POLICY)) {
if (!callerInfo.attrs.isFlagSet(VibrationAttributes.FLAG_BYPASS_INTERRUPTION_POLICY)) {
if (!shouldVibrateForRingerModeLocked(usage)) {
return Vibration.Status.IGNORED_FOR_RINGER_MODE;
}
@@ -420,8 +422,8 @@ final class VibrationSettings {
*
* @return true if the vibration should be cancelled when the screen goes off, false otherwise.
*/
public boolean shouldCancelVibrationOnScreenOff(int uid, String opPkg,
@VibrationAttributes.Usage int usage, long vibrationStartUptimeMillis) {
public boolean shouldCancelVibrationOnScreenOff(@NonNull Vibration.CallerInfo callerInfo,
long vibrationStartUptimeMillis) {
PowerManagerInternal pm;
synchronized (mLock) {
pm = mPowerManagerInternal;
@@ -442,12 +444,13 @@ final class VibrationSettings {
return false;
}
}
if (!SYSTEM_VIBRATION_SCREEN_OFF_USAGE_ALLOWLIST.contains(usage)) {
if (!SYSTEM_VIBRATION_SCREEN_OFF_USAGE_ALLOWLIST.contains(callerInfo.attrs.getUsage())) {
// Usages not allowed even for system vibrations should always be cancelled.
return true;
}
// Only allow vibrations from System packages to continue vibrating when the screen goes off
return uid != Process.SYSTEM_UID && uid != 0 && !mSystemUiPackage.equals(opPkg);
return callerInfo.uid != Process.SYSTEM_UID && callerInfo.uid != 0
&& !mSystemUiPackage.equals(callerInfo.opPkg);
}
/**

View File

@@ -16,6 +16,8 @@
package com.android.server.vibrator;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.SystemClock;
import android.os.vibrator.PrebakedSegment;
import android.os.vibrator.PrimitiveSegment;
@@ -159,15 +161,18 @@ 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(int endedByUid, int endedByUsage) {
boolean reportEnded(@Nullable Vibration.CallerInfo endedBy) {
if (hasEnded()) {
// Vibration already ended, keep first ending stats set and ignore this one.
return false;
}
mEndedByUid = endedByUid;
mEndedByUsage = endedByUsage;
if (endedBy != null) {
mEndedByUid = endedBy.uid;
mEndedByUsage = endedBy.attrs.getUsage();
}
mEndUptimeMillis = SystemClock.uptimeMillis();
mEndTimeDebug = System.currentTimeMillis();
return true;
}
@@ -177,9 +182,9 @@ 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(int interruptedUsage) {
void reportInterruptedAnotherVibration(@NonNull Vibration.CallerInfo callerInfo) {
if (mInterruptedUsage < 0) {
mInterruptedUsage = interruptedUsage;
mInterruptedUsage = callerInfo.attrs.getUsage();
}
}

View File

@@ -157,7 +157,7 @@ final class VibrationStepConductor implements IBinder.DeathRecipient {
mNextSteps.offer(new StartSequentialEffectStep(this, sequentialEffect));
// Vibration will start playing in the Vibrator, following the effect timings and delays.
// Report current time as the vibration start time, for debugging.
mVibration.stats().reportStarted();
mVibration.stats.reportStarted();
}
public HalVibration getVibration() {

View File

@@ -161,7 +161,8 @@ final class VibrationThread extends Thread {
// for this thread.
// No point doing this in finally, as if there's an exception, this thread will die
// and be unusable anyway.
mVibratorManagerHooks.onVibrationThreadReleased(mExecutingConductor.getVibration().id);
mVibratorManagerHooks.onVibrationThreadReleased(
mExecutingConductor.getVibration().id);
synchronized (mLock) {
mLock.notifyAll();
}
@@ -230,7 +231,8 @@ final class VibrationThread extends Thread {
/** Runs the VibrationThread ensuring that the wake lock is acquired and released. */
private void runCurrentVibrationWithWakeLock() {
WorkSource workSource = new WorkSource(mExecutingConductor.getVibration().uid);
WorkSource workSource = new WorkSource(
mExecutingConductor.getVibration().callerInfo.uid);
mWakeLock.setWorkSource(workSource);
mWakeLock.acquire();
try {
@@ -251,7 +253,7 @@ final class VibrationThread extends Thread {
* Called from within runWithWakeLock.
*/
private void runCurrentVibrationWithWakeLockAndDeathLink() {
IBinder vibrationBinderToken = mExecutingConductor.getVibration().token;
IBinder vibrationBinderToken = mExecutingConductor.getVibration().callerToken;
try {
vibrationBinderToken.linkToDeath(mExecutingConductor, 0);
} catch (RemoteException e) {

View File

@@ -77,7 +77,6 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import java.util.function.Function;
@@ -123,9 +122,6 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
}
}
// Used to generate globally unique vibration ids.
private final AtomicInteger mNextVibrationId = new AtomicInteger(1); // 0 = no callback
private final Object mLock = new Object();
private final Context mContext;
private final PowerManager.WakeLock mWakeLock;
@@ -367,8 +363,9 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
// missing on individual vibrators.
return false;
}
AlwaysOnVibration alwaysOnVibration = new AlwaysOnVibration(
alwaysOnId, uid, opPkg, attrs, effects);
AlwaysOnVibration alwaysOnVibration = new AlwaysOnVibration(alwaysOnId,
new Vibration.CallerInfo(attrs, uid, Display.DEFAULT_DISPLAY, opPkg,
null), effects);
mAlwaysOnEffects.put(alwaysOnId, alwaysOnVibration);
updateAlwaysOnLocked(alwaysOnVibration);
}
@@ -408,8 +405,8 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
}
attrs = fixupVibrationAttributes(attrs, effect);
// Create Vibration.Stats as close to the received request as possible, for tracking.
HalVibration vib = new HalVibration(token, mNextVibrationId.getAndIncrement(), effect,
attrs, uid, displayId, opPkg, reason);
HalVibration vib = new HalVibration(token, effect,
new Vibration.CallerInfo(attrs, uid, displayId, opPkg, reason));
fillVibrationFallbacks(vib, effect);
if (attrs.isFlagSet(VibrationAttributes.FLAG_INVALIDATE_SETTINGS_CACHE)) {
@@ -422,27 +419,23 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
if (DEBUG) {
Slog.d(TAG, "Starting vibrate for vibration " + vib.id);
}
int ignoredByUid = -1;
int ignoredByUsage = -1;
Vibration.Status status = null;
Vibration.CallerInfo ignoredByCallerInfo = null;
Vibration.Status status;
// Check if user settings or DnD is set to ignore this vibration.
status = shouldIgnoreVibrationLocked(vib.uid, vib.displayId, vib.opPkg, vib.attrs);
status = shouldIgnoreVibrationLocked(vib.callerInfo);
// Check if something has external control, assume it's more important.
if ((status == null) && (mCurrentExternalVibration != null)) {
status = Vibration.Status.IGNORED_FOR_EXTERNAL;
ignoredByUid = mCurrentExternalVibration.externalVibration.getUid();
ignoredByUsage = mCurrentExternalVibration.externalVibration
.getVibrationAttributes().getUsage();
ignoredByCallerInfo = mCurrentExternalVibration.callerInfo;
}
// Check if ongoing vibration is more important than this vibration.
if (status == null) {
status = shouldIgnoreVibrationForOngoingLocked(vib);
if (status != null) {
ignoredByUid = mCurrentVibration.getVibration().uid;
ignoredByUsage = mCurrentVibration.getVibration().attrs.getUsage();
ignoredByCallerInfo = mCurrentVibration.getVibration().callerInfo;
}
}
@@ -460,12 +453,11 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
Slog.d(TAG, "Pipelining vibration " + vib.id);
}
} else {
vib.stats().reportInterruptedAnotherVibration(
mCurrentVibration.getVibration().attrs.getUsage());
vib.stats.reportInterruptedAnotherVibration(
mCurrentVibration.getVibration().callerInfo);
mCurrentVibration.notifyCancelled(
new Vibration.EndInfo(
Vibration.Status.CANCELLED_SUPERSEDED, vib.uid,
vib.attrs.getUsage()),
new Vibration.EndInfo(Vibration.Status.CANCELLED_SUPERSEDED,
vib.callerInfo),
/* immediate= */ false);
}
}
@@ -478,7 +470,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
// Ignored or failed to start the vibration, end it and report metrics right away.
if (status != Vibration.Status.RUNNING) {
endVibrationLocked(vib,
new Vibration.EndInfo(status, ignoredByUid, ignoredByUsage),
new Vibration.EndInfo(status, ignoredByCallerInfo),
/* shouldWriteStats= */ true);
}
return vib;
@@ -641,8 +633,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
}
HalVibration vib = mCurrentVibration.getVibration();
Vibration.Status ignoreStatus = shouldIgnoreVibrationLocked(
vib.uid, vib.displayId, vib.opPkg, vib.attrs);
Vibration.Status ignoreStatus = shouldIgnoreVibrationLocked(vib.callerInfo);
if (inputDevicesChanged || (ignoreStatus != null)) {
if (DEBUG) {
@@ -671,10 +662,9 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
if (vibrator == null) {
continue;
}
Vibration.Status ignoreStatus = shouldIgnoreVibrationLocked(
vib.uid, Display.DEFAULT_DISPLAY, vib.opPkg, vib.attrs);
Vibration.Status ignoreStatus = shouldIgnoreVibrationLocked(vib.callerInfo);
if (ignoreStatus == null) {
effect = mVibrationScaler.scale(effect, vib.attrs.getUsage());
effect = mVibrationScaler.scale(effect, vib.callerInfo.attrs.getUsage());
} else {
// Vibration should not run, use null effect to remove registered effect.
effect = null;
@@ -687,9 +677,10 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
private Vibration.Status startVibrationLocked(HalVibration vib) {
Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "startVibrationLocked");
try {
vib.updateEffects(effect -> mVibrationScaler.scale(effect, vib.attrs.getUsage()));
vib.updateEffects(
effect -> mVibrationScaler.scale(effect, vib.callerInfo.attrs.getUsage()));
boolean inputDevicesAvailable = mInputDeviceDelegate.vibrateIfAvailable(
vib.uid, vib.opPkg, vib.getEffect(), vib.reason, vib.attrs);
vib.callerInfo, vib.getEffect());
if (inputDevicesAvailable) {
return Vibration.Status.FORWARDED_TO_INPUT_DEVICES;
}
@@ -704,8 +695,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.uid, vib.attrs.getUsage()));
new Vibration.EndInfo(Vibration.Status.IGNORED_SUPERSEDED, vib.callerInfo));
mNextVibration = conductor;
return Vibration.Status.RUNNING;
} finally {
@@ -718,7 +708,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "startVibrationThreadLocked");
try {
HalVibration vib = conductor.getVibration();
int mode = startAppOpModeLocked(vib.uid, vib.opPkg, vib.attrs);
int mode = startAppOpModeLocked(vib.callerInfo);
switch (mode) {
case AppOpsManager.MODE_ALLOWED:
Trace.asyncTraceBegin(Trace.TRACE_TAG_VIBRATOR, "vibration", 0);
@@ -731,7 +721,8 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
}
return Vibration.Status.RUNNING;
case AppOpsManager.MODE_ERRORED:
Slog.w(TAG, "Start AppOpsManager operation errored for uid " + vib.uid);
Slog.w(TAG, "Start AppOpsManager operation errored for uid "
+ vib.callerInfo.uid);
return Vibration.Status.IGNORED_ERROR_APP_OPS;
default:
return Vibration.Status.IGNORED_APP_OPS;
@@ -745,7 +736,8 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
private void endVibrationLocked(HalVibration vib, Vibration.EndInfo vibrationEndInfo,
boolean shouldWriteStats) {
vib.end(vibrationEndInfo);
logVibrationStatus(vib.uid, vib.attrs, vibrationEndInfo.status);
logVibrationStatus(vib.callerInfo.uid, vib.callerInfo.attrs,
vibrationEndInfo.status);
mVibratorManagerRecords.record(vib);
if (shouldWriteStats) {
mFrameworkStatsLogger.writeVibrationReportedAsync(
@@ -817,12 +809,13 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
try {
HalVibration vib = mCurrentVibration.getVibration();
if (DEBUG) {
Slog.d(TAG, "Reporting vibration " + vib.id + " finished with " + vibrationEndInfo);
Slog.d(TAG, "Reporting vibration " + vib.id + " finished with "
+ vibrationEndInfo);
}
// DO NOT write metrics at this point, wait for the VibrationThread to report the
// vibration was released, after all cleanup. The metrics will be reported then.
endVibrationLocked(vib, vibrationEndInfo, /* shouldWriteStats= */ false);
finishAppOpModeLocked(vib.uid, vib.opPkg);
finishAppOpModeLocked(vib.callerInfo);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
}
@@ -830,7 +823,8 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
private void onSyncedVibrationComplete(long vibrationId) {
synchronized (mLock) {
if (mCurrentVibration != null && mCurrentVibration.getVibration().id == vibrationId) {
if (mCurrentVibration != null
&& mCurrentVibration.getVibration().id == vibrationId) {
if (DEBUG) {
Slog.d(TAG, "Synced vibration " + vibrationId + " complete, notifying thread");
}
@@ -841,7 +835,8 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
private void onVibrationComplete(int vibratorId, long vibrationId) {
synchronized (mLock) {
if (mCurrentVibration != null && mCurrentVibration.getVibration().id == vibrationId) {
if (mCurrentVibration != null
&& mCurrentVibration.getVibration().id == vibrationId) {
if (DEBUG) {
Slog.d(TAG, "Vibration " + vibrationId + " on vibrator " + vibratorId
+ " complete, notifying thread");
@@ -871,8 +866,8 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
return null;
}
int currentUsage = currentVibration.attrs.getUsage();
int newUsage = vib.attrs.getUsage();
int currentUsage = currentVibration.callerInfo.attrs.getUsage();
int newUsage = vib.callerInfo.attrs.getUsage();
if (getVibrationImportance(currentUsage) > getVibrationImportance(newUsage)) {
// Current vibration has higher importance than this one and should not be cancelled.
return Vibration.Status.IGNORED_FOR_HIGHER_IMPORTANCE;
@@ -916,15 +911,13 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
*/
@GuardedBy("mLock")
@Nullable
private Vibration.Status shouldIgnoreVibrationLocked(int uid, int displayId, String opPkg,
VibrationAttributes attrs) {
Vibration.Status statusFromSettings = mVibrationSettings.shouldIgnoreVibration(uid,
displayId, attrs);
private Vibration.Status shouldIgnoreVibrationLocked(Vibration.CallerInfo callerInfo) {
Vibration.Status statusFromSettings = mVibrationSettings.shouldIgnoreVibration(callerInfo);
if (statusFromSettings != null) {
return statusFromSettings;
}
int mode = checkAppOpModeLocked(uid, opPkg, attrs);
int mode = checkAppOpModeLocked(callerInfo);
if (mode != AppOpsManager.MODE_ALLOWED) {
if (mode == AppOpsManager.MODE_ERRORED) {
// We might be getting calls from within system_server, so we don't actually
@@ -948,7 +941,8 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
* started with the same token can be cancelled with it.
*/
private boolean shouldCancelVibration(HalVibration vib, int usageFilter, IBinder token) {
return (vib.token == token) && shouldCancelVibration(vib.attrs, usageFilter);
return (vib.callerToken == token) && shouldCancelVibration(vib.callerInfo.attrs,
usageFilter);
}
/**
@@ -973,24 +967,25 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
* {@code attrs}. This will return one of the AppOpsManager.MODE_*.
*/
@GuardedBy("mLock")
private int checkAppOpModeLocked(int uid, String opPkg, VibrationAttributes attrs) {
private int checkAppOpModeLocked(Vibration.CallerInfo callerInfo) {
int mode = mAppOps.checkAudioOpNoThrow(AppOpsManager.OP_VIBRATE,
attrs.getAudioUsage(), uid, opPkg);
int fixedMode = fixupAppOpModeLocked(mode, attrs);
callerInfo.attrs.getAudioUsage(), callerInfo.uid, callerInfo.opPkg);
int fixedMode = fixupAppOpModeLocked(mode, callerInfo.attrs);
if (mode != fixedMode && fixedMode == AppOpsManager.MODE_ALLOWED) {
// If we're just ignoring the vibration op then this is set by DND and we should ignore
// if we're asked to bypass. AppOps won't be able to record this operation, so make
// sure we at least note it in the logs for debugging.
Slog.d(TAG, "Bypassing DND for vibrate from uid " + uid);
Slog.d(TAG, "Bypassing DND for vibrate from uid " + callerInfo.uid);
}
return fixedMode;
}
/** Start an operation in {@link AppOpsManager}, if allowed. */
@GuardedBy("mLock")
private int startAppOpModeLocked(int uid, String opPkg, VibrationAttributes attrs) {
private int startAppOpModeLocked(Vibration.CallerInfo callerInfo) {
return fixupAppOpModeLocked(
mAppOps.startOpNoThrow(AppOpsManager.OP_VIBRATE, uid, opPkg), attrs);
mAppOps.startOpNoThrow(AppOpsManager.OP_VIBRATE, callerInfo.uid, callerInfo.opPkg),
callerInfo.attrs);
}
/**
@@ -998,8 +993,8 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
* operation with same uid was previously started.
*/
@GuardedBy("mLock")
private void finishAppOpModeLocked(int uid, String opPkg) {
mAppOps.finishOp(AppOpsManager.OP_VIBRATE, uid, opPkg);
private void finishAppOpModeLocked(Vibration.CallerInfo callerInfo) {
mAppOps.finishOp(AppOpsManager.OP_VIBRATE, callerInfo.uid, callerInfo.opPkg);
}
/**
@@ -1186,8 +1181,8 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
return false;
}
HalVibration vib = conductor.getVibration();
return mVibrationSettings.shouldCancelVibrationOnScreenOff(
vib.uid, vib.opPkg, vib.attrs.getUsage(), vib.stats().getCreateUptimeMillis());
return mVibrationSettings.shouldCancelVibrationOnScreenOff(vib.callerInfo,
vib.stats.getCreateUptimeMillis());
}
@GuardedBy("mLock")
@@ -1385,31 +1380,33 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
*/
private static final class AlwaysOnVibration {
public final int alwaysOnId;
public final int uid;
public final String opPkg;
public final VibrationAttributes attrs;
public final Vibration.CallerInfo callerInfo;
public final SparseArray<PrebakedSegment> effects;
AlwaysOnVibration(int alwaysOnId, int uid, String opPkg, VibrationAttributes attrs,
AlwaysOnVibration(int alwaysOnId, Vibration.CallerInfo callerInfo,
SparseArray<PrebakedSegment> effects) {
this.alwaysOnId = alwaysOnId;
this.uid = uid;
this.opPkg = opPkg;
this.attrs = attrs;
this.callerInfo = callerInfo;
this.effects = effects;
}
}
/** Holder for a {@link ExternalVibration}. */
private final class ExternalVibrationHolder implements IBinder.DeathRecipient {
private final class ExternalVibrationHolder extends Vibration implements
IBinder.DeathRecipient {
public final ExternalVibration externalVibration;
public final VibrationStats stats = new VibrationStats();
public int scale;
private Vibration.Status mStatus;
private ExternalVibrationHolder(ExternalVibration externalVibration) {
super(externalVibration.getToken(), new Vibration.CallerInfo(
externalVibration.getVibrationAttributes(), externalVibration.getUid(),
// TODO(b/243604888): propagating displayID from IExternalVibration instead of
// using INVALID_DISPLAY for all external vibrations.
Display.INVALID_DISPLAY,
externalVibration.getPackage(), null));
this.externalVibration = externalVibration;
this.scale = IExternalVibratorService.SCALE_NONE;
mStatus = Vibration.Status.RUNNING;
@@ -1437,14 +1434,15 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
return;
}
mStatus = info.status;
stats.reportEnded(info.endedByUid, info.endedByUsage);
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());
stats.reportVibratorOn(
stats.getEndUptimeMillis() - stats.getStartUptimeMillis());
}
}
@@ -1462,13 +1460,8 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
}
public Vibration.DebugInfo getDebugInfo() {
return new Vibration.DebugInfo(
mStatus, stats, /* effect= */ null, /* originalEffect= */ null, scale,
externalVibration.getVibrationAttributes(), externalVibration.getUid(),
// TODO(b/243604888): propagating displayID from IExternalVibration instead of
// using INVALID_DISPLAY for all external vibrations.
Display.INVALID_DISPLAY,
externalVibration.getPackage(), /* reason= */ null);
return new Vibration.DebugInfo(mStatus, stats, /* effect= */ null,
/* originalEffect= */ null, scale, callerInfo);
}
public VibrationStats.StatsInfo getStatsInfo(long completionUptimeMillis) {
@@ -1538,7 +1531,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
}
synchronized void record(HalVibration vib) {
int usage = vib.attrs.getUsage();
int usage = vib.callerInfo.attrs.getUsage();
if (!mPreviousVibrations.contains(usage)) {
mPreviousVibrations.put(usage, new LinkedList<>());
}
@@ -1679,8 +1672,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
synchronized (mLock) {
// TODO(b/243604888): propagating displayID from IExternalVibration instead of
// using INVALID_DISPLAY for all external vibrations.
Vibration.Status ignoreStatus = shouldIgnoreVibrationLocked(
vib.getUid(), Display.INVALID_DISPLAY, vib.getPackage(), attrs);
Vibration.Status ignoreStatus = shouldIgnoreVibrationLocked(vibHolder.callerInfo);
if (ignoreStatus != null) {
vibHolder.scale = IExternalVibratorService.SCALE_MUTE;
// Failed to start the vibration, end it and report metrics right away.
@@ -1698,13 +1690,13 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
// vibration that may be playing and ready the vibrator for external control.
if (mCurrentVibration != null) {
vibHolder.stats.reportInterruptedAnotherVibration(
mCurrentVibration.getVibration().attrs.getUsage());
mCurrentVibration.getVibration().callerInfo);
clearNextVibrationLocked(
new Vibration.EndInfo(Vibration.Status.IGNORED_FOR_EXTERNAL,
vib.getUid(), attrs.getUsage()));
vibHolder.callerInfo));
mCurrentVibration.notifyCancelled(
new Vibration.EndInfo(Vibration.Status.CANCELLED_SUPERSEDED,
vib.getUid(), attrs.getUsage()),
vibHolder.callerInfo),
/* immediate= */ true);
waitForCompletion = true;
}
@@ -1720,11 +1712,10 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
alreadyUnderExternalControl = true;
mCurrentExternalVibration.mute();
vibHolder.stats.reportInterruptedAnotherVibration(
mCurrentExternalVibration.externalVibration
.getVibrationAttributes().getUsage());
mCurrentExternalVibration.callerInfo);
endExternalVibrateLocked(
new Vibration.EndInfo(Vibration.Status.CANCELLED_SUPERSEDED,
vib.getUid(), attrs.getUsage()),
vibHolder.callerInfo),
/* continueExternalControl= */ true);
}
mCurrentExternalVibration = vibHolder;

View File

@@ -263,7 +263,8 @@ public class InputDeviceDelegateTest {
public void vibrateIfAvailable_withNoInputDevice_returnsFalse() {
assertFalse(mInputDeviceDelegate.isAvailable());
assertFalse(mInputDeviceDelegate.vibrateIfAvailable(
UID, PACKAGE_NAME, SYNCED_EFFECT, REASON, VIBRATION_ATTRIBUTES));
new Vibration.CallerInfo(VIBRATION_ATTRIBUTES, UID, -1, PACKAGE_NAME, REASON),
SYNCED_EFFECT));
}
@Test
@@ -277,7 +278,8 @@ public class InputDeviceDelegateTest {
mInputDeviceDelegate.updateInputDeviceVibrators(/* vibrateInputDevices= */ true);
assertTrue(mInputDeviceDelegate.vibrateIfAvailable(
UID, PACKAGE_NAME, SYNCED_EFFECT, REASON, VIBRATION_ATTRIBUTES));
new Vibration.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());
}

View File

@@ -564,17 +564,17 @@ public class VibrationSettingsTest {
for (int usage : ALL_USAGES) {
// Non-system vibration
assertFalse(mVibrationSettings.shouldCancelVibrationOnScreenOff(
UID, "some.app", usage, vibrateStartTime));
assertFalse(mVibrationSettings.shouldCancelVibrationOnScreenOff(createCallerInfo(
UID, "some.app", usage), vibrateStartTime));
// Vibration with UID zero
assertFalse(mVibrationSettings.shouldCancelVibrationOnScreenOff(
/* uid= */ 0, "", usage, vibrateStartTime));
createCallerInfo(/* uid= */ 0, "", usage), vibrateStartTime));
// System vibration
assertFalse(mVibrationSettings.shouldCancelVibrationOnScreenOff(
Process.SYSTEM_UID, "", usage, vibrateStartTime));
createCallerInfo(Process.SYSTEM_UID, "", usage), vibrateStartTime));
// SysUI vibration
assertFalse(mVibrationSettings.shouldCancelVibrationOnScreenOff(
UID, SYSUI_PACKAGE_NAME, usage, vibrateStartTime));
createCallerInfo(UID, SYSUI_PACKAGE_NAME, usage), vibrateStartTime));
}
}
@@ -592,16 +592,16 @@ public class VibrationSettingsTest {
for (int usage : ALL_USAGES) {
// Non-system vibration
assertFalse(mVibrationSettings.shouldCancelVibrationOnScreenOff(
UID, "some.app", usage, vibrateStartTime));
createCallerInfo(UID, "some.app", usage), vibrateStartTime));
// Vibration with UID zero
assertFalse(mVibrationSettings.shouldCancelVibrationOnScreenOff(
/* uid= */ 0, "", usage, vibrateStartTime));
createCallerInfo(/* uid= */ 0, "", usage), vibrateStartTime));
// System vibration
assertFalse(mVibrationSettings.shouldCancelVibrationOnScreenOff(
Process.SYSTEM_UID, "", usage, vibrateStartTime));
createCallerInfo(Process.SYSTEM_UID, "", usage), vibrateStartTime));
// SysUI vibration
assertFalse(mVibrationSettings.shouldCancelVibrationOnScreenOff(
UID, SYSUI_PACKAGE_NAME, usage, vibrateStartTime));
createCallerInfo(UID, SYSUI_PACKAGE_NAME, usage), vibrateStartTime));
}
}
}
@@ -613,7 +613,7 @@ public class VibrationSettingsTest {
for (int usage : ALL_USAGES) {
assertTrue(mVibrationSettings.shouldCancelVibrationOnScreenOff(
UID, "some.app", usage, vibrateStartTime));
createCallerInfo(UID, "some.app", usage), vibrateStartTime));
}
}
@@ -626,10 +626,10 @@ public class VibrationSettingsTest {
if (usage == USAGE_TOUCH || usage == USAGE_HARDWARE_FEEDBACK
|| usage == USAGE_PHYSICAL_EMULATION) {
assertFalse(mVibrationSettings.shouldCancelVibrationOnScreenOff(
/* uid= */ 0, "", usage, vibrateStartTime));
createCallerInfo(/* uid= */ 0, "", usage), vibrateStartTime));
} else {
assertTrue(mVibrationSettings.shouldCancelVibrationOnScreenOff(
/* uid= */ 0, "", usage, vibrateStartTime));
createCallerInfo(/* uid= */ 0, "", usage), vibrateStartTime));
}
}
}
@@ -643,10 +643,10 @@ public class VibrationSettingsTest {
if (usage == USAGE_TOUCH || usage == USAGE_HARDWARE_FEEDBACK
|| usage == USAGE_PHYSICAL_EMULATION) {
assertFalse(mVibrationSettings.shouldCancelVibrationOnScreenOff(
Process.SYSTEM_UID, "", usage, vibrateStartTime));
createCallerInfo(Process.SYSTEM_UID, "", usage), vibrateStartTime));
} else {
assertTrue(mVibrationSettings.shouldCancelVibrationOnScreenOff(
Process.SYSTEM_UID, "", usage, vibrateStartTime));
createCallerInfo(Process.SYSTEM_UID, "", usage), vibrateStartTime));
}
}
}
@@ -660,10 +660,10 @@ public class VibrationSettingsTest {
if (usage == USAGE_TOUCH || usage == USAGE_HARDWARE_FEEDBACK
|| usage == USAGE_PHYSICAL_EMULATION) {
assertFalse(mVibrationSettings.shouldCancelVibrationOnScreenOff(
UID, SYSUI_PACKAGE_NAME, usage, vibrateStartTime));
createCallerInfo(UID, SYSUI_PACKAGE_NAME, usage), vibrateStartTime));
} else {
assertTrue(mVibrationSettings.shouldCancelVibrationOnScreenOff(
UID, SYSUI_PACKAGE_NAME, usage, vibrateStartTime));
createCallerInfo(UID, SYSUI_PACKAGE_NAME, usage), vibrateStartTime));
}
}
}
@@ -755,10 +755,10 @@ public class VibrationSettingsTest {
private void assertVibrationIgnoredForUsageAndDisplay(@VibrationAttributes.Usage int usage,
int displayId, Vibration.Status expectedStatus) {
assertEquals(errorMessageForUsage(usage),
expectedStatus,
mVibrationSettings.shouldIgnoreVibration(UID, displayId,
VibrationAttributes.createForUsage(usage)));
Vibration.CallerInfo callerInfo = new Vibration.CallerInfo(
VibrationAttributes.createForUsage(usage), UID, displayId, null, null);
assertEquals(errorMessageForUsage(usage), expectedStatus,
mVibrationSettings.shouldIgnoreVibration(callerInfo));
}
private void assertVibrationNotIgnoredForUsage(@VibrationAttributes.Usage int usage) {
@@ -767,24 +767,22 @@ public class VibrationSettingsTest {
private void assertVibrationNotIgnoredForUsageAndFlags(@VibrationAttributes.Usage int usage,
@VibrationAttributes.Flag int flags) {
assertVibrationNotIgnoredForUsageAndFlagsAndDidsplay(usage, Display.DEFAULT_DISPLAY, flags);
assertVibrationNotIgnoredForUsageAndFlagsAndDisplay(usage, Display.DEFAULT_DISPLAY, flags);
}
private void assertVibrationNotIgnoredForUsageAndDisplay(@VibrationAttributes.Usage int usage,
int displayId) {
assertVibrationNotIgnoredForUsageAndFlagsAndDidsplay(usage, displayId, /* flags= */ 0);
assertVibrationNotIgnoredForUsageAndFlagsAndDisplay(usage, displayId, /* flags= */ 0);
}
private void assertVibrationNotIgnoredForUsageAndFlagsAndDidsplay(
private void assertVibrationNotIgnoredForUsageAndFlagsAndDisplay(
@VibrationAttributes.Usage int usage, int displayId,
@VibrationAttributes.Flag int flags) {
Vibration.CallerInfo callerInfo = new Vibration.CallerInfo(
new VibrationAttributes.Builder().setUsage(usage).setFlags(flags).build(), UID,
displayId, null, null);
assertNull(errorMessageForUsage(usage),
mVibrationSettings.shouldIgnoreVibration(UID,
displayId,
new VibrationAttributes.Builder()
.setUsage(usage)
.setFlags(flags)
.build()));
mVibrationSettings.shouldIgnoreVibration(callerInfo));
}
@@ -826,4 +824,10 @@ public class VibrationSettingsTest {
when(mPowerManagerInternalMock.getLastGoToSleep()).thenReturn(
new PowerManager.SleepData(sleepTime, reason));
}
private Vibration.CallerInfo createCallerInfo(int uid, String opPkg,
@VibrationAttributes.Usage int usage) {
VibrationAttributes attrs = VibrationAttributes.createForUsage(usage);
return new Vibration.CallerInfo(attrs, uid, VIRTUAL_DISPLAY_ID, opPkg, null);
}
}

View File

@@ -154,10 +154,10 @@ public class VibrationThreadTest {
@Test
public void vibrate_noVibrator_ignoresVibration() {
mVibratorProviders.clear();
long vibrationId = 1;
CombinedVibration effect = CombinedVibration.createParallel(
VibrationEffect.get(VibrationEffect.EFFECT_CLICK));
startThreadAndDispatcher(vibrationId, effect);
VibrationStepConductor conductor = startThreadAndDispatcher(effect);
long vibrationId = conductor.getVibration().id;
waitForCompletion();
verify(mControllerCallbacks, never()).onComplete(anyInt(), eq(vibrationId));
@@ -166,12 +166,12 @@ public class VibrationThreadTest {
@Test
public void vibrate_missingVibrators_ignoresVibration() {
long vibrationId = 1;
CombinedVibration effect = CombinedVibration.startSequential()
.addNext(2, VibrationEffect.get(VibrationEffect.EFFECT_CLICK))
.addNext(3, VibrationEffect.get(VibrationEffect.EFFECT_TICK))
.combine();
startThreadAndDispatcher(vibrationId, effect);
VibrationStepConductor conductor = startThreadAndDispatcher(effect);
long vibrationId = conductor.getVibration().id;
waitForCompletion();
verify(mControllerCallbacks, never()).onComplete(anyInt(), eq(vibrationId));
@@ -182,9 +182,9 @@ public class VibrationThreadTest {
public void vibrate_singleVibratorOneShot_runsVibrationAndSetsAmplitude() throws Exception {
mVibratorProviders.get(VIBRATOR_ID).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL);
long vibrationId = 1;
VibrationEffect effect = VibrationEffect.createOneShot(10, 100);
startThreadAndDispatcher(vibrationId, effect);
VibrationStepConductor conductor = startThreadAndDispatcher(effect);
long vibrationId = conductor.getVibration().id;
waitForCompletion();
verify(mManagerHooks).noteVibratorOn(eq(UID), eq(10L));
@@ -201,9 +201,9 @@ public class VibrationThreadTest {
@Test
public void vibrate_oneShotWithoutAmplitudeControl_runsVibrationWithDefaultAmplitude()
throws Exception {
long vibrationId = 1;
VibrationEffect effect = VibrationEffect.createOneShot(10, 100);
startThreadAndDispatcher(vibrationId, effect);
VibrationStepConductor conductor = startThreadAndDispatcher(effect);
long vibrationId = conductor.getVibration().id;
waitForCompletion();
verify(mManagerHooks).noteVibratorOn(eq(UID), eq(10L));
@@ -222,10 +222,10 @@ public class VibrationThreadTest {
throws Exception {
mVibratorProviders.get(VIBRATOR_ID).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL);
long vibrationId = 1;
VibrationEffect effect = VibrationEffect.createWaveform(
new long[]{5, 5, 5}, new int[]{1, 2, 3}, -1);
startThreadAndDispatcher(vibrationId, effect);
VibrationStepConductor conductor = startThreadAndDispatcher(effect);
long vibrationId = conductor.getVibration().id;
waitForCompletion();
verify(mManagerHooks).noteVibratorOn(eq(UID), eq(15L));
@@ -246,10 +246,10 @@ public class VibrationThreadTest {
FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(VIBRATOR_ID);
fakeVibrator.setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL);
long vibrationId = 1;
int[] amplitudes = new int[]{1, 2, 3};
VibrationEffect effect = VibrationEffect.createWaveform(new long[]{5, 5, 5}, amplitudes, 0);
VibrationStepConductor conductor = startThreadAndDispatcher(vibrationId, effect);
VibrationStepConductor conductor = startThreadAndDispatcher(effect);
long vibrationId = conductor.getVibration().id;
assertTrue(
waitUntil(() -> fakeVibrator.getAmplitudes().size() > 2 * amplitudes.length,
@@ -259,8 +259,9 @@ public class VibrationThreadTest {
assertTrue(mControllers.get(VIBRATOR_ID).isVibrating());
Vibration.EndInfo cancelVibrationInfo = new Vibration.EndInfo(
Vibration.Status.CANCELLED_SUPERSEDED, /* endedByUid= */ 1,
/* endedByUsage= */ VibrationAttributes.USAGE_ALARM);
Vibration.Status.CANCELLED_SUPERSEDED, new Vibration.CallerInfo(
VibrationAttributes.createForUsage(VibrationAttributes.USAGE_ALARM), /* uid= */
1, /* displayId= */ -1, /* opPkg= */ null, /* reason= */ null));
conductor.notifyCancelled(
cancelVibrationInfo,
/* immediate= */ false);
@@ -287,11 +288,11 @@ public class VibrationThreadTest {
FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(VIBRATOR_ID);
fakeVibrator.setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL);
long vibrationId = 1;
int[] amplitudes = new int[]{1, 2, 3};
VibrationEffect effect = VibrationEffect.createWaveform(
new long[]{1, 10, 100}, amplitudes, 0);
VibrationStepConductor conductor = startThreadAndDispatcher(vibrationId, effect);
VibrationStepConductor conductor = startThreadAndDispatcher(effect);
long vibrationId = conductor.getVibration().id;
assertTrue(waitUntil(() -> !fakeVibrator.getAmplitudes().isEmpty(), TEST_TIMEOUT_MILLIS));
conductor.notifyCancelled(
@@ -315,7 +316,6 @@ public class VibrationThreadTest {
fakeVibrator.setMaxAmplitudes(1, 1, 1);
fakeVibrator.setPwleSizeMax(10);
long vibrationId = 1;
VibrationEffect effect = VibrationEffect.startWaveform(targetAmplitude(1))
// Very long segment so thread will be cancelled after first PWLE is triggered.
.addTransition(Duration.ofMillis(100), targetFrequency(100))
@@ -323,7 +323,8 @@ public class VibrationThreadTest {
VibrationEffect repeatingEffect = VibrationEffect.startComposition()
.repeatEffectIndefinitely(effect)
.compose();
VibrationStepConductor conductor = startThreadAndDispatcher(vibrationId, repeatingEffect);
VibrationStepConductor conductor = startThreadAndDispatcher(repeatingEffect);
long vibrationId = conductor.getVibration().id;
assertTrue(waitUntil(() -> !fakeVibrator.getEffectSegments(vibrationId).isEmpty(),
TEST_TIMEOUT_MILLIS));
@@ -346,7 +347,6 @@ public class VibrationThreadTest {
fakeVibrator.setSupportedPrimitives(VibrationEffect.Composition.PRIMITIVE_CLICK);
fakeVibrator.setCompositionSizeMax(10);
long vibrationId = 1;
VibrationEffect effect = VibrationEffect.startComposition()
// Very long delay so thread will be cancelled after first PWLE is triggered.
.addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1f, 100)
@@ -354,7 +354,8 @@ public class VibrationThreadTest {
VibrationEffect repeatingEffect = VibrationEffect.startComposition()
.repeatEffectIndefinitely(effect)
.compose();
VibrationStepConductor conductor = startThreadAndDispatcher(vibrationId, repeatingEffect);
VibrationStepConductor conductor = startThreadAndDispatcher(repeatingEffect);
long vibrationId = conductor.getVibration().id;
assertTrue(waitUntil(() -> !fakeVibrator.getEffectSegments(vibrationId).isEmpty(),
TEST_TIMEOUT_MILLIS));
@@ -375,11 +376,11 @@ public class VibrationThreadTest {
FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(VIBRATOR_ID);
fakeVibrator.setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL);
long vibrationId = 1;
int[] amplitudes = new int[]{1, 2, 3};
VibrationEffect effect = VibrationEffect.createWaveform(
new long[]{5000, 500, 50}, amplitudes, 0);
VibrationStepConductor conductor = startThreadAndDispatcher(vibrationId, effect);
VibrationStepConductor conductor = startThreadAndDispatcher(effect);
long vibrationId = conductor.getVibration().id;
assertTrue(waitUntil(() -> !fakeVibrator.getAmplitudes().isEmpty(), TEST_TIMEOUT_MILLIS));
conductor.notifyCancelled(
@@ -400,11 +401,11 @@ public class VibrationThreadTest {
FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(VIBRATOR_ID);
fakeVibrator.setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL);
long vibrationId = 1;
int[] amplitudes = new int[]{1, 2};
VibrationEffect effect = VibrationEffect.createWaveform(
new long[]{4900, 50}, amplitudes, 0);
VibrationStepConductor conductor = startThreadAndDispatcher(vibrationId, effect);
VibrationStepConductor conductor = startThreadAndDispatcher(effect);
long vibrationId = conductor.getVibration().id;
assertTrue(waitUntil(() -> fakeVibrator.getEffectSegments(vibrationId).size() > 1,
5000 + TEST_TIMEOUT_MILLIS));
@@ -433,13 +434,13 @@ public class VibrationThreadTest {
mVibratorProviders.get(VIBRATOR_ID).setSupportedPrimitives(
VibrationEffect.Composition.PRIMITIVE_CLICK);
long vibrationId = 1;
VibrationEffect effect = VibrationEffect.startComposition()
.addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1f, 100)
.addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1f, 100)
.addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1f, 100)
.compose();
VibrationStepConductor conductor = startThreadAndDispatcher(vibrationId, effect);
VibrationStepConductor conductor = startThreadAndDispatcher(effect);
long vibrationId = conductor.getVibration().id;
assertTrue(waitUntil(() -> mControllers.get(VIBRATOR_ID).isVibrating(),
TEST_TIMEOUT_MILLIS));
@@ -466,9 +467,9 @@ public class VibrationThreadTest {
throws Exception {
mVibratorProviders.get(VIBRATOR_ID).setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS);
long vibrationId = 1;
VibrationEffect effect = VibrationEffect.createWaveform(new long[]{100}, new int[]{100}, 0);
VibrationStepConductor conductor = startThreadAndDispatcher(vibrationId, effect);
VibrationStepConductor conductor = startThreadAndDispatcher(effect);
long vibrationId = conductor.getVibration().id;
assertTrue(waitUntil(() -> mControllers.get(VIBRATOR_ID).isVibrating(),
TEST_TIMEOUT_MILLIS));
@@ -494,9 +495,9 @@ public class VibrationThreadTest {
public void vibrate_singleVibratorPrebaked_runsVibration() throws Exception {
mVibratorProviders.get(1).setSupportedEffects(VibrationEffect.EFFECT_THUD);
long vibrationId = 1;
VibrationEffect effect = VibrationEffect.get(VibrationEffect.EFFECT_THUD);
startThreadAndDispatcher(vibrationId, effect);
VibrationStepConductor conductor = startThreadAndDispatcher(effect);
long vibrationId = conductor.getVibration().id;
waitForCompletion();
verify(mManagerHooks).noteVibratorOn(eq(UID), eq(20L));
@@ -514,12 +515,12 @@ public class VibrationThreadTest {
throws Exception {
mVibratorProviders.get(VIBRATOR_ID).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL);
long vibrationId = 1;
VibrationEffect fallback = VibrationEffect.createOneShot(10, 100);
HalVibration vibration = createVibration(vibrationId, CombinedVibration.createParallel(
HalVibration vibration = createVibration(CombinedVibration.createParallel(
VibrationEffect.get(VibrationEffect.EFFECT_CLICK)));
vibration.addFallback(VibrationEffect.EFFECT_CLICK, fallback);
startThreadAndDispatcher(vibration);
VibrationStepConductor conductor = startThreadAndDispatcher(vibration);
long vibrationId = conductor.getVibration().id;
waitForCompletion();
verify(mManagerHooks).noteVibratorOn(eq(UID), eq(10L));
@@ -536,9 +537,9 @@ public class VibrationThreadTest {
@Test
public void vibrate_singleVibratorPrebakedAndUnsupportedEffect_ignoresVibration()
throws Exception {
long vibrationId = 1;
VibrationEffect effect = VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
startThreadAndDispatcher(vibrationId, effect);
VibrationStepConductor conductor = startThreadAndDispatcher(effect);
long vibrationId = conductor.getVibration().id;
waitForCompletion();
verify(mManagerHooks).noteVibratorOn(eq(UID), eq(0L));
@@ -555,12 +556,12 @@ public class VibrationThreadTest {
fakeVibrator.setSupportedPrimitives(VibrationEffect.Composition.PRIMITIVE_CLICK,
VibrationEffect.Composition.PRIMITIVE_TICK);
long vibrationId = 1;
VibrationEffect effect = VibrationEffect.startComposition()
.addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1f)
.addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK, 0.5f)
.compose();
startThreadAndDispatcher(vibrationId, effect);
VibrationStepConductor conductor = startThreadAndDispatcher(effect);
long vibrationId = conductor.getVibration().id;
waitForCompletion();
verify(mManagerHooks).noteVibratorOn(eq(UID), eq(40L));
@@ -576,11 +577,11 @@ public class VibrationThreadTest {
@Test
public void vibrate_singleVibratorComposedAndNoCapability_ignoresVibration() {
long vibrationId = 1;
VibrationEffect effect = VibrationEffect.startComposition()
.addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1f)
.compose();
startThreadAndDispatcher(vibrationId, effect);
VibrationStepConductor conductor = startThreadAndDispatcher(effect);
long vibrationId = conductor.getVibration().id;
waitForCompletion();
verify(mManagerHooks).noteVibratorOn(eq(UID), eq(0L));
@@ -600,13 +601,13 @@ public class VibrationThreadTest {
VibrationEffect.Composition.PRIMITIVE_SPIN);
fakeVibrator.setCompositionSizeMax(2);
long vibrationId = 1;
VibrationEffect effect = VibrationEffect.startComposition()
.addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1f)
.addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK, 0.5f)
.addPrimitive(VibrationEffect.Composition.PRIMITIVE_SPIN, 0.8f)
.compose();
startThreadAndDispatcher(vibrationId, effect);
VibrationStepConductor conductor = startThreadAndDispatcher(effect);
long vibrationId = conductor.getVibration().id;
waitForCompletion();
verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
@@ -630,7 +631,6 @@ public class VibrationThreadTest {
fakeVibrator.setMaxAmplitudes(
0.5f /* 100Hz*/, 1 /* 150Hz */, 0.6f /* 200Hz */);
long vibrationId = 1;
VibrationEffect effect = VibrationEffect.startComposition()
.addEffect(VibrationEffect.createOneShot(10, 100))
.addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1f)
@@ -643,7 +643,8 @@ public class VibrationThreadTest {
.build())
.addEffect(VibrationEffect.get(VibrationEffect.EFFECT_CLICK))
.compose();
startThreadAndDispatcher(vibrationId, effect);
VibrationStepConductor conductor = startThreadAndDispatcher(effect);
long vibrationId = conductor.getVibration().id;
waitForCompletion();
// Use first duration the vibrator is turned on since we cannot estimate the clicks.
@@ -675,7 +676,6 @@ public class VibrationThreadTest {
VibrationEffect.Composition.PRIMITIVE_TICK);
fakeVibrator.setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS);
long vibrationId = 1;
VibrationEffect fallback = VibrationEffect.createOneShot(10, 100);
VibrationEffect effect = VibrationEffect.startComposition()
.addEffect(VibrationEffect.get(VibrationEffect.EFFECT_CLICK))
@@ -683,9 +683,10 @@ public class VibrationThreadTest {
.addEffect(VibrationEffect.get(VibrationEffect.EFFECT_TICK))
.addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK, 0.5f)
.compose();
HalVibration vib = createVibration(vibrationId, CombinedVibration.createParallel(effect));
HalVibration vib = createVibration(CombinedVibration.createParallel(effect));
vib.addFallback(VibrationEffect.EFFECT_TICK, fallback);
startThreadAndDispatcher(vib);
VibrationStepConductor conductor = startThreadAndDispatcher(vib);
long vibrationId = conductor.getVibration().id;
waitForCompletion();
// Use first duration the vibrator is turned on since we cannot estimate the clicks.
@@ -718,7 +719,6 @@ public class VibrationThreadTest {
fakeVibrator.setMaxAmplitudes(
0.5f /* 100Hz*/, 1 /* 150Hz */, 0.6f /* 200Hz */);
long vibrationId = 1;
VibrationEffect effect = VibrationEffect.startWaveform(targetAmplitude(1))
.addSustain(Duration.ofMillis(10))
.addTransition(Duration.ofMillis(20), targetAmplitude(0))
@@ -726,7 +726,8 @@ public class VibrationThreadTest {
.addSustain(Duration.ofMillis(30))
.addTransition(Duration.ofMillis(40), targetAmplitude(0.6f), targetFrequency(200))
.build();
startThreadAndDispatcher(vibrationId, effect);
VibrationStepConductor conductor = startThreadAndDispatcher(effect);
long vibrationId = conductor.getVibration().id;
waitForCompletion();
verify(mManagerHooks).noteVibratorOn(eq(UID), eq(100L));
@@ -756,7 +757,6 @@ public class VibrationThreadTest {
fakeVibrator.setMaxAmplitudes(1, 1, 1);
fakeVibrator.setPwleSizeMax(3);
long vibrationId = 1;
VibrationEffect effect = VibrationEffect.startWaveform(targetAmplitude(1))
.addSustain(Duration.ofMillis(10))
.addTransition(Duration.ofMillis(20), targetAmplitude(0))
@@ -768,7 +768,8 @@ public class VibrationThreadTest {
.addTransition(Duration.ofMillis(40), targetAmplitude(0.7f), targetFrequency(200))
.addTransition(Duration.ofMillis(40), targetAmplitude(0.6f), targetFrequency(200))
.build();
startThreadAndDispatcher(vibrationId, effect);
VibrationStepConductor conductor = startThreadAndDispatcher(effect);
long vibrationId = conductor.getVibration().id;
waitForCompletion();
verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
@@ -784,9 +785,9 @@ public class VibrationThreadTest {
FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(VIBRATOR_ID);
fakeVibrator.setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL);
long vibrationId = 1;
VibrationEffect effect = VibrationEffect.createWaveform(new long[]{5}, new int[]{100}, 0);
VibrationStepConductor conductor = startThreadAndDispatcher(vibrationId, effect);
VibrationStepConductor conductor = startThreadAndDispatcher(effect);
long vibrationId = conductor.getVibration().id;
assertTrue(waitUntil(() -> fakeVibrator.getAmplitudes().size() > 2, TEST_TIMEOUT_MILLIS));
// Vibration still running after 2 cycles.
@@ -804,9 +805,9 @@ public class VibrationThreadTest {
public void vibrate_singleVibrator_skipsSyncedCallbacks() {
mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL);
long vibrationId = 1;
startThreadAndDispatcher(vibrationId,
VibrationStepConductor conductor = startThreadAndDispatcher(
VibrationEffect.createOneShot(10, 100));
long vibrationId = conductor.getVibration().id;
waitForCompletion();
verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
@@ -820,12 +821,12 @@ public class VibrationThreadTest {
throws Exception {
mVibratorProviders.get(1).setSupportedEffects(VibrationEffect.EFFECT_TICK);
long vibrationId = 1;
CombinedVibration effect = CombinedVibration.startParallel()
.addVibrator(VIBRATOR_ID, VibrationEffect.get(VibrationEffect.EFFECT_TICK))
.addVibrator(2, VibrationEffect.get(VibrationEffect.EFFECT_TICK))
.combine();
startThreadAndDispatcher(vibrationId, effect);
VibrationStepConductor conductor = startThreadAndDispatcher(effect);
long vibrationId = conductor.getVibration().id;
waitForCompletion();
verify(mManagerHooks).noteVibratorOn(eq(UID), eq(20L));
@@ -846,10 +847,10 @@ public class VibrationThreadTest {
mVibratorProviders.get(2).setSupportedEffects(VibrationEffect.EFFECT_CLICK);
mVibratorProviders.get(3).setSupportedEffects(VibrationEffect.EFFECT_CLICK);
long vibrationId = 1;
CombinedVibration effect = CombinedVibration.createParallel(
VibrationEffect.get(VibrationEffect.EFFECT_CLICK));
startThreadAndDispatcher(vibrationId, effect);
VibrationStepConductor conductor = startThreadAndDispatcher(effect);
long vibrationId = conductor.getVibration().id;
waitForCompletion();
verify(mManagerHooks).noteVibratorOn(eq(UID), eq(20L));
@@ -881,7 +882,6 @@ public class VibrationThreadTest {
mVibratorProviders.get(4).setSupportedPrimitives(
VibrationEffect.Composition.PRIMITIVE_CLICK);
long vibrationId = 1;
VibrationEffect composed = VibrationEffect.startComposition()
.addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK)
.compose();
@@ -892,7 +892,8 @@ public class VibrationThreadTest {
new long[]{10, 10}, new int[]{1, 2}, -1))
.addVibrator(4, composed)
.combine();
startThreadAndDispatcher(vibrationId, effect);
VibrationStepConductor conductor = startThreadAndDispatcher(effect);
long vibrationId = conductor.getVibration().id;
waitForCompletion();
verify(mManagerHooks).noteVibratorOn(eq(UID), eq(20L));
@@ -929,7 +930,6 @@ public class VibrationThreadTest {
VibrationEffect.Composition.PRIMITIVE_CLICK);
mVibratorProviders.get(3).setSupportedEffects(VibrationEffect.EFFECT_CLICK);
long vibrationId = 1;
VibrationEffect composed = VibrationEffect.startComposition()
.addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK)
.compose();
@@ -938,7 +938,8 @@ public class VibrationThreadTest {
.addNext(1, VibrationEffect.createOneShot(10, 100), /* delay= */ 50)
.addNext(2, composed, /* delay= */ 50)
.combine();
startThreadAndDispatcher(vibrationId, effect);
VibrationStepConductor conductor = startThreadAndDispatcher(effect);
long vibrationId = conductor.getVibration().id;
waitForCompletion();
InOrder controllerVerifier = inOrder(mControllerCallbacks);
@@ -972,7 +973,6 @@ public class VibrationThreadTest {
@Test
public void vibrate_multipleSyncedCallbackTriggered_finishSteps() throws Exception {
int[] vibratorIds = new int[]{1, 2};
long vibrationId = 1;
mockVibrators(vibratorIds);
mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS);
mVibratorProviders.get(1).setSupportedPrimitives(
@@ -981,13 +981,15 @@ public class VibrationThreadTest {
mVibratorProviders.get(2).setSupportedPrimitives(
VibrationEffect.Composition.PRIMITIVE_CLICK);
when(mManagerHooks.prepareSyncedVibration(anyLong(), eq(vibratorIds))).thenReturn(true);
when(mManagerHooks.triggerSyncedVibration(eq(vibrationId))).thenReturn(true);
VibrationEffect composed = VibrationEffect.startComposition()
.addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1, 100)
.compose();
CombinedVibration effect = CombinedVibration.createParallel(composed);
VibrationStepConductor conductor = startThreadAndDispatcher(vibrationId, effect);
VibrationStepConductor conductor = startThreadAndDispatcher(effect);
long vibrationId = conductor.getVibration().id;
when(mManagerHooks.triggerSyncedVibration(eq(vibrationId))).thenReturn(true);
assertTrue(waitUntil(
() -> !mVibratorProviders.get(1).getEffectSegments(vibrationId).isEmpty()
@@ -1021,7 +1023,6 @@ public class VibrationThreadTest {
when(mManagerHooks.prepareSyncedVibration(anyLong(), any())).thenReturn(true);
when(mManagerHooks.triggerSyncedVibration(anyLong())).thenReturn(true);
long vibrationId = 1;
VibrationEffect composed = VibrationEffect.startComposition()
.addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK)
.compose();
@@ -1031,7 +1032,8 @@ public class VibrationThreadTest {
.addVibrator(3, VibrationEffect.createWaveform(new long[]{10}, new int[]{100}, -1))
.addVibrator(4, composed)
.combine();
startThreadAndDispatcher(vibrationId, effect);
VibrationStepConductor conductor = startThreadAndDispatcher(effect);
long vibrationId = conductor.getVibration().id;
waitForCompletion();
long expectedCap = IVibratorManager.CAP_SYNC
@@ -1055,12 +1057,12 @@ public class VibrationThreadTest {
mVibratorProviders.get(2).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL);
when(mManagerHooks.prepareSyncedVibration(anyLong(), any())).thenReturn(false);
long vibrationId = 1;
CombinedVibration effect = CombinedVibration.startParallel()
.addVibrator(1, VibrationEffect.createOneShot(10, 100))
.addVibrator(2, VibrationEffect.createWaveform(new long[]{5}, new int[]{200}, -1))
.combine();
startThreadAndDispatcher(vibrationId, effect);
VibrationStepConductor conductor = startThreadAndDispatcher(effect);
long vibrationId = conductor.getVibration().id;
waitForCompletion();
long expectedCap = IVibratorManager.CAP_SYNC | IVibratorManager.CAP_PREPARE_ON;
@@ -1084,12 +1086,12 @@ public class VibrationThreadTest {
when(mManagerHooks.prepareSyncedVibration(anyLong(), any())).thenReturn(true);
when(mManagerHooks.triggerSyncedVibration(anyLong())).thenReturn(false);
long vibrationId = 1;
CombinedVibration effect = CombinedVibration.startParallel()
.addVibrator(1, VibrationEffect.createOneShot(10, 100))
.addVibrator(2, VibrationEffect.get(VibrationEffect.EFFECT_CLICK))
.combine();
startThreadAndDispatcher(vibrationId, effect);
VibrationStepConductor conductor = startThreadAndDispatcher(effect);
long vibrationId = conductor.getVibration().id;
waitForCompletion();
long expectedCap = IVibratorManager.CAP_SYNC
@@ -1110,7 +1112,6 @@ public class VibrationThreadTest {
mVibratorProviders.get(2).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL);
mVibratorProviders.get(3).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL);
long vibrationId = 1;
CombinedVibration effect = CombinedVibration.startParallel()
.addVibrator(1, VibrationEffect.createWaveform(
new long[]{5, 10, 10}, new int[]{1, 2, 3}, -1))
@@ -1119,7 +1120,8 @@ public class VibrationThreadTest {
.addVibrator(3, VibrationEffect.createWaveform(
new long[]{60}, new int[]{6}, -1))
.combine();
startThreadAndDispatcher(vibrationId, effect);
VibrationStepConductor conductor = startThreadAndDispatcher(effect);
long vibrationId = conductor.getVibration().id;
// All vibrators are turned on in parallel.
assertTrue(waitUntil(
@@ -1169,8 +1171,7 @@ public class VibrationThreadTest {
Arrays.fill(amplitudes, VibrationEffect.DEFAULT_AMPLITUDE);
VibrationEffect effect = VibrationEffect.createWaveform(timings, amplitudes, -1);
long vibrationId = 1;
startThreadAndDispatcher(vibrationId, effect);
startThreadAndDispatcher(effect);
long startTime = SystemClock.elapsedRealtime();
waitForCompletion(totalDuration + TEST_TIMEOUT_MILLIS);
@@ -1192,9 +1193,9 @@ public class VibrationThreadTest {
long latency = 5_000; // 5s
fakeVibrator.setOnLatency(latency);
long vibrationId = 1;
VibrationEffect effect = VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
VibrationStepConductor conductor = startThreadAndDispatcher(vibrationId, effect);
VibrationStepConductor conductor = startThreadAndDispatcher(effect);
long vibrationId = conductor.getVibration().id;
assertTrue(waitUntil(() -> !fakeVibrator.getEffectSegments(vibrationId).isEmpty(),
TEST_TIMEOUT_MILLIS));
@@ -1226,7 +1227,6 @@ public class VibrationThreadTest {
mVibratorProviders.get(2).setSupportedPrimitives(
VibrationEffect.Composition.PRIMITIVE_CLICK);
long vibrationId = 1;
CombinedVibration effect = CombinedVibration.startParallel()
.addVibrator(1, VibrationEffect.get(VibrationEffect.EFFECT_CLICK))
.addVibrator(2, VibrationEffect.startComposition()
@@ -1235,7 +1235,8 @@ public class VibrationThreadTest {
.addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1f, 100)
.compose())
.combine();
VibrationStepConductor conductor = startThreadAndDispatcher(vibrationId, effect);
VibrationStepConductor conductor = startThreadAndDispatcher(effect);
long vibrationId = conductor.getVibration().id;
assertTrue(waitUntil(() -> mControllers.get(2).isVibrating(),
TEST_TIMEOUT_MILLIS));
@@ -1264,13 +1265,13 @@ public class VibrationThreadTest {
mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL);
mVibratorProviders.get(2).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL);
long vibrationId = 1;
CombinedVibration effect = CombinedVibration.startParallel()
.addVibrator(1, VibrationEffect.createWaveform(
new long[]{100, 100}, new int[]{1, 2}, 0))
.addVibrator(2, VibrationEffect.createOneShot(100, 100))
.combine();
VibrationStepConductor conductor = startThreadAndDispatcher(vibrationId, effect);
VibrationStepConductor conductor = startThreadAndDispatcher(effect);
long vibrationId = conductor.getVibration().id;
assertTrue(waitUntil(() -> mControllers.get(1).isVibrating()
&& mControllers.get(2).isVibrating(),
@@ -1296,9 +1297,9 @@ public class VibrationThreadTest {
@Test
public void vibrate_binderDied_cancelsVibration() throws Exception {
long vibrationId = 1;
VibrationEffect effect = VibrationEffect.createWaveform(new long[]{5}, new int[]{100}, 0);
VibrationStepConductor conductor = startThreadAndDispatcher(vibrationId, effect);
VibrationStepConductor conductor = startThreadAndDispatcher(effect);
long vibrationId = conductor.getVibration().id;
assertTrue(waitUntil(() -> mControllers.get(VIBRATOR_ID).isVibrating(),
TEST_TIMEOUT_MILLIS));
@@ -1320,10 +1321,10 @@ public class VibrationThreadTest {
mEffectAdapter = new DeviceVibrationEffectAdapter(mVibrationSettings);
mVibratorProviders.get(VIBRATOR_ID).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL);
long vibrationId = 1;
VibrationEffect effect = VibrationEffect.createWaveform(
new long[]{5, 5, 5}, new int[]{60, 120, 240}, -1);
startThreadAndDispatcher(vibrationId, effect);
VibrationStepConductor conductor = startThreadAndDispatcher(effect);
long vibrationId = conductor.getVibration().id;
waitForCompletion();
verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibrationId));
@@ -1346,9 +1347,9 @@ public class VibrationThreadTest {
mEffectAdapter = new DeviceVibrationEffectAdapter(mVibrationSettings);
mVibratorProviders.get(VIBRATOR_ID).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL);
long vibrationId = 1;
VibrationEffect effect = VibrationEffect.createOneShot(10, 200);
VibrationStepConductor conductor = startThreadAndDispatcher(vibrationId, effect);
VibrationStepConductor conductor = startThreadAndDispatcher(effect);
long vibrationId = conductor.getVibration().id;
// Vibration completed but vibrator not yet released.
verify(mManagerHooks, timeout(TEST_TIMEOUT_MILLIS)).onVibrationCompleted(eq(vibrationId),
@@ -1381,9 +1382,9 @@ public class VibrationThreadTest {
mEffectAdapter = new DeviceVibrationEffectAdapter(mVibrationSettings);
mVibratorProviders.get(VIBRATOR_ID).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL);
long vibrationId = 1;
VibrationEffect effect = VibrationEffect.createOneShot(10_000, 240);
VibrationStepConductor conductor = startThreadAndDispatcher(vibrationId, effect);
VibrationStepConductor conductor = startThreadAndDispatcher(effect);
long vibrationId = conductor.getVibration().id;
assertTrue(waitUntil(() -> mControllers.get(VIBRATOR_ID).isVibrating(),
TEST_TIMEOUT_MILLIS));
conductor.notifyCancelled(
@@ -1410,9 +1411,9 @@ public class VibrationThreadTest {
mVibratorProviders.get(VIBRATOR_ID).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL);
mVibratorProviders.get(VIBRATOR_ID).setSupportedEffects(VibrationEffect.EFFECT_CLICK);
long vibrationId = 1;
VibrationEffect effect = VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
startThreadAndDispatcher(vibrationId, effect);
VibrationStepConductor conductor = startThreadAndDispatcher(effect);
long vibrationId = conductor.getVibration().id;
waitForCompletion();
verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibrationId));
@@ -1432,11 +1433,11 @@ public class VibrationThreadTest {
mVibratorProviders.get(VIBRATOR_ID).setSupportedPrimitives(
VibrationEffect.Composition.PRIMITIVE_CLICK);
long vibrationId = 1;
VibrationEffect effect = VibrationEffect.startComposition()
.addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK)
.compose();
startThreadAndDispatcher(vibrationId, effect);
VibrationStepConductor conductor = startThreadAndDispatcher(effect);
long vibrationId = conductor.getVibration().id;
waitForCompletion();
verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibrationId));
@@ -1461,11 +1462,11 @@ public class VibrationThreadTest {
fakeVibrator.setMaxAmplitudes(1, 1, 1);
fakeVibrator.setPwleSizeMax(2);
long vibrationId = 1;
VibrationEffect effect = VibrationEffect.startWaveform()
.addTransition(Duration.ofMillis(1), targetAmplitude(1))
.build();
startThreadAndDispatcher(vibrationId, effect);
VibrationStepConductor conductor = startThreadAndDispatcher(effect);
long vibrationId = conductor.getVibration().id;
waitForCompletion();
verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibrationId));
@@ -1485,12 +1486,6 @@ public class VibrationThreadTest {
mVibratorProviders.get(VIBRATOR_ID).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL,
IVibrator.CAP_COMPOSE_EFFECTS);
long vibrationId1 = 1;
long vibrationId2 = 2;
long vibrationId3 = 3;
long vibrationId4 = 4;
long vibrationId5 = 5;
// A simple effect, followed by a repeating effect that gets cancelled, followed by another
// simple effect.
VibrationEffect effect1 = VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
@@ -1503,12 +1498,14 @@ public class VibrationThreadTest {
VibrationEffect effect4 = VibrationEffect.createOneShot(8000, 100);
VibrationEffect effect5 = VibrationEffect.createOneShot(20, 222);
startThreadAndDispatcher(vibrationId1, effect1);
VibrationStepConductor conductor1 = startThreadAndDispatcher(effect1);
long vibrationId1 = conductor1.getVibration().id;
waitForCompletion();
verify(mControllerCallbacks).onComplete(VIBRATOR_ID, vibrationId1);
verifyCallbacksTriggered(vibrationId1, Vibration.Status.FINISHED);
VibrationStepConductor conductor2 = startThreadAndDispatcher(vibrationId2, effect2);
VibrationStepConductor conductor2 = startThreadAndDispatcher(effect2);
long vibrationId2 = conductor2.getVibration().id;
// Effect2 won't complete on its own. Cancel it after a couple of repeats.
Thread.sleep(150); // More than two TICKs.
conductor2.notifyCancelled(
@@ -1516,12 +1513,14 @@ public class VibrationThreadTest {
/* immediate= */ false);
waitForCompletion();
startThreadAndDispatcher(vibrationId3, effect3);
VibrationStepConductor conductor3 = startThreadAndDispatcher(effect3);
long vibrationId3 = conductor3.getVibration().id;
waitForCompletion();
// Effect4 is a long oneshot, but it gets cancelled as fast as possible.
long start4 = System.currentTimeMillis();
VibrationStepConductor conductor4 = startThreadAndDispatcher(vibrationId4, effect4);
VibrationStepConductor conductor4 = startThreadAndDispatcher(effect4);
long vibrationId4 = conductor4.getVibration().id;
conductor4.notifyCancelled(
new Vibration.EndInfo(Vibration.Status.CANCELLED_BY_SCREEN_OFF),
/* immediate= */ true);
@@ -1529,7 +1528,8 @@ public class VibrationThreadTest {
long duration4 = System.currentTimeMillis() - start4;
// Effect5 is to show that things keep going after the immediate cancel.
startThreadAndDispatcher(vibrationId5, effect5);
VibrationStepConductor conductor5 = startThreadAndDispatcher(effect5);
long vibrationId5 = conductor5.getVibration().id;
waitForCompletion();
FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(VIBRATOR_ID);
@@ -1582,14 +1582,12 @@ public class VibrationThreadTest {
}
}
private VibrationStepConductor startThreadAndDispatcher(
long vibrationId, VibrationEffect effect) {
return startThreadAndDispatcher(vibrationId, CombinedVibration.createParallel(effect));
private VibrationStepConductor startThreadAndDispatcher(VibrationEffect effect) {
return startThreadAndDispatcher(CombinedVibration.createParallel(effect));
}
private VibrationStepConductor startThreadAndDispatcher(long vibrationId,
CombinedVibration effect) {
return startThreadAndDispatcher(createVibration(vibrationId, effect));
private VibrationStepConductor startThreadAndDispatcher(CombinedVibration effect) {
return startThreadAndDispatcher(createVibration(effect));
}
private VibrationStepConductor startThreadAndDispatcher(HalVibration vib) {
@@ -1624,9 +1622,9 @@ public class VibrationThreadTest {
mTestLooper.dispatchAll(); // Flush callbacks
}
private HalVibration createVibration(long id, CombinedVibration effect) {
return new HalVibration(mVibrationToken, (int) id, effect, ATTRS, UID, DISPLAY_ID,
PACKAGE_NAME, "reason");
private HalVibration createVibration(CombinedVibration effect) {
return new HalVibration(mVibrationToken, effect,
new Vibration.CallerInfo(ATTRS, UID, DISPLAY_ID, PACKAGE_NAME, "reason"));
}
private SparseArray<VibratorController> createVibratorControllers() {