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

Commit 12d3916a authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Refactor InputManager service for input rumble support."

parents 20c97e4f 6f0311bf
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import android.hardware.input.IInputDevicesChangedListener;
import android.hardware.input.ITabletModeChangedListener;
import android.hardware.input.TouchCalibration;
import android.os.IBinder;
import android.os.VibrationEffect;
import android.view.InputDevice;
import android.view.InputEvent;
import android.view.InputMonitor;
@@ -83,7 +84,7 @@ interface IInputManager {
    int isMicMuted();

    // Input device vibrator control.
    void vibrate(int deviceId, in long[] pattern, in int[] amplitudes, int repeat, IBinder token);
    void vibrate(int deviceId, in VibrationEffect effect, IBinder token);
    void cancelVibrate(int deviceId, IBinder token);

    void setPointerIconType(int typeId);
+1 −20
Original line number Diff line number Diff line
@@ -1297,27 +1297,8 @@ public final class InputManager {
        @Override
        public void vibrate(int uid, String opPkg, VibrationEffect effect,
                String reason, AudioAttributes attributes) {
            long[] pattern;
            int[] amplitudes;
            int repeat;
            if (effect instanceof VibrationEffect.OneShot) {
                VibrationEffect.OneShot oneShot = (VibrationEffect.OneShot) effect;
                pattern = new long[] { 0, oneShot.getDuration() };
                amplitudes = new int[] { 0, oneShot.getAmplitude() };
                repeat = -1;
            } else if (effect instanceof VibrationEffect.Waveform) {
                VibrationEffect.Waveform waveform = (VibrationEffect.Waveform) effect;
                pattern = waveform.getTimings();
                amplitudes = waveform.getAmplitudes();
                repeat = waveform.getRepeatIndex();
            } else {
                // TODO: Add support for prebaked effects
                Log.w(TAG, "Pre-baked effects aren't supported on input devices");
                return;
            }

            try {
                mIm.vibrate(mDeviceId, pattern, amplitudes, repeat, mToken);
                mIm.vibrate(mDeviceId, effect, mToken);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
+34 −2
Original line number Diff line number Diff line
@@ -63,6 +63,7 @@ import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ShellCallback;
import android.os.UserHandle;
import android.os.VibrationEffect;
import android.provider.DeviceConfig;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
@@ -141,6 +142,8 @@ public class InputManagerService extends IInputManager.Stub
    private static final int MSG_RELOAD_DEVICE_ALIASES = 5;
    private static final int MSG_DELIVER_TABLET_MODE_CHANGED = 6;

    private static final int DEFAULT_VIBRATION_MAGNITUDE = 192;

    // Pointer to native input manager service object.
    private final long mPtr;

@@ -1728,7 +1731,37 @@ public class InputManagerService extends IInputManager.Stub

    // Binder call
    @Override
    public void vibrate(int deviceId, long[] pattern, int[] amplitudes, int repeat, IBinder token) {
    public void vibrate(int deviceId, VibrationEffect effect, IBinder token) {
        long[] pattern;
        int[] amplitudes;
        int repeat;
        if (effect instanceof VibrationEffect.OneShot) {
            VibrationEffect.OneShot oneShot = (VibrationEffect.OneShot) effect;
            pattern = new long[] { 0, oneShot.getDuration() };
            int amplitude = oneShot.getAmplitude();
            // android framework uses DEFAULT_AMPLITUDE to signal that the vibration
            // should use some built-in default value, denoted here as DEFAULT_VIBRATION_MAGNITUDE
            if (amplitude == VibrationEffect.DEFAULT_AMPLITUDE) {
                amplitude = DEFAULT_VIBRATION_MAGNITUDE;
            }
            amplitudes = new int[] { 0, amplitude };
            repeat = -1;
        } else if (effect instanceof VibrationEffect.Waveform) {
            VibrationEffect.Waveform waveform = (VibrationEffect.Waveform) effect;
            pattern = waveform.getTimings();
            amplitudes = waveform.getAmplitudes();
            for (int i = 0; i < amplitudes.length; i++) {
                if (amplitudes[i] == VibrationEffect.DEFAULT_AMPLITUDE) {
                    amplitudes[i] = DEFAULT_VIBRATION_MAGNITUDE;
                }
            }
            repeat = waveform.getRepeatIndex();
        } else {
            // TODO: Add support for prebaked effects
            Log.w(TAG, "Pre-baked effects aren't supported on input devices");
            return;
        }

        if (repeat >= pattern.length) {
            throw new ArrayIndexOutOfBoundsException();
        }
@@ -1747,7 +1780,6 @@ public class InputManagerService extends IInputManager.Stub
                mVibratorTokens.put(token, v);
            }
        }

        synchronized (v) {
            v.mVibrating = true;
            nativeVibrate(mPtr, deviceId, pattern, amplitudes, repeat, v.mTokenValue);
+14 −6
Original line number Diff line number Diff line
@@ -75,6 +75,12 @@
using android::base::ParseUint;
using android::base::StringPrintf;

// Maximum allowable delay value in a vibration pattern before
// which the delay will be truncated.
static constexpr std::chrono::duration MAX_VIBRATE_PATTERN_DELAY = 100s;
static constexpr std::chrono::milliseconds MAX_VIBRATE_PATTERN_DELAY_MILLIS =
        std::chrono::duration_cast<std::chrono::milliseconds>(MAX_VIBRATE_PATTERN_DELAY);

namespace android {

// The exponent used to calculate the pointer speed scaling factor.
@@ -1636,17 +1642,19 @@ static void nativeVibrate(JNIEnv* env, jclass /* clazz */, jlong ptr, jint devic
            patternObj, nullptr));
    jint* amplitudes = static_cast<jint*>(env->GetPrimitiveArrayCritical(amplitudesObj, nullptr));

    std::vector<VibrationElement> pattern(patternSize);
    std::vector<VibrationElement> elements(patternSize);
    for (size_t i = 0; i < patternSize; i++) {
        jlong duration =
                max(min(patternMillis[i], (jlong)MAX_VIBRATE_PATTERN_DELAY_MSECS), (jlong)0);
        pattern[i].duration = std::chrono::milliseconds(duration);
        pattern[i].channels = {amplitudes[i]};
        // VibrationEffect.validate guarantees duration > 0.
        std::chrono::milliseconds duration(patternMillis[i]);
        elements[i].duration = std::min(duration, MAX_VIBRATE_PATTERN_DELAY_MILLIS);
        // TODO: (b/161629089) apply channel specific amplitudes from development API.
        elements[i].channels = {static_cast<uint8_t>(amplitudes[i]),
                                static_cast<uint8_t>(amplitudes[i])};
    }
    env->ReleasePrimitiveArrayCritical(patternObj, patternMillis, JNI_ABORT);
    env->ReleasePrimitiveArrayCritical(amplitudesObj, amplitudes, JNI_ABORT);

    im->getInputManager()->getReader()->vibrate(deviceId, pattern, repeat, token);
    im->getInputManager()->getReader()->vibrate(deviceId, elements, repeat, token);
}

static void nativeCancelVibrate(JNIEnv* /* env */,