Loading core/java/android/os/vibrator/VibrationConfig.java +63 −5 Original line number Diff line number Diff line Loading @@ -30,13 +30,17 @@ import static android.os.VibrationAttributes.USAGE_UNKNOWN; import android.annotation.Nullable; import android.content.res.Resources; import android.os.SystemProperties; import android.os.VibrationAttributes; import android.os.Vibrator; import android.os.Vibrator.VibrationIntensity; import android.util.IndentingPrintWriter; import com.android.internal.annotations.VisibleForTesting; import java.io.PrintWriter; import java.util.Arrays; import java.util.function.Function; /** * List of device-specific internal vibration configuration loaded from platform config.xml. Loading @@ -49,6 +53,37 @@ import java.util.Arrays; */ public class VibrationConfig { /** * The default gain to be applied between vibration scale levels. * * <p>Scale levels are defined as the difference between the user vibration intensity setting * and the device default config for each usage. The intensity values are defined as one of * Vibrator.VIBRATION_INTENSITY_*. * * <p>A user setting HIGH set on a device with default value LOW will cause the vibration * intensity to be scaled up 2 levels, i.e. scale with a factor of gain^2. A system with 3 * intensities LOW, MEDIUM and HIGH has the following 5 scale levels: * * <ol> * <li>VERY_HIGH: user(HIGH) - device(LOW) * <li>HIGH: user(HIGH) - device(MEDIUM) / user(MEDIUM) - device(LOW) * <li>NONE: user == device * <li>LOW: user(MEDIUM) - device(HIGH) / user(LOW) - device(MEDIUM) * <li>VERY_LOW: user(LOW) - device(HIGH) * </ol> * * <p>A device will only ever apply 3 out of these 5 levels based on the default intensity * config set for each usage (e.g. config_default[Alarm|Ring|Notification]VibrationIntensity). * * <p>This value must be greater than 1. The {@link #DEFAULT_SCALE_LEVEL_GAIN} will be used if * this property is undefined or invalid. * * @hide */ @VisibleForTesting static final String SCALE_LEVEL_GAIN_SYSTEM_PROPERTY = "vendor.vibrator.scale.level.gain"; /** * Hardcoded default scale level gain to be applied between each scale level to define their * scale factor value. Loading @@ -69,7 +104,7 @@ public class VibrationConfig { private final int mRampDownDurationMs; private final int mRequestVibrationParamsTimeoutMs; private final int[] mRequestVibrationParamsForUsages; private final float mDefaultVibrationScaleLevelGain; private final boolean mIgnoreVibrationsOnWirelessCharger; @VibrationIntensity Loading @@ -89,8 +124,18 @@ public class VibrationConfig { /** @hide */ public VibrationConfig(@Nullable Resources resources) { mDefaultVibrationAmplitude = resources.getInteger( com.android.internal.R.integer.config_defaultVibrationAmplitude); this(resources, SystemProperties::get); } /** @hide */ @VisibleForTesting public VibrationConfig(@Nullable Resources resources, Function<String, String> systemPropertiesGetter) { mDefaultVibrationAmplitude = loadInteger(resources, com.android.internal.R.integer.config_defaultVibrationAmplitude, DEFAULT_AMPLITUDE); mDefaultVibrationScaleLevelGain = loadFloat(systemPropertiesGetter, SCALE_LEVEL_GAIN_SYSTEM_PROPERTY, DEFAULT_SCALE_LEVEL_GAIN); mHapticChannelMaxVibrationAmplitude = loadFloat(resources, com.android.internal.R.dimen.config_hapticChannelMaxVibrationAmplitude); mRampDownDurationMs = loadInteger(resources, Loading Loading @@ -135,6 +180,15 @@ public class VibrationConfig { return res != null ? res.getFloat(resId) : 0f; } private static float loadFloat(Function<String, String> systemPropertiesGetter, String propertyKey, float defaultValue) { try { return Float.parseFloat(systemPropertiesGetter.apply(propertyKey)); } catch (Exception e) { return defaultValue; } } private static int loadInteger(@Nullable Resources res, int resId, int defaultValue) { return res != null ? res.getInteger(resId) : defaultValue; } Loading Loading @@ -176,9 +230,11 @@ public class VibrationConfig { * for each level. */ public float getDefaultVibrationScaleLevelGain() { // TODO(b/356407380): add device config for this if (mDefaultVibrationScaleLevelGain <= 1) { return DEFAULT_SCALE_LEVEL_GAIN; } return mDefaultVibrationScaleLevelGain; } /** * The duration, in milliseconds, that should be applied to the ramp to turn off the vibrator Loading Loading @@ -270,6 +326,7 @@ public class VibrationConfig { return "VibrationConfig{" + "mIgnoreVibrationsOnWirelessCharger=" + mIgnoreVibrationsOnWirelessCharger + ", mDefaultVibrationAmplitude=" + mDefaultVibrationAmplitude + ", mDefaultVibrationScaleLevelGain=" + mDefaultVibrationScaleLevelGain + ", mHapticChannelMaxVibrationAmplitude=" + mHapticChannelMaxVibrationAmplitude + ", mRampStepDurationMs=" + mRampStepDurationMs + ", mRampDownDurationMs=" + mRampDownDurationMs Loading @@ -296,6 +353,7 @@ public class VibrationConfig { pw.increaseIndent(); pw.println("ignoreVibrationsOnWirelessCharger = " + mIgnoreVibrationsOnWirelessCharger); pw.println("defaultVibrationAmplitude = " + mDefaultVibrationAmplitude); pw.println("defaultVibrationScaleLevelGain = " + mDefaultVibrationScaleLevelGain); pw.println("hapticChannelMaxAmplitude = " + mHapticChannelMaxVibrationAmplitude); pw.println("rampStepDurationMs = " + mRampStepDurationMs); pw.println("rampDownDurationMs = " + mRampDownDurationMs); Loading core/tests/vibrator/src/android/os/vibrator/VibrationConfigTest.java 0 → 100644 +100 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 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 android.os.vibrator; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.when; import android.content.res.Resources; import com.android.internal.R; import org.junit.Rule; import org.junit.Test; import org.mockito.Mock; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; import java.util.HashMap; import java.util.Map; public class VibrationConfigTest { @Rule public MockitoRule rule = MockitoJUnit.rule(); @Mock private Resources mResourcesMock; private final Map<String, String> mSystemProperties = new HashMap<>(); @Test public void getDefaultVibrationAmplitude_returnsConfiguredAmplitude() { when(mResourcesMock.getInteger(R.integer.config_defaultVibrationAmplitude)).thenReturn(1); assertThat(createConfig().getDefaultVibrationAmplitude()).isEqualTo(1); when(mResourcesMock.getInteger(R.integer.config_defaultVibrationAmplitude)).thenReturn(123); assertThat(createConfig().getDefaultVibrationAmplitude()).isEqualTo(123); when(mResourcesMock.getInteger(R.integer.config_defaultVibrationAmplitude)).thenReturn(255); assertThat(createConfig().getDefaultVibrationAmplitude()).isEqualTo(255); } @Test public void getDefaultVibrationAmplitude_invalidValue_returnsMaxAmplitude() { when(mResourcesMock.getInteger(R.integer.config_defaultVibrationAmplitude)).thenReturn(-1); assertThat(createConfig().getDefaultVibrationAmplitude()).isEqualTo(255); when(mResourcesMock.getInteger(R.integer.config_defaultVibrationAmplitude)).thenReturn(0); assertThat(createConfig().getDefaultVibrationAmplitude()).isEqualTo(255); when(mResourcesMock.getInteger(R.integer.config_defaultVibrationAmplitude)).thenReturn(500); assertThat(createConfig().getDefaultVibrationAmplitude()).isEqualTo(255); } @Test public void getDefaultVibrationScaleLevelGain_returnsConfiguredGain() { mSystemProperties.put(VibrationConfig.SCALE_LEVEL_GAIN_SYSTEM_PROPERTY, "1.2"); assertThat(createConfig().getDefaultVibrationScaleLevelGain()).isEqualTo(1.2f); mSystemProperties.put(VibrationConfig.SCALE_LEVEL_GAIN_SYSTEM_PROPERTY, "2"); assertThat(createConfig().getDefaultVibrationScaleLevelGain()).isEqualTo(2f); } @Test public void getDefaultVibrationScaleLevelGain_invalidValue_returnsFixedScaleGain() { mSystemProperties.put(VibrationConfig.SCALE_LEVEL_GAIN_SYSTEM_PROPERTY, ""); assertThat(createConfig().getDefaultVibrationScaleLevelGain()).isEqualTo(1.4f); mSystemProperties.put(VibrationConfig.SCALE_LEVEL_GAIN_SYSTEM_PROPERTY, "invalid"); assertThat(createConfig().getDefaultVibrationScaleLevelGain()).isEqualTo(1.4f); mSystemProperties.put(VibrationConfig.SCALE_LEVEL_GAIN_SYSTEM_PROPERTY, "-1"); assertThat(createConfig().getDefaultVibrationScaleLevelGain()).isEqualTo(1.4f); mSystemProperties.put(VibrationConfig.SCALE_LEVEL_GAIN_SYSTEM_PROPERTY, "0.5"); assertThat(createConfig().getDefaultVibrationScaleLevelGain()).isEqualTo(1.4f); mSystemProperties.put(VibrationConfig.SCALE_LEVEL_GAIN_SYSTEM_PROPERTY, "1.0"); assertThat(createConfig().getDefaultVibrationScaleLevelGain()).isEqualTo(1.4f); } private VibrationConfig createConfig() { return new VibrationConfig(mResourcesMock, mSystemProperties::get); } } Loading
core/java/android/os/vibrator/VibrationConfig.java +63 −5 Original line number Diff line number Diff line Loading @@ -30,13 +30,17 @@ import static android.os.VibrationAttributes.USAGE_UNKNOWN; import android.annotation.Nullable; import android.content.res.Resources; import android.os.SystemProperties; import android.os.VibrationAttributes; import android.os.Vibrator; import android.os.Vibrator.VibrationIntensity; import android.util.IndentingPrintWriter; import com.android.internal.annotations.VisibleForTesting; import java.io.PrintWriter; import java.util.Arrays; import java.util.function.Function; /** * List of device-specific internal vibration configuration loaded from platform config.xml. Loading @@ -49,6 +53,37 @@ import java.util.Arrays; */ public class VibrationConfig { /** * The default gain to be applied between vibration scale levels. * * <p>Scale levels are defined as the difference between the user vibration intensity setting * and the device default config for each usage. The intensity values are defined as one of * Vibrator.VIBRATION_INTENSITY_*. * * <p>A user setting HIGH set on a device with default value LOW will cause the vibration * intensity to be scaled up 2 levels, i.e. scale with a factor of gain^2. A system with 3 * intensities LOW, MEDIUM and HIGH has the following 5 scale levels: * * <ol> * <li>VERY_HIGH: user(HIGH) - device(LOW) * <li>HIGH: user(HIGH) - device(MEDIUM) / user(MEDIUM) - device(LOW) * <li>NONE: user == device * <li>LOW: user(MEDIUM) - device(HIGH) / user(LOW) - device(MEDIUM) * <li>VERY_LOW: user(LOW) - device(HIGH) * </ol> * * <p>A device will only ever apply 3 out of these 5 levels based on the default intensity * config set for each usage (e.g. config_default[Alarm|Ring|Notification]VibrationIntensity). * * <p>This value must be greater than 1. The {@link #DEFAULT_SCALE_LEVEL_GAIN} will be used if * this property is undefined or invalid. * * @hide */ @VisibleForTesting static final String SCALE_LEVEL_GAIN_SYSTEM_PROPERTY = "vendor.vibrator.scale.level.gain"; /** * Hardcoded default scale level gain to be applied between each scale level to define their * scale factor value. Loading @@ -69,7 +104,7 @@ public class VibrationConfig { private final int mRampDownDurationMs; private final int mRequestVibrationParamsTimeoutMs; private final int[] mRequestVibrationParamsForUsages; private final float mDefaultVibrationScaleLevelGain; private final boolean mIgnoreVibrationsOnWirelessCharger; @VibrationIntensity Loading @@ -89,8 +124,18 @@ public class VibrationConfig { /** @hide */ public VibrationConfig(@Nullable Resources resources) { mDefaultVibrationAmplitude = resources.getInteger( com.android.internal.R.integer.config_defaultVibrationAmplitude); this(resources, SystemProperties::get); } /** @hide */ @VisibleForTesting public VibrationConfig(@Nullable Resources resources, Function<String, String> systemPropertiesGetter) { mDefaultVibrationAmplitude = loadInteger(resources, com.android.internal.R.integer.config_defaultVibrationAmplitude, DEFAULT_AMPLITUDE); mDefaultVibrationScaleLevelGain = loadFloat(systemPropertiesGetter, SCALE_LEVEL_GAIN_SYSTEM_PROPERTY, DEFAULT_SCALE_LEVEL_GAIN); mHapticChannelMaxVibrationAmplitude = loadFloat(resources, com.android.internal.R.dimen.config_hapticChannelMaxVibrationAmplitude); mRampDownDurationMs = loadInteger(resources, Loading Loading @@ -135,6 +180,15 @@ public class VibrationConfig { return res != null ? res.getFloat(resId) : 0f; } private static float loadFloat(Function<String, String> systemPropertiesGetter, String propertyKey, float defaultValue) { try { return Float.parseFloat(systemPropertiesGetter.apply(propertyKey)); } catch (Exception e) { return defaultValue; } } private static int loadInteger(@Nullable Resources res, int resId, int defaultValue) { return res != null ? res.getInteger(resId) : defaultValue; } Loading Loading @@ -176,9 +230,11 @@ public class VibrationConfig { * for each level. */ public float getDefaultVibrationScaleLevelGain() { // TODO(b/356407380): add device config for this if (mDefaultVibrationScaleLevelGain <= 1) { return DEFAULT_SCALE_LEVEL_GAIN; } return mDefaultVibrationScaleLevelGain; } /** * The duration, in milliseconds, that should be applied to the ramp to turn off the vibrator Loading Loading @@ -270,6 +326,7 @@ public class VibrationConfig { return "VibrationConfig{" + "mIgnoreVibrationsOnWirelessCharger=" + mIgnoreVibrationsOnWirelessCharger + ", mDefaultVibrationAmplitude=" + mDefaultVibrationAmplitude + ", mDefaultVibrationScaleLevelGain=" + mDefaultVibrationScaleLevelGain + ", mHapticChannelMaxVibrationAmplitude=" + mHapticChannelMaxVibrationAmplitude + ", mRampStepDurationMs=" + mRampStepDurationMs + ", mRampDownDurationMs=" + mRampDownDurationMs Loading @@ -296,6 +353,7 @@ public class VibrationConfig { pw.increaseIndent(); pw.println("ignoreVibrationsOnWirelessCharger = " + mIgnoreVibrationsOnWirelessCharger); pw.println("defaultVibrationAmplitude = " + mDefaultVibrationAmplitude); pw.println("defaultVibrationScaleLevelGain = " + mDefaultVibrationScaleLevelGain); pw.println("hapticChannelMaxAmplitude = " + mHapticChannelMaxVibrationAmplitude); pw.println("rampStepDurationMs = " + mRampStepDurationMs); pw.println("rampDownDurationMs = " + mRampDownDurationMs); Loading
core/tests/vibrator/src/android/os/vibrator/VibrationConfigTest.java 0 → 100644 +100 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 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 android.os.vibrator; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.when; import android.content.res.Resources; import com.android.internal.R; import org.junit.Rule; import org.junit.Test; import org.mockito.Mock; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; import java.util.HashMap; import java.util.Map; public class VibrationConfigTest { @Rule public MockitoRule rule = MockitoJUnit.rule(); @Mock private Resources mResourcesMock; private final Map<String, String> mSystemProperties = new HashMap<>(); @Test public void getDefaultVibrationAmplitude_returnsConfiguredAmplitude() { when(mResourcesMock.getInteger(R.integer.config_defaultVibrationAmplitude)).thenReturn(1); assertThat(createConfig().getDefaultVibrationAmplitude()).isEqualTo(1); when(mResourcesMock.getInteger(R.integer.config_defaultVibrationAmplitude)).thenReturn(123); assertThat(createConfig().getDefaultVibrationAmplitude()).isEqualTo(123); when(mResourcesMock.getInteger(R.integer.config_defaultVibrationAmplitude)).thenReturn(255); assertThat(createConfig().getDefaultVibrationAmplitude()).isEqualTo(255); } @Test public void getDefaultVibrationAmplitude_invalidValue_returnsMaxAmplitude() { when(mResourcesMock.getInteger(R.integer.config_defaultVibrationAmplitude)).thenReturn(-1); assertThat(createConfig().getDefaultVibrationAmplitude()).isEqualTo(255); when(mResourcesMock.getInteger(R.integer.config_defaultVibrationAmplitude)).thenReturn(0); assertThat(createConfig().getDefaultVibrationAmplitude()).isEqualTo(255); when(mResourcesMock.getInteger(R.integer.config_defaultVibrationAmplitude)).thenReturn(500); assertThat(createConfig().getDefaultVibrationAmplitude()).isEqualTo(255); } @Test public void getDefaultVibrationScaleLevelGain_returnsConfiguredGain() { mSystemProperties.put(VibrationConfig.SCALE_LEVEL_GAIN_SYSTEM_PROPERTY, "1.2"); assertThat(createConfig().getDefaultVibrationScaleLevelGain()).isEqualTo(1.2f); mSystemProperties.put(VibrationConfig.SCALE_LEVEL_GAIN_SYSTEM_PROPERTY, "2"); assertThat(createConfig().getDefaultVibrationScaleLevelGain()).isEqualTo(2f); } @Test public void getDefaultVibrationScaleLevelGain_invalidValue_returnsFixedScaleGain() { mSystemProperties.put(VibrationConfig.SCALE_LEVEL_GAIN_SYSTEM_PROPERTY, ""); assertThat(createConfig().getDefaultVibrationScaleLevelGain()).isEqualTo(1.4f); mSystemProperties.put(VibrationConfig.SCALE_LEVEL_GAIN_SYSTEM_PROPERTY, "invalid"); assertThat(createConfig().getDefaultVibrationScaleLevelGain()).isEqualTo(1.4f); mSystemProperties.put(VibrationConfig.SCALE_LEVEL_GAIN_SYSTEM_PROPERTY, "-1"); assertThat(createConfig().getDefaultVibrationScaleLevelGain()).isEqualTo(1.4f); mSystemProperties.put(VibrationConfig.SCALE_LEVEL_GAIN_SYSTEM_PROPERTY, "0.5"); assertThat(createConfig().getDefaultVibrationScaleLevelGain()).isEqualTo(1.4f); mSystemProperties.put(VibrationConfig.SCALE_LEVEL_GAIN_SYSTEM_PROPERTY, "1.0"); assertThat(createConfig().getDefaultVibrationScaleLevelGain()).isEqualTo(1.4f); } private VibrationConfig createConfig() { return new VibrationConfig(mResourcesMock, mSystemProperties::get); } }