Loading core/java/android/hardware/display/DisplayManager.java +11 −1 Original line number Diff line number Diff line Loading @@ -122,7 +122,8 @@ public final class DisplayManager { VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS, VIRTUAL_DISPLAY_FLAG_TRUSTED, VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP, VIRTUAL_DISPLAY_FLAG_ALWAYS_UNLOCKED VIRTUAL_DISPLAY_FLAG_ALWAYS_UNLOCKED, VIRTUAL_DISPLAY_FLAG_TOUCH_FEEDBACK_DISABLED }) @Retention(RetentionPolicy.SOURCE) public @interface VirtualDisplayFlag {} Loading Loading @@ -379,6 +380,15 @@ public final class DisplayManager { */ public static final int VIRTUAL_DISPLAY_FLAG_ALWAYS_UNLOCKED = 1 << 12; /** * Virtual display flags: Indicates that the display should not play sound effects or perform * haptic feedback when the user touches the screen. * * @see #createVirtualDisplay * @hide */ public static final int VIRTUAL_DISPLAY_FLAG_TOUCH_FEEDBACK_DISABLED = 1 << 13; /** @hide */ @IntDef(prefix = {"MATCH_CONTENT_FRAMERATE_"}, value = { MATCH_CONTENT_FRAMERATE_UNKNOWN, Loading core/java/android/view/Display.java +9 −0 Original line number Diff line number Diff line Loading @@ -308,6 +308,15 @@ public final class Display { */ public static final int FLAG_ALWAYS_UNLOCKED = 1 << 9; /** * Flag: Indicates that the display should not play sound effects or perform haptic feedback * when the user touches the screen. * * @hide * @see #getFlags() */ public static final int FLAG_TOUCH_FEEDBACK_DISABLED = 1 << 10; /** * Display flag: Indicates that the contents of the display should not be scaled * to fit the physical screen dimensions. Used for development only to emulate Loading core/java/android/view/DisplayInfo.java +3 −0 Original line number Diff line number Diff line Loading @@ -865,6 +865,9 @@ public final class DisplayInfo implements Parcelable { if ((flags & Display.FLAG_ALWAYS_UNLOCKED) != 0) { result.append(", FLAG_ALWAYS_UNLOCKED"); } if ((flags & Display.FLAG_TOUCH_FEEDBACK_DISABLED) != 0) { result.append(", FLAG_TOUCH_FEEDBACK_DISABLED"); } return result.toString(); } } core/java/android/view/ViewRootImpl.java +8 −0 Original line number Diff line number Diff line Loading @@ -8200,6 +8200,10 @@ public final class ViewRootImpl implements ViewParent, */ @Override public void playSoundEffect(@SoundEffectConstants.SoundEffect int effectId) { if ((mDisplay.getFlags() & Display.FLAG_TOUCH_FEEDBACK_DISABLED) != 0) { return; } checkThread(); try { Loading Loading @@ -8248,6 +8252,10 @@ public final class ViewRootImpl implements ViewParent, */ @Override public boolean performHapticFeedback(int effectId, boolean always) { if ((mDisplay.getFlags() & Display.FLAG_TOUCH_FEEDBACK_DISABLED) != 0) { return false; } try { return mWindowSession.performHapticFeedback(effectId, always); } catch (RemoteException e) { Loading core/tests/coretests/src/android/view/ViewRootImplTest.java +52 −0 Original line number Diff line number Diff line Loading @@ -35,16 +35,19 @@ import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import android.app.Instrumentation; import android.content.Context; import android.hardware.display.DisplayManagerGlobal; import android.os.Binder; import android.platform.test.annotations.Presubmit; import android.view.WindowInsets.Side; import android.view.WindowInsets.Type; import androidx.test.annotation.UiThreadTest; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import androidx.test.platform.app.InstrumentationRegistry; Loading Loading @@ -334,6 +337,55 @@ public class ViewRootImplTest { }, false /*shouldReceiveKey*/); } @UiThreadTest @Test public void playSoundEffect_wrongEffectId_throwException() { ViewRootImpl viewRootImpl = new ViewRootImpl(sContext, sContext.getDisplayNoVerify()); View view = new View(sContext); WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams( TYPE_APPLICATION_OVERLAY); layoutParams.token = new Binder(); view.setLayoutParams(layoutParams); viewRootImpl.setView(view, layoutParams, /* panelParentView= */ null); assertThrows(IllegalArgumentException.class, () -> viewRootImpl.playSoundEffect(/* effectId= */ -1)); } @UiThreadTest @Test public void playSoundEffect_wrongEffectId_touchFeedbackDisabled_doNothing() { DisplayInfo displayInfo = new DisplayInfo(); displayInfo.flags = Display.FLAG_TOUCH_FEEDBACK_DISABLED; Display display = new Display(DisplayManagerGlobal.getInstance(), /* displayId= */ 0, displayInfo, new DisplayAdjustments()); ViewRootImpl viewRootImpl = new ViewRootImpl(sContext, display); View view = new View(sContext); WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams( TYPE_APPLICATION_OVERLAY); layoutParams.token = new Binder(); view.setLayoutParams(layoutParams); viewRootImpl.setView(view, layoutParams, /* panelParentView= */ null); viewRootImpl.playSoundEffect(/* effectId= */ -1); } @UiThreadTest @Test public void performHapticFeedback_touchFeedbackDisabled_doNothing() { DisplayInfo displayInfo = new DisplayInfo(); displayInfo.flags = Display.FLAG_TOUCH_FEEDBACK_DISABLED; Display display = new Display(DisplayManagerGlobal.getInstance(), /* displayId= */ 0, displayInfo, new DisplayAdjustments()); ViewRootImpl viewRootImpl = new ViewRootImpl(sContext, display); boolean result = viewRootImpl.performHapticFeedback( HapticFeedbackConstants.CONTEXT_CLICK, true); assertThat(result).isFalse(); } class KeyView extends View { KeyView(Context context) { super(context); Loading Loading
core/java/android/hardware/display/DisplayManager.java +11 −1 Original line number Diff line number Diff line Loading @@ -122,7 +122,8 @@ public final class DisplayManager { VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS, VIRTUAL_DISPLAY_FLAG_TRUSTED, VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP, VIRTUAL_DISPLAY_FLAG_ALWAYS_UNLOCKED VIRTUAL_DISPLAY_FLAG_ALWAYS_UNLOCKED, VIRTUAL_DISPLAY_FLAG_TOUCH_FEEDBACK_DISABLED }) @Retention(RetentionPolicy.SOURCE) public @interface VirtualDisplayFlag {} Loading Loading @@ -379,6 +380,15 @@ public final class DisplayManager { */ public static final int VIRTUAL_DISPLAY_FLAG_ALWAYS_UNLOCKED = 1 << 12; /** * Virtual display flags: Indicates that the display should not play sound effects or perform * haptic feedback when the user touches the screen. * * @see #createVirtualDisplay * @hide */ public static final int VIRTUAL_DISPLAY_FLAG_TOUCH_FEEDBACK_DISABLED = 1 << 13; /** @hide */ @IntDef(prefix = {"MATCH_CONTENT_FRAMERATE_"}, value = { MATCH_CONTENT_FRAMERATE_UNKNOWN, Loading
core/java/android/view/Display.java +9 −0 Original line number Diff line number Diff line Loading @@ -308,6 +308,15 @@ public final class Display { */ public static final int FLAG_ALWAYS_UNLOCKED = 1 << 9; /** * Flag: Indicates that the display should not play sound effects or perform haptic feedback * when the user touches the screen. * * @hide * @see #getFlags() */ public static final int FLAG_TOUCH_FEEDBACK_DISABLED = 1 << 10; /** * Display flag: Indicates that the contents of the display should not be scaled * to fit the physical screen dimensions. Used for development only to emulate Loading
core/java/android/view/DisplayInfo.java +3 −0 Original line number Diff line number Diff line Loading @@ -865,6 +865,9 @@ public final class DisplayInfo implements Parcelable { if ((flags & Display.FLAG_ALWAYS_UNLOCKED) != 0) { result.append(", FLAG_ALWAYS_UNLOCKED"); } if ((flags & Display.FLAG_TOUCH_FEEDBACK_DISABLED) != 0) { result.append(", FLAG_TOUCH_FEEDBACK_DISABLED"); } return result.toString(); } }
core/java/android/view/ViewRootImpl.java +8 −0 Original line number Diff line number Diff line Loading @@ -8200,6 +8200,10 @@ public final class ViewRootImpl implements ViewParent, */ @Override public void playSoundEffect(@SoundEffectConstants.SoundEffect int effectId) { if ((mDisplay.getFlags() & Display.FLAG_TOUCH_FEEDBACK_DISABLED) != 0) { return; } checkThread(); try { Loading Loading @@ -8248,6 +8252,10 @@ public final class ViewRootImpl implements ViewParent, */ @Override public boolean performHapticFeedback(int effectId, boolean always) { if ((mDisplay.getFlags() & Display.FLAG_TOUCH_FEEDBACK_DISABLED) != 0) { return false; } try { return mWindowSession.performHapticFeedback(effectId, always); } catch (RemoteException e) { Loading
core/tests/coretests/src/android/view/ViewRootImplTest.java +52 −0 Original line number Diff line number Diff line Loading @@ -35,16 +35,19 @@ import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import android.app.Instrumentation; import android.content.Context; import android.hardware.display.DisplayManagerGlobal; import android.os.Binder; import android.platform.test.annotations.Presubmit; import android.view.WindowInsets.Side; import android.view.WindowInsets.Type; import androidx.test.annotation.UiThreadTest; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import androidx.test.platform.app.InstrumentationRegistry; Loading Loading @@ -334,6 +337,55 @@ public class ViewRootImplTest { }, false /*shouldReceiveKey*/); } @UiThreadTest @Test public void playSoundEffect_wrongEffectId_throwException() { ViewRootImpl viewRootImpl = new ViewRootImpl(sContext, sContext.getDisplayNoVerify()); View view = new View(sContext); WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams( TYPE_APPLICATION_OVERLAY); layoutParams.token = new Binder(); view.setLayoutParams(layoutParams); viewRootImpl.setView(view, layoutParams, /* panelParentView= */ null); assertThrows(IllegalArgumentException.class, () -> viewRootImpl.playSoundEffect(/* effectId= */ -1)); } @UiThreadTest @Test public void playSoundEffect_wrongEffectId_touchFeedbackDisabled_doNothing() { DisplayInfo displayInfo = new DisplayInfo(); displayInfo.flags = Display.FLAG_TOUCH_FEEDBACK_DISABLED; Display display = new Display(DisplayManagerGlobal.getInstance(), /* displayId= */ 0, displayInfo, new DisplayAdjustments()); ViewRootImpl viewRootImpl = new ViewRootImpl(sContext, display); View view = new View(sContext); WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams( TYPE_APPLICATION_OVERLAY); layoutParams.token = new Binder(); view.setLayoutParams(layoutParams); viewRootImpl.setView(view, layoutParams, /* panelParentView= */ null); viewRootImpl.playSoundEffect(/* effectId= */ -1); } @UiThreadTest @Test public void performHapticFeedback_touchFeedbackDisabled_doNothing() { DisplayInfo displayInfo = new DisplayInfo(); displayInfo.flags = Display.FLAG_TOUCH_FEEDBACK_DISABLED; Display display = new Display(DisplayManagerGlobal.getInstance(), /* displayId= */ 0, displayInfo, new DisplayAdjustments()); ViewRootImpl viewRootImpl = new ViewRootImpl(sContext, display); boolean result = viewRootImpl.performHapticFeedback( HapticFeedbackConstants.CONTEXT_CLICK, true); assertThat(result).isFalse(); } class KeyView extends View { KeyView(Context context) { super(context); Loading