Add support for navigation repeat sound effects
NO_TYPO_CHECK=Existing typo in getContantForFocusDirection (e.g. b/3170596) Test: atest android.view.cts.SoundEffectConstantsTest Test: atest android.view.SoundEffectConstantsTest Bug: 157407957 Change-Id: I7377b1df6b151ea0d77476f0186b4bb21f1a55fe
This commit is contained in:
@@ -48009,10 +48009,15 @@ package android.view {
|
||||
}
|
||||
|
||||
public class SoundEffectConstants {
|
||||
method public static int getConstantForFocusDirection(int, boolean);
|
||||
method public static int getContantForFocusDirection(int);
|
||||
field public static final int CLICK = 0; // 0x0
|
||||
field public static final int NAVIGATION_DOWN = 4; // 0x4
|
||||
field public static final int NAVIGATION_LEFT = 1; // 0x1
|
||||
field public static final int NAVIGATION_REPEAT_DOWN = 8; // 0x8
|
||||
field public static final int NAVIGATION_REPEAT_LEFT = 5; // 0x5
|
||||
field public static final int NAVIGATION_REPEAT_RIGHT = 7; // 0x7
|
||||
field public static final int NAVIGATION_REPEAT_UP = 6; // 0x6
|
||||
field public static final int NAVIGATION_RIGHT = 3; // 0x3
|
||||
field public static final int NAVIGATION_UP = 2; // 0x2
|
||||
}
|
||||
|
||||
@@ -16,12 +16,21 @@
|
||||
|
||||
package android.view;
|
||||
|
||||
import android.media.AudioManager;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.annotations.VisibleForTesting.Visibility;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Constants to be used to play sound effects via {@link View#playSoundEffect(int)}
|
||||
* Constants to be used to play sound effects via {@link View#playSoundEffect(int)}
|
||||
*/
|
||||
public class SoundEffectConstants {
|
||||
|
||||
private SoundEffectConstants() {}
|
||||
private static final Random NAVIGATION_REPEAT_RANDOMIZER = new Random();
|
||||
private static int sLastNavigationRepeatSoundEffectId = -1;
|
||||
|
||||
public static final int CLICK = 0;
|
||||
|
||||
@@ -29,6 +38,14 @@ public class SoundEffectConstants {
|
||||
public static final int NAVIGATION_UP = 2;
|
||||
public static final int NAVIGATION_RIGHT = 3;
|
||||
public static final int NAVIGATION_DOWN = 4;
|
||||
/** Sound effect for a repeatedly triggered navigation, e.g. due to long pressing a button */
|
||||
public static final int NAVIGATION_REPEAT_LEFT = 5;
|
||||
/** @see #NAVIGATION_REPEAT_LEFT */
|
||||
public static final int NAVIGATION_REPEAT_UP = 6;
|
||||
/** @see #NAVIGATION_REPEAT_LEFT */
|
||||
public static final int NAVIGATION_REPEAT_RIGHT = 7;
|
||||
/** @see #NAVIGATION_REPEAT_LEFT */
|
||||
public static final int NAVIGATION_REPEAT_DOWN = 8;
|
||||
|
||||
/**
|
||||
* Get the sonification constant for the focus directions.
|
||||
@@ -40,7 +57,7 @@ public class SoundEffectConstants {
|
||||
* @throws {@link IllegalArgumentException} when the passed direction is not one of the
|
||||
* documented values.
|
||||
*/
|
||||
public static int getContantForFocusDirection(int direction) {
|
||||
public static int getContantForFocusDirection(@View.FocusDirection int direction) {
|
||||
switch (direction) {
|
||||
case View.FOCUS_RIGHT:
|
||||
return SoundEffectConstants.NAVIGATION_RIGHT;
|
||||
@@ -56,4 +73,65 @@ public class SoundEffectConstants {
|
||||
throw new IllegalArgumentException("direction must be one of "
|
||||
+ "{FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD, FOCUS_BACKWARD}.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the sonification constant for the focus directions
|
||||
* @param direction One of {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
|
||||
* {@link View#FOCUS_LEFT}, {@link View#FOCUS_RIGHT}, {@link View#FOCUS_FORWARD}
|
||||
* or {@link View#FOCUS_BACKWARD}
|
||||
* @param repeating True if the user long-presses a direction
|
||||
* @return The appropriate sonification constant
|
||||
* @throws IllegalArgumentException when the passed direction is not one of the
|
||||
* documented values.
|
||||
*/
|
||||
public static int getConstantForFocusDirection(@View.FocusDirection int direction,
|
||||
boolean repeating) {
|
||||
if (repeating) {
|
||||
switch (direction) {
|
||||
case View.FOCUS_RIGHT:
|
||||
return SoundEffectConstants.NAVIGATION_REPEAT_RIGHT;
|
||||
case View.FOCUS_FORWARD:
|
||||
case View.FOCUS_DOWN:
|
||||
return SoundEffectConstants.NAVIGATION_REPEAT_DOWN;
|
||||
case View.FOCUS_LEFT:
|
||||
return SoundEffectConstants.NAVIGATION_REPEAT_LEFT;
|
||||
case View.FOCUS_BACKWARD:
|
||||
case View.FOCUS_UP:
|
||||
return SoundEffectConstants.NAVIGATION_REPEAT_UP;
|
||||
}
|
||||
throw new IllegalArgumentException("direction must be one of {FOCUS_UP, FOCUS_DOWN, "
|
||||
+ "FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD, FOCUS_BACKWARD}.");
|
||||
} else {
|
||||
return getContantForFocusDirection(direction);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param effectId any of the effect ids defined in {@link SoundEffectConstants}
|
||||
* @return true if the given effect id is a navigation repeat one
|
||||
* @hide
|
||||
*/
|
||||
@VisibleForTesting(visibility = Visibility.PACKAGE)
|
||||
public static boolean isNavigationRepeat(int effectId) {
|
||||
return effectId == SoundEffectConstants.NAVIGATION_REPEAT_DOWN
|
||||
|| effectId == SoundEffectConstants.NAVIGATION_REPEAT_LEFT
|
||||
|| effectId == SoundEffectConstants.NAVIGATION_REPEAT_RIGHT
|
||||
|| effectId == SoundEffectConstants.NAVIGATION_REPEAT_UP;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The next navigation repeat sound effect id, chosen at random in a non-repeating
|
||||
* fashion
|
||||
* @hide
|
||||
*/
|
||||
@VisibleForTesting(visibility = Visibility.PACKAGE)
|
||||
public static int nextNavigationRepeatSoundEffectId() {
|
||||
int next = NAVIGATION_REPEAT_RANDOMIZER.nextInt(
|
||||
AudioManager.NUM_NAVIGATION_REPEAT_SOUND_EFFECTS - 1);
|
||||
if (next >= sLastNavigationRepeatSoundEffectId) {
|
||||
next++;
|
||||
}
|
||||
sLastNavigationRepeatSoundEffectId = next;
|
||||
return AudioManager.getNthNavigationRepeatSoundEffect(next);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -323,6 +323,8 @@ public final class ViewRootImpl implements ViewParent,
|
||||
private boolean mForceDisableBLAST;
|
||||
private boolean mEnableTripleBuffering;
|
||||
|
||||
private boolean mFastScrollSoundEffectsEnabled;
|
||||
|
||||
/**
|
||||
* Signals that compatibility booleans have been initialized according to
|
||||
* target SDK versions.
|
||||
@@ -813,6 +815,8 @@ public final class ViewRootImpl implements ViewParent,
|
||||
|
||||
loadSystemProperties();
|
||||
mImeFocusController = new ImeFocusController(this);
|
||||
AudioManager audioManager = mContext.getSystemService(AudioManager.class);
|
||||
mFastScrollSoundEffectsEnabled = audioManager.areNavigationRepeatSoundEffectsEnabled();
|
||||
}
|
||||
|
||||
public static void addFirstDrawHandler(Runnable callback) {
|
||||
@@ -6081,8 +6085,10 @@ public final class ViewRootImpl implements ViewParent,
|
||||
v, mTempRect);
|
||||
}
|
||||
if (v.requestFocus(direction, mTempRect)) {
|
||||
playSoundEffect(SoundEffectConstants
|
||||
.getContantForFocusDirection(direction));
|
||||
boolean isFastScrolling = event.getRepeatCount() > 0;
|
||||
playSoundEffect(
|
||||
SoundEffectConstants.getConstantForFocusDirection(direction,
|
||||
isFastScrolling));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -7743,20 +7749,31 @@ public final class ViewRootImpl implements ViewParent,
|
||||
try {
|
||||
final AudioManager audioManager = getAudioManager();
|
||||
|
||||
if (mFastScrollSoundEffectsEnabled
|
||||
&& SoundEffectConstants.isNavigationRepeat(effectId)) {
|
||||
audioManager.playSoundEffect(
|
||||
SoundEffectConstants.nextNavigationRepeatSoundEffectId());
|
||||
return;
|
||||
}
|
||||
|
||||
switch (effectId) {
|
||||
case SoundEffectConstants.CLICK:
|
||||
audioManager.playSoundEffect(AudioManager.FX_KEY_CLICK);
|
||||
return;
|
||||
case SoundEffectConstants.NAVIGATION_DOWN:
|
||||
case SoundEffectConstants.NAVIGATION_REPEAT_DOWN:
|
||||
audioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_DOWN);
|
||||
return;
|
||||
case SoundEffectConstants.NAVIGATION_LEFT:
|
||||
case SoundEffectConstants.NAVIGATION_REPEAT_LEFT:
|
||||
audioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_LEFT);
|
||||
return;
|
||||
case SoundEffectConstants.NAVIGATION_RIGHT:
|
||||
case SoundEffectConstants.NAVIGATION_REPEAT_RIGHT:
|
||||
audioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_RIGHT);
|
||||
return;
|
||||
case SoundEffectConstants.NAVIGATION_UP:
|
||||
case SoundEffectConstants.NAVIGATION_REPEAT_UP:
|
||||
audioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_UP);
|
||||
return;
|
||||
default:
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.view;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
/**
|
||||
* Tests for {@link SoundEffectConstants}
|
||||
*
|
||||
* Build/Install/Run:
|
||||
* atest FrameworksCoreTests:SoundEffectConstantsTest
|
||||
*/
|
||||
@SmallTest
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class SoundEffectConstantsTest {
|
||||
|
||||
@Test
|
||||
public void testIsNavigationRepeat() {
|
||||
assertTrue(SoundEffectConstants.isNavigationRepeat(
|
||||
SoundEffectConstants.NAVIGATION_REPEAT_RIGHT));
|
||||
assertTrue(SoundEffectConstants.isNavigationRepeat(
|
||||
SoundEffectConstants.NAVIGATION_REPEAT_LEFT));
|
||||
assertTrue(
|
||||
SoundEffectConstants.isNavigationRepeat(SoundEffectConstants.NAVIGATION_REPEAT_UP));
|
||||
assertTrue(SoundEffectConstants.isNavigationRepeat(
|
||||
SoundEffectConstants.NAVIGATION_REPEAT_DOWN));
|
||||
assertFalse(SoundEffectConstants.isNavigationRepeat(SoundEffectConstants.NAVIGATION_RIGHT));
|
||||
assertFalse(SoundEffectConstants.isNavigationRepeat(SoundEffectConstants.NAVIGATION_LEFT));
|
||||
assertFalse(SoundEffectConstants.isNavigationRepeat(SoundEffectConstants.NAVIGATION_UP));
|
||||
assertFalse(SoundEffectConstants.isNavigationRepeat(SoundEffectConstants.NAVIGATION_DOWN));
|
||||
assertFalse(SoundEffectConstants.isNavigationRepeat(-1));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user