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

Commit 3c729321 authored by Lais Andrade's avatar Lais Andrade
Browse files

Add support to slowly bring the vibrator down in VibrationThread

Add support to slowly bring down the vibrator amplitude when a vibration
ends at a positive amplitude or when it is cancelled while playing at a
positive amplitude.

This uses the same duration configured to ramp down PWLE and step
waveforms, and the duration is not considered part of the user defined
vibration.

Bug: 188431691
Test: VibrationThreadTest
Change-Id: I642e898c3b13b2c841543e870275e40df4d00b81
parent de8ea692
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -3370,8 +3370,7 @@
    <integer name="config_vibrationWaveformRampStepDuration">5</integer>

    <!-- The duration (in milliseconds) that should be applied to waveform vibrations that ends in
         non-zero amplitudes, . The waveform will
         be played as a PWLE instead of on/off calls if this value is set. -->
         non-zero amplitudes, to bring the vibrator amplitude down to zero using this timing. -->
    <integer name="config_vibrationWaveformRampDownDuration">0</integer>

    <!-- Number of retries Cell Data should attempt for a given error code before
+12 −4
Original line number Diff line number Diff line
@@ -99,16 +99,24 @@ final class VibrationSettings {
    private boolean mLowPowerMode;

    VibrationSettings(Context context, Handler handler) {
        this(context, handler,
                context.getResources().getInteger(
                        com.android.internal.R.integer.config_vibrationWaveformRampDownDuration),
                context.getResources().getInteger(
                        com.android.internal.R.integer.config_vibrationWaveformRampStepDuration));
    }

    @VisibleForTesting
    VibrationSettings(Context context, Handler handler, int rampDownDuration,
            int rampStepDuration) {
        mContext = context;
        mSettingObserver = new SettingsObserver(handler);
        mUidObserver = new UidObserver();
        mUserReceiver = new UserObserver();

        // TODO(b/191150049): move these to vibrator static config file
        mRampStepDuration = context.getResources().getInteger(
                com.android.internal.R.integer.config_vibrationWaveformRampStepDuration);
        mRampDownDuration = context.getResources().getInteger(
                com.android.internal.R.integer.config_vibrationWaveformRampDownDuration);
        mRampDownDuration = rampDownDuration;
        mRampStepDuration = rampStepDuration;

        VibrationEffect clickEffect = createEffectFromResource(
                com.android.internal.R.array.config_virtualKeyVibePattern);
+377 −66

File changed.

Preview size limit exceeded, changes collapsed.

+37 −7
Original line number Diff line number Diff line
@@ -54,6 +54,8 @@ final class VibratorController {
    private boolean mIsVibrating;
    @GuardedBy("mLock")
    private boolean mIsUnderExternalControl;
    @GuardedBy("mLock")
    private float mCurrentAmplitude;

    /** Listener for vibration completion callbacks from native. */
    public interface OnVibrationCompleteListener {
@@ -131,6 +133,23 @@ final class VibratorController {
        }
    }

    /**
     * Returns the current amplitude the device is vibrating.
     *
     * <p>This value is set to 1 by the method {@link #on(long, long)}, and can be updated via
     * {@link #setAmplitude(float)} if called while the device is vibrating.
     *
     * <p>If the device is vibrating via any other {@link #on} method then the current amplitude is
     * unknown and this will return -1.
     *
     * <p>If {@link #isVibrating()} is false then this will be zero.
     */
    public float getCurrentAmplitude() {
        synchronized (mLock) {
            return mCurrentAmplitude;
        }
    }

    /** Return {@code true} if this vibrator is under external control, false otherwise. */
    public boolean isUnderExternalControl() {
        synchronized (mLock) {
@@ -192,6 +211,9 @@ final class VibratorController {
            if (mVibratorInfo.hasCapability(IVibrator.CAP_AMPLITUDE_CONTROL)) {
                mNativeWrapper.setAmplitude(amplitude);
            }
            if (mIsVibrating) {
                mCurrentAmplitude = amplitude;
            }
        }
    }

@@ -208,6 +230,7 @@ final class VibratorController {
        synchronized (mLock) {
            long duration = mNativeWrapper.on(milliseconds, vibrationId);
            if (duration > 0) {
                mCurrentAmplitude = -1;
                notifyVibratorOnLocked();
            }
            return duration;
@@ -228,6 +251,7 @@ final class VibratorController {
            long duration = mNativeWrapper.perform(prebaked.getEffectId(),
                    prebaked.getEffectStrength(), vibrationId);
            if (duration > 0) {
                mCurrentAmplitude = -1;
                notifyVibratorOnLocked();
            }
            return duration;
@@ -250,6 +274,7 @@ final class VibratorController {
        synchronized (mLock) {
            long duration = mNativeWrapper.compose(primitives, vibrationId);
            if (duration > 0) {
                mCurrentAmplitude = -1;
                notifyVibratorOnLocked();
            }
            return duration;
@@ -272,6 +297,7 @@ final class VibratorController {
            int braking = mVibratorInfo.getDefaultBraking();
            long duration = mNativeWrapper.composePwle(primitives, braking, vibrationId);
            if (duration > 0) {
                mCurrentAmplitude = -1;
                notifyVibratorOnLocked();
            }
            return duration;
@@ -282,20 +308,24 @@ final class VibratorController {
    public void off() {
        synchronized (mLock) {
            mNativeWrapper.off();
            mCurrentAmplitude = 0;
            notifyVibratorOffLocked();
        }
    }

    @Override
    public String toString() {
        synchronized (mLock) {
            return "VibratorController{"
                    + "mVibratorInfo=" + mVibratorInfo
                    + ", mIsVibrating=" + mIsVibrating
                    + ", mCurrentAmplitude=" + mCurrentAmplitude
                    + ", mIsUnderExternalControl=" + mIsUnderExternalControl
                    + ", mVibratorStateListeners count="
                    + mVibratorStateListeners.getRegisteredCallbackCount()
                    + '}';
        }
    }

    @GuardedBy("mLock")
    private void notifyVibratorOnLocked() {
+21 −12
Original line number Diff line number Diff line
@@ -514,8 +514,9 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
                return Vibration.Status.FORWARDED_TO_INPUT_DEVICES;
            }

            VibrationThread vibThread = new VibrationThread(vib, mDeviceVibrationEffectAdapter,
                    mVibrators, mWakeLock, mBatteryStatsService, mVibrationCallbacks);
            VibrationThread vibThread = new VibrationThread(vib, mVibrationSettings,
                    mDeviceVibrationEffectAdapter, mVibrators, mWakeLock, mBatteryStatsService,
                    mVibrationCallbacks);

            if (mCurrentVibration == null) {
                return startVibrationThreadLocked(vibThread);
@@ -569,7 +570,6 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
        Trace.asyncTraceEnd(Trace.TRACE_TAG_VIBRATOR, "vibration", 0);
        try {
            Vibration vib = mCurrentVibration.getVibration();
            mCurrentVibration = null;
            endVibrationLocked(vib, status);
            finishAppOpModeLocked(vib.uid, vib.opPkg);
        } finally {
@@ -613,7 +613,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
            // Repeating vibrations always take precedence.
            return null;
        }
        if (mCurrentVibration != null) {
        if (mCurrentVibration != null && !mCurrentVibration.getVibration().hasEnded()) {
            if (mCurrentVibration.getVibration().attrs.getUsage()
                    == VibrationAttributes.USAGE_ALARM) {
                if (DEBUG) {
@@ -1003,15 +1003,25 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
        }

        @Override
        public void onVibrationEnded(long vibrationId, Vibration.Status status) {
        public void onVibrationCompleted(long vibrationId, Vibration.Status status) {
            if (DEBUG) {
                Slog.d(TAG, "Vibration " + vibrationId + " thread finished with status " + status);
                Slog.d(TAG, "Vibration " + vibrationId + " finished with status " + status);
            }
            synchronized (mLock) {
                if (mCurrentVibration != null
                        && mCurrentVibration.getVibration().id == vibrationId) {
                    reportFinishedVibrationLocked(status);
                }
            }
        }

        @Override
        public void onVibratorsReleased() {
            if (DEBUG) {
                Slog.d(TAG, "Vibrators released after finished vibration");
            }
            synchronized (mLock) {
                mCurrentVibration = null;
                if (mNextVibration != null) {
                    VibrationThread vibThread = mNextVibration;
                    mNextVibration = null;
@@ -1020,7 +1030,6 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
            }
        }
    }
    }

    /** Listener for synced vibration completion callbacks from native. */
    @VisibleForTesting
@@ -1337,7 +1346,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
                    // vibration that may be playing and ready the vibrator for external control.
                    if (mCurrentVibration != null) {
                        mNextVibration = null;
                        mCurrentVibration.cancel();
                        mCurrentVibration.cancelImmediately();
                        cancelingVibration = mCurrentVibration;
                    }
                } else {
Loading