Set external control to false on VibratorManagerService init

The VibratorManagerService turns off all vibrators during initialization
to handle the scenario where the system server has restarted (e.g. after
being killed by watchdog after a deadlock) but the vibrator hardware was
still performing a previous vibrate command.

This also sets the external control state to false, so the service won't
attemp to vibrate when the hardware is actually set for external
control.

Bug: 197165183
Test: VibratorManagerServiceTest
Change-Id: If4f0df57333fb5863fe9c1e781575634606ee662
This commit is contained in:
Lais Andrade
2021-08-31 18:47:20 +01:00
parent 637cc7dcea
commit 9fdaad5598
5 changed files with 51 additions and 5 deletions

View File

@@ -304,7 +304,7 @@ final class VibratorController {
}
}
/** Turns off the vibrator.This will affect the state of {@link #isVibrating()}. */
/** Turns off the vibrator. This will affect the state of {@link #isVibrating()}. */
public void off() {
synchronized (mLock) {
mNativeWrapper.off();
@@ -313,6 +313,15 @@ final class VibratorController {
}
}
/**
* Resets the vibrator hardware to a default state.
* This turns the vibrator off, which will affect the state of {@link #isVibrating()}.
*/
public void reset() {
setExternalControl(false);
off();
}
@Override
public String toString() {
synchronized (mLock) {

View File

@@ -219,7 +219,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
// fresh boot.
mNativeWrapper.cancelSynced();
for (int i = 0; i < mVibrators.size(); i++) {
mVibrators.valueAt(i).off();
mVibrators.valueAt(i).reset();
}
IntentFilter filter = new IntentFilter();

View File

@@ -52,6 +52,7 @@ final class FakeVibratorControllerProvider {
private boolean mIsAvailable = true;
private long mLatency;
private int mOffCount;
private int mCapabilities;
private int[] mSupportedEffects;
@@ -93,6 +94,7 @@ final class FakeVibratorControllerProvider {
@Override
public void off() {
mOffCount++;
}
@Override
@@ -308,6 +310,11 @@ final class FakeVibratorControllerProvider {
return mExternalControlStates;
}
/** Returns the number of times the vibrator was turned off. */
public int getOffCount() {
return mOffCount;
}
/**
* Return the {@link PrebakedSegment} effect enabled with given id, or {@code null} if
* missing or disabled.

View File

@@ -258,6 +258,21 @@ public class VibratorControllerTest {
verify(mNativeWrapperMock, times(2)).off();
}
@Test
public void reset_turnsOffVibratorAndDisablesExternalControl() {
mockVibratorCapabilities(IVibrator.CAP_EXTERNAL_CONTROL);
when(mNativeWrapperMock.on(anyLong(), anyLong())).thenAnswer(args -> args.getArgument(0));
VibratorController controller = createController();
controller.on(100, 1);
assertTrue(controller.isVibrating());
controller.reset();
assertFalse(controller.isVibrating());
verify(mNativeWrapperMock).setExternalControl(eq(false));
verify(mNativeWrapperMock).off();
}
@Test
public void registerVibratorStateListener_callbacksAreTriggered() throws Exception {
when(mNativeWrapperMock.on(anyLong(), anyLong())).thenAnswer(args -> args.getArgument(0));

View File

@@ -232,6 +232,19 @@ public class VibratorManagerServiceTest {
assertTrue(mVibratorProviders.get(2).isInitialized());
}
@Test
public void createService_resetsVibrators() {
mockVibrators(1, 2);
mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_EXTERNAL_CONTROL);
mVibratorProviders.get(2).setCapabilities(IVibrator.CAP_EXTERNAL_CONTROL);
createService();
assertEquals(1, mVibratorProviders.get(1).getOffCount());
assertEquals(1, mVibratorProviders.get(2).getOffCount());
assertEquals(Arrays.asList(false), mVibratorProviders.get(1).getExternalControlStates());
assertEquals(Arrays.asList(false), mVibratorProviders.get(2).getExternalControlStates());
}
@Test
public void createService_doNotCrashIfUsedBeforeSystemReady() {
mockVibrators(1, 2);
@@ -991,7 +1004,7 @@ public class VibratorManagerServiceTest {
mExternalVibratorService.onExternalVibrationStop(externalVibration);
assertEquals(IExternalVibratorService.SCALE_NONE, scale);
assertEquals(Arrays.asList(true, false),
assertEquals(Arrays.asList(false, true, false),
mVibratorProviders.get(1).getExternalControlStates());
}
@@ -1017,7 +1030,8 @@ public class VibratorManagerServiceTest {
verify(firstController).mute();
verify(secondController, never()).mute();
// Set external control called only once.
assertEquals(Arrays.asList(true), mVibratorProviders.get(1).getExternalControlStates());
assertEquals(Arrays.asList(false, true),
mVibratorProviders.get(1).getExternalControlStates());
}
@Test
@@ -1039,7 +1053,8 @@ public class VibratorManagerServiceTest {
// Vibration is cancelled.
assertTrue(waitUntil(s -> !s.isVibrating(1), service, TEST_TIMEOUT_MILLIS));
assertEquals(Arrays.asList(true), mVibratorProviders.get(1).getExternalControlStates());
assertEquals(Arrays.asList(false, true),
mVibratorProviders.get(1).getExternalControlStates());
}
private VibrationEffectSegment expectedPrebaked(int effectId) {