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.server.inputmethod;
18 
19 import android.annotation.AnyThread;
20 import android.annotation.NonNull;
21 import android.annotation.Nullable;
22 import android.view.inputmethod.InputMethodInfo;
23 import android.view.inputmethod.InputMethodSubtype;
24 
25 import com.android.internal.annotations.GuardedBy;
26 import com.android.internal.inputmethod.InputMethodSubtypeHandle;
27 
28 import java.util.ArrayList;
29 import java.util.List;
30 import java.util.Objects;
31 
32 final class HardwareKeyboardShortcutController {
33     @GuardedBy("ImfLock.class")
34     private final ArrayList<InputMethodSubtypeHandle> mSubtypeHandles = new ArrayList<>();
35 
36     @GuardedBy("ImfLock.class")
reset(@onNull InputMethodUtils.InputMethodSettings settings)37     void reset(@NonNull InputMethodUtils.InputMethodSettings settings) {
38         mSubtypeHandles.clear();
39         for (final InputMethodInfo imi : settings.getEnabledInputMethodListLocked()) {
40             if (!imi.shouldShowInInputMethodPicker()) {
41                 continue;
42             }
43             final List<InputMethodSubtype> subtypes =
44                     settings.getEnabledInputMethodSubtypeListLocked(imi, true);
45             if (subtypes.isEmpty()) {
46                 mSubtypeHandles.add(InputMethodSubtypeHandle.of(imi, null));
47             } else {
48                 for (final InputMethodSubtype subtype : subtypes) {
49                     if (subtype.isSuitableForPhysicalKeyboardLayoutMapping()) {
50                         mSubtypeHandles.add(InputMethodSubtypeHandle.of(imi, subtype));
51                     }
52                 }
53             }
54         }
55     }
56 
57     @AnyThread
58     @Nullable
getNeighborItem(@onNull List<T> list, @NonNull T value, boolean next)59     static <T> T getNeighborItem(@NonNull List<T> list, @NonNull T value, boolean next) {
60         final int size = list.size();
61         for (int i = 0; i < size; ++i) {
62             if (Objects.equals(value, list.get(i))) {
63                 final int nextIndex = (i + (next ? 1 : -1) + size) % size;
64                 return list.get(nextIndex);
65             }
66         }
67         return null;
68     }
69 
70     @GuardedBy("ImfLock.class")
71     @Nullable
onSubtypeSwitch( @onNull InputMethodSubtypeHandle currentImeAndSubtype, boolean forward)72     InputMethodSubtypeHandle onSubtypeSwitch(
73             @NonNull InputMethodSubtypeHandle currentImeAndSubtype, boolean forward) {
74         return getNeighborItem(mSubtypeHandles, currentImeAndSubtype, forward);
75     }
76 }
77