Merge "Add trace for AccessibilityInteractionClient callback interfaces." into sc-dev am: 06a5b97f6a

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/13809914

Change-Id: Ia7142414a73f4eb35160b3e849f13c2241521da0
This commit is contained in:
Hongming Jin
2021-04-03 00:16:14 +00:00
committed by Automerger Merge Worker
12 changed files with 333 additions and 71 deletions

View File

@@ -886,7 +886,7 @@ public abstract class AccessibilityService extends Service {
* them, otherwise an empty list.
*/
public List<AccessibilityWindowInfo> getWindows() {
return AccessibilityInteractionClient.getInstance().getWindows(mConnectionId);
return AccessibilityInteractionClient.getInstance(this).getWindows(mConnectionId);
}
/**
@@ -914,7 +914,8 @@ public abstract class AccessibilityService extends Service {
*/
@NonNull
public final SparseArray<List<AccessibilityWindowInfo>> getWindowsOnAllDisplays() {
return AccessibilityInteractionClient.getInstance().getWindowsOnAllDisplays(mConnectionId);
return AccessibilityInteractionClient.getInstance(this).getWindowsOnAllDisplays(
mConnectionId);
}
/**
@@ -940,7 +941,8 @@ public abstract class AccessibilityService extends Service {
* @return The root node if this service can retrieve window content.
*/
public AccessibilityNodeInfo getRootInActiveWindow() {
return AccessibilityInteractionClient.getInstance().getRootInActiveWindow(mConnectionId);
return AccessibilityInteractionClient.getInstance(this).getRootInActiveWindow(
mConnectionId);
}
/**
@@ -949,7 +951,7 @@ public abstract class AccessibilityService extends Service {
*/
public final void disableSelf() {
final IAccessibilityServiceConnection connection =
AccessibilityInteractionClient.getInstance().getConnection(mConnectionId);
AccessibilityInteractionClient.getInstance(this).getConnection(mConnectionId);
if (connection != null) {
try {
connection.disableSelf();
@@ -970,7 +972,7 @@ public abstract class AccessibilityService extends Service {
private void setDefaultTokenInternal(Context context, int displayId) {
final WindowManagerImpl wm = (WindowManagerImpl) context.getSystemService(WINDOW_SERVICE);
final IAccessibilityServiceConnection connection =
AccessibilityInteractionClient.getInstance().getConnection(mConnectionId);
AccessibilityInteractionClient.getInstance(this).getConnection(mConnectionId);
IBinder token = null;
if (connection != null) {
synchronized (mLock) {
@@ -1042,7 +1044,7 @@ public abstract class AccessibilityService extends Service {
public final @NonNull FingerprintGestureController getFingerprintGestureController() {
if (mFingerprintGestureController == null) {
mFingerprintGestureController = new FingerprintGestureController(
AccessibilityInteractionClient.getInstance().getConnection(mConnectionId));
AccessibilityInteractionClient.getInstance(this).getConnection(mConnectionId));
}
return mFingerprintGestureController;
}
@@ -1074,8 +1076,7 @@ public abstract class AccessibilityService extends Service {
@Nullable GestureResultCallback callback,
@Nullable Handler handler) {
final IAccessibilityServiceConnection connection =
AccessibilityInteractionClient.getInstance().getConnection(
mConnectionId);
AccessibilityInteractionClient.getInstance(this).getConnection(mConnectionId);
if (connection == null) {
return false;
}
@@ -1287,7 +1288,7 @@ public abstract class AccessibilityService extends Service {
private void setMagnificationCallbackEnabled(boolean enabled) {
final IAccessibilityServiceConnection connection =
AccessibilityInteractionClient.getInstance().getConnection(
AccessibilityInteractionClient.getInstance(mService).getConnection(
mService.mConnectionId);
if (connection != null) {
try {
@@ -1348,7 +1349,7 @@ public abstract class AccessibilityService extends Service {
*/
public float getScale() {
final IAccessibilityServiceConnection connection =
AccessibilityInteractionClient.getInstance().getConnection(
AccessibilityInteractionClient.getInstance(mService).getConnection(
mService.mConnectionId);
if (connection != null) {
try {
@@ -1377,7 +1378,7 @@ public abstract class AccessibilityService extends Service {
*/
public float getCenterX() {
final IAccessibilityServiceConnection connection =
AccessibilityInteractionClient.getInstance().getConnection(
AccessibilityInteractionClient.getInstance(mService).getConnection(
mService.mConnectionId);
if (connection != null) {
try {
@@ -1406,7 +1407,7 @@ public abstract class AccessibilityService extends Service {
*/
public float getCenterY() {
final IAccessibilityServiceConnection connection =
AccessibilityInteractionClient.getInstance().getConnection(
AccessibilityInteractionClient.getInstance(mService).getConnection(
mService.mConnectionId);
if (connection != null) {
try {
@@ -1440,7 +1441,7 @@ public abstract class AccessibilityService extends Service {
@NonNull
public Region getMagnificationRegion() {
final IAccessibilityServiceConnection connection =
AccessibilityInteractionClient.getInstance().getConnection(
AccessibilityInteractionClient.getInstance(mService).getConnection(
mService.mConnectionId);
if (connection != null) {
try {
@@ -1469,7 +1470,7 @@ public abstract class AccessibilityService extends Service {
*/
public boolean reset(boolean animate) {
final IAccessibilityServiceConnection connection =
AccessibilityInteractionClient.getInstance().getConnection(
AccessibilityInteractionClient.getInstance(mService).getConnection(
mService.mConnectionId);
if (connection != null) {
try {
@@ -1497,7 +1498,7 @@ public abstract class AccessibilityService extends Service {
*/
public boolean setScale(float scale, boolean animate) {
final IAccessibilityServiceConnection connection =
AccessibilityInteractionClient.getInstance().getConnection(
AccessibilityInteractionClient.getInstance(mService).getConnection(
mService.mConnectionId);
if (connection != null) {
try {
@@ -1529,7 +1530,7 @@ public abstract class AccessibilityService extends Service {
*/
public boolean setCenter(float centerX, float centerY, boolean animate) {
final IAccessibilityServiceConnection connection =
AccessibilityInteractionClient.getInstance().getConnection(
AccessibilityInteractionClient.getInstance(mService).getConnection(
mService.mConnectionId);
if (connection != null) {
try {
@@ -1701,7 +1702,7 @@ public abstract class AccessibilityService extends Service {
private void setSoftKeyboardCallbackEnabled(boolean enabled) {
final IAccessibilityServiceConnection connection =
AccessibilityInteractionClient.getInstance().getConnection(
AccessibilityInteractionClient.getInstance(mService).getConnection(
mService.mConnectionId);
if (connection != null) {
try {
@@ -1760,7 +1761,7 @@ public abstract class AccessibilityService extends Service {
@SoftKeyboardShowMode
public int getShowMode() {
final IAccessibilityServiceConnection connection =
AccessibilityInteractionClient.getInstance().getConnection(
AccessibilityInteractionClient.getInstance(mService).getConnection(
mService.mConnectionId);
if (connection != null) {
try {
@@ -1789,7 +1790,7 @@ public abstract class AccessibilityService extends Service {
*/
public boolean setShowMode(@SoftKeyboardShowMode int showMode) {
final IAccessibilityServiceConnection connection =
AccessibilityInteractionClient.getInstance().getConnection(
AccessibilityInteractionClient.getInstance(mService).getConnection(
mService.mConnectionId);
if (connection != null) {
try {
@@ -1835,7 +1836,7 @@ public abstract class AccessibilityService extends Service {
*/
public boolean switchToInputMethod(@NonNull String imeId) {
final IAccessibilityServiceConnection connection =
AccessibilityInteractionClient.getInstance().getConnection(
AccessibilityInteractionClient.getInstance(mService).getConnection(
mService.mConnectionId);
if (connection != null) {
try {
@@ -1888,7 +1889,7 @@ public abstract class AccessibilityService extends Service {
displayId);
if (controller == null) {
controller = new AccessibilityButtonController(
AccessibilityInteractionClient.getInstance().getConnection(mConnectionId));
AccessibilityInteractionClient.getInstance(this).getConnection(mConnectionId));
mAccessibilityButtonControllers.put(displayId, controller);
}
return controller;
@@ -1922,7 +1923,7 @@ public abstract class AccessibilityService extends Service {
*/
public final @NonNull List<AccessibilityAction> getSystemActions() {
IAccessibilityServiceConnection connection =
AccessibilityInteractionClient.getInstance().getConnection(mConnectionId);
AccessibilityInteractionClient.getInstance(this).getConnection(mConnectionId);
if (connection != null) {
try {
return connection.getSystemActions();
@@ -1955,7 +1956,7 @@ public abstract class AccessibilityService extends Service {
*/
public final boolean performGlobalAction(int action) {
IAccessibilityServiceConnection connection =
AccessibilityInteractionClient.getInstance().getConnection(mConnectionId);
AccessibilityInteractionClient.getInstance(this).getConnection(mConnectionId);
if (connection != null) {
try {
return connection.performGlobalAction(action);
@@ -1996,7 +1997,7 @@ public abstract class AccessibilityService extends Service {
* @see AccessibilityNodeInfo#FOCUS_ACCESSIBILITY
*/
public AccessibilityNodeInfo findFocus(int focus) {
return AccessibilityInteractionClient.getInstance().findFocus(mConnectionId,
return AccessibilityInteractionClient.getInstance(this).findFocus(mConnectionId,
AccessibilityWindowInfo.ANY_WINDOW_ID, AccessibilityNodeInfo.ROOT_NODE_ID, focus);
}
@@ -2012,7 +2013,7 @@ public abstract class AccessibilityService extends Service {
*/
public final AccessibilityServiceInfo getServiceInfo() {
IAccessibilityServiceConnection connection =
AccessibilityInteractionClient.getInstance().getConnection(mConnectionId);
AccessibilityInteractionClient.getInstance(this).getConnection(mConnectionId);
if (connection != null) {
try {
return connection.getServiceInfo();
@@ -2044,12 +2045,12 @@ public abstract class AccessibilityService extends Service {
*/
private void sendServiceInfo() {
IAccessibilityServiceConnection connection =
AccessibilityInteractionClient.getInstance().getConnection(mConnectionId);
AccessibilityInteractionClient.getInstance(this).getConnection(mConnectionId);
if (mInfo != null && connection != null) {
try {
connection.setServiceInfo(mInfo);
mInfo = null;
AccessibilityInteractionClient.getInstance().clearCache();
AccessibilityInteractionClient.getInstance(this).clearCache();
} catch (RemoteException re) {
Log.w(LOG_TAG, "Error while setting AccessibilityServiceInfo", re);
re.rethrowFromSystemServer();
@@ -2096,8 +2097,7 @@ public abstract class AccessibilityService extends Service {
Preconditions.checkNotNull(executor, "executor cannot be null");
Preconditions.checkNotNull(callback, "callback cannot be null");
final IAccessibilityServiceConnection connection =
AccessibilityInteractionClient.getInstance().getConnection(
mConnectionId);
AccessibilityInteractionClient.getInstance(this).getConnection(mConnectionId);
if (connection == null) {
sendScreenshotFailure(ERROR_TAKE_SCREENSHOT_INTERNAL_ERROR, executor, callback);
return;
@@ -2136,7 +2136,7 @@ public abstract class AccessibilityService extends Service {
*/
public void setAccessibilityFocusAppearance(int strokeWidth, @ColorInt int color) {
IAccessibilityServiceConnection connection =
AccessibilityInteractionClient.getInstance().getConnection(mConnectionId);
AccessibilityInteractionClient.getInstance(this).getConnection(mConnectionId);
if (connection != null) {
try {
connection.setFocusAppearance(strokeWidth, color);
@@ -2261,12 +2261,14 @@ public abstract class AccessibilityService extends Service {
private final HandlerCaller mCaller;
private final Callbacks mCallback;
private final Context mContext;
private int mConnectionId = AccessibilityInteractionClient.NO_ID;
public IAccessibilityServiceClientWrapper(Context context, Looper looper,
Callbacks callback) {
mCallback = callback;
mContext = context;
mCaller = new HandlerCaller(context, looper, this, true /*asyncHandler*/);
}
@@ -2366,7 +2368,8 @@ public abstract class AccessibilityService extends Service {
boolean serviceWantsEvent = message.arg1 != 0;
if (event != null) {
// Send the event to AccessibilityCache via AccessibilityInteractionClient
AccessibilityInteractionClient.getInstance().onAccessibilityEvent(event);
AccessibilityInteractionClient.getInstance(mContext).onAccessibilityEvent(
event);
if (serviceWantsEvent
&& (mConnectionId != AccessibilityInteractionClient.NO_ID)) {
// Send the event to AccessibilityService
@@ -2395,15 +2398,15 @@ public abstract class AccessibilityService extends Service {
IBinder windowToken = (IBinder) args.arg2;
args.recycle();
if (connection != null) {
AccessibilityInteractionClient.getInstance().addConnection(mConnectionId,
connection);
AccessibilityInteractionClient.getInstance(mContext).addConnection(
mConnectionId, connection);
mCallback.init(mConnectionId, windowToken);
mCallback.onServiceConnected();
} else {
AccessibilityInteractionClient.getInstance().removeConnection(
AccessibilityInteractionClient.getInstance(mContext).removeConnection(
mConnectionId);
mConnectionId = AccessibilityInteractionClient.NO_ID;
AccessibilityInteractionClient.getInstance().clearCache();
AccessibilityInteractionClient.getInstance(mContext).clearCache();
mCallback.init(AccessibilityInteractionClient.NO_ID, null);
}
return;
@@ -2415,14 +2418,14 @@ public abstract class AccessibilityService extends Service {
return;
}
case DO_CLEAR_ACCESSIBILITY_CACHE: {
AccessibilityInteractionClient.getInstance().clearCache();
AccessibilityInteractionClient.getInstance(mContext).clearCache();
return;
}
case DO_ON_KEY_EVENT: {
KeyEvent event = (KeyEvent) message.obj;
try {
IAccessibilityServiceConnection connection = AccessibilityInteractionClient
.getInstance().getConnection(mConnectionId);
.getInstance(mContext).getConnection(mConnectionId);
if (connection != null) {
final boolean result = mCallback.onKeyEvent(event);
final int sequence = message.arg1;
@@ -2637,7 +2640,7 @@ public abstract class AccessibilityService extends Service {
public void setGestureDetectionPassthroughRegion(int displayId, @NonNull Region region) {
Preconditions.checkNotNull(region, "region cannot be null");
final IAccessibilityServiceConnection connection =
AccessibilityInteractionClient.getInstance().getConnection(mConnectionId);
AccessibilityInteractionClient.getInstance(this).getConnection(mConnectionId);
if (connection != null) {
try {
connection.setGestureDetectionPassthroughRegion(displayId, region);
@@ -2663,7 +2666,7 @@ public abstract class AccessibilityService extends Service {
public void setTouchExplorationPassthroughRegion(int displayId, @NonNull Region region) {
Preconditions.checkNotNull(region, "region cannot be null");
final IAccessibilityServiceConnection connection =
AccessibilityInteractionClient.getInstance().getConnection(mConnectionId);
AccessibilityInteractionClient.getInstance(this).getConnection(mConnectionId);
if (connection != null) {
try {
connection.setTouchExplorationPassthroughRegion(displayId, region);

View File

@@ -117,4 +117,7 @@ interface IAccessibilityServiceConnection {
void setTouchExplorationPassthroughRegion(int displayId, in Region region);
void setFocusAppearance(int strokeWidth, int color);
oneway void logTrace(long timestamp, String where, String callingParams, int processId,
long threadId, int callingUid, in Bundle serializedCallingStackInBundle);
}

View File

@@ -20,6 +20,7 @@ import android.accessibilityservice.IAccessibilityServiceConnection;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
@@ -39,6 +40,7 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
@@ -83,6 +85,8 @@ public final class AccessibilityInteractionClient
public static final int NO_ID = -1;
public static final String CALL_STACK = "call_stack";
private static final String LOG_TAG = "AccessibilityInteractionClient";
private static final boolean DEBUG = false;
@@ -113,7 +117,10 @@ public final class AccessibilityInteractionClient
private final Object mInstanceLock = new Object();
private final AccessibilityManager mAccessibilityManager;
private volatile int mInteractionId = -1;
private volatile int mCallingUid = Process.INVALID_UID;
private AccessibilityNodeInfo mFindAccessibilityNodeInfoResult;
@@ -151,6 +158,37 @@ public final class AccessibilityInteractionClient
}
}
/**
* @return The client for the current thread.
*/
public static AccessibilityInteractionClient getInstance(Context context) {
final long threadId = Thread.currentThread().getId();
if (context != null) {
return getInstanceForThread(threadId, context);
}
return getInstanceForThread(threadId);
}
/**
* <strong>Note:</strong> We keep one instance per interrogating thread since
* the instance contains state which can lead to undesired thread interleavings.
* We do not have a thread local variable since other threads should be able to
* look up the correct client knowing a thread id. See ViewRootImpl for details.
*
* @return The client for a given <code>threadId</code>.
*/
public static AccessibilityInteractionClient getInstanceForThread(
long threadId, Context context) {
synchronized (sStaticLock) {
AccessibilityInteractionClient client = sClients.get(threadId);
if (client == null) {
client = new AccessibilityInteractionClient(context);
sClients.put(threadId, client);
}
return client;
}
}
/**
* Gets a cached accessibility service connection.
*
@@ -197,6 +235,11 @@ public final class AccessibilityInteractionClient
private AccessibilityInteractionClient() {
/* reducing constructor visibility */
mAccessibilityManager = null;
}
private AccessibilityInteractionClient(Context context) {
mAccessibilityManager = context.getSystemService(AccessibilityManager.class);
}
/**
@@ -453,6 +496,15 @@ public final class AccessibilityInteractionClient
if (packageNames != null) {
List<AccessibilityNodeInfo> infos = getFindAccessibilityNodeInfosResultAndClear(
interactionId);
if (mAccessibilityManager != null
&& mAccessibilityManager.isAccessibilityTracingEnabled()) {
logTrace(connection, "findAccessibilityNodeInfoByAccessibilityId",
"InteractionId:" + interactionId + ";Result: " + infos
+ ";connectionId=" + connectionId + ";accessibilityWindowId="
+ accessibilityWindowId + ";accessibilityNodeId="
+ accessibilityNodeId + ";bypassCache=" + bypassCache
+ ";prefetchFlags=" + prefetchFlags + ";arguments=" + arguments);
}
finalizeAndCacheAccessibilityNodeInfos(infos, connectionId,
bypassCache, packageNames);
if (infos != null && !infos.isEmpty()) {
@@ -514,6 +566,14 @@ public final class AccessibilityInteractionClient
if (packageNames != null) {
List<AccessibilityNodeInfo> infos = getFindAccessibilityNodeInfosResultAndClear(
interactionId);
if (mAccessibilityManager != null
&& mAccessibilityManager.isAccessibilityTracingEnabled()) {
logTrace(connection, "findAccessibilityNodeInfosByViewId", "InteractionId="
+ interactionId + ":Result: " + infos + ";connectionId="
+ connectionId + ";accessibilityWindowId=" + accessibilityWindowId
+ ";accessibilityNodeId=" + accessibilityNodeId + ";viewId="
+ viewId);
}
if (infos != null) {
finalizeAndCacheAccessibilityNodeInfos(infos, connectionId,
false, packageNames);
@@ -568,6 +628,13 @@ public final class AccessibilityInteractionClient
if (packageNames != null) {
List<AccessibilityNodeInfo> infos = getFindAccessibilityNodeInfosResultAndClear(
interactionId);
if (mAccessibilityManager != null
&& mAccessibilityManager.isAccessibilityTracingEnabled()) {
logTrace(connection, "findAccessibilityNodeInfosByText", "InteractionId="
+ interactionId + ":Result: " + infos + ";connectionId="
+ connectionId + ";accessibilityWindowId=" + accessibilityWindowId
+ ";accessibilityNodeId=" + accessibilityNodeId + ";text=" + text);
}
if (infos != null) {
finalizeAndCacheAccessibilityNodeInfos(infos, connectionId,
false, packageNames);
@@ -621,6 +688,14 @@ public final class AccessibilityInteractionClient
if (packageNames != null) {
AccessibilityNodeInfo info = getFindAccessibilityNodeInfoResultAndClear(
interactionId);
if (mAccessibilityManager != null
&& mAccessibilityManager.isAccessibilityTracingEnabled()) {
logTrace(connection, "findFocus", "InteractionId=" + interactionId
+ ":Result: " + info + ";connectionId=" + connectionId
+ ";accessibilityWindowId=" + accessibilityWindowId
+ ";accessibilityNodeId=" + accessibilityNodeId + ";focusType="
+ focusType);
}
finalizeAndCacheAccessibilityNodeInfo(info, connectionId, false, packageNames);
return info;
}
@@ -671,6 +746,14 @@ public final class AccessibilityInteractionClient
AccessibilityNodeInfo info = getFindAccessibilityNodeInfoResultAndClear(
interactionId);
finalizeAndCacheAccessibilityNodeInfo(info, connectionId, false, packageNames);
if (mAccessibilityManager != null
&& mAccessibilityManager.isAccessibilityTracingEnabled()) {
logTrace(connection, "focusSearch", "InteractionId=" + interactionId
+ ":Result: " + info + ";connectionId=" + connectionId
+ ";accessibilityWindowId=" + accessibilityWindowId
+ ";accessibilityNodeId=" + accessibilityNodeId + ";direction="
+ direction);
}
return info;
}
} else {
@@ -716,7 +799,17 @@ public final class AccessibilityInteractionClient
}
if (success) {
return getPerformAccessibilityActionResultAndClear(interactionId);
final boolean result =
getPerformAccessibilityActionResultAndClear(interactionId);
if (mAccessibilityManager != null
&& mAccessibilityManager.isAccessibilityTracingEnabled()) {
logTrace(connection, "performAccessibilityAction", "InteractionId="
+ interactionId + ":Result: " + result + ";connectionId="
+ connectionId + ";accessibilityWindowId=" + accessibilityWindowId
+ ";accessibilityNodeId=" + accessibilityNodeId + ";action="
+ action + ";arguments=" + arguments);
}
return result;
}
} else {
if (DEBUG) {
@@ -774,6 +867,7 @@ public final class AccessibilityInteractionClient
if (interactionId > mInteractionId) {
mFindAccessibilityNodeInfoResult = info;
mInteractionId = interactionId;
mCallingUid = Binder.getCallingUid();
}
mInstanceLock.notifyAll();
}
@@ -823,6 +917,7 @@ public final class AccessibilityInteractionClient
mFindAccessibilityNodeInfosResult = Collections.emptyList();
}
mInteractionId = interactionId;
mCallingUid = Binder.getCallingUid();
}
mInstanceLock.notifyAll();
}
@@ -851,6 +946,7 @@ public final class AccessibilityInteractionClient
if (interactionId > mInteractionId) {
mPerformAccessibilityActionResult = succeeded;
mInteractionId = interactionId;
mCallingUid = Binder.getCallingUid();
}
mInstanceLock.notifyAll();
}
@@ -1059,4 +1155,19 @@ public final class AccessibilityInteractionClient
}
return true;
}
private void logTrace(
IAccessibilityServiceConnection connection, String method, String params) {
try {
Bundle b = new Bundle();
ArrayList<StackTraceElement> callStack = new ArrayList<StackTraceElement>(
Arrays.asList(Thread.currentThread().getStackTrace()));
b.putSerializable(CALL_STACK, callStack);
connection.logTrace(SystemClock.elapsedRealtimeNanos(),
LOG_TAG + ".callback for " + method, params, Process.myPid(),
Thread.currentThread().getId(), mCallingUid, b);
} catch (RemoteException e) {
Log.e(LOG_TAG, "Failed to log trace. " + e);
}
}
}

View File

@@ -110,6 +110,9 @@ public final class AccessibilityManager {
/** @hide */
public static final int STATE_FLAG_REQUEST_MULTI_FINGER_GESTURES = 0x00000010;
/** @hide */
public static final int STATE_FLAG_ACCESSIBILITY_TRACING_ENABLED = 0x00000020;
/** @hide */
public static final int DALTONIZER_DISABLED = -1;
@@ -232,6 +235,9 @@ public final class AccessibilityManager {
@UnsupportedAppUsage(trackingBug = 123768939L)
boolean mIsHighTextContrastEnabled;
// Whether accessibility tracing is enabled or not
boolean mIsAccessibilityTracingEnabled = false;
AccessibilityPolicy mAccessibilityPolicy;
private int mPerformingAction = 0;
@@ -1003,6 +1009,17 @@ public final class AccessibilityManager {
}
}
/**
* Gets accessibility tracing enabled state.
*
* @hide
*/
public boolean isAccessibilityTracingEnabled() {
synchronized (mLock) {
return mIsAccessibilityTracingEnabled;
}
}
/**
* Get the preparers that are registered for an accessibility ID
*
@@ -1197,6 +1214,8 @@ public final class AccessibilityManager {
(stateFlags & STATE_FLAG_TOUCH_EXPLORATION_ENABLED) != 0;
final boolean highTextContrastEnabled =
(stateFlags & STATE_FLAG_HIGH_TEXT_CONTRAST_ENABLED) != 0;
final boolean accessibilityTracingEnabled =
(stateFlags & STATE_FLAG_ACCESSIBILITY_TRACING_ENABLED) != 0;
final boolean wasEnabled = isEnabled();
final boolean wasTouchExplorationEnabled = mIsTouchExplorationEnabled;
@@ -1218,6 +1237,8 @@ public final class AccessibilityManager {
if (wasHighTextContrastEnabled != highTextContrastEnabled) {
notifyHighTextContrastStateChanged();
}
updateAccessibilityTracingState(accessibilityTracingEnabled);
}
/**
@@ -1674,6 +1695,15 @@ public final class AccessibilityManager {
}
}
/**
* Update mIsAccessibilityTracingEnabled.
*/
private void updateAccessibilityTracingState(boolean enabled) {
synchronized (mLock) {
mIsAccessibilityTracingEnabled = enabled;
}
}
/**
* Update interactive and non-interactive UI timeout.
*

View File

@@ -163,4 +163,7 @@ public class AccessibilityServiceConnectionImpl extends IAccessibilityServiceCon
public void setGestureDetectionPassthroughRegion(int displayId, Region region) {}
public void setFocusAppearance(int strokeWidth, int color) {}
public void logTrace(long timestamp, String where, String callingParams, int processId,
long threadId, int callingUid, Bundle callingStack) {}
}

View File

@@ -22,6 +22,7 @@ import static android.accessibilityservice.AccessibilityService.KEY_ACCESSIBILIT
import static android.accessibilityservice.AccessibilityService.KEY_ACCESSIBILITY_SCREENSHOT_TIMESTAMP;
import static android.accessibilityservice.AccessibilityServiceInfo.DEFAULT;
import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
import static android.view.accessibility.AccessibilityInteractionClient.CALL_STACK;
import static android.view.accessibility.AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS;
import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS;
import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLICK;
@@ -1979,4 +1980,15 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ
"strokeWidth=" + strokeWidth + ";color=" + color);
}
}
@Override
public void logTrace(long timestamp, String where, String callingParams, int processId,
long threadId, int callingUid, Bundle callingStack) {
if (mTrace.isA11yTracingEnabled()) {
ArrayList<StackTraceElement> list =
(ArrayList<StackTraceElement>) callingStack.getSerializable(CALL_STACK);
mTrace.logTrace(timestamp, where, callingParams, processId, threadId, callingUid,
list.toArray(new StackTraceElement[list.size()]));
}
}
}

View File

@@ -1409,7 +1409,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
}
private int getClientStateLocked(AccessibilityUserState userState) {
return userState.getClientStateLocked(mUiAutomationManager.isUiAutomationRunningLocked());
return userState.getClientStateLocked(
mUiAutomationManager.isUiAutomationRunningLocked(),
mA11yController.isAccessibilityTracingEnabled());
}
private InteractionBridge getInteractionBridge() {
@@ -3322,7 +3324,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
mConnectionId = service.mId;
mClient = AccessibilityInteractionClient.getInstance();
mClient = AccessibilityInteractionClient.getInstance(mContext);
mClient.addConnection(mConnectionId, service);
//TODO: (multi-display) We need to support multiple displays.
@@ -3865,6 +3867,24 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
return mA11yController.isAccessibilityTracingEnabled();
}
@Override
public void startTrace() {
if (!mA11yController.isAccessibilityTracingEnabled()) {
mA11yController.startTrace();
final AccessibilityUserState userState = getUserStateLocked(UserHandle.USER_SYSTEM);
scheduleUpdateClientsIfNeededLocked(userState);
}
}
@Override
public void stopTrace() {
if (mA11yController.isAccessibilityTracingEnabled()) {
mA11yController.stopTrace();
final AccessibilityUserState userState = getUserStateLocked(UserHandle.USER_SYSTEM);
scheduleUpdateClientsIfNeededLocked(userState);
}
}
@Override
public void logTrace(String where) {
logTrace(where, "");
@@ -3875,4 +3895,13 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
mA11yController.logTrace(where, callingParams, "".getBytes(),
Binder.getCallingUid(), Thread.currentThread().getStackTrace());
}
@Override
public void logTrace(long timestamp, String where, String callingParams, int processId,
long threadId, int callingUid, StackTraceElement[] callStack) {
if (mA11yController.isAccessibilityTracingEnabled()) {
mA11yController.logTrace(where, callingParams, "".getBytes(), callingUid, callStack,
timestamp, processId, threadId);
}
}
}

View File

@@ -108,16 +108,12 @@ final class AccessibilityShellCommand extends ShellCommand {
}
private int startTrace() {
WindowManagerInternal.AccessibilityControllerInternal ac =
mWindowManagerService.getAccessibilityController();
ac.startTrace();
mService.startTrace();
return 0;
}
private int stopTrace() {
WindowManagerInternal.AccessibilityControllerInternal ac =
mWindowManagerService.getAccessibilityController();
ac.stopTrace();
mService.stopTrace();
return 0;
}

View File

@@ -24,6 +24,16 @@ public interface AccessibilityTrace {
*/
boolean isA11yTracingEnabled();
/**
* Start tracing.
*/
void startTrace();
/**
* Stop tracing.
*/
void stopTrace();
/**
* Log one trace entry.
* @param where A string to identify this log entry, which can be used to filter/search
@@ -38,4 +48,19 @@ public interface AccessibilityTrace {
* @param callingParams The parameters for the method to be logged.
*/
void logTrace(String where, String callingParams);
/**
* Log one trace entry. Accessibility services using AccessibilityInteractionClient to
* make screen content related requests use this API to log entry when receive callback.
* @param timestamp The timestamp when a callback is received.
* @param where A string to identify this log entry, which can be used to filter/search
* through the tracing file.
* @param callingParams The parameters for the callback.
* @param processId The process id of the calling component.
* @param threadId The threadId of the calling component.
* @param callingUid The calling uid of the callback.
* @param callStack The call stack of the callback.
*/
void logTrace(long timestamp, String where, String callingParams, int processId,
long threadId, int callingUid, StackTraceElement[] callStack);
}

View File

@@ -391,7 +391,7 @@ class AccessibilityUserState {
return mBoundServices;
}
int getClientStateLocked(boolean isUiAutomationRunning) {
int getClientStateLocked(boolean isUiAutomationRunning, boolean isTracingEnabled) {
int clientState = 0;
final boolean a11yEnabled = isUiAutomationRunning
|| isHandlingAccessibilityEventsLocked();
@@ -407,6 +407,9 @@ class AccessibilityUserState {
if (mIsTextHighContrastEnabled) {
clientState |= AccessibilityManager.STATE_FLAG_HIGH_TEXT_CONTRAST_ENABLED;
}
if (isTracingEnabled) {
clientState |= AccessibilityManager.STATE_FLAG_ACCESSIBILITY_TRACING_ENABLED;
}
return clientState;
}

View File

@@ -1903,6 +1903,14 @@ final class AccessibilityController {
StackTraceElement[] stackTrace) {
mTracing.logState(where, callingParams, a11yDump, callingUid, stackTrace);
}
@Override
public void logTrace(
String where, String callingParams, byte[] a11yDump, int callingUid,
StackTraceElement[] callStack, long timeStamp, int processId, long threadId) {
mTracing.logState(where, callingParams, a11yDump, callingUid, callStack, timeStamp,
processId, threadId);
}
}
private static final class AccessibilityTracing {
@@ -1916,7 +1924,7 @@ final class AccessibilityController {
}
}
private static final int BUFFER_CAPACITY = 4096 * 1024;
private static final int BUFFER_CAPACITY = 1024 * 1024 * 12;
private static final String TRACE_FILENAME = "/data/misc/a11ytrace/a11y_trace.pb";
private static final String TRACE_DIRECTORY = "/data/misc/a11ytrace/";
private static final String TAG = "AccessibilityTracing";
@@ -2034,7 +2042,22 @@ final class AccessibilityController {
return;
}
log(where, callingParams, a11yDump, callingUid, stackTrace);
log(where, callingParams, a11yDump, callingUid, stackTrace,
SystemClock.elapsedRealtimeNanos(),
Process.myPid() + ":" + Application.getProcessName(),
Thread.currentThread().getId() + ":" + Thread.currentThread().getName());
}
/**
* Write an accessibility trace log entry.
*/
void logState(String where, String callingParams, byte[] a11yDump, int callingUid,
StackTraceElement[] callingStack, long timeStamp, int processId, long threadId) {
if (!mEnabled) {
return;
}
log(where, callingParams, a11yDump, callingUid, callingStack, timeStamp,
String.valueOf(processId), String.valueOf(threadId));
}
private String toStackTraceString(StackTraceElement[] stackTraceElements) {
@@ -2058,18 +2081,17 @@ final class AccessibilityController {
* Write the current state to the buffer
*/
private void log(String where, String callingParams, byte[] a11yDump, int callingUid,
StackTraceElement[] stackTrace) {
SimpleDateFormat fm = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
StackTraceElement[] callingStack, long timeStamp, String processName,
String threadName) {
SomeArgs args = SomeArgs.obtain();
args.arg1 = SystemClock.elapsedRealtimeNanos();
args.arg2 = fm.format(new Date()).toString();
args.arg3 = where;
args.arg4 = Process.myPid() + ":" + Application.getProcessName();
args.arg5 = Thread.currentThread().getId() + ":" + Thread.currentThread().getName();
args.arg6 = callingUid;
args.arg7 = callingParams;
args.arg8 = stackTrace;
args.arg9 = a11yDump;
args.arg1 = timeStamp;
args.arg2 = where;
args.arg3 = processName;
args.arg4 = threadName;
args.arg5 = callingUid;
args.arg6 = callingParams;
args.arg7 = callingStack;
args.arg8 = a11yDump;
mHandler.obtainMessage(LogHandler.MESSAGE_LOG_TRACE_ENTRY, args).sendToTarget();
}
@@ -2100,17 +2122,26 @@ final class AccessibilityController {
long tokenOuter = os.start(ENTRY);
String callingStack =
toStackTraceString((StackTraceElement[]) args.arg8);
toStackTraceString((StackTraceElement[]) args.arg7);
os.write(ELAPSED_REALTIME_NANOS, (long) args.arg1);
os.write(CALENDAR_TIME, (String) args.arg2);
os.write(WHERE, (String) args.arg3);
os.write(PROCESS_NAME, (String) args.arg4);
os.write(THREAD_ID_NAME, (String) args.arg5);
os.write(CALLING_PKG, pmInternal.getNameForUid((int) args.arg6));
os.write(CALLING_PARAMS, (String) args.arg7);
long reportedTimeStampNanos = (long) args.arg1;
long currentElapsedRealtimeNanos = SystemClock.elapsedRealtimeNanos();
long timeDiffNanos =
currentElapsedRealtimeNanos - reportedTimeStampNanos;
long currentTimeMillis = (new Date()).getTime();
long reportedTimeMillis =
currentTimeMillis - (long) (timeDiffNanos / 1000000);
SimpleDateFormat fm = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
os.write(ELAPSED_REALTIME_NANOS, reportedTimeStampNanos);
os.write(CALENDAR_TIME, fm.format(reportedTimeMillis).toString());
os.write(WHERE, (String) args.arg2);
os.write(PROCESS_NAME, (String) args.arg3);
os.write(THREAD_ID_NAME, (String) args.arg4);
os.write(CALLING_PKG, pmInternal.getNameForUid((int) args.arg5));
os.write(CALLING_PARAMS, (String) args.arg6);
os.write(CALLING_STACKS, callingStack);
os.write(ACCESSIBILITY_SERVICE, (byte[]) args.arg9);
os.write(ACCESSIBILITY_SERVICE, (byte[]) args.arg8);
long tokenInner = os.start(WINDOW_MANAGER_SERVICE);
synchronized (mService.mGlobalLock) {

View File

@@ -81,6 +81,22 @@ public abstract class WindowManagerInternal {
void logTrace(
String where, String callingParams, byte[] a11yDump, int callingUid,
StackTraceElement[] stackTrace);
/**
* Add an accessibility trace entry.
*
* @param where A string to identify this log entry, which can be used to filter/search
* through the tracing file.
* @param callingParams The parameters for the method to be logged.
* @param a11yDump The proto byte array for a11y state when the entry is generated.
* @param callingUid The calling uid.
* @param callStack The call stack of the method to be logged.
* @param timeStamp The time when the method to be logged is called.
* @param processId The calling process Id.
* @param threadId The calling thread Id.
*/
void logTrace(String where, String callingParams, byte[] a11yDump, int callingUid,
StackTraceElement[] callStack, long timeStamp, int processId, long threadId);
}
/**