Merge "Touch exploration feature, event bubling, refactor"

This commit is contained in:
Svetoslav Ganov
2011-04-22 16:29:07 -07:00
committed by Android (Google) Code Review
25 changed files with 2529 additions and 488 deletions

View File

@@ -20,8 +20,8 @@ import com.android.server.wm.InputFilter;
import android.content.Context;
import android.util.Slog;
import android.view.InputDevice;
import android.view.InputEvent;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.WindowManagerPolicy;
@@ -32,10 +32,35 @@ import android.view.WindowManagerPolicy;
*/
public class AccessibilityInputFilter extends InputFilter {
private static final String TAG = "AccessibilityInputFilter";
private static final boolean DEBUG = true;
private static final boolean DEBUG = false;
private final Context mContext;
/**
* This is an interface for explorers that take a {@link MotionEvent}
* stream and perform touch exploration of the screen content.
*/
public interface Explorer {
/**
* Handles a {@link MotionEvent}.
*
* @param event The event to handle.
* @param policyFlags The policy flags associated with the event.
*/
public void onMotionEvent(MotionEvent event, int policyFlags);
/**
* Requests that the explorer clears its internal state.
*
* @param event The last received event.
* @param policyFlags The policy flags associated with the event.
*/
public void clear(MotionEvent event, int policyFlags);
}
private TouchExplorer mTouchExplorer;
private int mTouchscreenSourceDeviceId;
public AccessibilityInputFilter(Context context) {
super(context.getMainLooper());
mContext = context;
@@ -60,27 +85,27 @@ public class AccessibilityInputFilter extends InputFilter {
@Override
public void onInputEvent(InputEvent event, int policyFlags) {
if (DEBUG) {
Slog.d(TAG, "Accessibility input filter received input event: "
+ event + ", policyFlags=0x" + Integer.toHexString(policyFlags));
Slog.d(TAG, "Received event: " + event + ", policyFlags=0x"
+ Integer.toHexString(policyFlags));
}
// To prove that this is working as intended, we will silently transform
// Q key presses into non-repeating Z's as part of this stub implementation.
// TODO: Replace with the real thing.
if (event instanceof KeyEvent) {
final KeyEvent keyEvent = (KeyEvent)event;
if (keyEvent.getKeyCode() == KeyEvent.KEYCODE_Q) {
if (keyEvent.getRepeatCount() == 0) {
sendInputEvent(new KeyEvent(keyEvent.getDownTime(), keyEvent.getEventTime(),
keyEvent.getAction(), KeyEvent.KEYCODE_Z, keyEvent.getRepeatCount(),
keyEvent.getMetaState(), keyEvent.getDeviceId(), keyEvent.getScanCode(),
keyEvent.getFlags(), keyEvent.getSource()),
policyFlags | WindowManagerPolicy.FLAG_DISABLE_KEY_REPEAT);
if (event.getSource() == InputDevice.SOURCE_TOUCHSCREEN) {
MotionEvent motionEvent = (MotionEvent) event;
int deviceId = event.getDeviceId();
if (mTouchscreenSourceDeviceId != deviceId) {
mTouchscreenSourceDeviceId = deviceId;
if (mTouchExplorer != null) {
mTouchExplorer.clear(motionEvent, policyFlags);
} else {
mTouchExplorer = new TouchExplorer(this, mContext);
}
return;
}
if ((policyFlags & WindowManagerPolicy.FLAG_PASS_TO_USER) != 0) {
mTouchExplorer.onMotionEvent(motionEvent, policyFlags);
} else {
mTouchExplorer.clear(motionEvent, policyFlags);
}
} else {
super.onInputEvent(event, policyFlags);
}
super.onInputEvent(event, policyFlags);
}
}

View File

@@ -56,6 +56,7 @@ import android.view.accessibility.IAccessibilityManagerClient;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@@ -74,6 +75,8 @@ import java.util.Set;
public class AccessibilityManagerService extends IAccessibilityManager.Stub
implements HandlerCaller.Callback {
private static final boolean DEBUG = false;
private static final String LOG_TAG = "AccessibilityManagerService";
private static int sIdCounter = 0;
@@ -102,6 +105,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
private final SimpleStringSplitter mStringColonSplitter = new SimpleStringSplitter(':');
private final SparseArray<List<ServiceInfo>> mFeedbackTypeToEnabledServicesMap =
new SparseArray<List<ServiceInfo>>();
private PackageManager mPackageManager;
private int mHandledFeedbackTypes = 0;
@@ -211,7 +217,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
}
manageServicesLocked();
updateInputFilterLocked();
}
return;
@@ -252,7 +257,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
unbindAllServicesLocked();
}
updateClientsLocked();
updateInputFilterLocked();
}
}
});
@@ -300,6 +304,16 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
}
}
public List<ServiceInfo> getEnabledAccessibilityServiceList(int feedbackType) {
synchronized (mLock) {
List<ServiceInfo> enabledServices = mFeedbackTypeToEnabledServicesMap.get(feedbackType);
if (enabledServices == null) {
return Collections.emptyList();
}
return enabledServices;
}
}
public void interrupt() {
synchronized (mLock) {
for (int i = 0, count = mServices.size(); i < count; i++) {
@@ -339,6 +353,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
}
service.mNotificationTimeout = info.notificationTimeout;
service.mIsDefault = (info.flags & AccessibilityServiceInfo.DEFAULT) != 0;
updateStateOnEnabledService(service);
}
return;
default:
@@ -449,7 +465,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
try {
listener.onAccessibilityEvent(event);
if (false) {
if (DEBUG) {
Slog.i(LOG_TAG, "Event " + event + " sent to " + listener);
}
} catch (RemoteException re) {
@@ -469,10 +485,11 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
* @return True if the service was removed, false otherwise.
*/
private boolean removeDeadServiceLocked(Service service) {
if (false) {
if (DEBUG) {
Slog.i(LOG_TAG, "Dead service " + service.mService + " removed");
}
mHandler.removeMessages(service.mId);
updateStateOnDisabledService(service);
return mServices.remove(service);
}
@@ -593,7 +610,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
if (isEnabled) {
if (enabledServices.contains(componentName)) {
if (service == null) {
service = new Service(componentName);
service = new Service(componentName, intalledService);
}
service.bind();
} else if (!enabledServices.contains(componentName)) {
@@ -643,6 +660,47 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
}
}
/**
* Updates the set of enabled services for a given feedback type and
* if more than one of them provides spoken feedback enables touch
* exploration.
*
* @param service An enable service.
*/
private void updateStateOnEnabledService(Service service) {
int feedbackType = service.mFeedbackType;
List<ServiceInfo> enabledServices = mFeedbackTypeToEnabledServicesMap.get(feedbackType);
if (enabledServices == null) {
enabledServices = new ArrayList<ServiceInfo>();
mFeedbackTypeToEnabledServicesMap.put(feedbackType, enabledServices);
}
enabledServices.add(service.mServiceInfo);
// We enable touch exploration if at least one
// enabled service provides spoken feedback.
if (enabledServices.size() > 0
&& service.mFeedbackType == AccessibilityServiceInfo.FEEDBACK_SPOKEN) {
updateClientsLocked();
updateInputFilterLocked();
}
}
private void updateStateOnDisabledService(Service service) {
List<ServiceInfo> enabledServices =
mFeedbackTypeToEnabledServicesMap.get(service.mFeedbackType);
if (enabledServices == null) {
return;
}
enabledServices.remove(service.mServiceInfo);
// We disable touch exploration if no
// enabled service provides spoken feedback.
if (enabledServices.isEmpty()
&& service.mFeedbackType == AccessibilityServiceInfo.FEEDBACK_SPOKEN) {
updateClientsLocked();
updateInputFilterLocked();
}
}
/**
* This class represents an accessibility service. It stores all per service
* data required for the service management, provides API for starting/stopping the
@@ -654,6 +712,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
class Service extends IAccessibilityServiceConnection.Stub implements ServiceConnection {
int mId = 0;
ServiceInfo mServiceInfo;
IBinder mService;
IEventListener mServiceInterface;
@@ -678,9 +738,10 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
final SparseArray<AccessibilityEvent> mPendingEvents =
new SparseArray<AccessibilityEvent>();
Service(ComponentName componentName) {
Service(ComponentName componentName, ServiceInfo serviceInfo) {
mId = sIdCounter++;
mComponentName = componentName;
mServiceInfo = serviceInfo;
mIntent = new Intent().setComponent(mComponentName);
mIntent.putExtra(Intent.EXTRA_CLIENT_LABEL,
com.android.internal.R.string.accessibility_binding_label);
@@ -712,6 +773,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
mContext.unbindService(this);
mComponentNameToServiceMap.remove(mComponentName);
mServices.remove(this);
updateStateOnDisabledService(this);
return true;
}
return false;

File diff suppressed because it is too large Load Diff

View File

@@ -105,11 +105,13 @@ public abstract class InputFilter {
private final InputEventConsistencyVerifier mInboundInputEventConsistencyVerifier =
InputEventConsistencyVerifier.isInstrumentationEnabled() ?
new InputEventConsistencyVerifier(this,
InputEventConsistencyVerifier.FLAG_RAW_DEVICE_INPUT) : null;
InputEventConsistencyVerifier.FLAG_RAW_DEVICE_INPUT,
"InputFilter#InboundInputEventConsistencyVerifier") : null;
private final InputEventConsistencyVerifier mOutboundInputEventConsistencyVerifier =
InputEventConsistencyVerifier.isInstrumentationEnabled() ?
new InputEventConsistencyVerifier(this,
InputEventConsistencyVerifier.FLAG_RAW_DEVICE_INPUT) : null;
InputEventConsistencyVerifier.FLAG_RAW_DEVICE_INPUT,
"InputFilter#OutboundInputEventConsistencyVerifier") : null;
/**
* Creates the input filter.