1 /* 2 * Copyright (C) 2022 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 android.content.Context; 20 import android.hardware.input.InputDeviceIdentifier; 21 import android.hardware.input.InputManager; 22 import android.hardware.input.KeyboardLayout; 23 import android.os.Bundle; 24 import android.view.inputmethod.InputMethodInfo; 25 import android.view.inputmethod.InputMethodSubtype; 26 27 import androidx.fragment.app.Fragment; 28 import androidx.preference.Preference; 29 import androidx.preference.PreferenceScreen; 30 31 import com.android.settings.R; 32 import com.android.settings.core.BasePreferenceController; 33 import com.android.settings.widget.TickButtonPreference; 34 import com.android.settingslib.core.lifecycle.LifecycleObserver; 35 import com.android.settingslib.core.lifecycle.events.OnStart; 36 import com.android.settingslib.core.lifecycle.events.OnStop; 37 38 import java.util.HashMap; 39 import java.util.Map; 40 41 public class NewKeyboardLayoutPickerController extends BasePreferenceController implements 42 InputManager.InputDeviceListener, LifecycleObserver, OnStart, OnStop { 43 44 private final InputManager mIm; 45 private final Map<TickButtonPreference, KeyboardLayout> mPreferenceMap; 46 private Fragment mParent; 47 private CharSequence mTitle; 48 private int mInputDeviceId; 49 private int mUserId; 50 private InputDeviceIdentifier mInputDeviceIdentifier; 51 private InputMethodInfo mInputMethodInfo; 52 private InputMethodSubtype mInputMethodSubtype; 53 private KeyboardLayout[] mKeyboardLayouts; 54 private PreferenceScreen mScreen; 55 private String mPreviousSelection; 56 private String mLayout; 57 NewKeyboardLayoutPickerController(Context context, String key)58 public NewKeyboardLayoutPickerController(Context context, String key) { 59 super(context, key); 60 mIm = context.getSystemService(InputManager.class); 61 mInputDeviceId = -1; 62 mPreferenceMap = new HashMap<>(); 63 } 64 initialize(Fragment parent)65 public void initialize(Fragment parent) { 66 mParent = parent; 67 Bundle arguments = parent.getArguments(); 68 mTitle = arguments.getCharSequence(NewKeyboardSettingsUtils.EXTRA_TITLE); 69 mUserId = arguments.getInt(NewKeyboardSettingsUtils.EXTRA_USER_ID); 70 mInputDeviceIdentifier = 71 arguments.getParcelable(NewKeyboardSettingsUtils.EXTRA_INPUT_DEVICE_IDENTIFIER); 72 mInputMethodInfo = 73 arguments.getParcelable(NewKeyboardSettingsUtils.EXTRA_INPUT_METHOD_INFO); 74 mInputMethodSubtype = 75 arguments.getParcelable(NewKeyboardSettingsUtils.EXTRA_INPUT_METHOD_SUBTYPE); 76 mLayout = getSelectedLayoutLabel(); 77 mKeyboardLayouts = mIm.getKeyboardLayoutListForInputDevice( 78 mInputDeviceIdentifier, mUserId, mInputMethodInfo, mInputMethodSubtype); 79 parent.getActivity().setTitle(mTitle); 80 } 81 82 @Override onStart()83 public void onStart() { 84 mIm.registerInputDeviceListener(this, null); 85 if (mInputDeviceIdentifier == null 86 || NewKeyboardSettingsUtils.getInputDevice(mIm, mInputDeviceIdentifier) == null) { 87 return; 88 } 89 mInputDeviceId = 90 NewKeyboardSettingsUtils.getInputDevice(mIm, mInputDeviceIdentifier).getId(); 91 } 92 93 @Override onStop()94 public void onStop() { 95 mIm.unregisterInputDeviceListener(this); 96 mInputDeviceId = -1; 97 } 98 99 @Override displayPreference(PreferenceScreen screen)100 public void displayPreference(PreferenceScreen screen) { 101 super.displayPreference(screen); 102 mScreen = screen; 103 createPreferenceHierarchy(); 104 } 105 106 @Override getAvailabilityStatus()107 public int getAvailabilityStatus() { 108 return AVAILABLE; 109 } 110 111 @Override handlePreferenceTreeClick(Preference preference)112 public boolean handlePreferenceTreeClick(Preference preference) { 113 if (!(preference instanceof TickButtonPreference)) { 114 return false; 115 } 116 117 final TickButtonPreference pref = (TickButtonPreference) preference; 118 pref.setSelected(true); 119 if (mPreviousSelection != null && !mPreviousSelection.equals(preference.getKey())) { 120 TickButtonPreference preSelectedPref = mScreen.findPreference(mPreviousSelection); 121 preSelectedPref.setSelected(false); 122 } 123 setLayout(pref); 124 mPreviousSelection = preference.getKey(); 125 return true; 126 } 127 128 @Override onInputDeviceAdded(int deviceId)129 public void onInputDeviceAdded(int deviceId) { 130 // Do nothing. 131 } 132 133 @Override onInputDeviceRemoved(int deviceId)134 public void onInputDeviceRemoved(int deviceId) { 135 if (mInputDeviceId >= 0 && deviceId == mInputDeviceId) { 136 mParent.getActivity().finish(); 137 } 138 } 139 140 @Override onInputDeviceChanged(int deviceId)141 public void onInputDeviceChanged(int deviceId) { 142 // Do nothing. 143 } 144 createPreferenceHierarchy()145 private void createPreferenceHierarchy() { 146 if (mKeyboardLayouts == null) { 147 return; 148 } 149 for (KeyboardLayout layout : mKeyboardLayouts) { 150 final TickButtonPreference pref; 151 pref = new TickButtonPreference(mScreen.getContext()); 152 pref.setTitle(layout.getLabel()); 153 154 if (mLayout.equals(layout.getLabel())) { 155 pref.setSelected(true); 156 mPreviousSelection = layout.getDescriptor(); 157 } 158 pref.setKey(layout.getDescriptor()); 159 mScreen.addPreference(pref); 160 mPreferenceMap.put(pref, layout); 161 } 162 } 163 setLayout(TickButtonPreference preference)164 private void setLayout(TickButtonPreference preference) { 165 mIm.setKeyboardLayoutForInputDevice( 166 mInputDeviceIdentifier, 167 mUserId, 168 mInputMethodInfo, 169 mInputMethodSubtype, 170 mPreferenceMap.get(preference).getDescriptor()); 171 } 172 getSelectedLayoutLabel()173 private String getSelectedLayoutLabel() { 174 String label = mContext.getString(R.string.keyboard_default_layout); 175 String layout = NewKeyboardSettingsUtils.getKeyboardLayout( 176 mIm, mUserId, mInputDeviceIdentifier, mInputMethodInfo, mInputMethodSubtype); 177 KeyboardLayout[] keyboardLayouts = NewKeyboardSettingsUtils.getKeyboardLayouts( 178 mIm, mUserId, mInputDeviceIdentifier, mInputMethodInfo, mInputMethodSubtype); 179 if (layout != null) { 180 for (KeyboardLayout keyboardLayout : keyboardLayouts) { 181 if (keyboardLayout.getDescriptor().equals(layout)) { 182 label = keyboardLayout.getLabel(); 183 break; 184 } 185 } 186 } 187 return label; 188 } 189 } 190