Loading core/java/com/android/internal/inputmethod/IInputMethodManagerGlobal.java 0 → 100644 +158 −0 Original line number Diff line number Diff line /* * Copyright (C) 2022 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.annotation.RequiresNoPermission; import android.annotation.RequiresPermission; import android.content.Context; import android.os.RemoteException; import android.os.ServiceManager; import com.android.internal.view.IInputMethodManager; import java.util.function.Consumer; /** * A global wrapper to directly invoke {@link IInputMethodManager} IPCs. * * <p>All public static methods are guaranteed to be thread-safe.</p> * * <p>All public methods are guaranteed to do nothing when {@link IInputMethodManager} is * unavailable.</p> */ public final class IInputMethodManagerGlobal { @Nullable private static volatile IInputMethodManager sServiceCache = null; /** * @return {@code true} if {@link IInputMethodManager} is available. */ @AnyThread public static boolean isAvailable() { return getService() != null; } @AnyThread @Nullable private static IInputMethodManager getService() { IInputMethodManager service = sServiceCache; if (service == null) { service = IInputMethodManager.Stub.asInterface( ServiceManager.getService(Context.INPUT_METHOD_SERVICE)); if (service == null) { return null; } sServiceCache = service; } return service; } @AnyThread private static void handleRemoteExceptionOrRethrow(@NonNull RemoteException e, @Nullable Consumer<RemoteException> exceptionHandler) { if (exceptionHandler != null) { exceptionHandler.accept(e); } else { throw e.rethrowFromSystemServer(); } } /** * Invokes {@link IInputMethodManager#startProtoDump(byte[], int, String)}. * * @param protoDump client or service side information to be stored by the server * @param source where the information is coming from, refer to * {@link ImeTracing#IME_TRACING_FROM_CLIENT} and * {@link ImeTracing#IME_TRACING_FROM_IMS} * @param where where the information is coming from. * @param exceptionHandler an optional {@link RemoteException} handler. */ @RequiresNoPermission @AnyThread public static void startProtoDump(byte[] protoDump, int source, String where, @Nullable Consumer<RemoteException> exceptionHandler) { final IInputMethodManager service = getService(); if (service == null) { return; } try { service.startProtoDump(protoDump, source, where); } catch (RemoteException e) { handleRemoteExceptionOrRethrow(e, exceptionHandler); } } /** * Invokes {@link IInputMethodManager#startImeTrace()}. * * @param exceptionHandler an optional {@link RemoteException} handler. */ @RequiresPermission(android.Manifest.permission.CONTROL_UI_TRACING) @AnyThread public static void startImeTrace(@Nullable Consumer<RemoteException> exceptionHandler) { final IInputMethodManager service = getService(); if (service == null) { return; } try { service.startImeTrace(); } catch (RemoteException e) { handleRemoteExceptionOrRethrow(e, exceptionHandler); } } /** * Invokes {@link IInputMethodManager#stopImeTrace()}. * * @param exceptionHandler an optional {@link RemoteException} handler. */ @RequiresPermission(android.Manifest.permission.CONTROL_UI_TRACING) @AnyThread public static void stopImeTrace(@Nullable Consumer<RemoteException> exceptionHandler) { final IInputMethodManager service = getService(); if (service == null) { return; } try { service.stopImeTrace(); } catch (RemoteException e) { handleRemoteExceptionOrRethrow(e, exceptionHandler); } } /** * Invokes {@link IInputMethodManager#isImeTraceEnabled()}. * * @return The return value of {@link IInputMethodManager#isImeTraceEnabled()}. */ @RequiresNoPermission @AnyThread public static boolean isImeTraceEnabled() { final IInputMethodManager service = getService(); if (service == null) { return false; } try { return service.isImeTraceEnabled(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } } core/java/com/android/internal/inputmethod/ImeTracing.java +18 −32 Original line number Diff line number Diff line Loading @@ -19,16 +19,10 @@ package com.android.internal.inputmethod; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.app.ActivityThread; import android.content.Context; import android.os.RemoteException; import android.os.ServiceManager; import android.os.ServiceManager.ServiceNotFoundException; import android.util.Log; import android.util.proto.ProtoOutputStream; import android.view.inputmethod.InputMethodManager; import com.android.internal.view.IInputMethodManager; import java.io.PrintWriter; /** Loading @@ -49,16 +43,12 @@ public abstract class ImeTracing { private static ImeTracing sInstance; static boolean sEnabled = false; IInputMethodManager mService; private final boolean mIsAvailable = IInputMethodManagerGlobal.isAvailable(); protected boolean mDumpInProgress; protected final Object mDumpInProgressLock = new Object(); ImeTracing() throws ServiceNotFoundException { mService = IInputMethodManager.Stub.asInterface( ServiceManager.getServiceOrThrow(Context.INPUT_METHOD_SERVICE)); } /** * Returns an instance of {@link ImeTracingServerImpl} when called from a server side class * and an instance of {@link ImeTracingClientImpl} when called from a client side class. Loading @@ -68,11 +58,14 @@ public abstract class ImeTracing { */ public static ImeTracing getInstance() { if (sInstance == null) { if (isSystemProcess()) { sInstance = new ImeTracingServerImpl(); } else { try { sInstance = isSystemProcess() ? new ImeTracingServerImpl() : new ImeTracingClientImpl(); } catch (RemoteException | ServiceNotFoundException e) { Log.e(TAG, "Exception while creating ImeTracing instance", e); sInstance = new ImeTracingClientImpl(); } catch (RuntimeException e) { Log.e(TAG, "Exception while creating ImeTracingClientImpl instance", e); } } } return sInstance; Loading @@ -87,32 +80,25 @@ public abstract class ImeTracing { * and {@see #IME_TRACING_FROM_IMS} * @param where */ public void sendToService(byte[] protoDump, int source, String where) throws RemoteException { mService.startProtoDump(protoDump, source, where); public void sendToService(byte[] protoDump, int source, String where) { IInputMethodManagerGlobal.startProtoDump(protoDump, source, where, e -> Log.e(TAG, "Exception while sending ime-related dump to server", e)); } /** * Calling {@link IInputMethodManager#startImeTrace()}} to capture IME trace. * Start IME trace. */ @RequiresPermission(android.Manifest.permission.CONTROL_UI_TRACING) public final void startImeTrace() { try { mService.startImeTrace(); } catch (RemoteException e) { Log.e(TAG, "Could not start ime trace." + e); } IInputMethodManagerGlobal.startImeTrace(e -> Log.e(TAG, "Could not start ime trace.", e)); } /** * Calling {@link IInputMethodManager#stopImeTrace()} to stop IME trace. * Stop IME trace. */ @RequiresPermission(android.Manifest.permission.CONTROL_UI_TRACING) public final void stopImeTrace() { try { mService.stopImeTrace(); } catch (RemoteException e) { Log.e(TAG, "Could not stop ime trace." + e); } IInputMethodManagerGlobal.stopImeTrace(e -> Log.e(TAG, "Could not stop ime trace.", e)); } /** Loading Loading @@ -193,7 +179,7 @@ public abstract class ImeTracing { * @return {@code true} if tracing is available, {@code false} otherwise. */ public boolean isAvailable() { return mService != null; return mIsAvailable; } /** Loading core/java/com/android/internal/inputmethod/ImeTracingClientImpl.java +2 −9 Original line number Diff line number Diff line Loading @@ -18,9 +18,6 @@ package com.android.internal.inputmethod; import android.annotation.NonNull; import android.annotation.Nullable; import android.os.RemoteException; import android.os.ServiceManager.ServiceNotFoundException; import android.util.Log; import android.util.proto.ProtoOutputStream; import android.view.inputmethod.InputMethodManager; Loading @@ -30,8 +27,8 @@ import java.io.PrintWriter; * An implementation of {@link ImeTracing} for non system_server processes. */ class ImeTracingClientImpl extends ImeTracing { ImeTracingClientImpl() throws ServiceNotFoundException, RemoteException { sEnabled = mService.isImeTraceEnabled(); ImeTracingClientImpl() { sEnabled = IInputMethodManagerGlobal.isImeTraceEnabled(); } @Override Loading @@ -56,8 +53,6 @@ class ImeTracingClientImpl extends ImeTracing { ProtoOutputStream proto = new ProtoOutputStream(); immInstance.dumpDebug(proto, icProto); sendToService(proto.getBytes(), IME_TRACING_FROM_CLIENT, where); } catch (RemoteException e) { Log.e(TAG, "Exception while sending ime-related client dump to server", e); } finally { mDumpInProgress = false; } Loading @@ -81,8 +76,6 @@ class ImeTracingClientImpl extends ImeTracing { ProtoOutputStream proto = new ProtoOutputStream(); dumper.dumpToProto(proto, icProto); sendToService(proto.getBytes(), IME_TRACING_FROM_IMS, where); } catch (RemoteException e) { Log.e(TAG, "Exception while sending ime-related service dump to server", e); } finally { mDumpInProgress = false; } Loading core/java/com/android/internal/inputmethod/ImeTracingServerImpl.java +1 −5 Original line number Diff line number Diff line Loading @@ -19,8 +19,6 @@ package com.android.internal.inputmethod; import static android.os.Build.IS_USER; import android.annotation.Nullable; import android.os.RemoteException; import android.os.ServiceManager.ServiceNotFoundException; import android.os.SystemClock; import android.util.Log; import android.util.proto.ProtoOutputStream; Loading Loading @@ -71,7 +69,7 @@ class ImeTracingServerImpl extends ImeTracing { private final Object mEnabledLock = new Object(); ImeTracingServerImpl() throws ServiceNotFoundException { ImeTracingServerImpl() { mBufferClients = new TraceBuffer<>(BUFFER_CAPACITY); mTraceFileClients = new File(TRACE_DIRNAME + TRACE_FILENAME_CLIENTS); mBufferIms = new TraceBuffer<>(BUFFER_CAPACITY); Loading Loading @@ -132,8 +130,6 @@ class ImeTracingServerImpl extends ImeTracing { try { sendToService(null, IME_TRACING_FROM_IMMS, where); } catch (RemoteException e) { Log.e(TAG, "Exception while sending ime-related manager service dump to server", e); } finally { mDumpInProgress = false; } Loading core/java/com/android/internal/view/IInputMethodManager.aidl +1 −0 Original line number Diff line number Diff line Loading @@ -123,6 +123,7 @@ interface IInputMethodManager { @JavaPassthrough(annotation="@android.annotation.RequiresNoPermission") void startProtoDump(in byte[] protoDump, int source, String where); @JavaPassthrough(annotation="@android.annotation.RequiresNoPermission") boolean isImeTraceEnabled(); // Starts an ime trace. Loading Loading
core/java/com/android/internal/inputmethod/IInputMethodManagerGlobal.java 0 → 100644 +158 −0 Original line number Diff line number Diff line /* * Copyright (C) 2022 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.annotation.RequiresNoPermission; import android.annotation.RequiresPermission; import android.content.Context; import android.os.RemoteException; import android.os.ServiceManager; import com.android.internal.view.IInputMethodManager; import java.util.function.Consumer; /** * A global wrapper to directly invoke {@link IInputMethodManager} IPCs. * * <p>All public static methods are guaranteed to be thread-safe.</p> * * <p>All public methods are guaranteed to do nothing when {@link IInputMethodManager} is * unavailable.</p> */ public final class IInputMethodManagerGlobal { @Nullable private static volatile IInputMethodManager sServiceCache = null; /** * @return {@code true} if {@link IInputMethodManager} is available. */ @AnyThread public static boolean isAvailable() { return getService() != null; } @AnyThread @Nullable private static IInputMethodManager getService() { IInputMethodManager service = sServiceCache; if (service == null) { service = IInputMethodManager.Stub.asInterface( ServiceManager.getService(Context.INPUT_METHOD_SERVICE)); if (service == null) { return null; } sServiceCache = service; } return service; } @AnyThread private static void handleRemoteExceptionOrRethrow(@NonNull RemoteException e, @Nullable Consumer<RemoteException> exceptionHandler) { if (exceptionHandler != null) { exceptionHandler.accept(e); } else { throw e.rethrowFromSystemServer(); } } /** * Invokes {@link IInputMethodManager#startProtoDump(byte[], int, String)}. * * @param protoDump client or service side information to be stored by the server * @param source where the information is coming from, refer to * {@link ImeTracing#IME_TRACING_FROM_CLIENT} and * {@link ImeTracing#IME_TRACING_FROM_IMS} * @param where where the information is coming from. * @param exceptionHandler an optional {@link RemoteException} handler. */ @RequiresNoPermission @AnyThread public static void startProtoDump(byte[] protoDump, int source, String where, @Nullable Consumer<RemoteException> exceptionHandler) { final IInputMethodManager service = getService(); if (service == null) { return; } try { service.startProtoDump(protoDump, source, where); } catch (RemoteException e) { handleRemoteExceptionOrRethrow(e, exceptionHandler); } } /** * Invokes {@link IInputMethodManager#startImeTrace()}. * * @param exceptionHandler an optional {@link RemoteException} handler. */ @RequiresPermission(android.Manifest.permission.CONTROL_UI_TRACING) @AnyThread public static void startImeTrace(@Nullable Consumer<RemoteException> exceptionHandler) { final IInputMethodManager service = getService(); if (service == null) { return; } try { service.startImeTrace(); } catch (RemoteException e) { handleRemoteExceptionOrRethrow(e, exceptionHandler); } } /** * Invokes {@link IInputMethodManager#stopImeTrace()}. * * @param exceptionHandler an optional {@link RemoteException} handler. */ @RequiresPermission(android.Manifest.permission.CONTROL_UI_TRACING) @AnyThread public static void stopImeTrace(@Nullable Consumer<RemoteException> exceptionHandler) { final IInputMethodManager service = getService(); if (service == null) { return; } try { service.stopImeTrace(); } catch (RemoteException e) { handleRemoteExceptionOrRethrow(e, exceptionHandler); } } /** * Invokes {@link IInputMethodManager#isImeTraceEnabled()}. * * @return The return value of {@link IInputMethodManager#isImeTraceEnabled()}. */ @RequiresNoPermission @AnyThread public static boolean isImeTraceEnabled() { final IInputMethodManager service = getService(); if (service == null) { return false; } try { return service.isImeTraceEnabled(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } }
core/java/com/android/internal/inputmethod/ImeTracing.java +18 −32 Original line number Diff line number Diff line Loading @@ -19,16 +19,10 @@ package com.android.internal.inputmethod; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.app.ActivityThread; import android.content.Context; import android.os.RemoteException; import android.os.ServiceManager; import android.os.ServiceManager.ServiceNotFoundException; import android.util.Log; import android.util.proto.ProtoOutputStream; import android.view.inputmethod.InputMethodManager; import com.android.internal.view.IInputMethodManager; import java.io.PrintWriter; /** Loading @@ -49,16 +43,12 @@ public abstract class ImeTracing { private static ImeTracing sInstance; static boolean sEnabled = false; IInputMethodManager mService; private final boolean mIsAvailable = IInputMethodManagerGlobal.isAvailable(); protected boolean mDumpInProgress; protected final Object mDumpInProgressLock = new Object(); ImeTracing() throws ServiceNotFoundException { mService = IInputMethodManager.Stub.asInterface( ServiceManager.getServiceOrThrow(Context.INPUT_METHOD_SERVICE)); } /** * Returns an instance of {@link ImeTracingServerImpl} when called from a server side class * and an instance of {@link ImeTracingClientImpl} when called from a client side class. Loading @@ -68,11 +58,14 @@ public abstract class ImeTracing { */ public static ImeTracing getInstance() { if (sInstance == null) { if (isSystemProcess()) { sInstance = new ImeTracingServerImpl(); } else { try { sInstance = isSystemProcess() ? new ImeTracingServerImpl() : new ImeTracingClientImpl(); } catch (RemoteException | ServiceNotFoundException e) { Log.e(TAG, "Exception while creating ImeTracing instance", e); sInstance = new ImeTracingClientImpl(); } catch (RuntimeException e) { Log.e(TAG, "Exception while creating ImeTracingClientImpl instance", e); } } } return sInstance; Loading @@ -87,32 +80,25 @@ public abstract class ImeTracing { * and {@see #IME_TRACING_FROM_IMS} * @param where */ public void sendToService(byte[] protoDump, int source, String where) throws RemoteException { mService.startProtoDump(protoDump, source, where); public void sendToService(byte[] protoDump, int source, String where) { IInputMethodManagerGlobal.startProtoDump(protoDump, source, where, e -> Log.e(TAG, "Exception while sending ime-related dump to server", e)); } /** * Calling {@link IInputMethodManager#startImeTrace()}} to capture IME trace. * Start IME trace. */ @RequiresPermission(android.Manifest.permission.CONTROL_UI_TRACING) public final void startImeTrace() { try { mService.startImeTrace(); } catch (RemoteException e) { Log.e(TAG, "Could not start ime trace." + e); } IInputMethodManagerGlobal.startImeTrace(e -> Log.e(TAG, "Could not start ime trace.", e)); } /** * Calling {@link IInputMethodManager#stopImeTrace()} to stop IME trace. * Stop IME trace. */ @RequiresPermission(android.Manifest.permission.CONTROL_UI_TRACING) public final void stopImeTrace() { try { mService.stopImeTrace(); } catch (RemoteException e) { Log.e(TAG, "Could not stop ime trace." + e); } IInputMethodManagerGlobal.stopImeTrace(e -> Log.e(TAG, "Could not stop ime trace.", e)); } /** Loading Loading @@ -193,7 +179,7 @@ public abstract class ImeTracing { * @return {@code true} if tracing is available, {@code false} otherwise. */ public boolean isAvailable() { return mService != null; return mIsAvailable; } /** Loading
core/java/com/android/internal/inputmethod/ImeTracingClientImpl.java +2 −9 Original line number Diff line number Diff line Loading @@ -18,9 +18,6 @@ package com.android.internal.inputmethod; import android.annotation.NonNull; import android.annotation.Nullable; import android.os.RemoteException; import android.os.ServiceManager.ServiceNotFoundException; import android.util.Log; import android.util.proto.ProtoOutputStream; import android.view.inputmethod.InputMethodManager; Loading @@ -30,8 +27,8 @@ import java.io.PrintWriter; * An implementation of {@link ImeTracing} for non system_server processes. */ class ImeTracingClientImpl extends ImeTracing { ImeTracingClientImpl() throws ServiceNotFoundException, RemoteException { sEnabled = mService.isImeTraceEnabled(); ImeTracingClientImpl() { sEnabled = IInputMethodManagerGlobal.isImeTraceEnabled(); } @Override Loading @@ -56,8 +53,6 @@ class ImeTracingClientImpl extends ImeTracing { ProtoOutputStream proto = new ProtoOutputStream(); immInstance.dumpDebug(proto, icProto); sendToService(proto.getBytes(), IME_TRACING_FROM_CLIENT, where); } catch (RemoteException e) { Log.e(TAG, "Exception while sending ime-related client dump to server", e); } finally { mDumpInProgress = false; } Loading @@ -81,8 +76,6 @@ class ImeTracingClientImpl extends ImeTracing { ProtoOutputStream proto = new ProtoOutputStream(); dumper.dumpToProto(proto, icProto); sendToService(proto.getBytes(), IME_TRACING_FROM_IMS, where); } catch (RemoteException e) { Log.e(TAG, "Exception while sending ime-related service dump to server", e); } finally { mDumpInProgress = false; } Loading
core/java/com/android/internal/inputmethod/ImeTracingServerImpl.java +1 −5 Original line number Diff line number Diff line Loading @@ -19,8 +19,6 @@ package com.android.internal.inputmethod; import static android.os.Build.IS_USER; import android.annotation.Nullable; import android.os.RemoteException; import android.os.ServiceManager.ServiceNotFoundException; import android.os.SystemClock; import android.util.Log; import android.util.proto.ProtoOutputStream; Loading Loading @@ -71,7 +69,7 @@ class ImeTracingServerImpl extends ImeTracing { private final Object mEnabledLock = new Object(); ImeTracingServerImpl() throws ServiceNotFoundException { ImeTracingServerImpl() { mBufferClients = new TraceBuffer<>(BUFFER_CAPACITY); mTraceFileClients = new File(TRACE_DIRNAME + TRACE_FILENAME_CLIENTS); mBufferIms = new TraceBuffer<>(BUFFER_CAPACITY); Loading Loading @@ -132,8 +130,6 @@ class ImeTracingServerImpl extends ImeTracing { try { sendToService(null, IME_TRACING_FROM_IMMS, where); } catch (RemoteException e) { Log.e(TAG, "Exception while sending ime-related manager service dump to server", e); } finally { mDumpInProgress = false; } Loading
core/java/com/android/internal/view/IInputMethodManager.aidl +1 −0 Original line number Diff line number Diff line Loading @@ -123,6 +123,7 @@ interface IInputMethodManager { @JavaPassthrough(annotation="@android.annotation.RequiresNoPermission") void startProtoDump(in byte[] protoDump, int source, String where); @JavaPassthrough(annotation="@android.annotation.RequiresNoPermission") boolean isImeTraceEnabled(); // Starts an ime trace. Loading