Loading core/java/android/os/VibratorInfo.java +1 −1 Original line number Diff line number Diff line Loading @@ -371,7 +371,7 @@ public class VibratorInfo implements Parcelable { * supported or not. */ @Vibrator.VibrationEffectSupport public int isEffectSupported(@VibrationEffect.EffectType int effectId) { public int isEffectSupported(int effectId) { if (mSupportedEffects == null) { return Vibrator.VIBRATION_EFFECT_SUPPORT_UNKNOWN; } Loading services/core/java/com/android/server/vibrator/DeviceAdapter.java +5 −2 Original line number Diff line number Diff line Loading @@ -55,7 +55,8 @@ final class DeviceAdapter implements CombinedVibration.VibratorAdapter { DeviceAdapter(VibrationSettings settings, SparseArray<VibratorController> vibrators) { mSegmentAdapters = Arrays.asList( // TODO(b/167947076): add filter that replaces unsupported prebaked with fallback // Replace unsupported prebaked effects with fallback new PrebakedFallbackAdapter(settings.getFallbackEffects()), // Updates primitive delays to hardware supported pauses new PrimitiveDelayAdapter(), // Convert segments based on device capabilities Loading @@ -76,7 +77,9 @@ final class DeviceAdapter implements CombinedVibration.VibratorAdapter { // Validate Pwle segments base on the vibrators frequency range new PwleSegmentsValidator(), // Validate primitive segments based on device support new PrimitiveSegmentsValidator() new PrimitiveSegmentsValidator(), // Validate prebaked segments based on device support new PrebakedSegmentsValidator() ); mAvailableVibrators = vibrators; mAvailableVibratorIds = new int[vibrators.size()]; Loading services/core/java/com/android/server/vibrator/HalVibration.java +4 −0 Original line number Diff line number Diff line Loading @@ -38,6 +38,7 @@ import java.util.function.IntFunction; */ final class HalVibration extends Vibration { // TODO(b/409002423): remove this map once remove_hidl_support flag removed public final SparseArray<VibrationEffect> mFallbacks = new SparseArray<>(); /** A {@link CountDownLatch} to enable waiting for completion. */ Loading Loading @@ -91,6 +92,7 @@ final class HalVibration extends Vibration { * Add a fallback {@link VibrationEffect} to be played for each predefined effect id, which * might be necessary for replacement in realtime. */ // TODO(b/409002423): remove this method once remove_hidl_support flag removed public void fillFallbacks(IntFunction<VibrationEffect> fallbackProvider) { fillFallbacksForEffect(mEffectToPlay, fallbackProvider); } Loading Loading @@ -179,6 +181,7 @@ final class HalVibration extends Vibration { && vib.callerInfo.attrs.isFlagSet(VibrationAttributes.FLAG_PIPELINED_EFFECT); } // TODO(b/409002423): remove this method once remove_hidl_support flag removed private void fillFallbacksForEffect(CombinedVibration effect, IntFunction<VibrationEffect> fallbackProvider) { if (effect instanceof CombinedVibration.Mono) { Loading @@ -198,6 +201,7 @@ final class HalVibration extends Vibration { } } // TODO(b/409002423): remove this method once remove_hidl_support flag removed private void fillFallbacksForEffect(VibrationEffect effect, IntFunction<VibrationEffect> fallbackProvider) { if (!(effect instanceof VibrationEffect.Composed composed)) { Loading services/core/java/com/android/server/vibrator/PerformPrebakedVibratorStep.java +18 −14 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.server.vibrator; import android.annotation.NonNull; import android.os.Trace; import android.os.VibrationEffect; import android.os.vibrator.Flags; import android.os.vibrator.PrebakedSegment; import android.os.vibrator.VibrationEffectSegment; import android.util.Slog; Loading Loading @@ -62,19 +63,21 @@ final class PerformPrebakedVibratorStep extends AbstractComposedVibratorStep { + controller.getVibratorInfo().getId()); } VibrationEffect fallback = getVibration().getFallback(prebaked.getEffectId()); int stepId = conductor.nextVibratorCallbackStepId(getVibratorId()); long vibratorOnResult = controller.on(prebaked, getVibration().id, stepId); handleVibratorOnResult(vibratorOnResult); getVibration().stats.reportPerformEffect(vibratorOnResult, prebaked); if (!Flags.removeHidlSupport()) { VibrationEffect fallback = getVibration().getFallback(prebaked.getEffectId()); if (vibratorOnResult == 0 && prebaked.shouldFallback() && (fallback instanceof VibrationEffect.Composed)) { if (VibrationThread.DEBUG) { Slog.d(VibrationThread.TAG, "Playing fallback for effect " + VibrationEffect.effectIdToString(prebaked.getEffectId())); } AbstractVibratorStep fallbackStep = conductor.nextVibrateStep(startTime, controller, AbstractVibratorStep fallbackStep = conductor.nextVibrateStep(startTime, controller, replaceCurrentSegment((VibrationEffect.Composed) fallback), segmentIndex, mPendingVibratorOffDeadline); List<Step> fallbackResult = fallbackStep.play(); Loading @@ -83,6 +86,7 @@ final class PerformPrebakedVibratorStep extends AbstractComposedVibratorStep { handleVibratorOnResult(fallbackStep.getVibratorOnDuration()); return fallbackResult; } } return vibratorOnNextSteps(/* segmentsPlayed= */ 1); } finally { Loading services/core/java/com/android/server/vibrator/PrebakedFallbackAdapter.java 0 → 100644 +66 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.vibrator; import static android.os.Vibrator.VIBRATION_EFFECT_SUPPORT_YES; import android.os.VibrationEffect; import android.os.VibratorInfo; import android.os.vibrator.Flags; import android.os.vibrator.PrebakedSegment; import android.os.vibrator.VibrationEffectSegment; import android.util.SparseArray; import java.util.List; /** Adapter that replaces unsupported {@link PrebakedSegment} with fallback. */ final class PrebakedFallbackAdapter implements VibrationSegmentsAdapter { private final SparseArray<VibrationEffect> mFallbackEffects; PrebakedFallbackAdapter(SparseArray<VibrationEffect> fallbackEffects) { mFallbackEffects = fallbackEffects; } @Override public int adaptToVibrator(VibratorInfo info, List<VibrationEffectSegment> segments, int repeatIndex) { if (!Flags.removeHidlSupport()) { return repeatIndex; } for (int i = 0; i < segments.size(); i++) { if (!(segments.get(i) instanceof PrebakedSegment prebaked)) { continue; } int effectId = prebaked.getEffectId(); if (info.isEffectSupported(effectId) == VIBRATION_EFFECT_SUPPORT_YES || !prebaked.shouldFallback()) { continue; } if (!(mFallbackEffects.get(effectId) instanceof VibrationEffect.Composed fallback)) { continue; } segments.remove(i); segments.addAll(i, fallback.getSegments()); int segmentsAdded = fallback.getSegments().size() - 1; if (repeatIndex > i) { repeatIndex += segmentsAdded; } i += segmentsAdded; } return repeatIndex; } } Loading
core/java/android/os/VibratorInfo.java +1 −1 Original line number Diff line number Diff line Loading @@ -371,7 +371,7 @@ public class VibratorInfo implements Parcelable { * supported or not. */ @Vibrator.VibrationEffectSupport public int isEffectSupported(@VibrationEffect.EffectType int effectId) { public int isEffectSupported(int effectId) { if (mSupportedEffects == null) { return Vibrator.VIBRATION_EFFECT_SUPPORT_UNKNOWN; } Loading
services/core/java/com/android/server/vibrator/DeviceAdapter.java +5 −2 Original line number Diff line number Diff line Loading @@ -55,7 +55,8 @@ final class DeviceAdapter implements CombinedVibration.VibratorAdapter { DeviceAdapter(VibrationSettings settings, SparseArray<VibratorController> vibrators) { mSegmentAdapters = Arrays.asList( // TODO(b/167947076): add filter that replaces unsupported prebaked with fallback // Replace unsupported prebaked effects with fallback new PrebakedFallbackAdapter(settings.getFallbackEffects()), // Updates primitive delays to hardware supported pauses new PrimitiveDelayAdapter(), // Convert segments based on device capabilities Loading @@ -76,7 +77,9 @@ final class DeviceAdapter implements CombinedVibration.VibratorAdapter { // Validate Pwle segments base on the vibrators frequency range new PwleSegmentsValidator(), // Validate primitive segments based on device support new PrimitiveSegmentsValidator() new PrimitiveSegmentsValidator(), // Validate prebaked segments based on device support new PrebakedSegmentsValidator() ); mAvailableVibrators = vibrators; mAvailableVibratorIds = new int[vibrators.size()]; Loading
services/core/java/com/android/server/vibrator/HalVibration.java +4 −0 Original line number Diff line number Diff line Loading @@ -38,6 +38,7 @@ import java.util.function.IntFunction; */ final class HalVibration extends Vibration { // TODO(b/409002423): remove this map once remove_hidl_support flag removed public final SparseArray<VibrationEffect> mFallbacks = new SparseArray<>(); /** A {@link CountDownLatch} to enable waiting for completion. */ Loading Loading @@ -91,6 +92,7 @@ final class HalVibration extends Vibration { * Add a fallback {@link VibrationEffect} to be played for each predefined effect id, which * might be necessary for replacement in realtime. */ // TODO(b/409002423): remove this method once remove_hidl_support flag removed public void fillFallbacks(IntFunction<VibrationEffect> fallbackProvider) { fillFallbacksForEffect(mEffectToPlay, fallbackProvider); } Loading Loading @@ -179,6 +181,7 @@ final class HalVibration extends Vibration { && vib.callerInfo.attrs.isFlagSet(VibrationAttributes.FLAG_PIPELINED_EFFECT); } // TODO(b/409002423): remove this method once remove_hidl_support flag removed private void fillFallbacksForEffect(CombinedVibration effect, IntFunction<VibrationEffect> fallbackProvider) { if (effect instanceof CombinedVibration.Mono) { Loading @@ -198,6 +201,7 @@ final class HalVibration extends Vibration { } } // TODO(b/409002423): remove this method once remove_hidl_support flag removed private void fillFallbacksForEffect(VibrationEffect effect, IntFunction<VibrationEffect> fallbackProvider) { if (!(effect instanceof VibrationEffect.Composed composed)) { Loading
services/core/java/com/android/server/vibrator/PerformPrebakedVibratorStep.java +18 −14 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.server.vibrator; import android.annotation.NonNull; import android.os.Trace; import android.os.VibrationEffect; import android.os.vibrator.Flags; import android.os.vibrator.PrebakedSegment; import android.os.vibrator.VibrationEffectSegment; import android.util.Slog; Loading Loading @@ -62,19 +63,21 @@ final class PerformPrebakedVibratorStep extends AbstractComposedVibratorStep { + controller.getVibratorInfo().getId()); } VibrationEffect fallback = getVibration().getFallback(prebaked.getEffectId()); int stepId = conductor.nextVibratorCallbackStepId(getVibratorId()); long vibratorOnResult = controller.on(prebaked, getVibration().id, stepId); handleVibratorOnResult(vibratorOnResult); getVibration().stats.reportPerformEffect(vibratorOnResult, prebaked); if (!Flags.removeHidlSupport()) { VibrationEffect fallback = getVibration().getFallback(prebaked.getEffectId()); if (vibratorOnResult == 0 && prebaked.shouldFallback() && (fallback instanceof VibrationEffect.Composed)) { if (VibrationThread.DEBUG) { Slog.d(VibrationThread.TAG, "Playing fallback for effect " + VibrationEffect.effectIdToString(prebaked.getEffectId())); } AbstractVibratorStep fallbackStep = conductor.nextVibrateStep(startTime, controller, AbstractVibratorStep fallbackStep = conductor.nextVibrateStep(startTime, controller, replaceCurrentSegment((VibrationEffect.Composed) fallback), segmentIndex, mPendingVibratorOffDeadline); List<Step> fallbackResult = fallbackStep.play(); Loading @@ -83,6 +86,7 @@ final class PerformPrebakedVibratorStep extends AbstractComposedVibratorStep { handleVibratorOnResult(fallbackStep.getVibratorOnDuration()); return fallbackResult; } } return vibratorOnNextSteps(/* segmentsPlayed= */ 1); } finally { Loading
services/core/java/com/android/server/vibrator/PrebakedFallbackAdapter.java 0 → 100644 +66 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.vibrator; import static android.os.Vibrator.VIBRATION_EFFECT_SUPPORT_YES; import android.os.VibrationEffect; import android.os.VibratorInfo; import android.os.vibrator.Flags; import android.os.vibrator.PrebakedSegment; import android.os.vibrator.VibrationEffectSegment; import android.util.SparseArray; import java.util.List; /** Adapter that replaces unsupported {@link PrebakedSegment} with fallback. */ final class PrebakedFallbackAdapter implements VibrationSegmentsAdapter { private final SparseArray<VibrationEffect> mFallbackEffects; PrebakedFallbackAdapter(SparseArray<VibrationEffect> fallbackEffects) { mFallbackEffects = fallbackEffects; } @Override public int adaptToVibrator(VibratorInfo info, List<VibrationEffectSegment> segments, int repeatIndex) { if (!Flags.removeHidlSupport()) { return repeatIndex; } for (int i = 0; i < segments.size(); i++) { if (!(segments.get(i) instanceof PrebakedSegment prebaked)) { continue; } int effectId = prebaked.getEffectId(); if (info.isEffectSupported(effectId) == VIBRATION_EFFECT_SUPPORT_YES || !prebaked.shouldFallback()) { continue; } if (!(mFallbackEffects.get(effectId) instanceof VibrationEffect.Composed fallback)) { continue; } segments.remove(i); segments.addAll(i, fallback.getSegments()); int segmentsAdded = fallback.getSegments().size() - 1; if (repeatIndex > i) { repeatIndex += segmentsAdded; } i += segmentsAdded; } return repeatIndex; } }