summaryrefslogtreecommitdiffstats
path: root/core/java
diff options
context:
space:
mode:
authorSvetoslav Ganov <svetoslavganov@google.com>2011-11-21 18:41:59 -0800
committerSvetoslav Ganov <svetoslavganov@google.com>2011-11-29 18:51:30 -0800
commitd116d7c78a9c53f30a73bf273bd7618312cf3847 (patch)
treec46c6bdb1abeca54d711b304ab7596569e9aa43c /core/java
parent50b2042502bc459b40430fe3b3b83d7d61e5daf9 (diff)
downloadframeworks_base-d116d7c78a9c53f30a73bf273bd7618312cf3847.zip
frameworks_base-d116d7c78a9c53f30a73bf273bd7618312cf3847.tar.gz
frameworks_base-d116d7c78a9c53f30a73bf273bd7618312cf3847.tar.bz2
Fixing memory leaks in the accessiiblity layer.
1. AccessibilityInteractionConnections were removed from the AccessiiblityManagerService but their DeathRecipents were not unregistered, thus every removed interaction connection was essentially leaking. Such connection is registered in the system for every ViewRootImpl when accessiiblity is enabled and inregistered when disabled. 2. Every AccessibilityEvent and AccessiilbityEventInfo obtained from a widnow content querying accessibility service had a handle to a binder proxy over which to make queries. Hoewever, holding a proxy to a remote binder prevents the latter from being garbage collected. Therefore, now the events and infos have a connection id insteand and the hindden singleton AccessiiblityInteaction client via which queries are made has a registry with the connections. This class looks up the connection given its id before making an IPC. Now the connection is stored in one place and when an accessibility service is disconnected the system sets the connection to null so the binder object in the system process can be GCed. Note that before this change a bad implemented accessibility service could cache events or infos causing a leak in the system process. This should never happen. 3. SparseArray was not clearing the reference to the last moved element while garbage collecting thus causing a leak. bug:5664337 Change-Id: Id397f614b026d43bd7b57bb7f8186bca5cdfcff9
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/accessibilityservice/AccessibilityService.java33
-rw-r--r--core/java/android/accessibilityservice/IEventListener.aidl2
-rw-r--r--core/java/android/util/SparseArray.java1
-rw-r--r--core/java/android/view/accessibility/AccessibilityEvent.java36
-rw-r--r--core/java/android/view/accessibility/AccessibilityInteractionClient.java239
-rw-r--r--core/java/android/view/accessibility/AccessibilityNodeInfo.java55
-rw-r--r--core/java/android/view/accessibility/AccessibilityRecord.java50
-rw-r--r--core/java/android/view/accessibility/IAccessibilityManager.aidl2
8 files changed, 248 insertions, 170 deletions
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index 64a2755..211be52 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -16,8 +16,6 @@
package android.accessibilityservice;
-import com.android.internal.os.HandlerCaller;
-
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
@@ -25,8 +23,11 @@ import android.os.Message;
import android.os.RemoteException;
import android.util.Log;
import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityInteractionClient;
import android.view.accessibility.AccessibilityNodeInfo;
+import com.android.internal.os.HandlerCaller;
+
/**
* An accessibility service runs in the background and receives callbacks by the system
* when {@link AccessibilityEvent}s are fired. Such events denote some state transition
@@ -219,7 +220,7 @@ public abstract class AccessibilityService extends Service {
private AccessibilityServiceInfo mInfo;
- IAccessibilityServiceConnection mConnection;
+ private int mConnectionId;
/**
* Callback for {@link android.view.accessibility.AccessibilityEvent}s.
@@ -264,9 +265,11 @@ public abstract class AccessibilityService extends Service {
* AccessibilityManagerService.
*/
private void sendServiceInfo() {
- if (mInfo != null && mConnection != null) {
+ IAccessibilityServiceConnection connection =
+ AccessibilityInteractionClient.getInstance().getConnection(mConnectionId);
+ if (mInfo != null && connection != null) {
try {
- mConnection.setServiceInfo(mInfo);
+ connection.setServiceInfo(mInfo);
} catch (RemoteException re) {
Log.w(LOG_TAG, "Error while setting AccessibilityServiceInfo", re);
}
@@ -302,8 +305,9 @@ public abstract class AccessibilityService extends Service {
mCaller = new HandlerCaller(context, this);
}
- public void setConnection(IAccessibilityServiceConnection connection) {
- Message message = mCaller.obtainMessageO(DO_SET_SET_CONNECTION, connection);
+ public void setConnection(IAccessibilityServiceConnection connection, int connectionId) {
+ Message message = mCaller.obtainMessageIO(DO_SET_SET_CONNECTION, connectionId,
+ connection);
mCaller.sendMessage(message);
}
@@ -330,8 +334,19 @@ public abstract class AccessibilityService extends Service {
mTarget.onInterrupt();
return;
case DO_SET_SET_CONNECTION :
- mConnection = ((IAccessibilityServiceConnection) message.obj);
- mTarget.onServiceConnected();
+ final int connectionId = message.arg1;
+ IAccessibilityServiceConnection connection =
+ (IAccessibilityServiceConnection) message.obj;
+ if (connection != null) {
+ AccessibilityInteractionClient.getInstance().addConnection(connectionId,
+ connection);
+ mConnectionId = connectionId;
+ mTarget.onServiceConnected();
+ } else {
+ AccessibilityInteractionClient.getInstance().removeConnection(connectionId);
+ mConnectionId = AccessibilityInteractionClient.NO_ID;
+ // TODO: Do we need a onServiceDisconnected callback?
+ }
return;
default :
Log.w(LOG_TAG, "Unknown message type " + message.what);
diff --git a/core/java/android/accessibilityservice/IEventListener.aidl b/core/java/android/accessibilityservice/IEventListener.aidl
index 5b849f1..5536b3c 100644
--- a/core/java/android/accessibilityservice/IEventListener.aidl
+++ b/core/java/android/accessibilityservice/IEventListener.aidl
@@ -26,7 +26,7 @@ import android.view.accessibility.AccessibilityEvent;
*/
oneway interface IEventListener {
- void setConnection(in IAccessibilityServiceConnection connection);
+ void setConnection(in IAccessibilityServiceConnection connection, int connectionId);
void onAccessibilityEvent(in AccessibilityEvent event);
diff --git a/core/java/android/util/SparseArray.java b/core/java/android/util/SparseArray.java
index 7cf4579..366abd3 100644
--- a/core/java/android/util/SparseArray.java
+++ b/core/java/android/util/SparseArray.java
@@ -134,6 +134,7 @@ public class SparseArray<E> implements Cloneable {
if (i != o) {
keys[o] = keys[i];
values[o] = val;
+ values[i] = null;
}
o++;
diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java
index 7bf0c83..91dcac8 100644
--- a/core/java/android/view/accessibility/AccessibilityEvent.java
+++ b/core/java/android/view/accessibility/AccessibilityEvent.java
@@ -16,7 +16,6 @@
package android.view.accessibility;
-import android.accessibilityservice.IAccessibilityServiceConnection;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
@@ -590,24 +589,6 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
}
/**
- * Sets the connection for interacting with the AccessibilityManagerService.
- *
- * @param connection The connection.
- *
- * @hide
- */
- @Override
- public void setConnection(IAccessibilityServiceConnection connection) {
- super.setConnection(connection);
- List<AccessibilityRecord> records = mRecords;
- final int recordCount = records.size();
- for (int i = 0; i < recordCount; i++) {
- AccessibilityRecord record = records.get(i);
- record.setConnection(connection);
- }
- }
-
- /**
* Sets if this instance is sealed.
*
* @param sealed Whether is sealed.
@@ -821,23 +802,19 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
* @param parcel A parcel containing the state of a {@link AccessibilityEvent}.
*/
public void initFromParcel(Parcel parcel) {
- if (parcel.readInt() == 1) {
- mConnection = IAccessibilityServiceConnection.Stub.asInterface(
- parcel.readStrongBinder());
- }
- setSealed(parcel.readInt() == 1);
+ mSealed = (parcel.readInt() == 1);
mEventType = parcel.readInt();
mPackageName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
mEventTime = parcel.readLong();
+ mConnectionId = parcel.readInt();
readAccessibilityRecordFromParcel(this, parcel);
// Read the records.
final int recordCount = parcel.readInt();
for (int i = 0; i < recordCount; i++) {
AccessibilityRecord record = AccessibilityRecord.obtain();
- // Do this to write the connection only once.
- record.setConnection(mConnection);
readAccessibilityRecordFromParcel(record, parcel);
+ record.mConnectionId = mConnectionId;
mRecords.add(record);
}
}
@@ -875,16 +852,11 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
* {@inheritDoc}
*/
public void writeToParcel(Parcel parcel, int flags) {
- if (mConnection == null) {
- parcel.writeInt(0);
- } else {
- parcel.writeInt(1);
- parcel.writeStrongBinder(mConnection.asBinder());
- }
parcel.writeInt(isSealed() ? 1 : 0);
parcel.writeInt(mEventType);
TextUtils.writeToParcel(mPackageName, parcel, 0);
parcel.writeLong(mEventTime);
+ parcel.writeInt(mConnectionId);
writeAccessibilityRecordToParcel(this, parcel, flags);
// Write the records.
diff --git a/core/java/android/view/accessibility/AccessibilityInteractionClient.java b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
index 25b980b..00a7c87 100644
--- a/core/java/android/view/accessibility/AccessibilityInteractionClient.java
+++ b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
@@ -21,6 +21,8 @@ import android.graphics.Rect;
import android.os.Message;
import android.os.RemoteException;
import android.os.SystemClock;
+import android.util.Log;
+import android.util.SparseArray;
import java.util.Collections;
import java.util.List;
@@ -61,6 +63,12 @@ import java.util.concurrent.atomic.AtomicInteger;
public final class AccessibilityInteractionClient
extends IAccessibilityInteractionConnectionCallback.Stub {
+ public static final int NO_ID = -1;
+
+ private static final String LOG_TAG = "AccessibilityInteractionClient";
+
+ private static final boolean DEBUG = false;
+
private static final long TIMEOUT_INTERACTION_MILLIS = 5000;
private static final Object sStaticLock = new Object();
@@ -83,6 +91,9 @@ public final class AccessibilityInteractionClient
private final Rect mTempBounds = new Rect();
+ private final SparseArray<IAccessibilityServiceConnection> mConnectionCache =
+ new SparseArray<IAccessibilityServiceConnection>();
+
/**
* @return The singleton of this class.
*/
@@ -111,28 +122,37 @@ public final class AccessibilityInteractionClient
/**
* Finds an {@link AccessibilityNodeInfo} by accessibility id.
*
- * @param connection A connection for interacting with the system.
+ * @param connectionId The id of a connection for interacting with the system.
* @param accessibilityWindowId A unique window id.
* @param accessibilityViewId A unique View accessibility id.
* @return An {@link AccessibilityNodeInfo} if found, null otherwise.
*/
- public AccessibilityNodeInfo findAccessibilityNodeInfoByAccessibilityId(
- IAccessibilityServiceConnection connection, int accessibilityWindowId,
- int accessibilityViewId) {
+ public AccessibilityNodeInfo findAccessibilityNodeInfoByAccessibilityId(int connectionId,
+ int accessibilityWindowId, int accessibilityViewId) {
try {
- final int interactionId = mInteractionIdCounter.getAndIncrement();
- final float windowScale = connection.findAccessibilityNodeInfoByAccessibilityId(
- accessibilityWindowId, accessibilityViewId, interactionId, this,
- Thread.currentThread().getId());
- // If the scale is zero the call has failed.
- if (windowScale > 0) {
- AccessibilityNodeInfo info = getFindAccessibilityNodeInfoResultAndClear(
- interactionId);
- finalizeAccessibilityNodeInfo(info, connection, windowScale);
- return info;
+ IAccessibilityServiceConnection connection = getConnection(connectionId);
+ if (connection != null) {
+ final int interactionId = mInteractionIdCounter.getAndIncrement();
+ final float windowScale = connection.findAccessibilityNodeInfoByAccessibilityId(
+ accessibilityWindowId, accessibilityViewId, interactionId, this,
+ Thread.currentThread().getId());
+ // If the scale is zero the call has failed.
+ if (windowScale > 0) {
+ AccessibilityNodeInfo info = getFindAccessibilityNodeInfoResultAndClear(
+ interactionId);
+ finalizeAccessibilityNodeInfo(info, connectionId, windowScale);
+ return info;
+ }
+ } else {
+ if (DEBUG) {
+ Log.w(LOG_TAG, "No connection for connection id: " + connectionId);
+ }
}
} catch (RemoteException re) {
- /* ignore */
+ if (DEBUG) {
+ Log.w(LOG_TAG, "Error while calling remote"
+ + " findAccessibilityNodeInfoByAccessibilityId", re);
+ }
}
return null;
}
@@ -141,25 +161,36 @@ public final class AccessibilityInteractionClient
* Finds an {@link AccessibilityNodeInfo} by View id. The search is performed
* in the currently active window and starts from the root View in the window.
*
- * @param connection A connection for interacting with the system.
+ * @param connectionId The id of a connection for interacting with the system.
* @param viewId The id of the view.
* @return An {@link AccessibilityNodeInfo} if found, null otherwise.
*/
- public AccessibilityNodeInfo findAccessibilityNodeInfoByViewIdInActiveWindow(
- IAccessibilityServiceConnection connection, int viewId) {
+ public AccessibilityNodeInfo findAccessibilityNodeInfoByViewIdInActiveWindow(int connectionId,
+ int viewId) {
try {
- final int interactionId = mInteractionIdCounter.getAndIncrement();
- final float windowScale = connection.findAccessibilityNodeInfoByViewIdInActiveWindow(
- viewId, interactionId, this, Thread.currentThread().getId());
- // If the scale is zero the call has failed.
- if (windowScale > 0) {
- AccessibilityNodeInfo info = getFindAccessibilityNodeInfoResultAndClear(
- interactionId);
- finalizeAccessibilityNodeInfo(info, connection, windowScale);
- return info;
+ IAccessibilityServiceConnection connection = getConnection(connectionId);
+ if (connection != null) {
+ final int interactionId = mInteractionIdCounter.getAndIncrement();
+ final float windowScale =
+ connection.findAccessibilityNodeInfoByViewIdInActiveWindow(viewId,
+ interactionId, this, Thread.currentThread().getId());
+ // If the scale is zero the call has failed.
+ if (windowScale > 0) {
+ AccessibilityNodeInfo info = getFindAccessibilityNodeInfoResultAndClear(
+ interactionId);
+ finalizeAccessibilityNodeInfo(info, connectionId, windowScale);
+ return info;
+ }
+ } else {
+ if (DEBUG) {
+ Log.w(LOG_TAG, "No connection for connection id: " + connectionId);
+ }
}
} catch (RemoteException re) {
- /* ignore */
+ if (DEBUG) {
+ Log.w(LOG_TAG, "Error while calling remote"
+ + " findAccessibilityNodeInfoByViewIdInActiveWindow", re);
+ }
}
return null;
}
@@ -169,25 +200,36 @@ public final class AccessibilityInteractionClient
* insensitive containment. The search is performed in the currently
* active window and starts from the root View in the window.
*
- * @param connection A connection for interacting with the system.
+ * @param connectionId The id of a connection for interacting with the system.
* @param text The searched text.
* @return A list of found {@link AccessibilityNodeInfo}s.
*/
public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByViewTextInActiveWindow(
- IAccessibilityServiceConnection connection, String text) {
+ int connectionId, String text) {
try {
- final int interactionId = mInteractionIdCounter.getAndIncrement();
- final float windowScale = connection.findAccessibilityNodeInfosByViewTextInActiveWindow(
- text, interactionId, this, Thread.currentThread().getId());
- // If the scale is zero the call has failed.
- if (windowScale > 0) {
- List<AccessibilityNodeInfo> infos = getFindAccessibilityNodeInfosResultAndClear(
- interactionId);
- finalizeAccessibilityNodeInfos(infos, connection, windowScale);
- return infos;
+ IAccessibilityServiceConnection connection = getConnection(connectionId);
+ if (connection != null) {
+ final int interactionId = mInteractionIdCounter.getAndIncrement();
+ final float windowScale =
+ connection.findAccessibilityNodeInfosByViewTextInActiveWindow(text,
+ interactionId, this, Thread.currentThread().getId());
+ // If the scale is zero the call has failed.
+ if (windowScale > 0) {
+ List<AccessibilityNodeInfo> infos = getFindAccessibilityNodeInfosResultAndClear(
+ interactionId);
+ finalizeAccessibilityNodeInfos(infos, connectionId, windowScale);
+ return infos;
+ }
+ } else {
+ if (DEBUG) {
+ Log.w(LOG_TAG, "No connection for connection id: " + connectionId);
+ }
}
} catch (RemoteException re) {
- /* ignore */
+ if (DEBUG) {
+ Log.w(LOG_TAG, "Error while calling remote"
+ + " findAccessibilityNodeInfosByViewTextInActiveWindow", re);
+ }
}
return null;
}
@@ -198,30 +240,39 @@ public final class AccessibilityInteractionClient
* id is specified and starts from the View whose accessibility id is
* specified.
*
- * @param connection A connection for interacting with the system.
+ * @param connectionId The id of a connection for interacting with the system.
* @param text The searched text.
* @param accessibilityWindowId A unique window id.
* @param accessibilityViewId A unique View accessibility id from where to start the search.
* Use {@link android.view.View#NO_ID} to start from the root.
* @return A list of found {@link AccessibilityNodeInfo}s.
*/
- public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByViewText(
- IAccessibilityServiceConnection connection, String text, int accessibilityWindowId,
- int accessibilityViewId) {
+ public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByViewText(int connectionId,
+ String text, int accessibilityWindowId, int accessibilityViewId) {
try {
- final int interactionId = mInteractionIdCounter.getAndIncrement();
- final float windowScale = connection.findAccessibilityNodeInfosByViewText(text,
- accessibilityWindowId, accessibilityViewId, interactionId, this,
- Thread.currentThread().getId());
- // If the scale is zero the call has failed.
- if (windowScale > 0) {
- List<AccessibilityNodeInfo> infos = getFindAccessibilityNodeInfosResultAndClear(
- interactionId);
- finalizeAccessibilityNodeInfos(infos, connection, windowScale);
- return infos;
+ IAccessibilityServiceConnection connection = getConnection(connectionId);
+ if (connection != null) {
+ final int interactionId = mInteractionIdCounter.getAndIncrement();
+ final float windowScale = connection.findAccessibilityNodeInfosByViewText(text,
+ accessibilityWindowId, accessibilityViewId, interactionId, this,
+ Thread.currentThread().getId());
+ // If the scale is zero the call has failed.
+ if (windowScale > 0) {
+ List<AccessibilityNodeInfo> infos = getFindAccessibilityNodeInfosResultAndClear(
+ interactionId);
+ finalizeAccessibilityNodeInfos(infos, connectionId, windowScale);
+ return infos;
+ }
+ } else {
+ if (DEBUG) {
+ Log.w(LOG_TAG, "No connection for connection id: " + connectionId);
+ }
}
} catch (RemoteException re) {
- /* ignore */
+ if (DEBUG) {
+ Log.w(LOG_TAG, "Error while calling remote"
+ + " findAccessibilityNodeInfosByViewText", re);
+ }
}
return Collections.emptyList();
}
@@ -229,24 +280,33 @@ public final class AccessibilityInteractionClient
/**
* Performs an accessibility action on an {@link AccessibilityNodeInfo}.
*
- * @param connection A connection for interacting with the system.
+ * @param connectionId The id of a connection for interacting with the system.
* @param accessibilityWindowId The id of the window.
* @param accessibilityViewId A unique View accessibility id.
* @param action The action to perform.
* @return Whether the action was performed.
*/
- public boolean performAccessibilityAction(IAccessibilityServiceConnection connection,
- int accessibilityWindowId, int accessibilityViewId, int action) {
+ public boolean performAccessibilityAction(int connectionId, int accessibilityWindowId,
+ int accessibilityViewId, int action) {
try {
- final int interactionId = mInteractionIdCounter.getAndIncrement();
- final boolean success = connection.performAccessibilityAction(
- accessibilityWindowId, accessibilityViewId, action, interactionId, this,
- Thread.currentThread().getId());
- if (success) {
- return getPerformAccessibilityActionResult(interactionId);
+ IAccessibilityServiceConnection connection = getConnection(connectionId);
+ if (connection != null) {
+ final int interactionId = mInteractionIdCounter.getAndIncrement();
+ final boolean success = connection.performAccessibilityAction(
+ accessibilityWindowId, accessibilityViewId, action, interactionId, this,
+ Thread.currentThread().getId());
+ if (success) {
+ return getPerformAccessibilityActionResult(interactionId);
+ }
+ } else {
+ if (DEBUG) {
+ Log.w(LOG_TAG, "No connection for connection id: " + connectionId);
+ }
}
} catch (RemoteException re) {
- /* ignore */
+ if (DEBUG) {
+ Log.w(LOG_TAG, "Error while calling remote performAccessibilityAction", re);
+ }
}
return false;
}
@@ -406,14 +466,14 @@ public final class AccessibilityInteractionClient
* Finalize an {@link AccessibilityNodeInfo} before passing it to the client.
*
* @param info The info.
- * @param connection The current connection to the system.
+ * @param connectionId The id of the connection to the system.
* @param windowScale The source window compatibility scale.
*/
- private void finalizeAccessibilityNodeInfo(AccessibilityNodeInfo info,
- IAccessibilityServiceConnection connection, float windowScale) {
+ private void finalizeAccessibilityNodeInfo(AccessibilityNodeInfo info, int connectionId,
+ float windowScale) {
if (info != null) {
applyCompatibilityScaleIfNeeded(info, windowScale);
- info.setConnection(connection);
+ info.setConnectionId(connectionId);
info.setSealed(true);
}
}
@@ -422,16 +482,16 @@ public final class AccessibilityInteractionClient
* Finalize {@link AccessibilityNodeInfo}s before passing them to the client.
*
* @param infos The {@link AccessibilityNodeInfo}s.
- * @param connection The current connection to the system.
+ * @param connectionId The id of the connection to the system.
* @param windowScale The source window compatibility scale.
*/
private void finalizeAccessibilityNodeInfos(List<AccessibilityNodeInfo> infos,
- IAccessibilityServiceConnection connection, float windowScale) {
+ int connectionId, float windowScale) {
if (infos != null) {
final int infosCount = infos.size();
for (int i = 0; i < infosCount; i++) {
AccessibilityNodeInfo info = infos.get(i);
- finalizeAccessibilityNodeInfo(info, connection, windowScale);
+ finalizeAccessibilityNodeInfo(info, connectionId, windowScale);
}
}
}
@@ -449,4 +509,39 @@ public final class AccessibilityInteractionClient
return result;
}
}
+
+ /**
+ * Gets a cached accessibility service connection.
+ *
+ * @param connectionId The connection id.
+ * @return The cached connection if such.
+ */
+ public IAccessibilityServiceConnection getConnection(int connectionId) {
+ synchronized (mConnectionCache) {
+ return mConnectionCache.get(connectionId);
+ }
+ }
+
+ /**
+ * Adds a cached accessibility service connection.
+ *
+ * @param connectionId The connection id.
+ * @param connection The connection.
+ */
+ public void addConnection(int connectionId, IAccessibilityServiceConnection connection) {
+ synchronized (mConnectionCache) {
+ mConnectionCache.put(connectionId, connection);
+ }
+ }
+
+ /**
+ * Removes a cached accessibility service connection.
+ *
+ * @param connectionId The connection id.
+ */
+ public void removeConnection(int connectionId) {
+ synchronized (mConnectionCache) {
+ mConnectionCache.remove(connectionId);
+ }
+ }
}
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index fa34ee7..9b0f44a 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -16,7 +16,6 @@
package android.view.accessibility;
-import android.accessibilityservice.IAccessibilityServiceConnection;
import android.graphics.Rect;
import android.os.Parcel;
import android.os.Parcelable;
@@ -53,6 +52,8 @@ public class AccessibilityNodeInfo implements Parcelable {
private static final boolean DEBUG = false;
+ private static final int UNDEFINED = -1;
+
// Actions.
/**
@@ -107,9 +108,9 @@ public class AccessibilityNodeInfo implements Parcelable {
private boolean mSealed;
// Data.
- private int mAccessibilityViewId = View.NO_ID;
- private int mAccessibilityWindowId = View.NO_ID;
- private int mParentAccessibilityViewId = View.NO_ID;
+ private int mAccessibilityViewId = UNDEFINED;
+ private int mAccessibilityWindowId = UNDEFINED;
+ private int mParentAccessibilityViewId = UNDEFINED;
private int mBooleanProperties;
private final Rect mBoundsInParent = new Rect();
private final Rect mBoundsInScreen = new Rect();
@@ -122,7 +123,7 @@ public class AccessibilityNodeInfo implements Parcelable {
private SparseIntArray mChildAccessibilityIds = new SparseIntArray();
private int mActions;
- private IAccessibilityServiceConnection mConnection;
+ private int mConnectionId = UNDEFINED;
/**
* Hide constructor from clients.
@@ -181,7 +182,7 @@ public class AccessibilityNodeInfo implements Parcelable {
return null;
}
AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
- return client.findAccessibilityNodeInfoByAccessibilityId(mConnection,
+ return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId,
mAccessibilityWindowId, childAccessibilityViewId);
}
@@ -253,7 +254,7 @@ public class AccessibilityNodeInfo implements Parcelable {
return false;
}
AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
- return client.performAccessibilityAction(mConnection, mAccessibilityWindowId,
+ return client.performAccessibilityAction(mConnectionId, mAccessibilityWindowId,
mAccessibilityViewId, action);
}
@@ -277,7 +278,7 @@ public class AccessibilityNodeInfo implements Parcelable {
return Collections.emptyList();
}
AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
- return client.findAccessibilityNodeInfosByViewText(mConnection, text,
+ return client.findAccessibilityNodeInfosByViewText(mConnectionId, text,
mAccessibilityWindowId, mAccessibilityViewId);
}
@@ -297,7 +298,7 @@ public class AccessibilityNodeInfo implements Parcelable {
return null;
}
AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
- return client.findAccessibilityNodeInfoByAccessibilityId(mConnection,
+ return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId,
mAccessibilityWindowId, mParentAccessibilityViewId);
}
@@ -755,15 +756,16 @@ public class AccessibilityNodeInfo implements Parcelable {
}
/**
- * Sets the connection for interacting with the system.
+ * Sets the unique id of the IAccessibilityServiceConnection over which
+ * this instance can send requests to the system.
*
- * @param connection The client token.
+ * @param connectionId The connection id.
*
* @hide
*/
- public final void setConnection(IAccessibilityServiceConnection connection) {
+ public void setConnectionId(int connectionId) {
enforceNotSealed();
- mConnection = connection;
+ mConnectionId = connectionId;
}
/**
@@ -900,16 +902,11 @@ public class AccessibilityNodeInfo implements Parcelable {
* </p>
*/
public void writeToParcel(Parcel parcel, int flags) {
- if (mConnection == null) {
- parcel.writeInt(0);
- } else {
- parcel.writeInt(1);
- parcel.writeStrongBinder(mConnection.asBinder());
- }
parcel.writeInt(isSealed() ? 1 : 0);
parcel.writeInt(mAccessibilityViewId);
parcel.writeInt(mAccessibilityWindowId);
parcel.writeInt(mParentAccessibilityViewId);
+ parcel.writeInt(mConnectionId);
SparseIntArray childIds = mChildAccessibilityIds;
final int childIdsSize = childIds.size();
@@ -949,10 +946,10 @@ public class AccessibilityNodeInfo implements Parcelable {
*/
private void init(AccessibilityNodeInfo other) {
mSealed = other.mSealed;
- mConnection = other.mConnection;
mAccessibilityViewId = other.mAccessibilityViewId;
mParentAccessibilityViewId = other.mParentAccessibilityViewId;
mAccessibilityWindowId = other.mAccessibilityWindowId;
+ mConnectionId = other.mConnectionId;
mBoundsInParent.set(other.mBoundsInParent);
mBoundsInScreen.set(other.mBoundsInScreen);
mPackageName = other.mPackageName;
@@ -970,14 +967,11 @@ public class AccessibilityNodeInfo implements Parcelable {
* @param parcel A parcel containing the state of a {@link AccessibilityNodeInfo}.
*/
private void initFromParcel(Parcel parcel) {
- if (parcel.readInt() == 1) {
- mConnection = IAccessibilityServiceConnection.Stub.asInterface(
- parcel.readStrongBinder());
- }
mSealed = (parcel.readInt() == 1);
mAccessibilityViewId = parcel.readInt();
mAccessibilityWindowId = parcel.readInt();
mParentAccessibilityViewId = parcel.readInt();
+ mConnectionId = parcel.readInt();
SparseIntArray childIds = mChildAccessibilityIds;
final int childrenSize = parcel.readInt();
@@ -1011,10 +1005,10 @@ public class AccessibilityNodeInfo implements Parcelable {
*/
private void clear() {
mSealed = false;
- mConnection = null;
- mAccessibilityViewId = View.NO_ID;
- mParentAccessibilityViewId = View.NO_ID;
- mAccessibilityWindowId = View.NO_ID;
+ mAccessibilityViewId = UNDEFINED;
+ mParentAccessibilityViewId = UNDEFINED;
+ mAccessibilityWindowId = UNDEFINED;
+ mConnectionId = UNDEFINED;
mChildAccessibilityIds.clear();
mBoundsInParent.set(0, 0, 0, 0);
mBoundsInScreen.set(0, 0, 0, 0);
@@ -1048,9 +1042,8 @@ public class AccessibilityNodeInfo implements Parcelable {
}
private boolean canPerformRequestOverConnection(int accessibilityViewId) {
- return (mAccessibilityWindowId != View.NO_ID
- && accessibilityViewId != View.NO_ID
- && mConnection != null);
+ return (mConnectionId != UNDEFINED && mAccessibilityWindowId != UNDEFINED
+ && accessibilityViewId != UNDEFINED);
}
@Override
diff --git a/core/java/android/view/accessibility/AccessibilityRecord.java b/core/java/android/view/accessibility/AccessibilityRecord.java
index a4e0688..18d0f6f 100644
--- a/core/java/android/view/accessibility/AccessibilityRecord.java
+++ b/core/java/android/view/accessibility/AccessibilityRecord.java
@@ -16,7 +16,6 @@
package android.view.accessibility;
-import android.accessibilityservice.IAccessibilityServiceConnection;
import android.os.Parcelable;
import android.view.View;
@@ -78,8 +77,8 @@ public class AccessibilityRecord {
int mAddedCount= UNDEFINED;
int mRemovedCount = UNDEFINED;
- int mSourceViewId = View.NO_ID;
- int mSourceWindowId = View.NO_ID;
+ int mSourceViewId = UNDEFINED;
+ int mSourceWindowId = UNDEFINED;
CharSequence mClassName;
CharSequence mContentDescription;
@@ -87,7 +86,8 @@ public class AccessibilityRecord {
Parcelable mParcelableData;
final List<CharSequence> mText = new ArrayList<CharSequence>();
- IAccessibilityServiceConnection mConnection;
+
+ int mConnectionId = UNDEFINED;
/*
* Hide constructor.
@@ -108,8 +108,8 @@ public class AccessibilityRecord {
mSourceWindowId = source.getAccessibilityWindowId();
mSourceViewId = source.getAccessibilityViewId();
} else {
- mSourceWindowId = View.NO_ID;
- mSourceViewId = View.NO_ID;
+ mSourceWindowId = UNDEFINED;
+ mSourceViewId = UNDEFINED;
}
}
@@ -119,33 +119,21 @@ public class AccessibilityRecord {
* <strong>Note:</strong> It is a client responsibility to recycle the received info
* by calling {@link AccessibilityNodeInfo#recycle() AccessibilityNodeInfo#recycle()}
* to avoid creating of multiple instances.
- *
* </p>
* @return The info of the source.
*/
public AccessibilityNodeInfo getSource() {
enforceSealed();
- if (mSourceWindowId == View.NO_ID || mSourceViewId == View.NO_ID || mConnection == null) {
+ if (mConnectionId == UNDEFINED || mSourceWindowId == UNDEFINED
+ || mSourceViewId == UNDEFINED) {
return null;
}
AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
- return client.findAccessibilityNodeInfoByAccessibilityId(mConnection, mSourceWindowId,
+ return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId, mSourceWindowId,
mSourceViewId);
}
/**
- * Sets the connection for interacting with the AccessibilityManagerService.
- *
- * @param connection The connection.
- *
- * @hide
- */
- public void setConnection(IAccessibilityServiceConnection connection) {
- enforceNotSealed();
- mConnection = connection;
- }
-
- /**
* Gets the id of the window from which the event comes from.
*
* @return The window id.
@@ -561,6 +549,19 @@ public class AccessibilityRecord {
}
/**
+ * Sets the unique id of the IAccessibilityServiceConnection over which
+ * this instance can send requests to the system.
+ *
+ * @param connectionId The connection id.
+ *
+ * @hide
+ */
+ public void setConnectionId(int connectionId) {
+ enforceNotSealed();
+ mConnectionId = connectionId;
+ }
+
+ /**
* Sets if this instance is sealed.
*
* @param sealed Whether is sealed.
@@ -708,7 +709,7 @@ public class AccessibilityRecord {
mText.addAll(record.mText);
mSourceWindowId = record.mSourceWindowId;
mSourceViewId = record.mSourceViewId;
- mConnection = record.mConnection;
+ mConnectionId = record.mConnectionId;
}
/**
@@ -732,8 +733,9 @@ public class AccessibilityRecord {
mBeforeText = null;
mParcelableData = null;
mText.clear();
- mSourceViewId = View.NO_ID;
- mSourceWindowId = View.NO_ID;
+ mSourceViewId = UNDEFINED;
+ mSourceWindowId = UNDEFINED;
+ mConnectionId = UNDEFINED;
}
@Override
diff --git a/core/java/android/view/accessibility/IAccessibilityManager.aidl b/core/java/android/view/accessibility/IAccessibilityManager.aidl
index c621ff6..c3794be 100644
--- a/core/java/android/view/accessibility/IAccessibilityManager.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityManager.aidl
@@ -49,5 +49,5 @@ interface IAccessibilityManager {
void removeAccessibilityInteractionConnection(IWindow windowToken);
- IAccessibilityServiceConnection registerEventListener(IEventListener client);
+ void registerEventListener(IEventListener client);
}