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

Commit 8119ec5b authored by Simon Bowden's avatar Simon Bowden Committed by Automerger Merge Worker
Browse files

Merge "Handle binder death with the conductor rather than VibrationThread."...

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

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/17046343

Change-Id: Ifaba07bb3cdaaa358cf40b2e6cd3ff2c58023818
parents b189754f 180fe308
Loading
Loading
Loading
Loading
+15 −1
Original line number Original line Diff line number Diff line
@@ -20,6 +20,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Nullable;
import android.os.Build;
import android.os.Build;
import android.os.CombinedVibration;
import android.os.CombinedVibration;
import android.os.IBinder;
import android.os.VibrationEffect;
import android.os.VibrationEffect;
import android.os.vibrator.PrebakedSegment;
import android.os.vibrator.PrebakedSegment;
import android.os.vibrator.PrimitiveSegment;
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"
 * VibrationThread. The only thread-safe methods for calling from other threads are the "notify"
 * methods (which should never be used from the VibrationThread thread).
 * 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 boolean DEBUG = VibrationThread.DEBUG;
    private static final String TAG = VibrationThread.TAG;
    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
     * Notify the execution that cancellation is requested. This will be acted upon
     * asynchronously in the VibrationThread.
     * asynchronously in the VibrationThread.
+3 −20
Original line number Original line Diff line number Diff line
@@ -33,7 +33,7 @@ import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Objects;


/** Plays a {@link Vibration} in dedicated thread. */
/** 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 String TAG = "VibrationThread";
    static final boolean DEBUG = false;
    static final boolean DEBUG = false;


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


        long vibrationId = 1;
        long vibrationId = 1;
        VibrationEffect effect = VibrationEffect.createWaveform(new long[]{5}, new int[]{100}, 0);
        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));
        assertTrue(waitUntil(() -> fakeVibrator.getAmplitudes().size() > 2, TEST_TIMEOUT_MILLIS));
        // Vibration still running after 2 cycles.
        // Vibration still running after 2 cycles.
        assertTrue(mThread.isRunningVibrationId(vibrationId));
        assertTrue(mThread.isRunningVibrationId(vibrationId));
        assertTrue(mControllers.get(VIBRATOR_ID).isVibrating());
        assertTrue(mControllers.get(VIBRATOR_ID).isVibrating());


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


@@ -1128,17 +1128,17 @@ public class VibrationThreadTest {
    public void vibrate_binderDied_cancelsVibration() throws Exception {
    public void vibrate_binderDied_cancelsVibration() throws Exception {
        long vibrationId = 1;
        long vibrationId = 1;
        VibrationEffect effect = VibrationEffect.createWaveform(new long[]{5}, new int[]{100}, 0);
        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(),
        assertTrue(waitUntil(() -> mControllers.get(VIBRATOR_ID).isVibrating(),
                TEST_TIMEOUT_MILLIS));
                TEST_TIMEOUT_MILLIS));
        assertTrue(mThread.isRunningVibrationId(vibrationId));
        assertTrue(mThread.isRunningVibrationId(vibrationId));


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


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