Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 180fe308 authored by Simon Bowden's avatar Simon Bowden Committed by Android (Google) Code Review
Browse files

Merge "Handle binder death with the conductor rather than VibrationThread." into tm-dev

parents 159518e2 8e3d1870
Loading
Loading
Loading
Loading
+15 −1
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Build;
import android.os.CombinedVibration;
import android.os.IBinder;
import android.os.VibrationEffect;
import android.os.vibrator.PrebakedSegment;
import android.os.vibrator.PrimitiveSegment;
@@ -46,7 +47,7 @@ import java.util.Queue;
 * VibrationThread. The only thread-safe methods for calling from other threads are the "notify"
 * methods (which should never be used from the VibrationThread thread).
 */
final class VibrationStepConductor {
final class VibrationStepConductor implements IBinder.DeathRecipient {
    private static final boolean DEBUG = VibrationThread.DEBUG;
    private static final String TAG = VibrationThread.TAG;

@@ -289,6 +290,19 @@ final class VibrationStepConductor {
        }
    }

    /**
     * Binder death notification. VibrationThread registers this when it's running a conductor.
     * Note that cancellation could theoretically happen immediately, before the conductor has
     * started, but in this case it will be processed in the first signals loop.
     */
    @Override
    public void binderDied() {
        if (DEBUG) {
            Slog.d(TAG, "Binder died, cancelling vibration...");
        }
        notifyCancelled(/* immediate= */ false);
    }

    /**
     * Notify the execution that cancellation is requested. This will be acted upon
     * asynchronously in the VibrationThread.
+3 −20
Original line number Diff line number Diff line
@@ -33,7 +33,7 @@ import java.util.NoSuchElementException;
import java.util.Objects;

/** Plays a {@link Vibration} in dedicated thread. */
final class VibrationThread extends Thread implements IBinder.DeathRecipient {
final class VibrationThread extends Thread {
    static final String TAG = "VibrationThread";
    static final boolean DEBUG = false;

@@ -118,23 +118,6 @@ final class VibrationThread extends Thread implements IBinder.DeathRecipient {
        mVibratorManagerHooks = vibratorManagerHooks;
    }

    @Override
    public void binderDied() {
        if (DEBUG) {
            Slog.d(TAG, "Binder died, cancelling vibration...");
        }
        // The binder death link only exists while the conductor is set.
        // TODO: move the death linking to be associated with the conductor directly, this
        // awkwardness will go away.
        VibrationStepConductor conductor;
        synchronized (mLock) {
            conductor = mRequestedActiveConductor;
        }
        if (conductor != null) {
            conductor.notifyCancelled(/* immediate= */ false);
        }
    }

    /**
     * Sets/activates the current vibration. Must only be called after receiving
     * onVibratorsReleased from the previous vibration.
@@ -268,7 +251,7 @@ final class VibrationThread extends Thread implements IBinder.DeathRecipient {
    private void runCurrentVibrationWithWakeLockAndDeathLink() {
        IBinder vibrationBinderToken = mExecutingConductor.getVibration().token;
        try {
            vibrationBinderToken.linkToDeath(this, 0);
            vibrationBinderToken.linkToDeath(mExecutingConductor, 0);
        } catch (RemoteException e) {
            Slog.e(TAG, "Error linking vibration to token death", e);
            clientVibrationCompleteIfNotAlready(Vibration.Status.IGNORED_ERROR_TOKEN);
@@ -280,7 +263,7 @@ final class VibrationThread extends Thread implements IBinder.DeathRecipient {
            playVibration();
        } finally {
            try {
                vibrationBinderToken.unlinkToDeath(this, 0);
                vibrationBinderToken.unlinkToDeath(mExecutingConductor, 0);
            } catch (NoSuchElementException e) {
                Slog.wtf(TAG, "Failed to unlink token", e);
            }
+6 −6
Original line number Diff line number Diff line
@@ -636,14 +636,14 @@ public class VibrationThreadTest {

        long vibrationId = 1;
        VibrationEffect effect = VibrationEffect.createWaveform(new long[]{5}, new int[]{100}, 0);
        startThreadAndDispatcher(vibrationId, effect);
        VibrationStepConductor conductor = startThreadAndDispatcher(vibrationId, effect);

        assertTrue(waitUntil(() -> fakeVibrator.getAmplitudes().size() > 2, TEST_TIMEOUT_MILLIS));
        // Vibration still running after 2 cycles.
        assertTrue(mThread.isRunningVibrationId(vibrationId));
        assertTrue(mControllers.get(VIBRATOR_ID).isVibrating());

        mThread.binderDied();
        conductor.binderDied();
        waitForCompletion();
        assertFalse(mControllers.get(VIBRATOR_ID).isVibrating());

@@ -1128,17 +1128,17 @@ public class VibrationThreadTest {
    public void vibrate_binderDied_cancelsVibration() throws Exception {
        long vibrationId = 1;
        VibrationEffect effect = VibrationEffect.createWaveform(new long[]{5}, new int[]{100}, 0);
        startThreadAndDispatcher(vibrationId, effect);
        VibrationStepConductor conductor = startThreadAndDispatcher(vibrationId, effect);

        assertTrue(waitUntil(() -> mControllers.get(VIBRATOR_ID).isVibrating(),
                TEST_TIMEOUT_MILLIS));
        assertTrue(mThread.isRunningVibrationId(vibrationId));

        mThread.binderDied();
        conductor.binderDied();
        waitForCompletion();

        verify(mVibrationToken).linkToDeath(same(mThread), eq(0));
        verify(mVibrationToken).unlinkToDeath(same(mThread), eq(0));
        verify(mVibrationToken).linkToDeath(same(conductor), eq(0));
        verify(mVibrationToken).unlinkToDeath(same(conductor), eq(0));
        verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED);
        assertFalse(mVibratorProviders.get(VIBRATOR_ID).getEffectSegments(vibrationId).isEmpty());
        assertFalse(mControllers.get(VIBRATOR_ID).isVibrating());