Don't expose vibrator controllers via VibrationThread.

Also move "toSequential" into VibrationStepConductor - there's no reason
for that to be outside.

Bug: 193792066
Test: atest
Change-Id: I3de6343871ac5269daab9698b66563b4fc394a68
This commit is contained in:
Simon Bowden
2022-02-21 20:14:30 +00:00
parent ad20c09c80
commit 0709a084c9
3 changed files with 67 additions and 74 deletions

View File

@@ -16,7 +16,6 @@
package com.android.server.vibrator;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Build;
import android.os.CombinedVibration;
@@ -130,16 +129,17 @@ final class VibrationStepConductor {
previousStepVibratorOffTimeout);
}
public void initializeForEffect(@NonNull CombinedVibration.Sequential vibration) {
/** Called when this conductor is going to be started running by the VibrationThread. */
public void prepareToStart() {
if (Build.IS_DEBUGGABLE) {
expectIsVibrationThread(true);
}
CombinedVibration.Sequential sequentialEffect = toSequential(mVibration.getEffect());
synchronized (mLock) {
mPendingVibrateSteps++;
// This count is decremented at the completion of the step, so we don't subtract one.
mRemainingStartSequentialEffectSteps = vibration.getEffects().size();
mNextSteps.offer(new StartSequentialEffectStep(this, vibration));
mRemainingStartSequentialEffectSteps = sequentialEffect.getEffects().size();
mNextSteps.offer(new StartSequentialEffectStep(this, sequentialEffect));
}
}
@@ -447,6 +447,15 @@ final class VibrationStepConductor {
}
}
private static CombinedVibration.Sequential toSequential(CombinedVibration effect) {
if (effect instanceof CombinedVibration.Sequential) {
return (CombinedVibration.Sequential) effect;
}
return (CombinedVibration.Sequential) CombinedVibration.startSequential()
.addNext(effect)
.combine();
}
/**
* This check is used for debugging and documentation to indicate the thread that's expected
* to invoke a given public method on this class. Most methods are only invoked by

View File

@@ -16,7 +16,6 @@
package com.android.server.vibrator;
import android.os.CombinedVibration;
import android.os.IBinder;
import android.os.PowerManager;
import android.os.Process;
@@ -26,8 +25,6 @@ import android.os.WorkSource;
import android.util.Slog;
import android.util.SparseArray;
import com.android.internal.annotations.VisibleForTesting;
import java.util.NoSuchElementException;
/** Plays a {@link Vibration} in dedicated thread. */
@@ -106,11 +103,6 @@ final class VibrationThread extends Thread implements IBinder.DeathRecipient {
return mStepConductor.getVibration();
}
@VisibleForTesting
SparseArray<VibratorController> getVibrators() {
return mStepConductor.getVibrators();
}
@Override
public void binderDied() {
if (DEBUG) {
@@ -224,9 +216,7 @@ final class VibrationThread extends Thread implements IBinder.DeathRecipient {
private void playVibration() {
Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "playVibration");
try {
CombinedVibration.Sequential sequentialEffect =
toSequential(mStepConductor.getVibration().getEffect());
mStepConductor.initializeForEffect(sequentialEffect);
mStepConductor.prepareToStart();
while (!mStepConductor.isFinished()) {
// Skip wait and next step if mForceStop already happened.
@@ -265,14 +255,4 @@ final class VibrationThread extends Thread implements IBinder.DeathRecipient {
Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
}
}
private static CombinedVibration.Sequential toSequential(CombinedVibration effect) {
if (effect instanceof CombinedVibration.Sequential) {
return (CombinedVibration.Sequential) effect;
}
return (CombinedVibration.Sequential) CombinedVibration.startSequential()
.addNext(effect)
.combine();
}
}

View File

@@ -113,6 +113,9 @@ public class VibrationThreadTest {
private TestLooper mTestLooper;
private TestLooperAutoDispatcher mCustomTestLooperDispatcher;
// Setup from the providers when VibrationThread is initialized.
private SparseArray<VibratorController> mControllers;
@Before
public void setUp() throws Exception {
mTestLooper = new TestLooper();
@@ -178,7 +181,7 @@ public class VibrationThreadTest {
verify(mManagerHooks).noteVibratorOff(eq(UID));
verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibrationId));
verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
assertFalse(thread.getVibrators().get(VIBRATOR_ID).isVibrating());
assertFalse(mControllers.get(VIBRATOR_ID).isVibrating());
assertEquals(Arrays.asList(expectedOneShot(10)),
mVibratorProviders.get(VIBRATOR_ID).getEffectSegments());
@@ -197,7 +200,7 @@ public class VibrationThreadTest {
verify(mManagerHooks).noteVibratorOff(eq(UID));
verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibrationId));
verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
assertFalse(thread.getVibrators().get(VIBRATOR_ID).isVibrating());
assertFalse(mControllers.get(VIBRATOR_ID).isVibrating());
assertEquals(Arrays.asList(expectedOneShot(10)),
mVibratorProviders.get(VIBRATOR_ID).getEffectSegments());
@@ -219,7 +222,7 @@ public class VibrationThreadTest {
verify(mManagerHooks).noteVibratorOff(eq(UID));
verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibrationId));
verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
assertFalse(thread.getVibrators().get(VIBRATOR_ID).isVibrating());
assertFalse(mControllers.get(VIBRATOR_ID).isVibrating());
assertEquals(Arrays.asList(expectedOneShot(15)),
mVibratorProviders.get(VIBRATOR_ID).getEffectSegments());
@@ -243,7 +246,7 @@ public class VibrationThreadTest {
thread, TEST_TIMEOUT_MILLIS));
// Vibration still running after 2 cycles.
assertTrue(thread.isAlive());
assertTrue(thread.getVibrators().get(VIBRATOR_ID).isVibrating());
assertTrue(mControllers.get(VIBRATOR_ID).isVibrating());
thread.cancel();
waitForCompletion(thread);
@@ -251,7 +254,7 @@ public class VibrationThreadTest {
verify(mManagerHooks).noteVibratorOn(eq(UID), anyLong());
verify(mManagerHooks).noteVibratorOff(eq(UID));
verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED);
assertFalse(thread.getVibrators().get(VIBRATOR_ID).isVibrating());
assertFalse(mControllers.get(VIBRATOR_ID).isVibrating());
List<Float> playedAmplitudes = fakeVibrator.getAmplitudes();
assertFalse(fakeVibrator.getEffectSegments().isEmpty());
@@ -280,7 +283,7 @@ public class VibrationThreadTest {
waitForCompletion(thread);
verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED);
assertFalse(thread.getVibrators().get(VIBRATOR_ID).isVibrating());
assertFalse(mControllers.get(VIBRATOR_ID).isVibrating());
assertEquals(Arrays.asList(expectedOneShot(1000)), fakeVibrator.getEffectSegments());
}
@@ -302,7 +305,7 @@ public class VibrationThreadTest {
waitForCompletion(thread);
verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED);
assertFalse(thread.getVibrators().get(VIBRATOR_ID).isVibrating());
assertFalse(mControllers.get(VIBRATOR_ID).isVibrating());
assertEquals(Arrays.asList(expectedOneShot(5550)), fakeVibrator.getEffectSegments());
}
@@ -325,7 +328,7 @@ public class VibrationThreadTest {
waitForCompletion(thread);
verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED);
assertFalse(thread.getVibrators().get(VIBRATOR_ID).isVibrating());
assertFalse(mControllers.get(VIBRATOR_ID).isVibrating());
assertEquals(2, fakeVibrator.getEffectSegments().size());
// First time turn vibrator ON for minimum of 1s.
assertEquals(1000L, fakeVibrator.getEffectSegments().get(0).getDuration());
@@ -350,7 +353,7 @@ public class VibrationThreadTest {
.compose();
VibrationThread vibrationThread = startThreadAndDispatcher(vibrationId, effect);
assertTrue(waitUntil(t -> t.getVibrators().get(VIBRATOR_ID).isVibrating(), vibrationThread,
assertTrue(waitUntil(t -> mControllers.get(VIBRATOR_ID).isVibrating(), vibrationThread,
TEST_TIMEOUT_MILLIS));
assertTrue(vibrationThread.isAlive());
@@ -363,7 +366,7 @@ public class VibrationThreadTest {
waitForCompletion(cancellingThread);
verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED);
assertFalse(vibrationThread.getVibrators().get(VIBRATOR_ID).isVibrating());
assertFalse(mControllers.get(VIBRATOR_ID).isVibrating());
}
@Test
@@ -375,7 +378,7 @@ public class VibrationThreadTest {
VibrationEffect effect = VibrationEffect.createWaveform(new long[]{100}, new int[]{100}, 0);
VibrationThread vibrationThread = startThreadAndDispatcher(vibrationId, effect);
assertTrue(waitUntil(t -> t.getVibrators().get(VIBRATOR_ID).isVibrating(), vibrationThread,
assertTrue(waitUntil(t -> mControllers.get(VIBRATOR_ID).isVibrating(), vibrationThread,
TEST_TIMEOUT_MILLIS));
assertTrue(vibrationThread.isAlive());
@@ -388,7 +391,7 @@ public class VibrationThreadTest {
waitForCompletion(cancellingThread);
verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED);
assertFalse(vibrationThread.getVibrators().get(VIBRATOR_ID).isVibrating());
assertFalse(mControllers.get(VIBRATOR_ID).isVibrating());
}
@Test
@@ -404,7 +407,7 @@ public class VibrationThreadTest {
verify(mManagerHooks).noteVibratorOff(eq(UID));
verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibrationId));
verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
assertFalse(thread.getVibrators().get(VIBRATOR_ID).isVibrating());
assertFalse(mControllers.get(VIBRATOR_ID).isVibrating());
assertEquals(Arrays.asList(expectedPrebaked(VibrationEffect.EFFECT_THUD)),
mVibratorProviders.get(VIBRATOR_ID).getEffectSegments());
@@ -427,7 +430,7 @@ public class VibrationThreadTest {
verify(mManagerHooks).noteVibratorOff(eq(UID));
verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibrationId));
verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
assertFalse(thread.getVibrators().get(VIBRATOR_ID).isVibrating());
assertFalse(mControllers.get(VIBRATOR_ID).isVibrating());
assertEquals(Arrays.asList(expectedOneShot(10)),
mVibratorProviders.get(VIBRATOR_ID).getEffectSegments());
@@ -466,7 +469,7 @@ public class VibrationThreadTest {
verify(mManagerHooks).noteVibratorOff(eq(UID));
verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibrationId));
verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
assertFalse(thread.getVibrators().get(VIBRATOR_ID).isVibrating());
assertFalse(mControllers.get(VIBRATOR_ID).isVibrating());
assertEquals(Arrays.asList(
expectedPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1, 0),
expectedPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK, 0.5f, 0)),
@@ -536,7 +539,7 @@ public class VibrationThreadTest {
verify(mManagerHooks).noteVibratorOff(eq(UID));
verify(mControllerCallbacks, times(4)).onComplete(eq(VIBRATOR_ID), eq(vibrationId));
verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
assertFalse(thread.getVibrators().get(VIBRATOR_ID).isVibrating());
assertFalse(mControllers.get(VIBRATOR_ID).isVibrating());
assertEquals(Arrays.asList(
expectedOneShot(10),
expectedPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1, 0),
@@ -573,7 +576,7 @@ public class VibrationThreadTest {
verify(mManagerHooks).noteVibratorOff(eq(UID));
verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibrationId));
verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
assertFalse(thread.getVibrators().get(VIBRATOR_ID).isVibrating());
assertFalse(mControllers.get(VIBRATOR_ID).isVibrating());
assertEquals(Arrays.asList(
expectedRamp(/* amplitude= */ 1, /* frequencyHz= */ 150, /* duration= */ 10),
expectedRamp(/* startAmplitude= */ 1, /* endAmplitude= */ 0,
@@ -626,11 +629,11 @@ public class VibrationThreadTest {
TEST_TIMEOUT_MILLIS));
// Vibration still running after 2 cycles.
assertTrue(thread.isAlive());
assertTrue(thread.getVibrators().get(VIBRATOR_ID).isVibrating());
assertTrue(mControllers.get(VIBRATOR_ID).isVibrating());
thread.binderDied();
waitForCompletion(thread);
assertFalse(thread.getVibrators().get(VIBRATOR_ID).isVibrating());
assertFalse(mControllers.get(VIBRATOR_ID).isVibrating());
verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED);
}
@@ -667,7 +670,7 @@ public class VibrationThreadTest {
verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibrationId));
verify(mControllerCallbacks, never()).onComplete(eq(2), eq(vibrationId));
verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
assertFalse(thread.getVibrators().get(VIBRATOR_ID).isVibrating());
assertFalse(mControllers.get(VIBRATOR_ID).isVibrating());
assertEquals(Arrays.asList(expectedPrebaked(VibrationEffect.EFFECT_TICK)),
mVibratorProviders.get(VIBRATOR_ID).getEffectSegments());
@@ -692,9 +695,9 @@ public class VibrationThreadTest {
verify(mControllerCallbacks).onComplete(eq(2), eq(vibrationId));
verify(mControllerCallbacks).onComplete(eq(3), eq(vibrationId));
verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
assertFalse(thread.getVibrators().get(1).isVibrating());
assertFalse(thread.getVibrators().get(2).isVibrating());
assertFalse(thread.getVibrators().get(3).isVibrating());
assertFalse(mControllers.get(1).isVibrating());
assertFalse(mControllers.get(2).isVibrating());
assertFalse(mControllers.get(3).isVibrating());
VibrationEffectSegment expected = expectedPrebaked(VibrationEffect.EFFECT_CLICK);
assertEquals(Arrays.asList(expected), mVibratorProviders.get(1).getEffectSegments());
@@ -731,10 +734,10 @@ public class VibrationThreadTest {
verify(mControllerCallbacks).onComplete(eq(3), eq(vibrationId));
verify(mControllerCallbacks).onComplete(eq(4), eq(vibrationId));
verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
assertFalse(thread.getVibrators().get(1).isVibrating());
assertFalse(thread.getVibrators().get(2).isVibrating());
assertFalse(thread.getVibrators().get(3).isVibrating());
assertFalse(thread.getVibrators().get(4).isVibrating());
assertFalse(mControllers.get(1).isVibrating());
assertFalse(mControllers.get(2).isVibrating());
assertFalse(mControllers.get(3).isVibrating());
assertFalse(mControllers.get(4).isVibrating());
assertEquals(Arrays.asList(expectedPrebaked(VibrationEffect.EFFECT_CLICK)),
mVibratorProviders.get(1).getEffectSegments());
@@ -782,9 +785,9 @@ public class VibrationThreadTest {
batteryVerifier.verify(mManagerHooks).noteVibratorOff(eq(UID));
verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
assertFalse(thread.getVibrators().get(1).isVibrating());
assertFalse(thread.getVibrators().get(2).isVibrating());
assertFalse(thread.getVibrators().get(3).isVibrating());
assertFalse(mControllers.get(1).isVibrating());
assertFalse(mControllers.get(2).isVibrating());
assertFalse(mControllers.get(3).isVibrating());
assertEquals(Arrays.asList(expectedOneShot(10)),
mVibratorProviders.get(1).getEffectSegments());
@@ -941,9 +944,9 @@ public class VibrationThreadTest {
// All vibrators are turned on in parallel.
assertTrue(waitUntil(
t -> t.getVibrators().get(1).isVibrating()
&& t.getVibrators().get(2).isVibrating()
&& t.getVibrators().get(3).isVibrating(),
t -> mControllers.get(1).isVibrating()
&& mControllers.get(2).isVibrating()
&& mControllers.get(3).isVibrating(),
thread, TEST_TIMEOUT_MILLIS));
waitForCompletion(thread);
@@ -954,9 +957,9 @@ public class VibrationThreadTest {
verify(mControllerCallbacks).onComplete(eq(2), eq(vibrationId));
verify(mControllerCallbacks).onComplete(eq(3), eq(vibrationId));
verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
assertFalse(thread.getVibrators().get(1).isVibrating());
assertFalse(thread.getVibrators().get(2).isVibrating());
assertFalse(thread.getVibrators().get(3).isVibrating());
assertFalse(mControllers.get(1).isVibrating());
assertFalse(mControllers.get(2).isVibrating());
assertFalse(mControllers.get(3).isVibrating());
assertEquals(Arrays.asList(expectedOneShot(25)),
mVibratorProviders.get(1).getEffectSegments());
@@ -1031,7 +1034,7 @@ public class VibrationThreadTest {
// After the vibrator call ends the vibration is cancelled and the vibrator is turned off.
waitForCompletion(vibrationThread, /* timeout= */ latency + TEST_TIMEOUT_MILLIS);
verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED);
assertFalse(vibrationThread.getVibrators().get(VIBRATOR_ID).isVibrating());
assertFalse(mControllers.get(VIBRATOR_ID).isVibrating());
}
@Test
@@ -1051,7 +1054,7 @@ public class VibrationThreadTest {
.combine();
VibrationThread vibrationThread = startThreadAndDispatcher(vibrationId, effect);
assertTrue(waitUntil(t -> t.getVibrators().get(2).isVibrating(), vibrationThread,
assertTrue(waitUntil(t -> mControllers.get(2).isVibrating(), vibrationThread,
TEST_TIMEOUT_MILLIS));
assertTrue(vibrationThread.isAlive());
@@ -1064,8 +1067,8 @@ public class VibrationThreadTest {
waitForCompletion(cancellingThread);
verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED);
assertFalse(vibrationThread.getVibrators().get(1).isVibrating());
assertFalse(vibrationThread.getVibrators().get(2).isVibrating());
assertFalse(mControllers.get(1).isVibrating());
assertFalse(mControllers.get(2).isVibrating());
}
@Test
@@ -1082,8 +1085,8 @@ public class VibrationThreadTest {
.combine();
VibrationThread vibrationThread = startThreadAndDispatcher(vibrationId, effect);
assertTrue(waitUntil(t -> t.getVibrators().get(1).isVibrating()
&& t.getVibrators().get(2).isVibrating(),
assertTrue(waitUntil(t -> mControllers.get(1).isVibrating()
&& mControllers.get(2).isVibrating(),
vibrationThread, TEST_TIMEOUT_MILLIS));
assertTrue(vibrationThread.isAlive());
@@ -1096,8 +1099,8 @@ public class VibrationThreadTest {
waitForCompletion(cancellingThread);
verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED);
assertFalse(vibrationThread.getVibrators().get(1).isVibrating());
assertFalse(vibrationThread.getVibrators().get(2).isVibrating());
assertFalse(mControllers.get(1).isVibrating());
assertFalse(mControllers.get(2).isVibrating());
}
@Test
@@ -1106,7 +1109,7 @@ public class VibrationThreadTest {
VibrationEffect effect = VibrationEffect.createWaveform(new long[]{5}, new int[]{100}, 0);
VibrationThread thread = startThreadAndDispatcher(vibrationId, effect);
assertTrue(waitUntil(t -> t.getVibrators().get(VIBRATOR_ID).isVibrating(), thread,
assertTrue(waitUntil(t -> mControllers.get(VIBRATOR_ID).isVibrating(), thread,
TEST_TIMEOUT_MILLIS));
assertTrue(thread.isAlive());
@@ -1117,7 +1120,7 @@ public class VibrationThreadTest {
verify(mVibrationToken).unlinkToDeath(same(thread), eq(0));
verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED);
assertFalse(mVibratorProviders.get(VIBRATOR_ID).getEffectSegments().isEmpty());
assertFalse(thread.getVibrators().get(VIBRATOR_ID).isVibrating());
assertFalse(mControllers.get(VIBRATOR_ID).isVibrating());
}
@Test
@@ -1188,7 +1191,7 @@ public class VibrationThreadTest {
long vibrationId = 1;
VibrationEffect effect = VibrationEffect.createOneShot(10_000, 240);
VibrationThread thread = startThreadAndDispatcher(vibrationId, effect);
assertTrue(waitUntil(t -> t.getVibrators().get(VIBRATOR_ID).isVibrating(), thread,
assertTrue(waitUntil(t -> mControllers.get(VIBRATOR_ID).isVibrating(), thread,
TEST_TIMEOUT_MILLIS));
thread.cancel();
waitForCompletion(thread);
@@ -1295,8 +1298,9 @@ public class VibrationThreadTest {
}
private VibrationThread startThreadAndDispatcher(Vibration vib) {
mControllers = createVibratorControllers();
VibrationThread thread = new VibrationThread(vib, mVibrationSettings, mEffectAdapter,
createVibratorControllers(), mWakeLock, mManagerHooks);
mControllers, mWakeLock, mManagerHooks);
doAnswer(answer -> {
thread.vibratorComplete(answer.getArgument(0));
return null;