• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.settings.inputmethod;
18 
19 import static android.hardware.input.KeyboardLayoutSelectionResult.LAYOUT_SELECTION_CRITERIA_DEVICE;
20 import static android.hardware.input.KeyboardLayoutSelectionResult.LAYOUT_SELECTION_CRITERIA_USER;
21 import static android.hardware.input.KeyboardLayoutSelectionResult.LAYOUT_SELECTION_CRITERIA_VIRTUAL_KEYBOARD;
22 
23 import android.annotation.NonNull;
24 import android.annotation.Nullable;
25 import android.annotation.SuppressLint;
26 import android.annotation.UserIdInt;
27 import android.content.Context;
28 import android.hardware.input.InputDeviceIdentifier;
29 import android.hardware.input.InputManager;
30 import android.hardware.input.KeyboardLayout;
31 import android.hardware.input.KeyboardLayoutSelectionResult;
32 import android.hardware.input.KeyboardLayoutSelectionResult.LayoutSelectionCriteria;
33 import android.os.UserHandle;
34 import android.view.InputDevice;
35 import android.view.inputmethod.InputMethodInfo;
36 import android.view.inputmethod.InputMethodManager;
37 import android.view.inputmethod.InputMethodSubtype;
38 
39 import androidx.annotation.StringRes;
40 
41 import com.android.settings.R;
42 
43 import java.util.Arrays;
44 import java.util.Comparator;
45 
46 /**
47  * Utilities of input peripherals settings
48  */
49 public class InputPeripheralsSettingsUtils {
50 
51     static final String EXTRA_TITLE = "keyboard_layout_picker_title";
52     static final String EXTRA_USER_ID = "user_id";
53     static final String EXTRA_INPUT_DEVICE_IDENTIFIER = "input_device_identifier";
54     static final String EXTRA_INPUT_DEVICE = "input_device";
55     static final String EXTRA_INPUT_METHOD_INFO = "input_method_info";
56     static final String EXTRA_INPUT_METHOD_SUBTYPE = "input_method_subtype";
57 
58     /**
59      * Returns whether any hard keyboard is connected.
60      */
isHardKeyboard()61     static boolean isHardKeyboard() {
62         for (int deviceId : InputDevice.getDeviceIds()) {
63             final InputDevice device = InputDevice.getDevice(deviceId);
64             if (device == null) {
65                 continue;
66             }
67             if (device.isFullKeyboard() && !device.isVirtual()) {
68                 return true;
69             }
70         }
71         return false;
72     }
73 
74     /**
75      * Returns whether any touchpad is connected.
76      */
isTouchpad()77     static boolean isTouchpad() {
78         for (int deviceId : InputDevice.getDeviceIds()) {
79             final InputDevice device = InputDevice.getDevice(deviceId);
80             if (device == null) {
81                 continue;
82             }
83             if ((device.getSources() & InputDevice.SOURCE_TOUCHPAD)
84                     == InputDevice.SOURCE_TOUCHPAD) {
85                 return true;
86             }
87         }
88         return false;
89     }
90 
91     /**
92      * Returns whether any mouse is connected.
93      */
isMouse()94     static boolean isMouse() {
95         for (int deviceId : InputDevice.getDeviceIds()) {
96             final InputDevice device = InputDevice.getDevice(deviceId);
97             if (device == null) {
98                 continue;
99             }
100             if ((device.getSources() & InputDevice.SOURCE_MOUSE)
101                     == InputDevice.SOURCE_MOUSE) {
102                 return true;
103             }
104         }
105         return false;
106     }
107 
getTouchpadAndMouseTitleTitleResId()108     static @StringRes int getTouchpadAndMouseTitleTitleResId() {
109         boolean isMouse = isMouse();
110         boolean isTouchpad = isTouchpad();
111         if (isMouse && isTouchpad) {
112             return R.string.trackpad_mouse_settings;
113         } else if (isMouse) {
114             return R.string.mouse_settings;
115         } else {
116             return R.string.trackpad_settings;
117         }
118     }
119 
120     @SuppressLint("MissingPermission")
121     @Nullable
getSelectedKeyboardLayoutLabelForUser(Context context, @UserIdInt int userId, InputDeviceIdentifier inputDeviceIdentifier)122     static String getSelectedKeyboardLayoutLabelForUser(Context context, @UserIdInt int userId,
123             InputDeviceIdentifier inputDeviceIdentifier) {
124         InputMethodManager imm = context.getSystemService(InputMethodManager.class);
125         InputManager im = context.getSystemService(InputManager.class);
126         if (imm == null || im == null) {
127             return null;
128         }
129         InputMethodInfo imeInfo = imm.getCurrentInputMethodInfoAsUser(UserHandle.of(userId));
130         InputMethodSubtype subtype = imm.getCurrentInputMethodSubtype();
131         KeyboardLayout[] keyboardLayouts = getKeyboardLayouts(im, userId, inputDeviceIdentifier,
132                 imeInfo, subtype);
133         KeyboardLayoutSelectionResult result = getKeyboardLayout(im, userId, inputDeviceIdentifier,
134                 imeInfo, subtype);
135         if (result != null) {
136             for (KeyboardLayout keyboardLayout : keyboardLayouts) {
137                 if (keyboardLayout.getDescriptor().equals(result.getLayoutDescriptor())) {
138                     return keyboardLayout.getLabel();
139                 }
140             }
141         }
142         return null;
143     }
144 
145     static class KeyboardInfo {
146         CharSequence mSubtypeLabel;
147         String mLayout;
148         @LayoutSelectionCriteria int mSelectionCriteria;
149         InputMethodInfo mInputMethodInfo;
150         InputMethodSubtype mInputMethodSubtype;
151 
KeyboardInfo( CharSequence subtypeLabel, String layout, @LayoutSelectionCriteria int selectionCriteria, InputMethodInfo inputMethodInfo, InputMethodSubtype inputMethodSubtype)152         KeyboardInfo(
153                 CharSequence subtypeLabel,
154                 String layout,
155                 @LayoutSelectionCriteria int selectionCriteria,
156                 InputMethodInfo inputMethodInfo,
157                 InputMethodSubtype inputMethodSubtype) {
158             mSubtypeLabel = subtypeLabel;
159             mLayout = layout;
160             mSelectionCriteria = selectionCriteria;
161             mInputMethodInfo = inputMethodInfo;
162             mInputMethodSubtype = inputMethodSubtype;
163         }
164 
getPrefId()165         String getPrefId() {
166             return mInputMethodInfo.getId() + "_" + mInputMethodSubtype.hashCode();
167         }
168 
getSubtypeLabel()169         CharSequence getSubtypeLabel() {
170             return mSubtypeLabel;
171         }
172 
getLayout()173         String getLayout() {
174             return mLayout;
175         }
176 
getLayoutSummaryText(Context context)177         String getLayoutSummaryText(Context context) {
178             if (isAutomaticSelection(mSelectionCriteria)) {
179                 return context.getResources().getString(R.string.automatic_keyboard_layout_label,
180                         mLayout);
181             } else if (isUserSelection(mSelectionCriteria)) {
182                 return context.getResources().getString(
183                         R.string.user_selected_keyboard_layout_label, mLayout);
184             }
185             return mLayout;
186         }
187 
getInputMethodInfo()188         InputMethodInfo getInputMethodInfo() {
189             return mInputMethodInfo;
190         }
191 
getInputMethodSubtype()192         InputMethodSubtype getInputMethodSubtype() {
193             return mInputMethodSubtype;
194         }
195     }
196 
getInputDevice(InputManager im, InputDeviceIdentifier identifier)197     static InputDevice getInputDevice(InputManager im, InputDeviceIdentifier identifier) {
198         return identifier == null ? null : im.getInputDeviceByDescriptor(
199                 identifier.getDescriptor());
200     }
201 
getKeyboardLayouts(InputManager inputManager, int userId, InputDeviceIdentifier identifier, InputMethodInfo info, InputMethodSubtype subtype)202     static KeyboardLayout[] getKeyboardLayouts(InputManager inputManager, int userId,
203             InputDeviceIdentifier identifier, InputMethodInfo info, InputMethodSubtype subtype) {
204         return inputManager.getKeyboardLayoutListForInputDevice(identifier, userId, info, subtype);
205     }
206 
207     @NonNull
getKeyboardLayout(InputManager inputManager, int userId, InputDeviceIdentifier identifier, InputMethodInfo info, InputMethodSubtype subtype)208     static KeyboardLayoutSelectionResult getKeyboardLayout(InputManager inputManager, int userId,
209             InputDeviceIdentifier identifier, InputMethodInfo info, InputMethodSubtype subtype) {
210         return inputManager.getKeyboardLayoutForInputDevice(identifier, userId, info, subtype);
211     }
212 
isAutomaticSelection(@ayoutSelectionCriteria int criteria)213     static boolean isAutomaticSelection(@LayoutSelectionCriteria int criteria) {
214         return criteria == LAYOUT_SELECTION_CRITERIA_DEVICE
215                 || criteria == LAYOUT_SELECTION_CRITERIA_VIRTUAL_KEYBOARD;
216     }
217 
isUserSelection(@ayoutSelectionCriteria int criteria)218     static boolean isUserSelection(@LayoutSelectionCriteria int criteria) {
219         return criteria == LAYOUT_SELECTION_CRITERIA_USER;
220     }
221 
sortKeyboardLayoutsByLabel(KeyboardLayout[] keyboardLayouts)222     static void sortKeyboardLayoutsByLabel(KeyboardLayout[] keyboardLayouts) {
223         Arrays.sort(
224                 keyboardLayouts,
225                 Comparator.comparing(KeyboardLayout::getLabel)
226         );
227     }
228 }
229