From 0c07f164437efe78d57ae0bfb1d556ea9b1207d2 Mon Sep 17 00:00:00 2001 From: shaoweishen Date: Tue, 25 Feb 2025 05:15:37 +0000 Subject: [PATCH] [Physical Keyboard] Listen input devices change Create new fragment which listen input device change, when input device detached while pages show, it will exist correctly. Bug: 399284521 Flag: com.android.settings.keyboard.keyboard_and_touchpad_a11y_new_page_enabled Test: atest packages/apps/Settings/tests/robotests/src/com/android/settings/inputmethod/ Change-Id: I3d6b9a4558866a8c4a3aa4fc30e500b8b6be90cd --- .../InputDeviceDashboardFragment.java | 92 +++++++++++++++++++ .../InputPeripheralsSettingsUtils.java | 24 ++++- .../inputmethod/ModifierKeysSettings.java | 8 +- .../inputmethod/MouseSettingFragment.java | 8 +- .../PointerColorCustomizationFragment.java | 8 +- .../inputmethod/PointerTouchpadFragment.java | 8 +- .../inputmethod/TouchpadSettingFragment.java | 8 +- .../TouchpadThreeFingerTapFragment.java | 8 +- 8 files changed, 151 insertions(+), 13 deletions(-) create mode 100644 src/com/android/settings/inputmethod/InputDeviceDashboardFragment.java diff --git a/src/com/android/settings/inputmethod/InputDeviceDashboardFragment.java b/src/com/android/settings/inputmethod/InputDeviceDashboardFragment.java new file mode 100644 index 00000000000..a6f0268c007 --- /dev/null +++ b/src/com/android/settings/inputmethod/InputDeviceDashboardFragment.java @@ -0,0 +1,92 @@ +/* + * Copyright 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.settings.inputmethod; + +import android.hardware.input.InputManager; +import android.os.Bundle; + +import androidx.annotation.NonNull; + +import com.android.internal.util.Preconditions; +import com.android.settings.dashboard.DashboardFragment; + +public abstract class InputDeviceDashboardFragment extends DashboardFragment + implements InputManager.InputDeviceListener { + private InputManager mInputManager; + + @Override + public void onCreate(@NonNull Bundle icicle) { + super.onCreate(icicle); + mInputManager = Preconditions.checkNotNull(getActivity() + .getSystemService(InputManager.class)); + } + + @Override + public void onResume() { + super.onResume(); + finishEarlyIfNeeded(); + mInputManager.registerInputDeviceListener(this /* listener */, null /* handler */); + } + + @Override + public void onPause() { + super.onPause(); + mInputManager.unregisterInputDeviceListener(this /* listener */); + } + + @Override + public void onInputDeviceAdded(int deviceId) { + finishEarlyIfNeeded(); + } + + @Override + public void onInputDeviceRemoved(int deviceId) { + finishEarlyIfNeeded(); + } + + @Override + public void onInputDeviceChanged(int deviceId) { + finishEarlyIfNeeded(); + } + + private void finishEarlyIfNeeded() { + if (getActivity() == null) { + return; + } + if (needToFinishEarly()) { + getActivity().finish(); + } + } + + /** + * Returns whether the fragment should still be displayed given the input devices that are + * currently connected. + */ + protected abstract boolean needToFinishEarly(); + + protected static boolean isTouchpadDetached() { + return !InputPeripheralsSettingsUtils.isTouchpad(); + } + + protected static boolean isMouseDetached() { + return !InputPeripheralsSettingsUtils.isMouse(); + } + + protected static boolean isHardKeyboardDetached() { + return !InputPeripheralsSettingsUtils.isHardKeyboard(); + } +} diff --git a/src/com/android/settings/inputmethod/InputPeripheralsSettingsUtils.java b/src/com/android/settings/inputmethod/InputPeripheralsSettingsUtils.java index 14f79bf93d1..5e6649ee755 100644 --- a/src/com/android/settings/inputmethod/InputPeripheralsSettingsUtils.java +++ b/src/com/android/settings/inputmethod/InputPeripheralsSettingsUtils.java @@ -16,8 +16,8 @@ package com.android.settings.inputmethod; -import static android.hardware.input.KeyboardLayoutSelectionResult.LAYOUT_SELECTION_CRITERIA_USER; import static android.hardware.input.KeyboardLayoutSelectionResult.LAYOUT_SELECTION_CRITERIA_DEVICE; +import static android.hardware.input.KeyboardLayoutSelectionResult.LAYOUT_SELECTION_CRITERIA_USER; import static android.hardware.input.KeyboardLayoutSelectionResult.LAYOUT_SELECTION_CRITERIA_VIRTUAL_KEYBOARD; import android.annotation.NonNull; @@ -55,6 +55,25 @@ public class InputPeripheralsSettingsUtils { static final String EXTRA_INPUT_METHOD_INFO = "input_method_info"; static final String EXTRA_INPUT_METHOD_SUBTYPE = "input_method_subtype"; + /** + * Returns whether any hard keyboard is connected. + */ + static boolean isHardKeyboard() { + for (int deviceId : InputDevice.getDeviceIds()) { + final InputDevice device = InputDevice.getDevice(deviceId); + if (device == null) { + continue; + } + if (device.isFullKeyboard() && !device.isVirtual()) { + return true; + } + } + return false; + } + + /** + * Returns whether any touchpad is connected. + */ static boolean isTouchpad() { for (int deviceId : InputDevice.getDeviceIds()) { final InputDevice device = InputDevice.getDevice(deviceId); @@ -69,6 +88,9 @@ public class InputPeripheralsSettingsUtils { return false; } + /** + * Returns whether any mouse is connected. + */ static boolean isMouse() { for (int deviceId : InputDevice.getDeviceIds()) { final InputDevice device = InputDevice.getDevice(deviceId); diff --git a/src/com/android/settings/inputmethod/ModifierKeysSettings.java b/src/com/android/settings/inputmethod/ModifierKeysSettings.java index f17459805b5..270c922b5ae 100644 --- a/src/com/android/settings/inputmethod/ModifierKeysSettings.java +++ b/src/com/android/settings/inputmethod/ModifierKeysSettings.java @@ -21,12 +21,11 @@ import android.content.Context; import android.util.FeatureFlagUtils; import com.android.settings.R; -import com.android.settings.dashboard.DashboardFragment; import com.android.settings.search.BaseSearchIndexProvider; import com.android.settingslib.search.SearchIndexable; @SearchIndexable -public class ModifierKeysSettings extends DashboardFragment { +public class ModifierKeysSettings extends InputDeviceDashboardFragment { private static final String TAG = "ModifierKeysSettings"; @@ -52,6 +51,11 @@ public class ModifierKeysSettings extends DashboardFragment { return R.xml.modifier_keys_settings; } + @Override + protected boolean needToFinishEarly() { + return isHardKeyboardDetached(); + } + public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = new BaseSearchIndexProvider(R.xml.modifier_keys_settings) { @Override diff --git a/src/com/android/settings/inputmethod/MouseSettingFragment.java b/src/com/android/settings/inputmethod/MouseSettingFragment.java index de9e3e0592e..bffe006416d 100644 --- a/src/com/android/settings/inputmethod/MouseSettingFragment.java +++ b/src/com/android/settings/inputmethod/MouseSettingFragment.java @@ -20,13 +20,12 @@ import android.app.settings.SettingsEnums; import android.content.Context; import com.android.settings.R; -import com.android.settings.dashboard.DashboardFragment; import com.android.settings.keyboard.Flags; import com.android.settings.search.BaseSearchIndexProvider; import com.android.settingslib.search.SearchIndexable; @SearchIndexable -public class MouseSettingFragment extends DashboardFragment { +public class MouseSettingFragment extends InputDeviceDashboardFragment { private static final String TAG = MouseSettingFragment.class.getSimpleName(); @Override @@ -52,4 +51,9 @@ public class MouseSettingFragment extends DashboardFragment { && InputPeripheralsSettingsUtils.isMouse(); } }; + + @Override + protected boolean needToFinishEarly() { + return isMouseDetached(); + } } diff --git a/src/com/android/settings/inputmethod/PointerColorCustomizationFragment.java b/src/com/android/settings/inputmethod/PointerColorCustomizationFragment.java index 49c0413dfe8..736225a9ea1 100644 --- a/src/com/android/settings/inputmethod/PointerColorCustomizationFragment.java +++ b/src/com/android/settings/inputmethod/PointerColorCustomizationFragment.java @@ -23,13 +23,12 @@ import android.app.settings.SettingsEnums; import android.content.Context; import com.android.settings.R; -import com.android.settings.dashboard.DashboardFragment; import com.android.settings.search.BaseSearchIndexProvider; import com.android.settingslib.search.SearchIndexable; /** Settings for pointer and touchpad. */ @SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC) -public class PointerColorCustomizationFragment extends DashboardFragment { +public class PointerColorCustomizationFragment extends InputDeviceDashboardFragment { private static final String TAG = "PointerColorCustomizationFragment"; @@ -56,4 +55,9 @@ public class PointerColorCustomizationFragment extends DashboardFragment { return isTouchpad() || isMouse(); } }; + + @Override + protected boolean needToFinishEarly() { + return isMouseDetached() && isTouchpadDetached(); + } } diff --git a/src/com/android/settings/inputmethod/PointerTouchpadFragment.java b/src/com/android/settings/inputmethod/PointerTouchpadFragment.java index 441bddd2574..450f6bbb448 100644 --- a/src/com/android/settings/inputmethod/PointerTouchpadFragment.java +++ b/src/com/android/settings/inputmethod/PointerTouchpadFragment.java @@ -23,7 +23,6 @@ import android.app.settings.SettingsEnums; import android.content.Context; import com.android.settings.R; -import com.android.settings.dashboard.DashboardFragment; import com.android.settings.search.BaseSearchIndexProvider; import com.android.settings.widget.PreferenceCategoryController; import com.android.settingslib.core.AbstractPreferenceController; @@ -33,7 +32,7 @@ import java.util.List; /** Accessibility settings for pointer and touchpad. */ @SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC) -public class PointerTouchpadFragment extends DashboardFragment { +public class PointerTouchpadFragment extends InputDeviceDashboardFragment { private static final String TAG = "PointerTouchpadFragment"; @@ -80,4 +79,9 @@ public class PointerTouchpadFragment extends DashboardFragment { return buildPreferenceControllers(context); } }; + + @Override + protected boolean needToFinishEarly() { + return isMouseDetached() && isTouchpadDetached(); + } } diff --git a/src/com/android/settings/inputmethod/TouchpadSettingFragment.java b/src/com/android/settings/inputmethod/TouchpadSettingFragment.java index 026357efdec..0ab5c12b5ac 100644 --- a/src/com/android/settings/inputmethod/TouchpadSettingFragment.java +++ b/src/com/android/settings/inputmethod/TouchpadSettingFragment.java @@ -20,13 +20,12 @@ import android.app.settings.SettingsEnums; import android.content.Context; import com.android.settings.R; -import com.android.settings.dashboard.DashboardFragment; import com.android.settings.keyboard.Flags; import com.android.settings.search.BaseSearchIndexProvider; import com.android.settingslib.search.SearchIndexable; @SearchIndexable -public class TouchpadSettingFragment extends DashboardFragment { +public class TouchpadSettingFragment extends InputDeviceDashboardFragment { private static final String TAG = TouchpadSettingFragment.class.getSimpleName(); @Override @@ -52,4 +51,9 @@ public class TouchpadSettingFragment extends DashboardFragment { && InputPeripheralsSettingsUtils.isTouchpad(); } }; + + @Override + protected boolean needToFinishEarly() { + return isTouchpadDetached(); + } } diff --git a/src/com/android/settings/inputmethod/TouchpadThreeFingerTapFragment.java b/src/com/android/settings/inputmethod/TouchpadThreeFingerTapFragment.java index 3aee4bf8927..3d354788965 100644 --- a/src/com/android/settings/inputmethod/TouchpadThreeFingerTapFragment.java +++ b/src/com/android/settings/inputmethod/TouchpadThreeFingerTapFragment.java @@ -22,13 +22,12 @@ import android.app.settings.SettingsEnums; import android.content.Context; import com.android.settings.R; -import com.android.settings.dashboard.DashboardFragment; import com.android.settings.search.BaseSearchIndexProvider; import com.android.settingslib.search.SearchIndexable; /** Input settings for touchpad three finger tap. */ @SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC) -public class TouchpadThreeFingerTapFragment extends DashboardFragment { +public class TouchpadThreeFingerTapFragment extends InputDeviceDashboardFragment { private static final String TAG = "TouchpadThreeFingerTapFragment"; @@ -54,4 +53,9 @@ public class TouchpadThreeFingerTapFragment extends DashboardFragment { return isTouchpad(); } }; + + @Override + protected boolean needToFinishEarly() { + return isTouchpadDetached(); + } }