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

Commit c25834c5 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Introduce primitive scale to vibrator adb" into main

parents 9a8a9152 6944e462
Loading
Loading
Loading
Loading
+89 −68
Original line number Original line Diff line number Diff line
@@ -61,6 +61,7 @@ import android.os.VibratorInfo;
import android.os.vibrator.Flags;
import android.os.vibrator.Flags;
import android.os.vibrator.IVibrationSessionCallback;
import android.os.vibrator.IVibrationSessionCallback;
import android.os.vibrator.PrebakedSegment;
import android.os.vibrator.PrebakedSegment;
import android.os.vibrator.PrimitiveSegment;
import android.os.vibrator.VibrationConfig;
import android.os.vibrator.VibrationConfig;
import android.os.vibrator.VibrationEffectSegment;
import android.os.vibrator.VibrationEffectSegment;
import android.os.vibrator.VibratorInfoFactory;
import android.os.vibrator.VibratorInfoFactory;
@@ -2672,7 +2673,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
            CombinedVibration.ParallelCombination combination =
            CombinedVibration.ParallelCombination combination =
                    CombinedVibration.startParallel();
                    CombinedVibration.startParallel();
            while ("-v".equals(getNextOption())) {
            while ("-v".equals(getNextOption())) {
                int vibratorId = Integer.parseInt(getNextArgRequired());
                int vibratorId = parseInt(getNextArgRequired(), "Expected vibrator id after -v");
                combination.addVibrator(vibratorId, nextEffect());
                combination.addVibrator(vibratorId, nextEffect());
            }
            }
            runVibrate(commonOptions, combination.combine());
            runVibrate(commonOptions, combination.combine());
@@ -2684,7 +2685,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
            CombinedVibration.SequentialCombination combination =
            CombinedVibration.SequentialCombination combination =
                    CombinedVibration.startSequential();
                    CombinedVibration.startSequential();
            while ("-v".equals(getNextOption())) {
            while ("-v".equals(getNextOption())) {
                int vibratorId = Integer.parseInt(getNextArgRequired());
                int vibratorId = parseInt(getNextArgRequired(), "Expected vibrator id after -v");
                combination.addNext(vibratorId, nextEffect());
                combination.addNext(vibratorId, nextEffect());
            }
            }
            runVibrate(commonOptions, combination.combine());
            runVibrate(commonOptions, combination.combine());
@@ -2709,7 +2710,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {


        private int runHapticFeedback() {
        private int runHapticFeedback() {
            CommonOptions commonOptions = new CommonOptions();
            CommonOptions commonOptions = new CommonOptions();
            int constant = Integer.parseInt(getNextArgRequired());
            int constant = parseInt(getNextArgRequired(), "Expected haptic feedback constant id");


            IBinder deathBinder = commonOptions.background ? VibratorManagerService.this
            IBinder deathBinder = commonOptions.background ? VibratorManagerService.this
                    : mShellCallbacksToken;
                    : mShellCallbacksToken;
@@ -2757,12 +2758,13 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
                if ("-a".equals(nextOption)) {
                if ("-a".equals(nextOption)) {
                    hasAmplitude = true;
                    hasAmplitude = true;
                } else if ("-w".equals(nextOption)) {
                } else if ("-w".equals(nextOption)) {
                    delay = Integer.parseInt(getNextArgRequired());
                    delay = parseInt(getNextArgRequired(), "Expected delay millis after -w");
                }
                }
            }
            }


            long duration = Long.parseLong(getNextArgRequired());
            long duration = parseInt(getNextArgRequired(), "Expected one-shot duration millis");
            int amplitude = hasAmplitude ? Integer.parseInt(getNextArgRequired())
            int amplitude = hasAmplitude
                    ? parseInt(getNextArgRequired(), "Expected one-shot amplitude")
                    : VibrationEffect.DEFAULT_AMPLITUDE;
                    : VibrationEffect.DEFAULT_AMPLITUDE;
            composition.addOffDuration(Duration.ofMillis(delay));
            composition.addOffDuration(Duration.ofMillis(delay));
            composition.addEffect(VibrationEffect.createOneShot(duration, amplitude));
            composition.addEffect(VibrationEffect.createOneShot(duration, amplitude));
@@ -2837,8 +2839,10 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
            while ((nextOption = getNextOption()) != null) {
            while ((nextOption = getNextOption()) != null) {
                switch (nextOption) {
                switch (nextOption) {
                    case "-a" -> isAdvanced = true;
                    case "-a" -> isAdvanced = true;
                    case "-i" -> initialSharpness = Float.parseFloat(getNextArgRequired());
                    case "-i" -> initialSharpness = parseFloat(getNextArgRequired(),
                    case "-r" -> repeat = Integer.parseInt(getNextArgRequired());
                            "Expected initial sharpness after -i");
                    case "-r" -> repeat = parseInt(getNextArgRequired(),
                            "Expected repeat index after -r");
                }
                }
            }
            }


@@ -2864,8 +2868,8 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
                    // nextArg is not a duration, finish reading.
                    // nextArg is not a duration, finish reading.
                    break;
                    break;
                }
                }
                intensity = Float.parseFloat(getNextArgRequired());
                intensity = parseFloat(getNextArgRequired(), "Expected envelope intensity");
                sharpness = Float.parseFloat(getNextArgRequired());
                sharpness = parseFloat(getNextArgRequired(), "Expected envelope sharpness");
                builder.addControlPoint(intensity, sharpness, duration);
                builder.addControlPoint(intensity, sharpness, duration);
                pos++;
                pos++;
            }
            }
