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_USER; 20 import static android.hardware.input.KeyboardLayoutSelectionResult.LAYOUT_SELECTION_CRITERIA_DEVICE; 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 com.android.settings.R; 40 41 import java.util.Arrays; 42 import java.util.Comparator; 43 44 /** 45 * Utilities of keyboard settings 46 */ 47 public class NewKeyboardSettingsUtils { 48 49 static final String EXTRA_TITLE = "keyboard_layout_picker_title"; 50 static final String EXTRA_USER_ID = "user_id"; 51 static final String EXTRA_INPUT_DEVICE_IDENTIFIER = "input_device_identifier"; 52 static final String EXTRA_INPUT_METHOD_INFO = "input_method_info"; 53 static final String EXTRA_INPUT_METHOD_SUBTYPE = "input_method_subtype"; 54 isTouchpad()55 static boolean isTouchpad() { 56 for (int deviceId : InputDevice.getDeviceIds()) { 57 final InputDevice device = InputDevice.getDevice(deviceId); 58 if (device == null) { 59 continue; 60 } 61 if ((device.getSources() & InputDevice.SOURCE_TOUCHPAD) 62 == InputDevice.SOURCE_TOUCHPAD) { 63 return true; 64 } 65 } 66 return false; 67 } 68 69 @SuppressLint("MissingPermission") 70 @Nullable getSelectedKeyboardLayoutLabelForUser(Context context, @UserIdInt int userId, InputDeviceIdentifier inputDeviceIdentifier)71 static String getSelectedKeyboardLayoutLabelForUser(Context context, @UserIdInt int userId, 72 InputDeviceIdentifier inputDeviceIdentifier) { 73 InputMethodManager imm = context.getSystemService(InputMethodManager.class); 74 InputManager im = context.getSystemService(InputManager.class); 75 if (imm == null || im == null) { 76 return null; 77 } 78 InputMethodInfo imeInfo = imm.getCurrentInputMethodInfoAsUser(UserHandle.of(userId)); 79 InputMethodSubtype subtype = imm.getCurrentInputMethodSubtype(); 80 KeyboardLayout[] keyboardLayouts = getKeyboardLayouts(im, userId, inputDeviceIdentifier, 81 imeInfo, subtype); 82 KeyboardLayoutSelectionResult result = getKeyboardLayout(im, userId, inputDeviceIdentifier, 83 imeInfo, subtype); 84 if (result != null) { 85 for (KeyboardLayout keyboardLayout : keyboardLayouts) { 86 if (keyboardLayout.getDescriptor().equals(result.getLayoutDescriptor())) { 87 return keyboardLayout.getLabel(); 88 } 89 } 90 } 91 return null; 92 } 93 94 static class KeyboardInfo { 95 CharSequence mSubtypeLabel; 96 String mLayout; 97 @LayoutSelectionCriteria int mSelectionCriteria; 98 InputMethodInfo mInputMethodInfo; 99 InputMethodSubtype mInputMethodSubtype; 100 KeyboardInfo( CharSequence subtypeLabel, String layout, @LayoutSelectionCriteria int selectionCriteria, InputMethodInfo inputMethodInfo, InputMethodSubtype inputMethodSubtype)101 KeyboardInfo( 102 CharSequence subtypeLabel, 103 String layout, 104 @LayoutSelectionCriteria int selectionCriteria, 105 InputMethodInfo inputMethodInfo, 106 InputMethodSubtype inputMethodSubtype) { 107 mSubtypeLabel = subtypeLabel; 108 mLayout = layout; 109 mSelectionCriteria = selectionCriteria; 110 mInputMethodInfo = inputMethodInfo; 111 mInputMethodSubtype = inputMethodSubtype; 112 } 113 getPrefId()114 String getPrefId() { 115 return mInputMethodInfo.getId() + "_" + mInputMethodSubtype.hashCode(); 116 } 117 getSubtypeLabel()118 CharSequence getSubtypeLabel() { 119 return mSubtypeLabel; 120 } 121 getLayout()122 String getLayout() { 123 return mLayout; 124 } 125 getLayoutSummaryText(Context context)126 String getLayoutSummaryText(Context context) { 127 if (isAutomaticSelection(mSelectionCriteria)) { 128 return context.getResources().getString(R.string.automatic_keyboard_layout_label, 129 mLayout); 130 } else if (isUserSelection(mSelectionCriteria)) { 131 return context.getResources().getString( 132 R.string.user_selected_keyboard_layout_label, mLayout); 133 } 134 return mLayout; 135 } 136 getInputMethodInfo()137 InputMethodInfo getInputMethodInfo() { 138 return mInputMethodInfo; 139 } 140 getInputMethodSubtype()141 InputMethodSubtype getInputMethodSubtype() { 142 return mInputMethodSubtype; 143 } 144 } 145 getInputDevice(InputManager im, InputDeviceIdentifier identifier)146 static InputDevice getInputDevice(InputManager im, InputDeviceIdentifier identifier) { 147 return identifier == null ? null : im.getInputDeviceByDescriptor( 148 identifier.getDescriptor()); 149 } 150 getKeyboardLayouts(InputManager inputManager, int userId, InputDeviceIdentifier identifier, InputMethodInfo info, InputMethodSubtype subtype)151 static KeyboardLayout[] getKeyboardLayouts(InputManager inputManager, int userId, 152 InputDeviceIdentifier identifier, InputMethodInfo info, InputMethodSubtype subtype) { 153 return inputManager.getKeyboardLayoutListForInputDevice(identifier, userId, info, subtype); 154 } 155 156 @NonNull getKeyboardLayout(InputManager inputManager, int userId, InputDeviceIdentifier identifier, InputMethodInfo info, InputMethodSubtype subtype)157 static KeyboardLayoutSelectionResult getKeyboardLayout(InputManager inputManager, int userId, 158 InputDeviceIdentifier identifier, InputMethodInfo info, InputMethodSubtype subtype) { 159 return inputManager.getKeyboardLayoutForInputDevice(identifier, userId, info, subtype); 160 } 161 isAutomaticSelection(@ayoutSelectionCriteria int criteria)162 static boolean isAutomaticSelection(@LayoutSelectionCriteria int criteria) { 163 return criteria == LAYOUT_SELECTION_CRITERIA_DEVICE 164 || criteria == LAYOUT_SELECTION_CRITERIA_VIRTUAL_KEYBOARD; 165 } 166 isUserSelection(@ayoutSelectionCriteria int criteria)167 static boolean isUserSelection(@LayoutSelectionCriteria int criteria) { 168 return criteria == LAYOUT_SELECTION_CRITERIA_USER; 169 } 170 sortKeyboardLayoutsByLabel(KeyboardLayout[] keyboardLayouts)171 static void sortKeyboardLayoutsByLabel(KeyboardLayout[] keyboardLayouts) { 172 Arrays.sort( 173 keyboardLayouts, 174 Comparator.comparing(KeyboardLayout::getLabel) 175 ); 176 } 177 } 178