Merge "Fix ConcurrentModificationException in TextServicesManagerService" into ics-mr1
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.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 @@
private AccessibilityServiceInfo mInfo;
- IAccessibilityServiceConnection mConnection;
+ private int mConnectionId;
/**
* Callback for {@link android.view.accessibility.AccessibilityEvent}s.
@@ -264,9 +265,11 @@
* 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 @@
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 @@
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 @@
*/
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/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 303f81b..0c761fc 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -175,11 +175,11 @@
// These can be accessed by multiple threads; mPackages is the lock.
// XXX For now we keep around information about all packages we have
// seen, not removing entries from this map.
- // NOTE: The activity manager in its process needs to call in to
+ // NOTE: The activity and window managers need to call in to
// ActivityThread to do things like update resource configurations,
- // which means this lock gets held while the activity manager holds its
- // own lock. Thus you MUST NEVER call back into the activity manager
- // or anything that depends on it while holding this lock.
+ // which means this lock gets held while the activity and window managers
+ // holds their own lock. Thus you MUST NEVER call back into the activity manager
+ // or window manager or anything that depends on them while holding this lock.
final HashMap<String, WeakReference<LoadedApk>> mPackages
= new HashMap<String, WeakReference<LoadedApk>>();
final HashMap<String, WeakReference<LoadedApk>> mResourcePackages
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 8ed7481..180a442 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -625,7 +625,7 @@
return info.activityInfo.loadIcon(this);
}
- throw new NameNotFoundException(intent.toURI());
+ throw new NameNotFoundException(intent.toUri(0));
}
@Override public Drawable getDefaultActivityIcon() {
@@ -728,15 +728,22 @@
private Drawable getCachedIcon(ResourceName name) {
synchronized (sSync) {
- WeakReference<Drawable> wr = sIconCache.get(name);
+ WeakReference<Drawable.ConstantState> wr = sIconCache.get(name);
if (DEBUG_ICONS) Log.v(TAG, "Get cached weak drawable ref for "
+ name + ": " + wr);
if (wr != null) { // we have the activity
- Drawable dr = wr.get();
- if (dr != null) {
- if (DEBUG_ICONS) Log.v(TAG, "Get cached drawable for "
- + name + ": " + dr);
- return dr;
+ Drawable.ConstantState state = wr.get();
+ if (state != null) {
+ if (DEBUG_ICONS) {
+ Log.v(TAG, "Get cached drawable state for " + name + ": " + state);
+ }
+ // Note: It's okay here to not use the newDrawable(Resources) variant
+ // of the API. The ConstantState comes from a drawable that was
+ // originally created by passing the proper app Resources instance
+ // which means the state should already contain the proper
+ // resources specific information (like density.) See
+ // BitmapDrawable.BitmapState for instance.
+ return state.newDrawable();
}
// our entry has been purged
sIconCache.remove(name);
@@ -747,14 +754,12 @@
private void putCachedIcon(ResourceName name, Drawable dr) {
synchronized (sSync) {
- sIconCache.put(name, new WeakReference<Drawable>(dr));
- if (DEBUG_ICONS) Log.v(TAG, "Added cached drawable for "
- + name + ": " + dr);
+ sIconCache.put(name, new WeakReference<Drawable.ConstantState>(dr.getConstantState()));
+ if (DEBUG_ICONS) Log.v(TAG, "Added cached drawable state for " + name + ": " + dr);
}
}
- static final void handlePackageBroadcast(int cmd, String[] pkgList,
- boolean hasPkgInfo) {
+ static void handlePackageBroadcast(int cmd, String[] pkgList, boolean hasPkgInfo) {
boolean immediateGc = false;
if (cmd == IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE) {
immediateGc = true;
@@ -1226,8 +1231,8 @@
private final IPackageManager mPM;
private static final Object sSync = new Object();
- private static HashMap<ResourceName, WeakReference<Drawable> > sIconCache
- = new HashMap<ResourceName, WeakReference<Drawable> >();
- private static HashMap<ResourceName, WeakReference<CharSequence> > sStringCache
- = new HashMap<ResourceName, WeakReference<CharSequence> >();
+ private static HashMap<ResourceName, WeakReference<Drawable.ConstantState>> sIconCache
+ = new HashMap<ResourceName, WeakReference<Drawable.ConstantState>>();
+ private static HashMap<ResourceName, WeakReference<CharSequence>> sStringCache
+ = new HashMap<ResourceName, WeakReference<CharSequence>>();
}
diff --git a/core/java/android/app/DatePickerDialog.java b/core/java/android/app/DatePickerDialog.java
index 8b70370..bf8fde0 100644
--- a/core/java/android/app/DatePickerDialog.java
+++ b/core/java/android/app/DatePickerDialog.java
@@ -91,13 +91,14 @@
mCallBack = callBack;
- setButton(BUTTON_POSITIVE, context.getText(R.string.date_time_set), this);
- setButton(BUTTON_NEGATIVE, context.getText(R.string.cancel), (OnClickListener) null);
+ Context themeContext = getContext();
+ setButton(BUTTON_POSITIVE, themeContext.getText(R.string.date_time_set), this);
+ setButton(BUTTON_NEGATIVE, themeContext.getText(R.string.cancel), (OnClickListener) null);
setIcon(0);
setTitle(R.string.date_picker_dialog_title);
LayoutInflater inflater =
- (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ (LayoutInflater) themeContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.date_picker_dialog, null);
setView(view);
mDatePicker = (DatePicker) view.findViewById(R.id.datePicker);
diff --git a/core/java/android/app/TimePickerDialog.java b/core/java/android/app/TimePickerDialog.java
index a990ee9..353b415 100644
--- a/core/java/android/app/TimePickerDialog.java
+++ b/core/java/android/app/TimePickerDialog.java
@@ -92,16 +92,16 @@
mInitialMinute = minute;
mIs24HourView = is24HourView;
- setCanceledOnTouchOutside(false);
setIcon(0);
setTitle(R.string.time_picker_dialog_title);
- setButton(BUTTON_POSITIVE, context.getText(R.string.date_time_set), this);
- setButton(BUTTON_NEGATIVE, context.getText(R.string.cancel),
+ Context themeContext = getContext();
+ setButton(BUTTON_POSITIVE, themeContext.getText(R.string.date_time_set), this);
+ setButton(BUTTON_NEGATIVE, themeContext.getText(R.string.cancel),
(OnClickListener) null);
LayoutInflater inflater =
- (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ (LayoutInflater) themeContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.time_picker_dialog, null);
setView(view);
mTimePicker = (TimePicker) view.findViewById(R.id.timePicker);
diff --git a/core/java/android/speech/tts/AudioPlaybackHandler.java b/core/java/android/speech/tts/AudioPlaybackHandler.java
index fd00dce..46a78dc 100644
--- a/core/java/android/speech/tts/AudioPlaybackHandler.java
+++ b/core/java/android/speech/tts/AudioPlaybackHandler.java
@@ -428,7 +428,8 @@
final AudioTrack audioTrack = params.getAudioTrack();
if (audioTrack == null) {
- params.getDispatcher().dispatchOnError();
+ // There was already a call to handleSynthesisDone for
+ // this token.
return;
}
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 @@
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 @@
}
/**
- * 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 @@
* @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 @@
* {@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.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 @@
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 @@
private final Rect mTempBounds = new Rect();
+ private final SparseArray<IAccessibilityServiceConnection> mConnectionCache =
+ new SparseArray<IAccessibilityServiceConnection>();
+
/**
* @return The singleton of this class.
*/
@@ -111,28 +122,37 @@
/**
* 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 @@
* 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 @@
* 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 @@
* 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 @@
/**
* 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 @@
* 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 @@
* 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 @@
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 @@
private static final boolean DEBUG = false;
+ private static final int UNDEFINED = -1;
+
// Actions.
/**
@@ -107,9 +108,9 @@
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 @@
private SparseIntArray mChildAccessibilityIds = new SparseIntArray();
private int mActions;
- private IAccessibilityServiceConnection mConnection;
+ private int mConnectionId = UNDEFINED;
/**
* Hide constructor from clients.
@@ -181,7 +182,7 @@
return null;
}
AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
- return client.findAccessibilityNodeInfoByAccessibilityId(mConnection,
+ return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId,
mAccessibilityWindowId, childAccessibilityViewId);
}
@@ -253,7 +254,7 @@
return false;
}
AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
- return client.performAccessibilityAction(mConnection, mAccessibilityWindowId,
+ return client.performAccessibilityAction(mConnectionId, mAccessibilityWindowId,
mAccessibilityViewId, action);
}
@@ -277,7 +278,7 @@
return Collections.emptyList();
}
AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
- return client.findAccessibilityNodeInfosByViewText(mConnection, text,
+ return client.findAccessibilityNodeInfosByViewText(mConnectionId, text,
mAccessibilityWindowId, mAccessibilityViewId);
}
@@ -297,7 +298,7 @@
return null;
}
AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
- return client.findAccessibilityNodeInfoByAccessibilityId(mConnection,
+ return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId,
mAccessibilityWindowId, mParentAccessibilityViewId);
}
@@ -755,15 +756,16 @@
}
/**
- * 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 @@
* </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 @@
*/
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 @@
* @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 @@
*/
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 @@
}
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 @@
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 @@
Parcelable mParcelableData;
final List<CharSequence> mText = new ArrayList<CharSequence>();
- IAccessibilityServiceConnection mConnection;
+
+ int mConnectionId = UNDEFINED;
/*
* Hide constructor.
@@ -108,8 +108,8 @@
mSourceWindowId = source.getAccessibilityWindowId();
mSourceViewId = source.getAccessibilityViewId();
} else {
- mSourceWindowId = View.NO_ID;
- mSourceViewId = View.NO_ID;
+ mSourceWindowId = UNDEFINED;
+ mSourceViewId = UNDEFINED;
}
}
@@ -119,33 +119,21 @@
* <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 @@
}
/**
+ * 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 @@
mText.addAll(record.mText);
mSourceWindowId = record.mSourceWindowId;
mSourceViewId = record.mSourceViewId;
- mConnection = record.mConnection;
+ mConnectionId = record.mConnectionId;
}
/**
@@ -732,8 +733,9 @@
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 @@
void removeAccessibilityInteractionConnection(IWindow windowToken);
- IAccessibilityServiceConnection registerEventListener(IEventListener client);
+ void registerEventListener(IEventListener client);
}
diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java
index 1a1b8d0..d185370 100644
--- a/core/java/android/widget/NumberPicker.java
+++ b/core/java/android/widget/NumberPicker.java
@@ -165,6 +165,11 @@
};
/**
+ * Constant for unspecified size.
+ */
+ private static final int SIZE_UNSPECIFIED = -1;
+
+ /**
* Use a custom NumberPicker formatting callback to use two-digit minutes
* strings like "01". Keeping a static formatter etc. is the most efficient
* way to do this; it avoids creating temporary objects on every call to
@@ -542,16 +547,20 @@
getResources().getDisplayMetrics());
mSelectionDividerHeight = attributesArray.getDimensionPixelSize(
R.styleable.NumberPicker_selectionDividerHeight, defSelectionDividerHeight);
- mMinHeight = attributesArray.getDimensionPixelSize(R.styleable.NumberPicker_minHeight, 0);
+ mMinHeight = attributesArray.getDimensionPixelSize(R.styleable.NumberPicker_minHeight,
+ SIZE_UNSPECIFIED);
mMaxHeight = attributesArray.getDimensionPixelSize(R.styleable.NumberPicker_maxHeight,
- Integer.MAX_VALUE);
- if (mMinHeight > mMaxHeight) {
+ SIZE_UNSPECIFIED);
+ if (mMinHeight != SIZE_UNSPECIFIED && mMaxHeight != SIZE_UNSPECIFIED
+ && mMinHeight > mMaxHeight) {
throw new IllegalArgumentException("minHeight > maxHeight");
}
- mMinWidth = attributesArray.getDimensionPixelSize(R.styleable.NumberPicker_minWidth, 0);
+ mMinWidth = attributesArray.getDimensionPixelSize(R.styleable.NumberPicker_minWidth,
+ SIZE_UNSPECIFIED);
mMaxWidth = attributesArray.getDimensionPixelSize(R.styleable.NumberPicker_maxWidth,
- Integer.MAX_VALUE);
- if (mMinWidth > mMaxWidth) {
+ SIZE_UNSPECIFIED);
+ if (mMinWidth != SIZE_UNSPECIFIED && mMaxWidth != SIZE_UNSPECIFIED
+ && mMinWidth > mMaxWidth) {
throw new IllegalArgumentException("minWidth > maxWidth");
}
mComputeMaxWidth = (mMaxWidth == Integer.MAX_VALUE);
@@ -746,10 +755,10 @@
final int newHeightMeasureSpec = makeMeasureSpec(heightMeasureSpec, mMaxHeight);
super.onMeasure(newWidthMeasureSpec, newHeightMeasureSpec);
// Flag if we are measured with width or height less than the respective min.
- final int desiredWidth = Math.max(mMinWidth, getMeasuredWidth());
- final int desiredHeight = Math.max(mMinHeight, getMeasuredHeight());
- final int widthSize = resolveSizeAndState(desiredWidth, newWidthMeasureSpec, 0);
- final int heightSize = resolveSizeAndState(desiredHeight, newHeightMeasureSpec, 0);
+ final int widthSize = resolveSizeAndStateRespectingMinSize(mMinWidth, getMeasuredWidth(),
+ widthMeasureSpec);
+ final int heightSize = resolveSizeAndStateRespectingMinSize(mMinHeight, getMeasuredHeight(),
+ heightMeasureSpec);
setMeasuredDimension(widthSize, heightSize);
}
@@ -1243,6 +1252,7 @@
}
updateInputTextView();
initializeSelectorWheelIndices();
+ tryComputeMaxWidth();
}
@Override
@@ -1368,6 +1378,9 @@
* @return A measure spec greedily imposing the max size.
*/
private int makeMeasureSpec(int measureSpec, int maxSize) {
+ if (maxSize == SIZE_UNSPECIFIED) {
+ return measureSpec;
+ }
final int size = MeasureSpec.getSize(measureSpec);
final int mode = MeasureSpec.getMode(measureSpec);
switch (mode) {
@@ -1383,6 +1396,26 @@
}
/**
+ * Utility to reconcile a desired size and state, with constraints imposed by
+ * a MeasureSpec. Tries to respect the min size, unless a different size is
+ * imposed by the constraints.
+ *
+ * @param minSize The minimal desired size.
+ * @param measuredSize The currently measured size.
+ * @param measureSpec The current measure spec.
+ * @return The resolved size and state.
+ */
+ private int resolveSizeAndStateRespectingMinSize(int minSize, int measuredSize,
+ int measureSpec) {
+ if (minSize != SIZE_UNSPECIFIED) {
+ final int desiredWidth = Math.max(minSize, measuredSize);
+ return resolveSizeAndState(desiredWidth, measureSpec, 0);
+ } else {
+ return measuredSize;
+ }
+ }
+
+ /**
* Resets the selector indices and clear the cached
* string representation of these indices.
*/
diff --git a/core/res/res/layout/date_picker.xml b/core/res/res/layout/date_picker.xml
index 6f0517d..9c1def2 100644
--- a/core/res/res/layout/date_picker.xml
+++ b/core/res/res/layout/date_picker.xml
@@ -32,7 +32,6 @@
<LinearLayout android:id="@+id/pickers"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginRight="22dip"
android:layout_weight="1"
android:orientation="horizontal"
android:gravity="center">
@@ -77,7 +76,7 @@
android:id="@+id/calendar_view"
android:layout_width="245dip"
android:layout_height="280dip"
- android:layout_marginLeft="22dip"
+ android:layout_marginLeft="44dip"
android:layout_weight="1"
android:focusable="true"
android:focusableInTouchMode="true"
diff --git a/core/tests/coretests/src/android/accessibilityservice/InterrogationActivityTest.java b/core/tests/coretests/src/android/accessibilityservice/InterrogationActivityTest.java
index 3521296..ec12124 100644
--- a/core/tests/coretests/src/android/accessibilityservice/InterrogationActivityTest.java
+++ b/core/tests/coretests/src/android/accessibilityservice/InterrogationActivityTest.java
@@ -26,6 +26,7 @@
import android.test.ActivityInstrumentationTestCase2;
import android.test.suitebuilder.annotation.LargeTest;
import android.util.Log;
+import android.view.View;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityInteractionClient;
import android.view.accessibility.AccessibilityManager;
@@ -54,28 +55,31 @@
// Timeout before give up wait for the system to process an accessibility setting change.
private static final int TIMEOUT_PROPAGATE_ACCESSIBLITY_SETTING = 2000;
+ // Timeout for the accessibility state of an Activity to be fully initialized.
+ private static final int TIMEOUT_ACCESSIBLITY_STATE_INITIALIZED_MILLIS = 100;
+
// Handle to a connection to the AccessibilityManagerService
- private static IAccessibilityServiceConnection sConnection;
+ private static int sConnectionId = View.NO_ID;
// The last received accessibility event
- private static volatile AccessibilityEvent sLastFocusAccessibilityEvent;
+ private volatile AccessibilityEvent mLastAccessibilityEvent;
public InterrogationActivityTest() {
super(InterrogationActivity.class);
}
+ @Override
+ public void setUp() throws Exception {
+ ensureConnection();
+ bringUpActivityWithInitalizedAccessbility();
+ }
+
@LargeTest
public void testFindAccessibilityNodeInfoByViewId() throws Exception {
final long startTimeMillis = SystemClock.uptimeMillis();
try {
- // hook into the system first
- IAccessibilityServiceConnection connection = getConnection();
-
- // bring up the activity
- getActivity();
-
AccessibilityNodeInfo button = AccessibilityInteractionClient.getInstance()
- .findAccessibilityNodeInfoByViewIdInActiveWindow(connection, R.id.button5);
+ .findAccessibilityNodeInfoByViewIdInActiveWindow(sConnectionId, R.id.button5);
assertNotNull(button);
assertEquals(0, button.getChildCount());
@@ -120,15 +124,9 @@
public void testFindAccessibilityNodeInfoByViewText() throws Exception {
final long startTimeMillis = SystemClock.uptimeMillis();
try {
- // hook into the system first
- IAccessibilityServiceConnection connection = getConnection();
-
- // bring up the activity
- getActivity();
-
// find a view by text
- List<AccessibilityNodeInfo> buttons = AccessibilityInteractionClient.getInstance()
- .findAccessibilityNodeInfosByViewTextInActiveWindow(connection, "butto");
+ List<AccessibilityNodeInfo> buttons = AccessibilityInteractionClient.getInstance()
+ .findAccessibilityNodeInfosByViewTextInActiveWindow(sConnectionId, "butto");
assertEquals(9, buttons.size());
} finally {
if (DEBUG) {
@@ -143,15 +141,11 @@
public void testFindAccessibilityNodeInfoByViewTextContentDescription() throws Exception {
final long startTimeMillis = SystemClock.uptimeMillis();
try {
- // hook into the system first
- IAccessibilityServiceConnection connection = getConnection();
-
- // bring up the activity
- getActivity();
+ bringUpActivityWithInitalizedAccessbility();
// find a view by text
- List<AccessibilityNodeInfo> buttons = AccessibilityInteractionClient.getInstance()
- .findAccessibilityNodeInfosByViewTextInActiveWindow(connection,
+ List<AccessibilityNodeInfo> buttons = AccessibilityInteractionClient.getInstance()
+ .findAccessibilityNodeInfosByViewTextInActiveWindow(sConnectionId,
"contentDescription");
assertEquals(1, buttons.size());
} finally {
@@ -167,12 +161,6 @@
public void testTraverseAllViews() throws Exception {
final long startTimeMillis = SystemClock.uptimeMillis();
try {
- // hook into the system first
- IAccessibilityServiceConnection connection = getConnection();
-
- // bring up the activity
- getActivity();
-
// make list of expected nodes
List<String> classNameAndTextList = new ArrayList<String>();
classNameAndTextList.add("android.widget.LinearLayout");
@@ -190,7 +178,7 @@
classNameAndTextList.add("android.widget.ButtonButton9");
AccessibilityNodeInfo root = AccessibilityInteractionClient.getInstance()
- .findAccessibilityNodeInfoByViewIdInActiveWindow(connection, R.id.root);
+ .findAccessibilityNodeInfoByViewIdInActiveWindow(sConnectionId, R.id.root);
assertNotNull("We must find the existing root.", root);
Queue<AccessibilityNodeInfo> fringe = new LinkedList<AccessibilityNodeInfo>();
@@ -227,23 +215,17 @@
public void testPerformAccessibilityActionFocus() throws Exception {
final long startTimeMillis = SystemClock.uptimeMillis();
try {
- // hook into the system first
- IAccessibilityServiceConnection connection = getConnection();
-
- // bring up the activity
- getActivity();
-
// find a view and make sure it is not focused
AccessibilityNodeInfo button = AccessibilityInteractionClient.getInstance()
- .findAccessibilityNodeInfoByViewIdInActiveWindow(connection, R.id.button5);
+ .findAccessibilityNodeInfoByViewIdInActiveWindow(sConnectionId, R.id.button5);
assertFalse(button.isFocused());
// focus the view
assertTrue(button.performAction(ACTION_FOCUS));
// find the view again and make sure it is focused
- button = AccessibilityInteractionClient.getInstance()
- .findAccessibilityNodeInfoByViewIdInActiveWindow(connection, R.id.button5);
+ button = AccessibilityInteractionClient.getInstance()
+ .findAccessibilityNodeInfoByViewIdInActiveWindow(sConnectionId, R.id.button5);
assertTrue(button.isFocused());
} finally {
if (DEBUG) {
@@ -257,15 +239,9 @@
public void testPerformAccessibilityActionClearFocus() throws Exception {
final long startTimeMillis = SystemClock.uptimeMillis();
try {
- // hook into the system first
- IAccessibilityServiceConnection connection = getConnection();
-
- // bring up the activity
- getActivity();
-
// find a view and make sure it is not focused
AccessibilityNodeInfo button = AccessibilityInteractionClient.getInstance()
- .findAccessibilityNodeInfoByViewIdInActiveWindow(connection, R.id.button5);
+ .findAccessibilityNodeInfoByViewIdInActiveWindow(sConnectionId, R.id.button5);
assertFalse(button.isFocused());
// focus the view
@@ -273,7 +249,7 @@
// find the view again and make sure it is focused
button = AccessibilityInteractionClient.getInstance()
- .findAccessibilityNodeInfoByViewIdInActiveWindow(connection, R.id.button5);
+ .findAccessibilityNodeInfoByViewIdInActiveWindow(sConnectionId, R.id.button5);
assertTrue(button.isFocused());
// unfocus the view
@@ -281,7 +257,7 @@
// find the view again and make sure it is not focused
button = AccessibilityInteractionClient.getInstance()
- .findAccessibilityNodeInfoByViewIdInActiveWindow(connection, R.id.button5);
+ .findAccessibilityNodeInfoByViewIdInActiveWindow(sConnectionId, R.id.button5);
assertFalse(button.isFocused());
} finally {
if (DEBUG) {
@@ -296,15 +272,9 @@
public void testPerformAccessibilityActionSelect() throws Exception {
final long startTimeMillis = SystemClock.uptimeMillis();
try {
- // hook into the system first
- IAccessibilityServiceConnection connection = getConnection();
-
- // bring up the activity
- getActivity();
-
// find a view and make sure it is not selected
AccessibilityNodeInfo button = AccessibilityInteractionClient.getInstance()
- .findAccessibilityNodeInfoByViewIdInActiveWindow(connection, R.id.button5);
+ .findAccessibilityNodeInfoByViewIdInActiveWindow(sConnectionId, R.id.button5);
assertFalse(button.isSelected());
// select the view
@@ -312,7 +282,7 @@
// find the view again and make sure it is selected
button = AccessibilityInteractionClient.getInstance()
- .findAccessibilityNodeInfoByViewIdInActiveWindow(connection, R.id.button5);
+ .findAccessibilityNodeInfoByViewIdInActiveWindow(sConnectionId, R.id.button5);
assertTrue(button.isSelected());
} finally {
if (DEBUG) {
@@ -326,15 +296,9 @@
public void testPerformAccessibilityActionClearSelection() throws Exception {
final long startTimeMillis = SystemClock.uptimeMillis();
try {
- // hook into the system first
- IAccessibilityServiceConnection connection = getConnection();
-
- // bring up the activity
- getActivity();
-
// find a view and make sure it is not selected
AccessibilityNodeInfo button = AccessibilityInteractionClient.getInstance()
- .findAccessibilityNodeInfoByViewIdInActiveWindow(connection, R.id.button5);
+ .findAccessibilityNodeInfoByViewIdInActiveWindow(sConnectionId, R.id.button5);
assertFalse(button.isSelected());
// select the view
@@ -342,15 +306,15 @@
// find the view again and make sure it is selected
button = AccessibilityInteractionClient.getInstance()
- .findAccessibilityNodeInfoByViewIdInActiveWindow(connection, R.id.button5);
+ .findAccessibilityNodeInfoByViewIdInActiveWindow(sConnectionId, R.id.button5);
assertTrue(button.isSelected());
// unselect the view
assertTrue(button.performAction(ACTION_CLEAR_SELECTION));
// find the view again and make sure it is not selected
- button = AccessibilityInteractionClient.getInstance()
- .findAccessibilityNodeInfoByViewIdInActiveWindow(connection, R.id.button5);
+ button = AccessibilityInteractionClient.getInstance()
+ .findAccessibilityNodeInfoByViewIdInActiveWindow(sConnectionId, R.id.button5);
assertFalse(button.isSelected());
} finally {
if (DEBUG) {
@@ -365,30 +329,24 @@
public void testAccessibilityEventGetSource() throws Exception {
final long startTimeMillis = SystemClock.uptimeMillis();
try {
- // hook into the system first
- IAccessibilityServiceConnection connection = getConnection();
-
- // bring up the activity
- getActivity();
-
// find a view and make sure it is not focused
AccessibilityNodeInfo button = AccessibilityInteractionClient.getInstance()
- .findAccessibilityNodeInfoByViewIdInActiveWindow(connection, R.id.button5);
+ .findAccessibilityNodeInfoByViewIdInActiveWindow(sConnectionId, R.id.button5);
assertFalse(button.isSelected());
// focus the view
assertTrue(button.performAction(ACTION_FOCUS));
- synchronized (sConnection) {
+ synchronized (this) {
try {
- sConnection.wait(500);
+ wait(TIMEOUT_ACCESSIBLITY_STATE_INITIALIZED_MILLIS);
} catch (InterruptedException ie) {
/* ignore */
}
}
// check that last event source
- AccessibilityNodeInfo source = sLastFocusAccessibilityEvent.getSource();
+ AccessibilityNodeInfo source = mLastAccessibilityEvent.getSource();
assertNotNull(source);
// bounds
@@ -430,15 +388,9 @@
public void testObjectContract() throws Exception {
final long startTimeMillis = SystemClock.uptimeMillis();
try {
- // hook into the system first
- IAccessibilityServiceConnection connection = getConnection();
-
- // bring up the activity
- getActivity();
-
// find a view and make sure it is not focused
AccessibilityNodeInfo button = AccessibilityInteractionClient.getInstance()
- .findAccessibilityNodeInfoByViewIdInActiveWindow(connection, R.id.button5);
+ .findAccessibilityNodeInfoByViewIdInActiveWindow(sConnectionId, R.id.button5);
AccessibilityNodeInfo parent = button.getParent();
final int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
@@ -459,24 +411,57 @@
}
}
- @Override
- protected void scrubClass(Class<?> testCaseClass) {
- /* intentionally do not scrub */
+ private void bringUpActivityWithInitalizedAccessbility() {
+ mLastAccessibilityEvent = null;
+ // bring up the activity
+ getActivity();
+
+ final long startTimeMillis = SystemClock.uptimeMillis();
+ while (true) {
+ if (mLastAccessibilityEvent != null) {
+ final int eventType = mLastAccessibilityEvent.getEventType();
+ if (eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
+ return;
+ }
+ }
+ final long remainingTimeMillis = TIMEOUT_ACCESSIBLITY_STATE_INITIALIZED_MILLIS
+ - (SystemClock.uptimeMillis() - startTimeMillis);
+ if (remainingTimeMillis <= 0) {
+ return;
+ }
+ synchronized (this) {
+ try {
+ wait(remainingTimeMillis);
+ } catch (InterruptedException e) {
+ /* ignore */
+ }
+ }
+ }
}
- private IAccessibilityServiceConnection getConnection() throws Exception {
- if (sConnection == null) {
+ private void ensureConnection() throws Exception {
+ if (sConnectionId == View.NO_ID) {
IEventListener listener = new IEventListener.Stub() {
- public void setConnection(IAccessibilityServiceConnection connection) {}
+ public void setConnection(IAccessibilityServiceConnection connection,
+ int connectionId) {
+ sConnectionId = connectionId;
+ if (connection != null) {
+ AccessibilityInteractionClient.getInstance().addConnection(connectionId,
+ connection);
+ } else {
+ AccessibilityInteractionClient.getInstance().removeConnection(connectionId);
+ }
+ synchronized (this) {
+ notifyAll();
+ }
+ }
public void onInterrupt() {}
public void onAccessibilityEvent(AccessibilityEvent event) {
- if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_FOCUSED) {
- sLastFocusAccessibilityEvent = AccessibilityEvent.obtain(event);
- }
- synchronized (sConnection) {
- sConnection.notifyAll();
+ mLastAccessibilityEvent = AccessibilityEvent.obtain(event);
+ synchronized (this) {
+ notifyAll();
}
}
};
@@ -485,28 +470,11 @@
AccessibilityManager.getInstance(getInstrumentation().getContext());
synchronized (this) {
- if (!accessibilityManager.isEnabled()) {
- // Make sure we wake ourselves as the desired state is propagated.
- accessibilityManager.addAccessibilityStateChangeListener(
- new AccessibilityManager.AccessibilityStateChangeListener() {
- public void onAccessibilityStateChanged(boolean enabled) {
- synchronized (this) {
- notifyAll();
- }
- }
- });
- IAccessibilityManager manager = IAccessibilityManager.Stub.asInterface(
+ IAccessibilityManager manager = IAccessibilityManager.Stub.asInterface(
ServiceManager.getService(Context.ACCESSIBILITY_SERVICE));
- sConnection = manager.registerEventListener(listener);
-
- wait(TIMEOUT_PROPAGATE_ACCESSIBLITY_SETTING);
- } else {
- IAccessibilityManager manager = IAccessibilityManager.Stub.asInterface(
- ServiceManager.getService(Context.ACCESSIBILITY_SERVICE));
- sConnection = manager.registerEventListener(listener);
- }
+ manager.registerEventListener(listener);
+ wait(TIMEOUT_PROPAGATE_ACCESSIBLITY_SETTING);
}
}
- return sConnection;
}
}
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index a63d5b0..2b0ed5d 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -49,6 +49,8 @@
// ----------------------------------------------------------------------------
+#define EGL_VERSION_HW_ANDROID 0x3143
+
struct extention_map_t {
const char* name;
__eglMustCastToProperFunctionPointerType address;
@@ -972,6 +974,12 @@
return dp->getExtensionString();
case EGL_CLIENT_APIS:
return dp->getClientApiString();
+ case EGL_VERSION_HW_ANDROID: {
+ if (gEGLImpl[IMPL_HARDWARE].dso) {
+ return dp->disp[IMPL_HARDWARE].queryString.version;
+ }
+ return dp->disp[IMPL_SOFTWARE].queryString.version;
+ }
}
return setError(EGL_BAD_PARAMETER, (const char *)0);
}
diff --git a/opengl/specs/README b/opengl/specs/README
index 2fa2587..16b278f 100644
--- a/opengl/specs/README
+++ b/opengl/specs/README
@@ -9,4 +9,5 @@
0x3140 EGL_ANDROID_image_native_buffer
0x3141 (unused)
0x3142 EGL_ANDROID_recordable
-0x3143 - 0x314F (unused)
+0x3143 EGL_VERSION_HW_ANDROID (internal use)
+0x3144 - 0x314F (unused)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
index 55a5b0a..135a04c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -898,7 +898,7 @@
combinedSignalIconId = mDataSignalIconId; // set by updateDataIcon()
mContentDescriptionCombinedSignal = mContentDescriptionDataType;
}
-
+
if (mWifiConnected) {
if (mWifiSsid == null) {
label = context.getString(R.string.status_bar_settings_signal_meter_wifi_nossid);
@@ -932,19 +932,23 @@
mContentDescriptionCombinedSignal = mContext.getString(
R.string.accessibility_bluetooth_tether);
}
-
+
if (mAirplaneMode &&
(mServiceState == null || (!hasService() && !mServiceState.isEmergencyOnly()))) {
// Only display the flight-mode icon if not in "emergency calls only" mode.
- label = context.getString(R.string.status_bar_settings_signal_meter_disconnected);
- mContentDescriptionCombinedSignal = mContentDescriptionPhoneSignal
- = mContext.getString(R.string.accessibility_airplane_mode);
-
+
// look again; your radios are now airplanes
+ mContentDescriptionPhoneSignal = mContext.getString(
+ R.string.accessibility_airplane_mode);
mPhoneSignalIconId = mDataSignalIconId = R.drawable.stat_sys_signal_flightmode;
mDataTypeIconId = 0;
- combinedSignalIconId = mDataSignalIconId;
+ // combined values from connected wifi take precedence over airplane mode
+ if (!mWifiConnected) {
+ label = context.getString(R.string.status_bar_settings_signal_meter_disconnected);
+ mContentDescriptionCombinedSignal = mContentDescriptionPhoneSignal;
+ combinedSignalIconId = mDataSignalIconId;
+ }
}
else if (!mDataConnected && !mWifiConnected && !mBluetoothTethered && !mWimaxConnected) {
// pretty much totally disconnected
diff --git a/services/java/com/android/server/EventLogTags.logtags b/services/java/com/android/server/EventLogTags.logtags
index 5408436..4dad209 100644
--- a/services/java/com/android/server/EventLogTags.logtags
+++ b/services/java/com/android/server/EventLogTags.logtags
@@ -50,12 +50,12 @@
# NotificationManagerService.java
# ---------------------------
# when a NotificationManager.notify is called
-2750 notification_enqueue (pkg|3),(id|1|5),(notification|3)
+2750 notification_enqueue (pkg|3),(id|1|5),(tag|3),(notification|3)
# when someone tries to cancel a notification, the notification manager sometimes
# calls this with flags too
-2751 notification_cancel (pkg|3),(id|1|5),(required_flags|1)
+2751 notification_cancel (pkg|3),(id|1|5),(tag|3),(required_flags|1),(forbidden_flags|1)
# when someone tries to cancel all of the notifications for a particular package
-2752 notification_cancel_all (pkg|3),(required_flags|1)
+2752 notification_cancel_all (pkg|3),(required_flags|1),(forbidden_flags|1)
# ---------------------------
diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java
index 7d1d976..5039294 100755
--- a/services/java/com/android/server/NotificationManagerService.java
+++ b/services/java/com/android/server/NotificationManagerService.java
@@ -707,7 +707,8 @@
// behalf of the download manager without affecting other apps.
if (!pkg.equals("com.android.providers.downloads")
|| Log.isLoggable("DownloadManager", Log.VERBOSE)) {
- EventLog.writeEvent(EventLogTags.NOTIFICATION_ENQUEUE, pkg, id, notification.toString());
+ EventLog.writeEvent(EventLogTags.NOTIFICATION_ENQUEUE, pkg, id, tag,
+ notification.toString());
}
if (pkg == null || notification == null) {
@@ -944,7 +945,8 @@
*/
private void cancelNotification(String pkg, String tag, int id, int mustHaveFlags,
int mustNotHaveFlags, boolean sendDelete) {
- EventLog.writeEvent(EventLogTags.NOTIFICATION_CANCEL, pkg, id, mustHaveFlags);
+ EventLog.writeEvent(EventLogTags.NOTIFICATION_CANCEL, pkg, id, tag,
+ mustHaveFlags, mustNotHaveFlags);
synchronized (mNotificationList) {
int index = indexOfNotificationLocked(pkg, tag, id);
@@ -972,7 +974,8 @@
*/
boolean cancelAllNotificationsInt(String pkg, int mustHaveFlags,
int mustNotHaveFlags, boolean doit) {
- EventLog.writeEvent(EventLogTags.NOTIFICATION_CANCEL_ALL, pkg, mustHaveFlags);
+ EventLog.writeEvent(EventLogTags.NOTIFICATION_CANCEL_ALL, pkg, mustHaveFlags,
+ mustNotHaveFlags);
synchronized (mNotificationList) {
final int N = mNotificationList.size();
diff --git a/services/java/com/android/server/WallpaperManagerService.java b/services/java/com/android/server/WallpaperManagerService.java
index 7fa404e..4925a4e 100644
--- a/services/java/com/android/server/WallpaperManagerService.java
+++ b/services/java/com/android/server/WallpaperManagerService.java
@@ -476,6 +476,13 @@
ParcelFileDescriptor updateWallpaperBitmapLocked(String name) {
if (name == null) name = "";
try {
+ if (!WALLPAPER_DIR.exists()) {
+ WALLPAPER_DIR.mkdir();
+ FileUtils.setPermissions(
+ WALLPAPER_DIR.getPath(),
+ FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
+ -1, -1);
+ }
ParcelFileDescriptor fd = ParcelFileDescriptor.open(WALLPAPER_FILE,
MODE_CREATE|MODE_READ_WRITE);
mName = name;
diff --git a/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
index fd528cc..b70ed96 100644
--- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -115,8 +115,8 @@
private final Set<ComponentName> mEnabledServices = new HashSet<ComponentName>();
- private final SparseArray<IAccessibilityInteractionConnection> mWindowIdToInteractionConnectionMap =
- new SparseArray<IAccessibilityInteractionConnection>();
+ private final SparseArray<AccessibilityConnectionWrapper> mWindowIdToInteractionConnectionWrapperMap =
+ new SparseArray<AccessibilityConnectionWrapper>();
private final SparseArray<IBinder> mWindowIdToWindowTokenMap = new SparseArray<IBinder>();
@@ -439,16 +439,11 @@
final IWindow addedWindowToken = windowToken;
final IAccessibilityInteractionConnection addedConnection = connection;
final int windowId = sNextWindowId++;
- addedConnection.asBinder().linkToDeath(new DeathRecipient() {
- public void binderDied() {
- synchronized (mLock) {
- addedConnection.asBinder().unlinkToDeath(this, 0);
- removeAccessibilityInteractionConnection(addedWindowToken);
- }
- }
- }, 0);
+ AccessibilityConnectionWrapper wrapper = new AccessibilityConnectionWrapper(windowId,
+ connection);
+ wrapper.linkToDeath();
mWindowIdToWindowTokenMap.put(windowId, addedWindowToken.asBinder());
- mWindowIdToInteractionConnectionMap.put(windowId, connection);
+ mWindowIdToInteractionConnectionWrapperMap.put(windowId, wrapper);
if (DEBUG) {
Slog.i(LOG_TAG, "Adding interaction connection to windowId: " + windowId);
}
@@ -462,18 +457,17 @@
for (int i = 0; i < count; i++) {
if (mWindowIdToWindowTokenMap.valueAt(i) == windowToken.asBinder()) {
final int windowId = mWindowIdToWindowTokenMap.keyAt(i);
- mWindowIdToWindowTokenMap.remove(windowId);
- mWindowIdToInteractionConnectionMap.remove(windowId);
- if (DEBUG) {
- Slog.i(LOG_TAG, "Removing interaction connection to windowId: " + windowId);
- }
+ AccessibilityConnectionWrapper wrapper =
+ mWindowIdToInteractionConnectionWrapperMap.get(windowId);
+ wrapper.unlinkToDeath();
+ removeAccessibilityInteractionConnectionLocked(windowId);
return;
}
}
}
}
- public IAccessibilityServiceConnection registerEventListener(IEventListener listener) {
+ public void registerEventListener(IEventListener listener) {
mSecurityPolicy.enforceCallingPermission(Manifest.permission.RETRIEVE_WINDOW_CONTENT,
FUNCTION_REGISTER_EVENT_LISTENER);
ComponentName componentName = new ComponentName("foo.bar",
@@ -501,7 +495,19 @@
accessibilityServiceInfo.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC;
Service service = new Service(componentName, accessibilityServiceInfo, true);
service.onServiceConnected(componentName, listener.asBinder());
- return service;
+ }
+
+ /**
+ * Removes an AccessibilityInteractionConnection.
+ *
+ * @param windowId The id of the window to which the connection is targeted.
+ */
+ private void removeAccessibilityInteractionConnectionLocked(int windowId) {
+ mWindowIdToWindowTokenMap.remove(windowId);
+ mWindowIdToInteractionConnectionWrapperMap.remove(windowId);
+ if (DEBUG) {
+ Slog.i(LOG_TAG, "Removing interaction connection to windowId: " + windowId);
+ }
}
/**
@@ -594,6 +600,13 @@
*/
private void notifyEventListenerLocked(Service service, int eventType) {
IEventListener listener = service.mServiceInterface;
+
+ // If the service died/was disabled while the message for dispatching
+ // the accessibility event was propagating the listener may be null.
+ if (listener == null) {
+ return;
+ }
+
AccessibilityEvent event = service.mPendingEvents.get(eventType);
// Check for null here because there is a concurrent scenario in which this
@@ -618,7 +631,7 @@
service.mPendingEvents.remove(eventType);
try {
if (mSecurityPolicy.canRetrieveWindowContent(service)) {
- event.setConnection(service);
+ event.setConnectionId(service.mId);
} else {
event.setSource(null);
}
@@ -666,6 +679,7 @@
mComponentNameToServiceMap.remove(service.mComponentName);
mHandler.removeMessages(service.mId);
service.unlinkToOwnDeath();
+ service.dispose();
updateInputFilterLocked();
return removed;
}
@@ -895,6 +909,33 @@
sendStateToClientsLocked();
}
+ private class AccessibilityConnectionWrapper implements DeathRecipient {
+ private final int mWindowId;
+ private final IAccessibilityInteractionConnection mConnection;
+
+ public AccessibilityConnectionWrapper(int windowId,
+ IAccessibilityInteractionConnection connection) {
+ mWindowId = windowId;
+ mConnection = connection;
+ }
+
+ public void linkToDeath() throws RemoteException {
+ mConnection.asBinder().linkToDeath(this, 0);
+ }
+
+ public void unlinkToDeath() {
+ mConnection.asBinder().unlinkToDeath(this, 0);
+ }
+
+ @Override
+ public void binderDied() {
+ unlinkToDeath();
+ synchronized (mLock) {
+ removeAccessibilityInteractionConnectionLocked(mWindowId);
+ }
+ }
+ }
+
/**
* This class represents an accessibility service. It stores all per service
* data required for the service management, provides API for starting/stopping the
@@ -997,7 +1038,6 @@
if (!mIsAutomation) {
mContext.unbindService(this);
}
- mService = null;
return true;
}
return false;
@@ -1021,7 +1061,7 @@
mService = service;
mServiceInterface = IEventListener.Stub.asInterface(service);
try {
- mServiceInterface.setConnection(this);
+ mServiceInterface.setConnection(this, mId);
synchronized (mLock) {
tryAddServiceLocked(this);
}
@@ -1123,14 +1163,16 @@
if (!permissionGranted) {
return 0;
} else {
- connection = mWindowIdToInteractionConnectionMap.get(accessibilityWindowId);
- if (connection == null) {
+ AccessibilityConnectionWrapper wrapper =
+ mWindowIdToInteractionConnectionWrapperMap.get(accessibilityWindowId);
+ if (wrapper == null) {
if (DEBUG) {
Slog.e(LOG_TAG, "No interaction connection to window: "
+ accessibilityWindowId);
}
return 0;
}
+ connection = wrapper.mConnection;
}
}
final int interrogatingPid = Binder.getCallingPid();
@@ -1159,14 +1201,16 @@
if (!permissionGranted) {
return false;
} else {
- connection = mWindowIdToInteractionConnectionMap.get(accessibilityWindowId);
- if (connection == null) {
+ AccessibilityConnectionWrapper wrapper =
+ mWindowIdToInteractionConnectionWrapperMap.get(accessibilityWindowId);
+ if (wrapper == null) {
if (DEBUG) {
Slog.e(LOG_TAG, "No interaction connection to window: "
+ accessibilityWindowId);
}
return false;
}
+ connection = wrapper.mConnection;
}
}
final int interrogatingPid = Binder.getCallingPid();
@@ -1197,9 +1241,21 @@
mService.unlinkToDeath(this, 0);
}
+ public void dispose() {
+ try {
+ // Clear the proxy in the other process so this
+ // IAccessibilityServiceConnection can be garbage collected.
+ mServiceInterface.setConnection(null, mId);
+ } catch (RemoteException re) {
+ /* ignore */
+ }
+ mService = null;
+ mServiceInterface = null;
+ }
+
public void binderDied() {
synchronized (mLock) {
- mService.unlinkToDeath(this, 0);
+ unlinkToOwnDeath();
tryRemoveServiceLocked(this);
// We no longer have an automation service, so restore
// the state based on values in the settings database.
@@ -1214,7 +1270,9 @@
if (DEBUG) {
Slog.i(LOG_TAG, "Trying to get interaction connection to windowId: " + windowId);
}
- return mWindowIdToInteractionConnectionMap.get(windowId);
+ AccessibilityConnectionWrapper wrapper =
+ mWindowIdToInteractionConnectionWrapperMap.get(windowId);
+ return (wrapper != null) ? wrapper.mConnection : null;
}
private float getCompatibilityScale(int windowId) {
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 367844d..b36ba3a 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -14249,7 +14249,7 @@
if (app.curAdj != app.setAdj) {
if (Process.setOomAdj(app.pid, app.curAdj)) {
- if (true || DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
+ if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
TAG, "Set " + app.pid + " " + app.processName +
" adj " + app.curAdj + ": " + app.adjType);
app.setAdj = app.curAdj;
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 769e6cf..f5c2de9 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -429,6 +429,18 @@
boolean mSystemBooted = false;
boolean mForceDisplayEnabled = false;
boolean mShowingBootMessages = false;
+
+ // This protects the following display size properties, so that
+ // getDisplaySize() doesn't need to acquire the global lock. This is
+ // needed because the window manager sometimes needs to use ActivityThread
+ // while it has its global state locked (for example to load animation
+ // resources), but the ActivityThread also needs get the current display
+ // size sometimes when it has its package lock held.
+ //
+ // These will only be modified with both mWindowMap and mDisplaySizeLock
+ // held (in that order) so the window manager doesn't need to acquire this
+ // lock when needing these values in its normal operation.
+ final Object mDisplaySizeLock = new Object();
int mInitialDisplayWidth = 0;
int mInitialDisplayHeight = 0;
int mBaseDisplayWidth = 0;
@@ -437,6 +449,7 @@
int mCurDisplayHeight = 0;
int mAppDisplayWidth = 0;
int mAppDisplayHeight = 0;
+
int mRotation = 0;
int mForcedAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
boolean mAltOrientation = false;
@@ -6006,25 +6019,27 @@
final int realdw = rotated ? mBaseDisplayHeight : mBaseDisplayWidth;
final int realdh = rotated ? mBaseDisplayWidth : mBaseDisplayHeight;
- if (mAltOrientation) {
- mCurDisplayWidth = realdw;
- mCurDisplayHeight = realdh;
- if (realdw > realdh) {
- // Turn landscape into portrait.
- int maxw = (int)(realdh/1.3f);
- if (maxw < realdw) {
- mCurDisplayWidth = maxw;
+ synchronized(mDisplaySizeLock) {
+ if (mAltOrientation) {
+ mCurDisplayWidth = realdw;
+ mCurDisplayHeight = realdh;
+ if (realdw > realdh) {
+ // Turn landscape into portrait.
+ int maxw = (int)(realdh/1.3f);
+ if (maxw < realdw) {
+ mCurDisplayWidth = maxw;
+ }
+ } else {
+ // Turn portrait into landscape.
+ int maxh = (int)(realdw/1.3f);
+ if (maxh < realdh) {
+ mCurDisplayHeight = maxh;
+ }
}
} else {
- // Turn portrait into landscape.
- int maxh = (int)(realdw/1.3f);
- if (maxh < realdh) {
- mCurDisplayHeight = maxh;
- }
+ mCurDisplayWidth = realdw;
+ mCurDisplayHeight = realdh;
}
- } else {
- mCurDisplayWidth = realdw;
- mCurDisplayHeight = realdh;
}
final int dw = mCurDisplayWidth;
@@ -6043,8 +6058,12 @@
// Update application display metrics.
final DisplayMetrics dm = mDisplayMetrics;
- mAppDisplayWidth = mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation);
- mAppDisplayHeight = mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation);
+ final int appWidth = mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation);
+ final int appHeight = mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation);
+ synchronized(mDisplaySizeLock) {
+ mAppDisplayWidth = appWidth;
+ mAppDisplayHeight = appHeight;
+ }
if (false) {
Slog.i(TAG, "Set app display size: " + mAppDisplayWidth
+ " x " + mAppDisplayHeight);
@@ -6414,18 +6433,20 @@
}
WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
mDisplay = wm.getDefaultDisplay();
- mInitialDisplayWidth = mDisplay.getRawWidth();
- mInitialDisplayHeight = mDisplay.getRawHeight();
- int rot = mDisplay.getRotation();
- if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) {
- // If the screen is currently rotated, we need to swap the
- // initial width and height to get the true natural values.
- int tmp = mInitialDisplayWidth;
- mInitialDisplayWidth = mInitialDisplayHeight;
- mInitialDisplayHeight = tmp;
+ synchronized(mDisplaySizeLock) {
+ mInitialDisplayWidth = mDisplay.getRawWidth();
+ mInitialDisplayHeight = mDisplay.getRawHeight();
+ int rot = mDisplay.getRotation();
+ if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) {
+ // If the screen is currently rotated, we need to swap the
+ // initial width and height to get the true natural values.
+ int tmp = mInitialDisplayWidth;
+ mInitialDisplayWidth = mInitialDisplayHeight;
+ mInitialDisplayHeight = tmp;
+ }
+ mBaseDisplayWidth = mCurDisplayWidth = mAppDisplayWidth = mInitialDisplayWidth;
+ mBaseDisplayHeight = mCurDisplayHeight = mAppDisplayHeight = mInitialDisplayHeight;
}
- mBaseDisplayWidth = mCurDisplayWidth = mAppDisplayWidth = mInitialDisplayWidth;
- mBaseDisplayHeight = mCurDisplayHeight = mAppDisplayHeight = mInitialDisplayHeight;
mInputManager.setDisplaySize(Display.DEFAULT_DISPLAY,
mDisplay.getRawWidth(), mDisplay.getRawHeight(),
mDisplay.getRawExternalWidth(), mDisplay.getRawExternalHeight());
@@ -6963,28 +6984,28 @@
}
public void getDisplaySize(Point size) {
- synchronized(mWindowMap) {
+ synchronized(mDisplaySizeLock) {
size.x = mAppDisplayWidth;
size.y = mAppDisplayHeight;
}
}
public void getRealDisplaySize(Point size) {
- synchronized(mWindowMap) {
+ synchronized(mDisplaySizeLock) {
size.x = mCurDisplayWidth;
size.y = mCurDisplayHeight;
}
}
public void getInitialDisplaySize(Point size) {
- synchronized(mWindowMap) {
+ synchronized(mDisplaySizeLock) {
size.x = mInitialDisplayWidth;
size.y = mInitialDisplayHeight;
}
}
public int getMaximumSizeDimension() {
- synchronized(mWindowMap) {
+ synchronized(mDisplaySizeLock) {
// Do this based on the raw screen size, until we are smarter.
return mBaseDisplayWidth > mBaseDisplayHeight
? mBaseDisplayWidth : mBaseDisplayHeight;
@@ -7077,8 +7098,10 @@
private void setForcedDisplaySizeLocked(int width, int height) {
Slog.i(TAG, "Using new display size: " + width + "x" + height);
- mBaseDisplayWidth = width;
- mBaseDisplayHeight = height;
+ synchronized(mDisplaySizeLock) {
+ mBaseDisplayWidth = width;
+ mBaseDisplayHeight = height;
+ }
mPolicy.setInitialDisplaySize(mBaseDisplayWidth, mBaseDisplayHeight);
mLayoutNeeded = true;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 1b00e93..f38e948 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -65,6 +65,8 @@
#define AID_GRAPHICS 1003
#endif
+#define EGL_VERSION_HW_ANDROID 0x3143
+
#define DISPLAY_COUNT 1
namespace android {
@@ -1527,7 +1529,7 @@
* Dump the layers in the purgatory
*/
- const size_t purgatorySize = mLayerPurgatory.size();
+ const size_t purgatorySize = mLayerPurgatory.size();
snprintf(buffer, SIZE, "Purgatory state (%d entries)\n", purgatorySize);
result.append(buffer);
for (size_t i=0 ; i<purgatorySize ; i++) {
@@ -1548,6 +1550,12 @@
extensions.getRenderer(),
extensions.getVersion());
result.append(buffer);
+
+ snprintf(buffer, SIZE, "EGL : %s\n",
+ eglQueryString(graphicPlane(0).getEGLDisplay(),
+ EGL_VERSION_HW_ANDROID));
+ result.append(buffer);
+
snprintf(buffer, SIZE, "EXTS: %s\n", extensions.getExtension());
result.append(buffer);