@@ -2893,16 +2897,14 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
            getNextArgRequired(); // consume "waveform"
            getNextArgRequired(); // consume "waveform"
            String nextOption;
            String nextOption;
            while ((nextOption = getNextOption()) != null) {
            while ((nextOption = getNextOption()) != null) {
                if ("-a".equals(nextOption)) {
                switch (nextOption) {
                    hasAmplitudes = true;
                    case "-a" -> hasAmplitudes = true;
                } else if ("-r".equals(nextOption)) {
                    case "-f" -> hasFrequencies = true;
                    repeat = Integer.parseInt(getNextArgRequired());
                    case "-c" -> isContinuous = true;
                } else if ("-w".equals(nextOption)) {
                    case "-r" -> repeat = parseInt(getNextArgRequired(),
                    delay = Integer.parseInt(getNextArgRequired());
                            "Expected repeat index after -r");
                } else if ("-f".equals(nextOption)) {
                    case "-w" -> delay = parseInt(getNextArgRequired(),
                    hasFrequencies = true;
                            "Expected delay millis after -w");
                } else if ("-c".equals(nextOption)) {
                    isContinuous = true;
                }
                }
            }
            }
            List<Integer> durations = new ArrayList<>();
            List<Integer> durations = new ArrayList<>();
@@ -2920,14 +2922,15 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
                    break;
                    break;
                }
                }
                if (hasAmplitudes) {
                if (hasAmplitudes) {
                    amplitudes.add(
                    int amplitude = parseInt(getNextArgRequired(), "Expected waveform amplitude");
                            Float.parseFloat(getNextArgRequired()) / VibrationEffect.MAX_AMPLITUDE);
                    amplitudes.add((float) amplitude / VibrationEffect.MAX_AMPLITUDE);
                } else {
                } else {
                    amplitudes.add(nextAmplitude);
                    amplitudes.add(nextAmplitude);
                    nextAmplitude = 1 - nextAmplitude;
                    nextAmplitude = 1 - nextAmplitude;
                }
                }
                if (hasFrequencies) {
                if (hasFrequencies) {
                    frequencies.add(Float.parseFloat(getNextArgRequired()));
                    frequencies.add(
                            parseFloat(getNextArgRequired(), "Expected waveform frequency"));
                }
                }
            }
            }


