blob: f8c6640afce66f460db60fabd74457de6bf5a792 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
/*
* Copyright (C) 2018 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.internal.inputmethod;
import android.annotation.AnyThread;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.IBinder;
import com.android.internal.annotations.GuardedBy;
import java.lang.ref.WeakReference;
import java.util.WeakHashMap;
/**
* A weak-reference-based mapper from IME token to {@link InputMethodPrivilegedOperations} that is
* used only to support deprecated IME APIs in {@link android.view.inputmethod.InputMethodManager}.
*
* <p>This class is designed to be used as a per-process global registry.</p>
*/
public final class InputMethodPrivilegedOperationsRegistry {
private InputMethodPrivilegedOperationsRegistry() {
// Not intended to be instantiated.
}
private static final Object sLock = new Object();
@Nullable
@GuardedBy("sLock")
private static WeakHashMap<IBinder, WeakReference<InputMethodPrivilegedOperations>> sRegistry;
@Nullable
private static InputMethodPrivilegedOperations sNop;
@NonNull
@AnyThread
private static InputMethodPrivilegedOperations getNopOps() {
// Strict thread-safety is not necessary because temporarily creating multiple nop instance
// is basically harmless
if (sNop == null) {
sNop = new InputMethodPrivilegedOperations();
}
return sNop;
}
/**
* Put a new entry to the registry.
*
* <p>Note: {@link InputMethodPrivilegedOperationsRegistry} does not hold strong reference to
* {@code token} and {@code ops}. The caller must be responsible for holding strong references
* to those objects, that is until {@link android.inputmethodservice.InputMethodService} is
* destroyed.</p>
*
* @param token IME token
* @param ops {@link InputMethodPrivilegedOperations} to be associated with the given IME token
*/
@AnyThread
public static void put(IBinder token, InputMethodPrivilegedOperations ops) {
synchronized (sLock) {
if (sRegistry == null) {
sRegistry = new WeakHashMap<>();
}
sRegistry.put(token, new WeakReference<>(ops));
}
}
/**
* Get a {@link InputMethodPrivilegedOperations} from the given IME token. If it is not
* available, return a fake instance that does nothing except for showing warning messages.
*
* @param token IME token
* @return real {@link InputMethodPrivilegedOperations} object if {@code token} is still valid.
* Otherwise a fake instance of {@link InputMethodPrivilegedOperations} hat does nothing
* except for showing warning messages
*/
@NonNull
@AnyThread
public static InputMethodPrivilegedOperations get(IBinder token) {
synchronized (sLock) {
if (sRegistry == null) {
return getNopOps();
}
final WeakReference<InputMethodPrivilegedOperations> wrapperRef = sRegistry.get(token);
if (wrapperRef == null) {
return getNopOps();
}
final InputMethodPrivilegedOperations wrapper = wrapperRef.get();
if (wrapper == null) {
return getNopOps();
}
return wrapper;
}
}
/**
* Explicitly removes the specified entry.
*
* <p>Note: Calling this method is optional. In general, {@link WeakHashMap} and
* {@link WeakReference} guarantee that the entry will be removed after specified binder proxies
* are garbage collected.</p>
*
* @param token IME token to be removed.
*/
@AnyThread
public static void remove(IBinder token) {
synchronized (sLock) {
if (sRegistry == null) {
return;
}
sRegistry.remove(token);
if (sRegistry.isEmpty()) {
sRegistry = null;
}
}
}
}
|