• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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 android.util.imetracing;
18 
19 import android.annotation.Nullable;
20 import android.app.ActivityThread;
21 import android.content.Context;
22 import android.inputmethodservice.AbstractInputMethodService;
23 import android.os.RemoteException;
24 import android.os.ServiceManager;
25 import android.os.ServiceManager.ServiceNotFoundException;
26 import android.util.Log;
27 import android.util.proto.ProtoOutputStream;
28 import android.view.inputmethod.InputMethodManager;
29 
30 import com.android.internal.view.IInputMethodManager;
31 
32 import java.io.PrintWriter;
33 
34 /**
35  *
36  * An abstract class that declares the methods for ime trace related operations - enable trace,
37  * schedule trace and add new trace to buffer. Both the client and server side classes can use
38  * it by getting an implementation through {@link ImeTracing#getInstance()}.
39  *
40  * @hide
41  */
42 public abstract class ImeTracing {
43 
44     static final String TAG = "imeTracing";
45     public static final String PROTO_ARG = "--proto-com-android-imetracing";
46 
47     /* Constants describing the component type that triggered a dump. */
48     public static final int IME_TRACING_FROM_CLIENT = 0;
49     public static final int IME_TRACING_FROM_IMS = 1;
50     public static final int IME_TRACING_FROM_IMMS = 2;
51 
52     private static ImeTracing sInstance;
53     static boolean sEnabled = false;
54     IInputMethodManager mService;
55 
56     protected boolean mDumpInProgress;
57     protected final Object mDumpInProgressLock = new Object();
58 
ImeTracing()59     ImeTracing() throws ServiceNotFoundException {
60         mService = IInputMethodManager.Stub.asInterface(
61                 ServiceManager.getServiceOrThrow(Context.INPUT_METHOD_SERVICE));
62     }
63 
64     /**
65      * Returns an instance of {@link ImeTracingServerImpl} when called from a server side class
66      * and an instance of {@link ImeTracingClientImpl} when called from a client side class.
67      * Useful to schedule a dump for next frame or save a dump when certain methods are called.
68      *
69      * @return Instance of one of the children classes of {@link ImeTracing}
70      */
getInstance()71     public static ImeTracing getInstance() {
72         if (sInstance == null) {
73             try {
74                 sInstance = isSystemProcess()
75                         ? new ImeTracingServerImpl() : new ImeTracingClientImpl();
76             } catch (RemoteException | ServiceNotFoundException e) {
77                 Log.e(TAG, "Exception while creating ImeTracing instance", e);
78             }
79         }
80         return sInstance;
81     }
82 
83     /**
84      * Transmits the information from client or InputMethodService side to the server, in order to
85      * be stored persistently to the current IME tracing dump.
86      *
87      * @param protoDump client or service side information to be stored by the server
88      * @param source where the information is coming from, refer to {@see #IME_TRACING_FROM_CLIENT}
89      * and {@see #IME_TRACING_FROM_IMS}
90      * @param where
91      */
sendToService(byte[] protoDump, int source, String where)92     public void sendToService(byte[] protoDump, int source, String where) throws RemoteException {
93         mService.startProtoDump(protoDump, source, where);
94     }
95 
96     /**
97      * @param proto dump to be added to the buffer
98      */
addToBuffer(ProtoOutputStream proto, int source)99     public abstract void addToBuffer(ProtoOutputStream proto, int source);
100 
101     /**
102      * Starts a proto dump of the client side information.
103      *
104      * @param where Place where the trace was triggered.
105      * @param immInstance The {@link InputMethodManager} instance to dump.
106      * @param icProto {@link android.view.inputmethod.InputConnection} call data in proto format.
107      */
triggerClientDump(String where, InputMethodManager immInstance, ProtoOutputStream icProto)108     public abstract void triggerClientDump(String where, InputMethodManager immInstance,
109             ProtoOutputStream icProto);
110 
111     /**
112      * Starts a proto dump of the currently connected InputMethodService information.
113      *
114      * @param where Place where the trace was triggered.
115      * @param service The {@link android.inputmethodservice.InputMethodService} to be dumped.
116      * @param icProto {@link android.view.inputmethod.InputConnection} call data in proto format.
117      */
triggerServiceDump(String where, AbstractInputMethodService service, ProtoOutputStream icProto)118     public abstract void triggerServiceDump(String where, AbstractInputMethodService service,
119             ProtoOutputStream icProto);
120 
121     /**
122      * Starts a proto dump of the InputMethodManagerService information.
123      *
124      * @param where Place where the trace was triggered.
125      */
triggerManagerServiceDump(String where)126     public abstract void triggerManagerServiceDump(String where);
127 
128     /**
129      * Being called while taking a bugreport so that tracing files can be included in the bugreport
130      * when the IME tracing is running.  Does nothing otherwise.
131      *
132      * @param pw Print writer
133      */
saveForBugreport(@ullable PrintWriter pw)134     public void saveForBugreport(@Nullable PrintWriter pw) {
135         // does nothing by default.
136     }
137 
138     /**
139      * Sets whether ime tracing is enabled.
140      *
141      * @param enabled Tells whether ime tracing should be enabled or disabled.
142      */
setEnabled(boolean enabled)143     public void setEnabled(boolean enabled) {
144         sEnabled = enabled;
145     }
146 
147     /**
148      * @return {@code true} if dumping is enabled, {@code false} otherwise.
149      */
isEnabled()150     public boolean isEnabled() {
151         return sEnabled;
152     }
153 
154     /**
155      * @return {@code true} if tracing is available, {@code false} otherwise.
156      */
isAvailable()157     public boolean isAvailable() {
158         return mService != null;
159     }
160 
161     /**
162      * Starts a new IME trace if one is not already started.
163      *
164      * @param pw Print writer
165      */
startTrace(@ullable PrintWriter pw)166     public abstract void startTrace(@Nullable PrintWriter pw);
167 
168     /**
169      * Stops the IME trace if one was previously started and writes the current buffers to disk.
170      *
171      * @param pw Print writer
172      */
stopTrace(@ullable PrintWriter pw)173     public abstract void stopTrace(@Nullable PrintWriter pw);
174 
isSystemProcess()175     private static boolean isSystemProcess() {
176         return ActivityThread.isSystem();
177     }
178 
logAndPrintln(@ullable PrintWriter pw, String msg)179     protected void logAndPrintln(@Nullable PrintWriter pw, String msg) {
180         Log.i(TAG, msg);
181         if (pw != null) {
182             pw.println(msg);
183             pw.flush();
184         }
185     }
186 
187 }
188