Loading core/java/android/inputmethodservice/InputMethodService.java +3 −2 Original line number Diff line number Diff line Loading @@ -85,6 +85,7 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.inputmethod.IInputContentUriToken; import com.android.internal.inputmethod.IInputMethodPrivilegedOperations; import com.android.internal.inputmethod.InputMethodPrivilegedOperations; import com.android.internal.inputmethod.InputMethodPrivilegedOperationsRegistry; import java.io.FileDescriptor; import java.io.PrintWriter; Loading Loading @@ -465,7 +466,7 @@ public class InputMethodService extends AbstractInputMethodService { public final void initializeInternal(IBinder token, int displayId, IInputMethodPrivilegedOperations privilegedOperations) { mPrivOps.set(privilegedOperations); mImm.registerInputMethodPrivOps(token, mPrivOps); InputMethodPrivilegedOperationsRegistry.put(token, mPrivOps); updateInputMethodDisplay(displayId); attachToken(token); } Loading Loading @@ -1031,7 +1032,7 @@ public class InputMethodService extends AbstractInputMethodService { if (mToken != null) { // This is completely optional, but allows us to show more explicit error messages // when IME developers are doing something unsupported. mImm.unregisterInputMethodPrivOps(mToken); InputMethodPrivilegedOperationsRegistry.remove(mToken); } } Loading core/java/android/view/inputmethod/InputMethodManager.java +15 −47 Original line number Diff line number Diff line Loading @@ -57,7 +57,6 @@ import android.view.ViewRootImpl; import android.view.WindowManager.LayoutParams.SoftInputModeFlags; import android.view.autofill.AutofillManager; import com.android.internal.inputmethod.InputMethodPrivilegedOperations; import com.android.internal.inputmethod.InputMethodPrivilegedOperationsRegistry; import com.android.internal.os.SomeArgs; import com.android.internal.view.IInputConnectionWrapper; Loading Loading @@ -387,9 +386,6 @@ public final class InputMethodManager { final Pool<PendingEvent> mPendingEventPool = new SimplePool<>(20); final SparseArray<PendingEvent> mPendingEvents = new SparseArray<>(20); private final InputMethodPrivilegedOperationsRegistry mPrivOpsRegistry = new InputMethodPrivilegedOperationsRegistry(); // ----------------------------------------------------------- static final int MSG_DUMP = 1; Loading Loading @@ -741,7 +737,7 @@ public final class InputMethodManager { */ @Deprecated public void showStatusIcon(IBinder imeToken, String packageName, @DrawableRes int iconId) { mPrivOpsRegistry.get(imeToken).updateStatusIcon(packageName, iconId); InputMethodPrivilegedOperationsRegistry.get(imeToken).updateStatusIcon(packageName, iconId); } /** Loading @@ -751,7 +747,7 @@ public final class InputMethodManager { */ @Deprecated public void hideStatusIcon(IBinder imeToken) { mPrivOpsRegistry.get(imeToken).updateStatusIcon(null, 0); InputMethodPrivilegedOperationsRegistry.get(imeToken).updateStatusIcon(null, 0); } /** @hide */ Loading Loading @@ -1792,7 +1788,7 @@ public final class InputMethodManager { public void setInputMethod(IBinder token, String id) { if (token == null) { // Note: null token is allowed for callers that have WRITE_SECURE_SETTINGS permission. // Thus we cannot always rely on mPrivOpsRegistry unfortunately. // Thus we cannot always rely on InputMethodPrivilegedOperationsRegistry unfortunately. // TODO(Bug 114488811): Consider deprecating null token rule. try { mService.setInputMethod(token, id); Loading @@ -1801,7 +1797,7 @@ public final class InputMethodManager { } return; } mPrivOpsRegistry.get(token).setInputMethod(id); InputMethodPrivilegedOperationsRegistry.get(token).setInputMethod(id); } /** Loading @@ -1821,7 +1817,7 @@ public final class InputMethodManager { public void setInputMethodAndSubtype(IBinder token, String id, InputMethodSubtype subtype) { if (token == null) { // Note: null token is allowed for callers that have WRITE_SECURE_SETTINGS permission. // Thus we cannot always rely on mPrivOpsRegistry unfortunately. // Thus we cannot always rely on InputMethodPrivilegedOperationsRegistry unfortunately. // TODO(Bug 114488811): Consider deprecating null token rule. try { mService.setInputMethodAndSubtype(token, id, subtype); Loading @@ -1830,7 +1826,7 @@ public final class InputMethodManager { } return; } mPrivOpsRegistry.get(token).setInputMethodAndSubtype(id, subtype); InputMethodPrivilegedOperationsRegistry.get(token).setInputMethodAndSubtype(id, subtype); } /** Loading @@ -1850,7 +1846,7 @@ public final class InputMethodManager { */ @Deprecated public void hideSoftInputFromInputMethod(IBinder token, int flags) { mPrivOpsRegistry.get(token).hideMySoftInput(flags); InputMethodPrivilegedOperationsRegistry.get(token).hideMySoftInput(flags); } /** Loading @@ -1871,7 +1867,7 @@ public final class InputMethodManager { */ @Deprecated public void showSoftInputFromInputMethod(IBinder token, int flags) { mPrivOpsRegistry.get(token).showMySoftInput(flags); InputMethodPrivilegedOperationsRegistry.get(token).showMySoftInput(flags); } /** Loading Loading @@ -2231,7 +2227,7 @@ public final class InputMethodManager { public boolean switchToLastInputMethod(IBinder imeToken) { if (imeToken == null) { // Note: null token is allowed for callers that have WRITE_SECURE_SETTINGS permission. // Thus we cannot always rely on mPrivOpsRegistry unfortunately. // Thus we cannot always rely on InputMethodPrivilegedOperationsRegistry unfortunately. // TODO(Bug 114488811): Consider deprecating null token rule. try { return mService.switchToPreviousInputMethod(imeToken); Loading @@ -2239,7 +2235,7 @@ public final class InputMethodManager { throw e.rethrowFromSystemServer(); } } return mPrivOpsRegistry.get(imeToken).switchToPreviousInputMethod(); return InputMethodPrivilegedOperationsRegistry.get(imeToken).switchToPreviousInputMethod(); } /** Loading @@ -2259,7 +2255,7 @@ public final class InputMethodManager { public boolean switchToNextInputMethod(IBinder imeToken, boolean onlyCurrentIme) { if (imeToken == null) { // Note: null token is allowed for callers that have WRITE_SECURE_SETTINGS permission. // Thus we cannot always rely on mPrivOpsRegistry unfortunately. // Thus we cannot always rely on InputMethodPrivilegedOperationsRegistry unfortunately. // TODO(Bug 114488811): Consider deprecating null token rule. try { return mService.switchToNextInputMethod(imeToken, onlyCurrentIme); Loading @@ -2267,7 +2263,8 @@ public final class InputMethodManager { throw e.rethrowFromSystemServer(); } } return mPrivOpsRegistry.get(imeToken).switchToNextInputMethod(onlyCurrentIme); return InputMethodPrivilegedOperationsRegistry.get(imeToken) .switchToNextInputMethod(onlyCurrentIme); } /** Loading @@ -2286,7 +2283,8 @@ public final class InputMethodManager { */ @Deprecated public boolean shouldOfferSwitchingToNextInputMethod(IBinder imeToken) { return mPrivOpsRegistry.get(imeToken).shouldOfferSwitchingToNextInputMethod(); return InputMethodPrivilegedOperationsRegistry.get(imeToken) .shouldOfferSwitchingToNextInputMethod(); } /** Loading Loading @@ -2422,34 +2420,4 @@ public final class InputMethodManager { sb.append(",temporaryDetach=" + view.isTemporarilyDetached()); return sb.toString(); } /** * Called by {@link InputMethodService} so that API calls to deprecated ones defined in this * class can be forwarded to {@link InputMethodPrivilegedOperations}. * * <p>Note: this method does not hold strong references to {@code token} and {@code ops}. The * registry entry will be automatically cleared after {@code token} is garbage collected.</p> * * @param token IME token that is associated with {@code ops} * @param ops {@link InputMethodPrivilegedOperations} that is associated with {@code token} * @hide */ public void registerInputMethodPrivOps(IBinder token, InputMethodPrivilegedOperations ops) { mPrivOpsRegistry.put(token, ops); } /** * Called from {@link InputMethodService#onDestroy()} to make sure that deprecated IME APIs * defined in this class can no longer access to {@link InputMethodPrivilegedOperations}. * * <p>Note: Calling this method is optional, but at least gives more explict error message in * logcat when IME developers are doing something unsupported (e.g. trying to call IME APIs * after {@link InputMethodService#onDestroy()}).</p> * * @param token IME token to be removed. * @hide */ public void unregisterInputMethodPrivOps(IBinder token) { mPrivOpsRegistry.remove(token); } } core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperationsRegistry.java +32 −13 Original line number Diff line number Diff line Loading @@ -29,12 +29,19 @@ 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 final Object mLock = new Object(); @GuardedBy("mLock") private final WeakHashMap<IBinder, WeakReference<InputMethodPrivilegedOperations>> mRegistry = new WeakHashMap<>(); 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; Loading Loading @@ -62,10 +69,13 @@ public final class InputMethodPrivilegedOperationsRegistry { * @param ops {@link InputMethodPrivilegedOperations} to be associated with the given IME token */ @AnyThread public void put(IBinder token, InputMethodPrivilegedOperations ops) { synchronized (mLock) { public static void put(IBinder token, InputMethodPrivilegedOperations ops) { synchronized (sLock) { if (sRegistry == null) { sRegistry = new WeakHashMap<>(); } final WeakReference<InputMethodPrivilegedOperations> previousOps = mRegistry.put(token, new WeakReference<>(ops)); sRegistry.put(token, new WeakReference<>(ops)); if (previousOps != null) { throw new IllegalStateException(previousOps.get() + " is already registered for " + " this token=" + token + " newOps=" + ops); Loading @@ -84,9 +94,12 @@ public final class InputMethodPrivilegedOperationsRegistry { */ @NonNull @AnyThread public InputMethodPrivilegedOperations get(IBinder token) { synchronized (mLock) { final WeakReference<InputMethodPrivilegedOperations> wrapperRef = mRegistry.get(token); 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(); } Loading @@ -108,9 +121,15 @@ public final class InputMethodPrivilegedOperationsRegistry { * @param token IME token to be removed. */ @AnyThread public void remove(IBinder token) { synchronized (mLock) { mRegistry.remove(token); public static void remove(IBinder token) { synchronized (sLock) { if (sRegistry == null) { return; } sRegistry.remove(token); if (sRegistry.isEmpty()) { sRegistry = null; } } } } Loading
core/java/android/inputmethodservice/InputMethodService.java +3 −2 Original line number Diff line number Diff line Loading @@ -85,6 +85,7 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.inputmethod.IInputContentUriToken; import com.android.internal.inputmethod.IInputMethodPrivilegedOperations; import com.android.internal.inputmethod.InputMethodPrivilegedOperations; import com.android.internal.inputmethod.InputMethodPrivilegedOperationsRegistry; import java.io.FileDescriptor; import java.io.PrintWriter; Loading Loading @@ -465,7 +466,7 @@ public class InputMethodService extends AbstractInputMethodService { public final void initializeInternal(IBinder token, int displayId, IInputMethodPrivilegedOperations privilegedOperations) { mPrivOps.set(privilegedOperations); mImm.registerInputMethodPrivOps(token, mPrivOps); InputMethodPrivilegedOperationsRegistry.put(token, mPrivOps); updateInputMethodDisplay(displayId); attachToken(token); } Loading Loading @@ -1031,7 +1032,7 @@ public class InputMethodService extends AbstractInputMethodService { if (mToken != null) { // This is completely optional, but allows us to show more explicit error messages // when IME developers are doing something unsupported. mImm.unregisterInputMethodPrivOps(mToken); InputMethodPrivilegedOperationsRegistry.remove(mToken); } } Loading
core/java/android/view/inputmethod/InputMethodManager.java +15 −47 Original line number Diff line number Diff line Loading @@ -57,7 +57,6 @@ import android.view.ViewRootImpl; import android.view.WindowManager.LayoutParams.SoftInputModeFlags; import android.view.autofill.AutofillManager; import com.android.internal.inputmethod.InputMethodPrivilegedOperations; import com.android.internal.inputmethod.InputMethodPrivilegedOperationsRegistry; import com.android.internal.os.SomeArgs; import com.android.internal.view.IInputConnectionWrapper; Loading Loading @@ -387,9 +386,6 @@ public final class InputMethodManager { final Pool<PendingEvent> mPendingEventPool = new SimplePool<>(20); final SparseArray<PendingEvent> mPendingEvents = new SparseArray<>(20); private final InputMethodPrivilegedOperationsRegistry mPrivOpsRegistry = new InputMethodPrivilegedOperationsRegistry(); // ----------------------------------------------------------- static final int MSG_DUMP = 1; Loading Loading @@ -741,7 +737,7 @@ public final class InputMethodManager { */ @Deprecated public void showStatusIcon(IBinder imeToken, String packageName, @DrawableRes int iconId) { mPrivOpsRegistry.get(imeToken).updateStatusIcon(packageName, iconId); InputMethodPrivilegedOperationsRegistry.get(imeToken).updateStatusIcon(packageName, iconId); } /** Loading @@ -751,7 +747,7 @@ public final class InputMethodManager { */ @Deprecated public void hideStatusIcon(IBinder imeToken) { mPrivOpsRegistry.get(imeToken).updateStatusIcon(null, 0); InputMethodPrivilegedOperationsRegistry.get(imeToken).updateStatusIcon(null, 0); } /** @hide */ Loading Loading @@ -1792,7 +1788,7 @@ public final class InputMethodManager { public void setInputMethod(IBinder token, String id) { if (token == null) { // Note: null token is allowed for callers that have WRITE_SECURE_SETTINGS permission. // Thus we cannot always rely on mPrivOpsRegistry unfortunately. // Thus we cannot always rely on InputMethodPrivilegedOperationsRegistry unfortunately. // TODO(Bug 114488811): Consider deprecating null token rule. try { mService.setInputMethod(token, id); Loading @@ -1801,7 +1797,7 @@ public final class InputMethodManager { } return; } mPrivOpsRegistry.get(token).setInputMethod(id); InputMethodPrivilegedOperationsRegistry.get(token).setInputMethod(id); } /** Loading @@ -1821,7 +1817,7 @@ public final class InputMethodManager { public void setInputMethodAndSubtype(IBinder token, String id, InputMethodSubtype subtype) { if (token == null) { // Note: null token is allowed for callers that have WRITE_SECURE_SETTINGS permission. // Thus we cannot always rely on mPrivOpsRegistry unfortunately. // Thus we cannot always rely on InputMethodPrivilegedOperationsRegistry unfortunately. // TODO(Bug 114488811): Consider deprecating null token rule. try { mService.setInputMethodAndSubtype(token, id, subtype); Loading @@ -1830,7 +1826,7 @@ public final class InputMethodManager { } return; } mPrivOpsRegistry.get(token).setInputMethodAndSubtype(id, subtype); InputMethodPrivilegedOperationsRegistry.get(token).setInputMethodAndSubtype(id, subtype); } /** Loading @@ -1850,7 +1846,7 @@ public final class InputMethodManager { */ @Deprecated public void hideSoftInputFromInputMethod(IBinder token, int flags) { mPrivOpsRegistry.get(token).hideMySoftInput(flags); InputMethodPrivilegedOperationsRegistry.get(token).hideMySoftInput(flags); } /** Loading @@ -1871,7 +1867,7 @@ public final class InputMethodManager { */ @Deprecated public void showSoftInputFromInputMethod(IBinder token, int flags) { mPrivOpsRegistry.get(token).showMySoftInput(flags); InputMethodPrivilegedOperationsRegistry.get(token).showMySoftInput(flags); } /** Loading Loading @@ -2231,7 +2227,7 @@ public final class InputMethodManager { public boolean switchToLastInputMethod(IBinder imeToken) { if (imeToken == null) { // Note: null token is allowed for callers that have WRITE_SECURE_SETTINGS permission. // Thus we cannot always rely on mPrivOpsRegistry unfortunately. // Thus we cannot always rely on InputMethodPrivilegedOperationsRegistry unfortunately. // TODO(Bug 114488811): Consider deprecating null token rule. try { return mService.switchToPreviousInputMethod(imeToken); Loading @@ -2239,7 +2235,7 @@ public final class InputMethodManager { throw e.rethrowFromSystemServer(); } } return mPrivOpsRegistry.get(imeToken).switchToPreviousInputMethod(); return InputMethodPrivilegedOperationsRegistry.get(imeToken).switchToPreviousInputMethod(); } /** Loading @@ -2259,7 +2255,7 @@ public final class InputMethodManager { public boolean switchToNextInputMethod(IBinder imeToken, boolean onlyCurrentIme) { if (imeToken == null) { // Note: null token is allowed for callers that have WRITE_SECURE_SETTINGS permission. // Thus we cannot always rely on mPrivOpsRegistry unfortunately. // Thus we cannot always rely on InputMethodPrivilegedOperationsRegistry unfortunately. // TODO(Bug 114488811): Consider deprecating null token rule. try { return mService.switchToNextInputMethod(imeToken, onlyCurrentIme); Loading @@ -2267,7 +2263,8 @@ public final class InputMethodManager { throw e.rethrowFromSystemServer(); } } return mPrivOpsRegistry.get(imeToken).switchToNextInputMethod(onlyCurrentIme); return InputMethodPrivilegedOperationsRegistry.get(imeToken) .switchToNextInputMethod(onlyCurrentIme); } /** Loading @@ -2286,7 +2283,8 @@ public final class InputMethodManager { */ @Deprecated public boolean shouldOfferSwitchingToNextInputMethod(IBinder imeToken) { return mPrivOpsRegistry.get(imeToken).shouldOfferSwitchingToNextInputMethod(); return InputMethodPrivilegedOperationsRegistry.get(imeToken) .shouldOfferSwitchingToNextInputMethod(); } /** Loading Loading @@ -2422,34 +2420,4 @@ public final class InputMethodManager { sb.append(",temporaryDetach=" + view.isTemporarilyDetached()); return sb.toString(); } /** * Called by {@link InputMethodService} so that API calls to deprecated ones defined in this * class can be forwarded to {@link InputMethodPrivilegedOperations}. * * <p>Note: this method does not hold strong references to {@code token} and {@code ops}. The * registry entry will be automatically cleared after {@code token} is garbage collected.</p> * * @param token IME token that is associated with {@code ops} * @param ops {@link InputMethodPrivilegedOperations} that is associated with {@code token} * @hide */ public void registerInputMethodPrivOps(IBinder token, InputMethodPrivilegedOperations ops) { mPrivOpsRegistry.put(token, ops); } /** * Called from {@link InputMethodService#onDestroy()} to make sure that deprecated IME APIs * defined in this class can no longer access to {@link InputMethodPrivilegedOperations}. * * <p>Note: Calling this method is optional, but at least gives more explict error message in * logcat when IME developers are doing something unsupported (e.g. trying to call IME APIs * after {@link InputMethodService#onDestroy()}).</p> * * @param token IME token to be removed. * @hide */ public void unregisterInputMethodPrivOps(IBinder token) { mPrivOpsRegistry.remove(token); } }
core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperationsRegistry.java +32 −13 Original line number Diff line number Diff line Loading @@ -29,12 +29,19 @@ 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 final Object mLock = new Object(); @GuardedBy("mLock") private final WeakHashMap<IBinder, WeakReference<InputMethodPrivilegedOperations>> mRegistry = new WeakHashMap<>(); 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; Loading Loading @@ -62,10 +69,13 @@ public final class InputMethodPrivilegedOperationsRegistry { * @param ops {@link InputMethodPrivilegedOperations} to be associated with the given IME token */ @AnyThread public void put(IBinder token, InputMethodPrivilegedOperations ops) { synchronized (mLock) { public static void put(IBinder token, InputMethodPrivilegedOperations ops) { synchronized (sLock) { if (sRegistry == null) { sRegistry = new WeakHashMap<>(); } final WeakReference<InputMethodPrivilegedOperations> previousOps = mRegistry.put(token, new WeakReference<>(ops)); sRegistry.put(token, new WeakReference<>(ops)); if (previousOps != null) { throw new IllegalStateException(previousOps.get() + " is already registered for " + " this token=" + token + " newOps=" + ops); Loading @@ -84,9 +94,12 @@ public final class InputMethodPrivilegedOperationsRegistry { */ @NonNull @AnyThread public InputMethodPrivilegedOperations get(IBinder token) { synchronized (mLock) { final WeakReference<InputMethodPrivilegedOperations> wrapperRef = mRegistry.get(token); 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(); } Loading @@ -108,9 +121,15 @@ public final class InputMethodPrivilegedOperationsRegistry { * @param token IME token to be removed. */ @AnyThread public void remove(IBinder token) { synchronized (mLock) { mRegistry.remove(token); public static void remove(IBinder token) { synchronized (sLock) { if (sRegistry == null) { return; } sRegistry.remove(token); if (sRegistry.isEmpty()) { sRegistry = null; } } } }