Loading core/java/android/provider/Settings.java +9 −1 Original line number Diff line number Diff line Loading @@ -5627,13 +5627,21 @@ public final class Settings { public static final String SHOW_TOUCHES = "show_touches"; /** * Show key presses and other events dispatched to focused windows on the screen. * Show key presses dispatched to focused windows on the screen. * 0 = no * 1 = yes * @hide */ public static final String SHOW_KEY_PRESSES = "show_key_presses"; /** * Show rotary input dispatched to focused windows on the screen. * 0 = no * 1 = yes * @hide */ public static final String SHOW_ROTARY_INPUT = "show_rotary_input"; /** * Log raw orientation data from * {@link com.android.server.policy.WindowOrientationListener} for use with the Loading packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java +1 −0 Original line number Diff line number Diff line Loading @@ -184,6 +184,7 @@ public class SystemSettingsValidators { VALIDATORS.put(System.POINTER_LOCATION, BOOLEAN_VALIDATOR); VALIDATORS.put(System.SHOW_TOUCHES, BOOLEAN_VALIDATOR); VALIDATORS.put(System.SHOW_KEY_PRESSES, BOOLEAN_VALIDATOR); VALIDATORS.put(System.SHOW_ROTARY_INPUT, BOOLEAN_VALIDATOR); VALIDATORS.put(System.WINDOW_ORIENTATION_LISTENER_LOG, BOOLEAN_VALIDATOR); VALIDATORS.put(System.LOCKSCREEN_SOUNDS_ENABLED, BOOLEAN_VALIDATOR); VALIDATORS.put(System.LOCKSCREEN_DISABLED, BOOLEAN_VALIDATOR); Loading packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java +1 −0 Original line number Diff line number Diff line Loading @@ -79,6 +79,7 @@ public class SettingsBackupTest { Settings.System.SHOW_GTALK_SERVICE_STATUS, // candidate for backup? Settings.System.SHOW_TOUCHES, Settings.System.SHOW_KEY_PRESSES, Settings.System.SHOW_ROTARY_INPUT, Settings.System.SIP_ADDRESS_ONLY, // value, not a setting Settings.System.SIP_ALWAYS, // value, not a setting Settings.System.SYSTEM_LOCALES, // bug? Loading services/core/java/com/android/server/input/FocusEventDebugGlobalMonitor.java 0 → 100644 +48 −0 Original line number Diff line number Diff line /* * Copyright 2023 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.input; import android.view.Display; import android.view.InputEvent; import android.view.InputEventReceiver; import android.view.MotionEvent; import com.android.server.UiThread; /** * Receives input events before they are dispatched and reports them to FocusEventDebugView. */ class FocusEventDebugGlobalMonitor extends InputEventReceiver { private final FocusEventDebugView mDebugView; FocusEventDebugGlobalMonitor(FocusEventDebugView debugView, InputManagerService service) { super(service.monitorInput("FocusEventDebugGlobalMonitor", Display.DEFAULT_DISPLAY), UiThread.getHandler().getLooper()); mDebugView = debugView; } @Override public void onInputEvent(InputEvent event) { try { if (event instanceof MotionEvent) { mDebugView.reportMotionEvent((MotionEvent) event); } } finally { finishInputEvent(event, false); } } } services/core/java/com/android/server/input/FocusEventDebugView.java +104 −25 Original line number Diff line number Diff line Loading @@ -22,17 +22,20 @@ import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; import android.animation.LayoutTransition; import android.annotation.AnyThread; import android.annotation.Nullable; import android.content.Context; import android.graphics.Color; import android.graphics.ColorFilter; import android.graphics.ColorMatrixColorFilter; import android.graphics.Typeface; import android.util.Log; import android.util.Pair; import android.util.Slog; import android.util.TypedValue; import android.view.Gravity; import android.view.InputEvent; import android.view.InputDevice; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.RoundedCorner; import android.view.View; import android.view.WindowInsets; Loading Loading @@ -64,42 +67,31 @@ class FocusEventDebugView extends LinearLayout { private static final int KEY_VIEW_MIN_WIDTH_DP = 32; private static final int KEY_VIEW_TEXT_SIZE_SP = 12; private final InputManagerService mService; private final int mOuterPadding; // Tracks all keys that are currently pressed/down. private final Map<Pair<Integer /*deviceId*/, Integer /*scanCode*/>, PressedKeyView> mPressedKeys = new HashMap<>(); private final PressedKeyContainer mPressedKeyContainer; private final PressedKeyContainer mPressedModifierContainer; @Nullable private FocusEventDebugGlobalMonitor mFocusEventDebugGlobalMonitor; @Nullable private PressedKeyContainer mPressedKeyContainer; @Nullable private PressedKeyContainer mPressedModifierContainer; FocusEventDebugView(Context c) { FocusEventDebugView(Context c, InputManagerService service) { super(c); setFocusableInTouchMode(true); mService = service; final var dm = mContext.getResources().getDisplayMetrics(); mOuterPadding = (int) TypedValue.applyDimension(COMPLEX_UNIT_DIP, OUTER_PADDING_DP, dm); setOrientation(HORIZONTAL); setLayoutDirection(LAYOUT_DIRECTION_RTL); setGravity(Gravity.START | Gravity.BOTTOM); mPressedKeyContainer = new PressedKeyContainer(mContext); mPressedKeyContainer.setOrientation(HORIZONTAL); mPressedKeyContainer.setGravity(Gravity.RIGHT | Gravity.BOTTOM); mPressedKeyContainer.setLayoutDirection(LAYOUT_DIRECTION_LTR); final var scroller = new HorizontalScrollView(mContext); scroller.addView(mPressedKeyContainer); scroller.setHorizontalScrollBarEnabled(false); scroller.addOnLayoutChangeListener( (view, l, t, r, b, ol, ot, or, ob) -> scroller.fullScroll(View.FOCUS_RIGHT)); scroller.setHorizontalFadingEdgeEnabled(true); addView(scroller, new LayoutParams(0, WRAP_CONTENT, 1)); mPressedModifierContainer = new PressedKeyContainer(mContext); mPressedModifierContainer.setOrientation(VERTICAL); mPressedModifierContainer.setGravity(Gravity.LEFT | Gravity.BOTTOM); addView(mPressedModifierContainer, new LayoutParams(WRAP_CONTENT, WRAP_CONTENT)); } @Override Loading Loading @@ -135,17 +127,82 @@ class FocusEventDebugView extends LinearLayout { return super.dispatchKeyEvent(event); } /** Report an input event to the debug view. */ @AnyThread public void reportEvent(InputEvent event) { if (!(event instanceof KeyEvent)) { // TODO: Support non-pointer MotionEvents. public void updateShowKeyPresses(boolean enabled) { post(() -> handleUpdateShowKeyPresses(enabled)); } @AnyThread public void updateShowRotaryInput(boolean enabled) { post(() -> handleUpdateShowRotaryInput(enabled)); } private void handleUpdateShowKeyPresses(boolean enabled) { if (enabled == showKeyPresses()) { return; } if (!enabled) { removeView(mPressedKeyContainer); mPressedKeyContainer = null; removeView(mPressedModifierContainer); mPressedModifierContainer = null; return; } mPressedKeyContainer = new PressedKeyContainer(mContext); mPressedKeyContainer.setOrientation(HORIZONTAL); mPressedKeyContainer.setGravity(Gravity.RIGHT | Gravity.BOTTOM); mPressedKeyContainer.setLayoutDirection(LAYOUT_DIRECTION_LTR); final var scroller = new HorizontalScrollView(mContext); scroller.addView(mPressedKeyContainer); scroller.setHorizontalScrollBarEnabled(false); scroller.addOnLayoutChangeListener( (view, l, t, r, b, ol, ot, or, ob) -> scroller.fullScroll(View.FOCUS_RIGHT)); scroller.setHorizontalFadingEdgeEnabled(true); addView(scroller, new LayoutParams(0, WRAP_CONTENT, 1)); mPressedModifierContainer = new PressedKeyContainer(mContext); mPressedModifierContainer.setOrientation(VERTICAL); mPressedModifierContainer.setGravity(Gravity.LEFT | Gravity.BOTTOM); addView(mPressedModifierContainer, new LayoutParams(WRAP_CONTENT, WRAP_CONTENT)); } private void handleUpdateShowRotaryInput(boolean enabled) { if (enabled == showRotaryInput()) { return; } if (!enabled) { mFocusEventDebugGlobalMonitor.dispose(); mFocusEventDebugGlobalMonitor = null; return; } mFocusEventDebugGlobalMonitor = new FocusEventDebugGlobalMonitor(this, mService); } /** Report a key event to the debug view. */ @AnyThread public void reportKeyEvent(KeyEvent event) { post(() -> handleKeyEvent(KeyEvent.obtain((KeyEvent) event))); } /** Report a motion event to the debug view. */ @AnyThread public void reportMotionEvent(MotionEvent event) { if (event.getSource() != InputDevice.SOURCE_ROTARY_ENCODER) { return; } post(() -> handleRotaryInput(MotionEvent.obtain((MotionEvent) event))); } private void handleKeyEvent(KeyEvent keyEvent) { if (!showKeyPresses()) { return; } final var identifier = new Pair<>(keyEvent.getDeviceId(), keyEvent.getScanCode()); final var container = KeyEvent.isModifierKey(keyEvent.getKeyCode()) ? mPressedModifierContainer Loading Loading @@ -185,6 +242,18 @@ class FocusEventDebugView extends LinearLayout { keyEvent.recycle(); } private void handleRotaryInput(MotionEvent motionEvent) { if (!showRotaryInput()) { return; } float scrollAxisValue = motionEvent.getAxisValue(MotionEvent.AXIS_SCROLL); // TODO(b/286086154): replace log with visualization. Log.d(TAG, "ROTARY INPUT: " + String.valueOf(scrollAxisValue)); motionEvent.recycle(); } private static String getLabel(KeyEvent event) { switch (event.getKeyCode()) { case KeyEvent.KEYCODE_SPACE: Loading Loading @@ -232,6 +301,16 @@ class FocusEventDebugView extends LinearLayout { return label; } /** Determine whether to show key presses by checking one of the key-related objects. */ private boolean showKeyPresses() { return mPressedKeyContainer != null; } /** Determine whether to show rotary input by checking one of the rotary-related objects. */ private boolean showRotaryInput() { return mFocusEventDebugGlobalMonitor != null; } private static class PressedKeyView extends TextView { private static final ColorFilter sInvertColors = new ColorMatrixColorFilter(new float[]{ Loading Loading
core/java/android/provider/Settings.java +9 −1 Original line number Diff line number Diff line Loading @@ -5627,13 +5627,21 @@ public final class Settings { public static final String SHOW_TOUCHES = "show_touches"; /** * Show key presses and other events dispatched to focused windows on the screen. * Show key presses dispatched to focused windows on the screen. * 0 = no * 1 = yes * @hide */ public static final String SHOW_KEY_PRESSES = "show_key_presses"; /** * Show rotary input dispatched to focused windows on the screen. * 0 = no * 1 = yes * @hide */ public static final String SHOW_ROTARY_INPUT = "show_rotary_input"; /** * Log raw orientation data from * {@link com.android.server.policy.WindowOrientationListener} for use with the Loading
packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java +1 −0 Original line number Diff line number Diff line Loading @@ -184,6 +184,7 @@ public class SystemSettingsValidators { VALIDATORS.put(System.POINTER_LOCATION, BOOLEAN_VALIDATOR); VALIDATORS.put(System.SHOW_TOUCHES, BOOLEAN_VALIDATOR); VALIDATORS.put(System.SHOW_KEY_PRESSES, BOOLEAN_VALIDATOR); VALIDATORS.put(System.SHOW_ROTARY_INPUT, BOOLEAN_VALIDATOR); VALIDATORS.put(System.WINDOW_ORIENTATION_LISTENER_LOG, BOOLEAN_VALIDATOR); VALIDATORS.put(System.LOCKSCREEN_SOUNDS_ENABLED, BOOLEAN_VALIDATOR); VALIDATORS.put(System.LOCKSCREEN_DISABLED, BOOLEAN_VALIDATOR); Loading
packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java +1 −0 Original line number Diff line number Diff line Loading @@ -79,6 +79,7 @@ public class SettingsBackupTest { Settings.System.SHOW_GTALK_SERVICE_STATUS, // candidate for backup? Settings.System.SHOW_TOUCHES, Settings.System.SHOW_KEY_PRESSES, Settings.System.SHOW_ROTARY_INPUT, Settings.System.SIP_ADDRESS_ONLY, // value, not a setting Settings.System.SIP_ALWAYS, // value, not a setting Settings.System.SYSTEM_LOCALES, // bug? Loading
services/core/java/com/android/server/input/FocusEventDebugGlobalMonitor.java 0 → 100644 +48 −0 Original line number Diff line number Diff line /* * Copyright 2023 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.input; import android.view.Display; import android.view.InputEvent; import android.view.InputEventReceiver; import android.view.MotionEvent; import com.android.server.UiThread; /** * Receives input events before they are dispatched and reports them to FocusEventDebugView. */ class FocusEventDebugGlobalMonitor extends InputEventReceiver { private final FocusEventDebugView mDebugView; FocusEventDebugGlobalMonitor(FocusEventDebugView debugView, InputManagerService service) { super(service.monitorInput("FocusEventDebugGlobalMonitor", Display.DEFAULT_DISPLAY), UiThread.getHandler().getLooper()); mDebugView = debugView; } @Override public void onInputEvent(InputEvent event) { try { if (event instanceof MotionEvent) { mDebugView.reportMotionEvent((MotionEvent) event); } } finally { finishInputEvent(event, false); } } }
services/core/java/com/android/server/input/FocusEventDebugView.java +104 −25 Original line number Diff line number Diff line Loading @@ -22,17 +22,20 @@ import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; import android.animation.LayoutTransition; import android.annotation.AnyThread; import android.annotation.Nullable; import android.content.Context; import android.graphics.Color; import android.graphics.ColorFilter; import android.graphics.ColorMatrixColorFilter; import android.graphics.Typeface; import android.util.Log; import android.util.Pair; import android.util.Slog; import android.util.TypedValue; import android.view.Gravity; import android.view.InputEvent; import android.view.InputDevice; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.RoundedCorner; import android.view.View; import android.view.WindowInsets; Loading Loading @@ -64,42 +67,31 @@ class FocusEventDebugView extends LinearLayout { private static final int KEY_VIEW_MIN_WIDTH_DP = 32; private static final int KEY_VIEW_TEXT_SIZE_SP = 12; private final InputManagerService mService; private final int mOuterPadding; // Tracks all keys that are currently pressed/down. private final Map<Pair<Integer /*deviceId*/, Integer /*scanCode*/>, PressedKeyView> mPressedKeys = new HashMap<>(); private final PressedKeyContainer mPressedKeyContainer; private final PressedKeyContainer mPressedModifierContainer; @Nullable private FocusEventDebugGlobalMonitor mFocusEventDebugGlobalMonitor; @Nullable private PressedKeyContainer mPressedKeyContainer; @Nullable private PressedKeyContainer mPressedModifierContainer; FocusEventDebugView(Context c) { FocusEventDebugView(Context c, InputManagerService service) { super(c); setFocusableInTouchMode(true); mService = service; final var dm = mContext.getResources().getDisplayMetrics(); mOuterPadding = (int) TypedValue.applyDimension(COMPLEX_UNIT_DIP, OUTER_PADDING_DP, dm); setOrientation(HORIZONTAL); setLayoutDirection(LAYOUT_DIRECTION_RTL); setGravity(Gravity.START | Gravity.BOTTOM); mPressedKeyContainer = new PressedKeyContainer(mContext); mPressedKeyContainer.setOrientation(HORIZONTAL); mPressedKeyContainer.setGravity(Gravity.RIGHT | Gravity.BOTTOM); mPressedKeyContainer.setLayoutDirection(LAYOUT_DIRECTION_LTR); final var scroller = new HorizontalScrollView(mContext); scroller.addView(mPressedKeyContainer); scroller.setHorizontalScrollBarEnabled(false); scroller.addOnLayoutChangeListener( (view, l, t, r, b, ol, ot, or, ob) -> scroller.fullScroll(View.FOCUS_RIGHT)); scroller.setHorizontalFadingEdgeEnabled(true); addView(scroller, new LayoutParams(0, WRAP_CONTENT, 1)); mPressedModifierContainer = new PressedKeyContainer(mContext); mPressedModifierContainer.setOrientation(VERTICAL); mPressedModifierContainer.setGravity(Gravity.LEFT | Gravity.BOTTOM); addView(mPressedModifierContainer, new LayoutParams(WRAP_CONTENT, WRAP_CONTENT)); } @Override Loading Loading @@ -135,17 +127,82 @@ class FocusEventDebugView extends LinearLayout { return super.dispatchKeyEvent(event); } /** Report an input event to the debug view. */ @AnyThread public void reportEvent(InputEvent event) { if (!(event instanceof KeyEvent)) { // TODO: Support non-pointer MotionEvents. public void updateShowKeyPresses(boolean enabled) { post(() -> handleUpdateShowKeyPresses(enabled)); } @AnyThread public void updateShowRotaryInput(boolean enabled) { post(() -> handleUpdateShowRotaryInput(enabled)); } private void handleUpdateShowKeyPresses(boolean enabled) { if (enabled == showKeyPresses()) { return; } if (!enabled) { removeView(mPressedKeyContainer); mPressedKeyContainer = null; removeView(mPressedModifierContainer); mPressedModifierContainer = null; return; } mPressedKeyContainer = new PressedKeyContainer(mContext); mPressedKeyContainer.setOrientation(HORIZONTAL); mPressedKeyContainer.setGravity(Gravity.RIGHT | Gravity.BOTTOM); mPressedKeyContainer.setLayoutDirection(LAYOUT_DIRECTION_LTR); final var scroller = new HorizontalScrollView(mContext); scroller.addView(mPressedKeyContainer); scroller.setHorizontalScrollBarEnabled(false); scroller.addOnLayoutChangeListener( (view, l, t, r, b, ol, ot, or, ob) -> scroller.fullScroll(View.FOCUS_RIGHT)); scroller.setHorizontalFadingEdgeEnabled(true); addView(scroller, new LayoutParams(0, WRAP_CONTENT, 1)); mPressedModifierContainer = new PressedKeyContainer(mContext); mPressedModifierContainer.setOrientation(VERTICAL); mPressedModifierContainer.setGravity(Gravity.LEFT | Gravity.BOTTOM); addView(mPressedModifierContainer, new LayoutParams(WRAP_CONTENT, WRAP_CONTENT)); } private void handleUpdateShowRotaryInput(boolean enabled) { if (enabled == showRotaryInput()) { return; } if (!enabled) { mFocusEventDebugGlobalMonitor.dispose(); mFocusEventDebugGlobalMonitor = null; return; } mFocusEventDebugGlobalMonitor = new FocusEventDebugGlobalMonitor(this, mService); } /** Report a key event to the debug view. */ @AnyThread public void reportKeyEvent(KeyEvent event) { post(() -> handleKeyEvent(KeyEvent.obtain((KeyEvent) event))); } /** Report a motion event to the debug view. */ @AnyThread public void reportMotionEvent(MotionEvent event) { if (event.getSource() != InputDevice.SOURCE_ROTARY_ENCODER) { return; } post(() -> handleRotaryInput(MotionEvent.obtain((MotionEvent) event))); } private void handleKeyEvent(KeyEvent keyEvent) { if (!showKeyPresses()) { return; } final var identifier = new Pair<>(keyEvent.getDeviceId(), keyEvent.getScanCode()); final var container = KeyEvent.isModifierKey(keyEvent.getKeyCode()) ? mPressedModifierContainer Loading Loading @@ -185,6 +242,18 @@ class FocusEventDebugView extends LinearLayout { keyEvent.recycle(); } private void handleRotaryInput(MotionEvent motionEvent) { if (!showRotaryInput()) { return; } float scrollAxisValue = motionEvent.getAxisValue(MotionEvent.AXIS_SCROLL); // TODO(b/286086154): replace log with visualization. Log.d(TAG, "ROTARY INPUT: " + String.valueOf(scrollAxisValue)); motionEvent.recycle(); } private static String getLabel(KeyEvent event) { switch (event.getKeyCode()) { case KeyEvent.KEYCODE_SPACE: Loading Loading @@ -232,6 +301,16 @@ class FocusEventDebugView extends LinearLayout { return label; } /** Determine whether to show key presses by checking one of the key-related objects. */ private boolean showKeyPresses() { return mPressedKeyContainer != null; } /** Determine whether to show rotary input by checking one of the rotary-related objects. */ private boolean showRotaryInput() { return mFocusEventDebugGlobalMonitor != null; } private static class PressedKeyView extends TextView { private static final ColorFilter sInvertColors = new ColorMatrixColorFilter(new float[]{ Loading