@@ -2986,27 +2989,37 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
                if ("-b".equals(nextOption)) {
                if ("-b".equals(nextOption)) {
                    shouldFallback = true;
                    shouldFallback = true;
                } else if ("-w".equals(nextOption)) {
                } else if ("-w".equals(nextOption)) {
                    delay = Integer.parseInt(getNextArgRequired());
                    delay = parseInt(getNextArgRequired(), "Expected delay millis after -w");
                }
                }
            }
            }


            int effectId = Integer.parseInt(getNextArgRequired());
            int effectId = parseInt(getNextArgRequired(), "Expected prebaked effect id");
            composition.addOffDuration(Duration.ofMillis(delay));
            composition.addOffDuration(Duration.ofMillis(delay));
            composition.addEffect(VibrationEffect.get(effectId, shouldFallback));
            composition.addEffect(VibrationEffect.get(effectId, shouldFallback));
        }
        }


        private void addPrimitivesToComposition(VibrationEffect.Composition composition) {
        private void addPrimitivesToComposition(VibrationEffect.Composition composition) {
            getNextArgRequired(); // consume "primitives"
            getNextArgRequired(); // consume "primitives"
            String nextArg;
            while (peekNextArg() != null) {
            while ((nextArg = peekNextArg()) != null) {
                int delay = 0;
                int delay = 0;
                if ("-w".equals(nextArg)) {
                float scale = 1f;
                    getNextArgRequired(); // consume "-w"
                int delayType = PrimitiveSegment.DEFAULT_DELAY_TYPE;
                    delay = Integer.parseInt(getNextArgRequired());

                    nextArg = peekNextArg();
                String nextOption;
                while ((nextOption = getNextOption()) != null) {
                    if ("-s".equals(nextOption)) {
                        scale = parseFloat(getNextArgRequired(), "Expected scale after -s");
                    } else if ("-o".equals(nextOption)) {
                        delayType = VibrationEffect.Composition.DELAY_TYPE_RELATIVE_START_OFFSET;
                        delay = parseInt(getNextArgRequired(), "Expected offset millis after -o");
                    } else if ("-w".equals(nextOption)) {
                        delayType = PrimitiveSegment.DEFAULT_DELAY_TYPE;
                        delay = parseInt(getNextArgRequired(), "Expected delay millis after -w");
                    }
                }
                }
                try {
                try {
                    composition.addPrimitive(Integer.parseInt(nextArg), /* scale= */ 1, delay);
                    String nextArg = peekNextArg(); // Just in case this is not a primitive.
                    composition.addPrimitive(Integer.parseInt(nextArg), scale, delay, delayType);
                    getNextArgRequired(); // consume the primitive id
                    getNextArgRequired(); // consume the primitive id
                } catch (NumberFormatException | NullPointerException e) {
                } catch (NumberFormatException | NullPointerException e) {
                    // nextArg is not describing a primitive, leave it to be consumed by outer loops
                    // nextArg is not describing a primitive, leave it to be consumed by outer loops
@@ -3032,17 +3045,15 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
                        VibrationXmlParser.parseDocument(new StringReader(xml));
                        VibrationXmlParser.parseDocument(new StringReader(xml));
                VibratorInfo combinedVibratorInfo = getCombinedVibratorInfo();
                VibratorInfo combinedVibratorInfo = getCombinedVibratorInfo();
                if (combinedVibratorInfo == null) {
                if (combinedVibratorInfo == null) {
                    throw new IllegalStateException(
                    throw new IllegalStateException("No vibrator info available to parse XML");
                            "No combined vibrator info to parse vibration XML " + xml);
                }
                }
                VibrationEffect effect = parsedVibration.resolve(combinedVibratorInfo);
                VibrationEffect effect = parsedVibration.resolve(combinedVibratorInfo);
                if (effect == null) {
                if (effect == null) {
                    throw new IllegalArgumentException(
                    throw new IllegalArgumentException("Parsed XML cannot be resolved: " + xml);
                            "Parsed vibration cannot be resolved for vibration XML " + xml);
                }
                }
                return CombinedVibration.createParallel(effect);
                return CombinedVibration.createParallel(effect);
            } catch (IOException e) {
            } catch (IOException e) {
                throw new RuntimeException("Error parsing vibration XML " + xml, e);
                throw new RuntimeException("Error parsing XML: " + xml, e);
            }
            }
        }
        }


@@ -3060,16 +3071,30 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
            }
            }
        }
        }


        private static int parseInt(String text, String errorMessage) {
            try {
                return Integer.parseInt(text);
            } catch (NumberFormatException | NullPointerException e) {
                throw new IllegalArgumentException(errorMessage, e);
            }
        }

        private static float parseFloat(String text, String errorMessage) {
            try {
                return Float.parseFloat(text);
            } catch (NumberFormatException | NullPointerException e) {
                throw new IllegalArgumentException(errorMessage, e);
            }
        }

        @Override
        @Override
        public void onHelp() {
        public void onHelp() {
            try (PrintWriter pw = getOutPrintWriter();) {
            try (PrintWriter pw = getOutPrintWriter();) {
                pw.println("Vibrator Manager commands:");
                pw.println("Vibrator Manager commands:");
                pw.println("  help");
                pw.println("  help");
                pw.println("    Prints this help text.");
                pw.println("    Prints this help text.");
                pw.println("");
                pw.println("  list");
                pw.println("  list");
                pw.println("    Prints the id of device vibrators. This does not include any ");
                pw.println("    Prints device vibrator ids; does not include input devices.");
                pw.println("    connected input device.");
                pw.println("  synced [options] <effect>...");
                pw.println("  synced [options] <effect>...");
                pw.println("    Vibrates effect on all vibrators in sync.");
                pw.println("    Vibrates effect on all vibrators in sync.");
                pw.println("  combined [options] (-v <vibrator-id> <effect>...)...");
                pw.println("  combined [options] (-v <vibrator-id> <effect>...)...");
@@ -3079,51 +3104,41 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
                pw.println("  xml [options] <xml>");
                pw.println("  xml [options] <xml>");
                pw.println("    Vibrates using combined vibration described in given XML string");
                pw.println("    Vibrates using combined vibration described in given XML string");
                pw.println("    on all vibrators in sync. The XML could be:");
                pw.println("    on all vibrators in sync. The XML could be:");
                pw.println("        XML containing a single effect, or");
                pw.println("        A single <vibration-effect>, or");
                pw.println("        A vibration select XML containing multiple effects.");
                pw.println("        A <vibration-select> containing multiple effects.");
                pw.println("    Vibrates using combined vibration described in given XML string.");
                pw.println("  feedback [options] <constant>");
                pw.println("    XML containing a single effect it runs on all vibrators in sync.");
                pw.println("    Performs a haptic feedback with the given constant.");
                pw.println("  cancel");
                pw.println("  cancel");
                pw.println("    Cancels any active vibration");
                pw.println("    Cancels any active vibration");
                pw.println("  feedback [-f] [-d <description>] <constant>");
                pw.println("    Performs a haptic feedback with the given constant.");
                pw.println("    The force (-f) option enables the `always` configuration, which");
                pw.println("    plays the haptic irrespective of the vibration intensity settings");
                pw.println("");
                pw.println("");
                pw.println("Effect commands:");
                pw.println("Effect commands:");
                pw.println("  oneshot [-w delay] [-a] <duration> [<amplitude>]");
                pw.println("  oneshot [-w delay] [-a] <duration> [<amplitude>]");
                pw.println("    Vibrates for duration milliseconds; ignored when device is on ");
                pw.println("    Vibrates for duration milliseconds.");
                pw.println("    DND (Do Not Disturb) mode; touch feedback strength user setting ");
                pw.println("    will be used to scale amplitude.");
                pw.println("    If -w is provided, the effect will be played after the specified");
                pw.println("    If -w is provided, the effect will be played after the specified");
                pw.println("    wait time in milliseconds.");
                pw.println("    wait time in milliseconds.");
                pw.println("    If -a is provided, the command accepts a second argument for ");
                pw.println("    If -a is provided, the command accepts a second argument for ");
                pw.println("    amplitude, in a scale of 1-255.");
                pw.println("    amplitude, in a scale of 1-255.");
                pw.print("  waveform [-w delay] [-r index] [-a] [-f] [-c] ");
                pw.print("  waveform [-w delay] [-r index] [-a] [-f] [-c] ");
                pw.println("(<duration> [<amplitude>] [<frequency>])...");
                pw.println("(<duration> [<amplitude>] [<frequency>])...");
                pw.println("    Vibrates for durations and amplitudes in list; ignored when ");
                pw.println("    Vibrates for durations and amplitudes in list.");
                pw.println("    device is on DND (Do Not Disturb) mode; touch feedback strength ");
                pw.println("    user setting will be used to scale amplitude.");
                pw.println("    If -w is provided, the effect will be played after the specified");
                pw.println("    If -w is provided, the effect will be played after the specified");
                pw.println("    wait time in milliseconds.");
                pw.println("    wait time in milliseconds.");
                pw.println("    If -r is provided, the waveform loops back to the specified");
                pw.println("    If -r is provided, the waveform loops back to the specified");
                pw.println("    index (e.g. 0 loops from the beginning)");
                pw.println("    index (e.g. 0 loops from the beginning).");
                pw.println("    If -a is provided, the command expects amplitude to follow each");
                pw.println("    If -a is provided, the command expects amplitude to follow each");
                pw.println("    duration; otherwise, it accepts durations only and alternates");
                pw.println("    duration; otherwise, it accepts durations only and alternates");
                pw.println("    off/on");
                pw.println("    off/on.");
                pw.println("    If -f is provided, the command expects frequency to follow each");
                pw.println("    If -f is provided, the command expects frequency to follow each");
                pw.println("    amplitude or duration; otherwise, it uses resonant frequency");
                pw.println("    amplitude or duration; otherwise, it uses resonant frequency.");
                pw.println("    If -c is provided, the waveform is continuous and will ramp");
                pw.println("    If -c is provided, the waveform is continuous and will ramp");
                pw.println("    between values; otherwise each entry is a fixed step.");
                pw.println("    between values; otherwise each entry is a fixed step.");
                pw.println("    Duration is in milliseconds; amplitude is a scale of 1-255;");
                pw.println("    Duration is in milliseconds; amplitude is a scale of 1-255;");
                pw.println("    frequency is an absolute value in hertz;");
                pw.println("    frequency is an absolute value in hertz.");
                pw.print("  envelope [-a] [-i initial sharpness] [-r index]  ");
                pw.print("  envelope [-a] [-i initial sharpness] [-r index]  ");
                pw.println("[<duration1> <intensity1> <sharpness1>]...");
                pw.println("[<duration1> <intensity1> <sharpness1>]...");
                pw.println("    Generates a vibration pattern based on a series of duration, ");
                pw.println("    Generates a vibration pattern based on a series of duration, ");
                pw.println("    intensity, and sharpness values. The total vibration time is ");
                pw.println("    intensity, and sharpness values. The total vibration time is ");
                pw.println("    the sum of all durations; Ignored when device is on ");
                pw.println("    the sum of all durations.");
                pw.println("    DND (Do Not Disturb) mode; touch feedback strength user setting ");
                pw.println("    will be used to scale amplitude.");
                pw.println("    If -a is provided, the waveform will use the advanced APIs to ");
                pw.println("    If -a is provided, the waveform will use the advanced APIs to ");
                pw.println("    generate the vibration pattern and the input parameters ");
                pw.println("    generate the vibration pattern and the input parameters ");
                pw.println("    become [<duration1> <amplitude1> <frequency1>].");
                pw.println("    become [<duration1> <amplitude1> <frequency1>].");
@@ -3132,19 +3147,20 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
                pw.println("    If -r is provided, the waveform loops back to the specified index");
                pw.println("    If -r is provided, the waveform loops back to the specified index");
                pw.println("    (e.g. 0 loops from the beginning).");
                pw.println("    (e.g. 0 loops from the beginning).");
                pw.println("  prebaked [-w delay] [-b] <effect-id>");
                pw.println("  prebaked [-w delay] [-b] <effect-id>");
                pw.println("    Vibrates with prebaked effect; ignored when device is on DND ");
                pw.println("    Vibrates with prebaked effect.");
                pw.println("    (Do Not Disturb) mode; touch feedback strength user setting ");
                pw.println("    will be used to scale amplitude.");
                pw.println("    If -w is provided, the effect will be played after the specified");
                pw.println("    If -w is provided, the effect will be played after the specified");
                pw.println("    wait time in milliseconds.");
                pw.println("    wait time in milliseconds.");
                pw.println("    If -b is provided, the prebaked fallback effect will be played if");
                pw.println("    If -b is provided, the prebaked fallback effect will be played if");
                pw.println("    the device doesn't support the given effect-id.");
                pw.println("    the device doesn't support the given effect-id.");
                pw.println("  primitives ([-w delay] <primitive-id>)...");
                pw.print("  primitives ([-w delay] [-o time] [-s scale]");
                pw.println("    Vibrates with a composed effect; ignored when device is on DND ");
                pw.println("<primitive-id> [<scale>])...");
                pw.println("    (Do Not Disturb) mode; touch feedback strength user setting ");
                pw.println("    Vibrates with a composed effect.");
                pw.println("    will be used to scale primitive intensities.");
                pw.println("    If -w is provided, the next primitive will be played after the ");
                pw.println("    If -w is provided, the next primitive will be played after the ");
                pw.println("    specified wait time in milliseconds.");
                pw.println("    specified wait time in milliseconds.");
                pw.println("    If -o is provided, the next primitive will be played at the ");
                pw.println("    specified start offset time in milliseconds.");
                pw.println("    If -s is provided, the next primitive will be played with the");
                pw.println("    specified amplitude scale, in a scale of [0,1].");
                pw.println("");
                pw.println("");
                pw.println("Common Options:");
                pw.println("Common Options:");
                pw.println("  -f");
                pw.println("  -f");
@@ -3155,6 +3171,11 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
                pw.println("  -d <description>");
                pw.println("  -d <description>");
                pw.println("    Add description to the vibration.");
                pw.println("    Add description to the vibration.");
                pw.println("");
                pw.println("");
                pw.println("Notes");
                pw.println("    Vibrations triggered by these commands will be ignored when");
                pw.println("    device is on DND (Do Not Disturb) mode; notification strength");
                pw.println("    user settings will be applied for scale.");
                pw.println("");
            }
            }
        }
        }
    }
    }