Small code cleanups

Multi-project commit with I249d5fbe

Change-Id: Ia28c4e970992aa1299a30e604eaa5d096655c3a5
main
Ken Wakasa 2013-01-06 11:10:27 +09:00
parent f677681330
commit b6ca354431
25 changed files with 236 additions and 241 deletions

View File

@ -71,12 +71,11 @@ public final class AccessibilityEntityProvider extends AccessibilityNodeProvider
/** The current keyboard view. */ /** The current keyboard view. */
private KeyboardView mKeyboardView; private KeyboardView mKeyboardView;
public AccessibilityEntityProvider(KeyboardView keyboardView, InputMethodService inputMethod) { public AccessibilityEntityProvider(final KeyboardView keyboardView,
final InputMethodService inputMethod) {
mInputMethodService = inputMethod; mInputMethodService = inputMethod;
mKeyCodeDescriptionMapper = KeyCodeDescriptionMapper.getInstance(); mKeyCodeDescriptionMapper = KeyCodeDescriptionMapper.getInstance();
mAccessibilityUtils = AccessibilityUtils.getInstance(); mAccessibilityUtils = AccessibilityUtils.getInstance();
setView(keyboardView); setView(keyboardView);
} }
@ -85,21 +84,19 @@ public final class AccessibilityEntityProvider extends AccessibilityNodeProvider
* *
* @param keyboardView The keyboard view to represent. * @param keyboardView The keyboard view to represent.
*/ */
public void setView(KeyboardView keyboardView) { public void setView(final KeyboardView keyboardView) {
mKeyboardView = keyboardView; mKeyboardView = keyboardView;
updateParentLocation(); updateParentLocation();
// Since this class is constructed lazily, we might not get a subsequent // Since this class is constructed lazily, we might not get a subsequent
// call to setKeyboard() and therefore need to call it now. // call to setKeyboard() and therefore need to call it now.
setKeyboard(mKeyboardView.getKeyboard()); setKeyboard();
} }
/** /**
* Sets the keyboard represented by this node provider. * Sets the keyboard represented by this node provider.
*
* @param keyboard The keyboard to represent.
*/ */
public void setKeyboard(Keyboard keyboard) { public void setKeyboard() {
assignVirtualViewIds(); assignVirtualViewIds();
} }
@ -112,19 +109,16 @@ public final class AccessibilityEntityProvider extends AccessibilityNodeProvider
* @return A populated {@link AccessibilityEvent} for the key. * @return A populated {@link AccessibilityEvent} for the key.
* @see AccessibilityEvent * @see AccessibilityEvent
*/ */
public AccessibilityEvent createAccessibilityEvent(Key key, int eventType) { public AccessibilityEvent createAccessibilityEvent(final Key key, final int eventType) {
final int virtualViewId = generateVirtualViewIdForKey(key); final int virtualViewId = generateVirtualViewIdForKey(key);
final String keyDescription = getKeyDescription(key); final String keyDescription = getKeyDescription(key);
final AccessibilityEvent event = AccessibilityEvent.obtain(eventType); final AccessibilityEvent event = AccessibilityEvent.obtain(eventType);
event.setPackageName(mKeyboardView.getContext().getPackageName()); event.setPackageName(mKeyboardView.getContext().getPackageName());
event.setClassName(key.getClass().getName()); event.setClassName(key.getClass().getName());
event.setContentDescription(keyDescription); event.setContentDescription(keyDescription);
event.setEnabled(true); event.setEnabled(true);
final AccessibilityRecordCompat record = new AccessibilityRecordCompat(event); final AccessibilityRecordCompat record = new AccessibilityRecordCompat(event);
record.setSource(mKeyboardView, virtualViewId); record.setSource(mKeyboardView, virtualViewId);
return event; return event;
} }
@ -145,68 +139,65 @@ public final class AccessibilityEntityProvider extends AccessibilityNodeProvider
* </p> * </p>
* *
* @param virtualViewId A client defined virtual view id. * @param virtualViewId A client defined virtual view id.
* @return A populated {@link AccessibilityNodeInfoCompat} for a virtual * @return A populated {@link AccessibilityNodeInfoCompat} for a virtual descendant or the host
* descendant or the host View. * View.
* @see AccessibilityNodeInfoCompat * @see AccessibilityNodeInfoCompat
*/ */
@Override @Override
public AccessibilityNodeInfoCompat createAccessibilityNodeInfo(int virtualViewId) { public AccessibilityNodeInfoCompat createAccessibilityNodeInfo(final int virtualViewId) {
AccessibilityNodeInfoCompat info = null;
if (virtualViewId == UNDEFINED) { if (virtualViewId == UNDEFINED) {
return null; return null;
} else if (virtualViewId == View.NO_ID) { }
if (virtualViewId == View.NO_ID) {
// We are requested to create an AccessibilityNodeInfo describing // We are requested to create an AccessibilityNodeInfo describing
// this View, i.e. the root of the virtual sub-tree. // this View, i.e. the root of the virtual sub-tree.
info = AccessibilityNodeInfoCompat.obtain(mKeyboardView); final AccessibilityNodeInfoCompat rootInfo =
ViewCompat.onInitializeAccessibilityNodeInfo(mKeyboardView, info); AccessibilityNodeInfoCompat.obtain(mKeyboardView);
ViewCompat.onInitializeAccessibilityNodeInfo(mKeyboardView, rootInfo);
// Add the virtual children of the root View. // Add the virtual children of the root View.
final Keyboard keyboard = mKeyboardView.getKeyboard(); final Keyboard keyboard = mKeyboardView.getKeyboard();
final Key[] keys = keyboard.mKeys; final Key[] keys = keyboard.mKeys;
for (Key key : keys) { for (Key key : keys) {
final int childVirtualViewId = generateVirtualViewIdForKey(key); final int childVirtualViewId = generateVirtualViewIdForKey(key);
info.addChild(mKeyboardView, childVirtualViewId); rootInfo.addChild(mKeyboardView, childVirtualViewId);
}
} else {
// Find the view that corresponds to the given id.
final Key key = mVirtualViewIdToKey.get(virtualViewId);
if (key == null) {
Log.e(TAG, "Invalid virtual view ID: " + virtualViewId);
return null;
}
final String keyDescription = getKeyDescription(key);
final Rect boundsInParent = key.mHitBox;
// Calculate the key's in-screen bounds.
mTempBoundsInScreen.set(boundsInParent);
mTempBoundsInScreen.offset(
CoordinateUtils.x(mParentLocation), CoordinateUtils.y(mParentLocation));
final Rect boundsInScreen = mTempBoundsInScreen;
// Obtain and initialize an AccessibilityNodeInfo with
// information about the virtual view.
info = AccessibilityNodeInfoCompat.obtain();
info.setPackageName(mKeyboardView.getContext().getPackageName());
info.setClassName(key.getClass().getName());
info.setContentDescription(keyDescription);
info.setBoundsInParent(boundsInParent);
info.setBoundsInScreen(boundsInScreen);
info.setParent(mKeyboardView);
info.setSource(mKeyboardView, virtualViewId);
info.setBoundsInScreen(boundsInScreen);
info.setEnabled(true);
info.setVisibleToUser(true);
if (mAccessibilityFocusedView == virtualViewId) {
info.addAction(AccessibilityNodeInfoCompat.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
} else {
info.addAction(AccessibilityNodeInfoCompat.ACTION_ACCESSIBILITY_FOCUS);
} }
return rootInfo;
} }
// Find the view that corresponds to the given id.
final Key key = mVirtualViewIdToKey.get(virtualViewId);
if (key == null) {
Log.e(TAG, "Invalid virtual view ID: " + virtualViewId);
return null;
}
final String keyDescription = getKeyDescription(key);
final Rect boundsInParent = key.mHitBox;
// Calculate the key's in-screen bounds.
mTempBoundsInScreen.set(boundsInParent);
mTempBoundsInScreen.offset(
CoordinateUtils.x(mParentLocation), CoordinateUtils.y(mParentLocation));
final Rect boundsInScreen = mTempBoundsInScreen;
// Obtain and initialize an AccessibilityNodeInfo with information about the virtual view.
final AccessibilityNodeInfoCompat info = AccessibilityNodeInfoCompat.obtain();
info.setPackageName(mKeyboardView.getContext().getPackageName());
info.setClassName(key.getClass().getName());
info.setContentDescription(keyDescription);
info.setBoundsInParent(boundsInParent);
info.setBoundsInScreen(boundsInScreen);
info.setParent(mKeyboardView);
info.setSource(mKeyboardView, virtualViewId);
info.setBoundsInScreen(boundsInScreen);
info.setEnabled(true);
info.setVisibleToUser(true);
if (mAccessibilityFocusedView == virtualViewId) {
info.addAction(AccessibilityNodeInfoCompat.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
} else {
info.addAction(AccessibilityNodeInfoCompat.ACTION_ACCESSIBILITY_FOCUS);
}
return info; return info;
} }
@ -216,7 +207,7 @@ public final class AccessibilityEntityProvider extends AccessibilityNodeProvider
* *
* @param key The key to press. * @param key The key to press.
*/ */
void simulateKeyPress(Key key) { void simulateKeyPress(final Key key) {
final int x = key.mHitBox.centerX(); final int x = key.mHitBox.centerX();
final int y = key.mHitBox.centerY(); final int y = key.mHitBox.centerY();
final long downTime = SystemClock.uptimeMillis(); final long downTime = SystemClock.uptimeMillis();
@ -227,19 +218,17 @@ public final class AccessibilityEntityProvider extends AccessibilityNodeProvider
mKeyboardView.onTouchEvent(downEvent); mKeyboardView.onTouchEvent(downEvent);
mKeyboardView.onTouchEvent(upEvent); mKeyboardView.onTouchEvent(upEvent);
downEvent.recycle(); downEvent.recycle();
upEvent.recycle(); upEvent.recycle();
} }
@Override @Override
public boolean performAction(int virtualViewId, int action, Bundle arguments) { public boolean performAction(final int virtualViewId, final int action,
final Bundle arguments) {
final Key key = mVirtualViewIdToKey.get(virtualViewId); final Key key = mVirtualViewIdToKey.get(virtualViewId);
if (key == null) { if (key == null) {
return false; return false;
} }
return performActionForKey(key, action, arguments); return performActionForKey(key, action, arguments);
} }
@ -249,10 +238,9 @@ public final class AccessibilityEntityProvider extends AccessibilityNodeProvider
* @param key The on which to perform the action. * @param key The on which to perform the action.
* @param action The action to perform. * @param action The action to perform.
* @param arguments The action's arguments. * @param arguments The action's arguments.
* @return The result of performing the action, or false if the action is * @return The result of performing the action, or false if the action is not supported.
* not supported.
*/ */
boolean performActionForKey(Key key, int action, Bundle arguments) { boolean performActionForKey(final Key key, final int action, final Bundle arguments) {
final int virtualViewId = generateVirtualViewIdForKey(key); final int virtualViewId = generateVirtualViewIdForKey(key);
switch (action) { switch (action) {
@ -272,9 +260,9 @@ public final class AccessibilityEntityProvider extends AccessibilityNodeProvider
sendAccessibilityEventForKey( sendAccessibilityEventForKey(
key, AccessibilityEventCompat.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED); key, AccessibilityEventCompat.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
return true; return true;
default:
return false;
} }
return false;
} }
/** /**
@ -283,7 +271,7 @@ public final class AccessibilityEntityProvider extends AccessibilityNodeProvider
* @param key The key that's sending the event. * @param key The key that's sending the event.
* @param eventType The type of event to send. * @param eventType The type of event to send.
*/ */
void sendAccessibilityEventForKey(Key key, int eventType) { void sendAccessibilityEventForKey(final Key key, final int eventType) {
final AccessibilityEvent event = createAccessibilityEvent(key, eventType); final AccessibilityEvent event = createAccessibilityEvent(key, eventType);
mAccessibilityUtils.requestSendAccessibilityEvent(event); mAccessibilityUtils.requestSendAccessibilityEvent(event);
} }
@ -294,12 +282,11 @@ public final class AccessibilityEntityProvider extends AccessibilityNodeProvider
* @param key The key to describe. * @param key The key to describe.
* @return The context-specific description of the key. * @return The context-specific description of the key.
*/ */
private String getKeyDescription(Key key) { private String getKeyDescription(final Key key) {
final EditorInfo editorInfo = mInputMethodService.getCurrentInputEditorInfo(); final EditorInfo editorInfo = mInputMethodService.getCurrentInputEditorInfo();
final boolean shouldObscure = mAccessibilityUtils.shouldObscureInput(editorInfo); final boolean shouldObscure = mAccessibilityUtils.shouldObscureInput(editorInfo);
final String keyDescription = mKeyCodeDescriptionMapper.getDescriptionForKey( final String keyDescription = mKeyCodeDescriptionMapper.getDescriptionForKey(
mKeyboardView.getContext(), mKeyboardView.getKeyboard(), key, shouldObscure); mKeyboardView.getContext(), mKeyboardView.getKeyboard(), key, shouldObscure);
return keyDescription; return keyDescription;
} }
@ -311,7 +298,6 @@ public final class AccessibilityEntityProvider extends AccessibilityNodeProvider
if (keyboard == null) { if (keyboard == null) {
return; return;
} }
mVirtualViewIdToKey.clear(); mVirtualViewIdToKey.clear();
final Key[] keys = keyboard.mKeys; final Key[] keys = keyboard.mKeys;
@ -335,7 +321,7 @@ public final class AccessibilityEntityProvider extends AccessibilityNodeProvider
* @param key The key to identify. * @param key The key to identify.
* @return A virtual view identifier. * @return A virtual view identifier.
*/ */
private static int generateVirtualViewIdForKey(Key key) { private static int generateVirtualViewIdForKey(final Key key) {
// The key x- and y-coordinates are stable between layout changes. // The key x- and y-coordinates are stable between layout changes.
// Generate an identifier by bit-shifting the x-coordinate to the // Generate an identifier by bit-shifting the x-coordinate to the
// left-half of the integer and OR'ing with the y-coordinate. // left-half of the integer and OR'ing with the y-coordinate.

View File

@ -55,7 +55,7 @@ public final class AccessibilityUtils {
*/ */
private static final boolean ENABLE_ACCESSIBILITY = true; private static final boolean ENABLE_ACCESSIBILITY = true;
public static void init(InputMethodService inputMethod) { public static void init(final InputMethodService inputMethod) {
if (!ENABLE_ACCESSIBILITY) return; if (!ENABLE_ACCESSIBILITY) return;
// These only need to be initialized if the kill switch is off. // These only need to be initialized if the kill switch is off.
@ -72,7 +72,7 @@ public final class AccessibilityUtils {
// This class is not publicly instantiable. // This class is not publicly instantiable.
} }
private void initInternal(Context context) { private void initInternal(final Context context) {
mContext = context; mContext = context;
mAccessibilityManager = mAccessibilityManager =
(AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE); (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);
@ -100,9 +100,8 @@ public final class AccessibilityUtils {
* @param event The event to check. * @param event The event to check.
* @return {@true} is the event is a touch exploration event * @return {@true} is the event is a touch exploration event
*/ */
public boolean isTouchExplorationEvent(MotionEvent event) { public boolean isTouchExplorationEvent(final MotionEvent event) {
final int action = event.getAction(); final int action = event.getAction();
return action == MotionEvent.ACTION_HOVER_ENTER return action == MotionEvent.ACTION_HOVER_ENTER
|| action == MotionEvent.ACTION_HOVER_EXIT || action == MotionEvent.ACTION_HOVER_EXIT
|| action == MotionEvent.ACTION_HOVER_MOVE; || action == MotionEvent.ACTION_HOVER_MOVE;
@ -114,7 +113,7 @@ public final class AccessibilityUtils {
* *
* @return {@code true} if the device should obscure password characters. * @return {@code true} if the device should obscure password characters.
*/ */
public boolean shouldObscureInput(EditorInfo editorInfo) { public boolean shouldObscureInput(final EditorInfo editorInfo) {
if (editorInfo == null) return false; if (editorInfo == null) return false;
// The user can optionally force speaking passwords. // The user can optionally force speaking passwords.
@ -140,7 +139,7 @@ public final class AccessibilityUtils {
* @param view The source view. * @param view The source view.
* @param text The text to speak. * @param text The text to speak.
*/ */
public void announceForAccessibility(View view, CharSequence text) { public void announceForAccessibility(final View view, final CharSequence text) {
if (!mAccessibilityManager.isEnabled()) { if (!mAccessibilityManager.isEnabled()) {
Log.e(TAG, "Attempted to speak when accessibility was disabled!"); Log.e(TAG, "Attempted to speak when accessibility was disabled!");
return; return;
@ -157,8 +156,9 @@ public final class AccessibilityUtils {
event.setEnabled(true); event.setEnabled(true);
event.getText().add(text); event.getText().add(text);
// Platforms starting at SDK 16 should use announce events. // Platforms starting at SDK version 16 (Build.VERSION_CODES.JELLY_BEAN) should use
if (Build.VERSION.SDK_INT >= 16) { // announce events.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
event.setEventType(AccessibilityEventCompat.TYPE_ANNOUNCEMENT); event.setEventType(AccessibilityEventCompat.TYPE_ANNOUNCEMENT);
} else { } else {
event.setEventType(AccessibilityEvent.TYPE_VIEW_FOCUSED); event.setEventType(AccessibilityEvent.TYPE_VIEW_FOCUSED);
@ -181,7 +181,8 @@ public final class AccessibilityUtils {
* @param editorInfo The input connection's editor info attribute. * @param editorInfo The input connection's editor info attribute.
* @param restarting Whether the connection is being restarted. * @param restarting Whether the connection is being restarted.
*/ */
public void onStartInputViewInternal(View view, EditorInfo editorInfo, boolean restarting) { public void onStartInputViewInternal(final View view, final EditorInfo editorInfo,
final boolean restarting) {
if (shouldObscureInput(editorInfo)) { if (shouldObscureInput(editorInfo)) {
final CharSequence text = mContext.getText(R.string.spoken_use_headphones); final CharSequence text = mContext.getText(R.string.spoken_use_headphones);
announceForAccessibility(view, text); announceForAccessibility(view, text);
@ -194,7 +195,7 @@ public final class AccessibilityUtils {
* *
* @param event The event to send. * @param event The event to send.
*/ */
public void requestSendAccessibilityEvent(AccessibilityEvent event) { public void requestSendAccessibilityEvent(final AccessibilityEvent event) {
if (mAccessibilityManager.isEnabled()) { if (mAccessibilityManager.isEnabled()) {
mAccessibilityManager.sendAccessibilityEvent(event); mAccessibilityManager.sendAccessibilityEvent(event);
} }

View File

@ -42,12 +42,11 @@ public final class AccessibleKeyboardViewProxy extends AccessibilityDelegateComp
private Key mLastHoverKey = null; private Key mLastHoverKey = null;
/** /**
* Inset in pixels to look for keys when the user's finger exits the * Inset in pixels to look for keys when the user's finger exits the keyboard area.
* keyboard area.
*/ */
private int mEdgeSlop; private int mEdgeSlop;
public static void init(InputMethodService inputMethod) { public static void init(final InputMethodService inputMethod) {
sInstance.initInternal(inputMethod); sInstance.initInternal(inputMethod);
} }
@ -59,7 +58,7 @@ public final class AccessibleKeyboardViewProxy extends AccessibilityDelegateComp
// Not publicly instantiable. // Not publicly instantiable.
} }
private void initInternal(InputMethodService inputMethod) { private void initInternal(final InputMethodService inputMethod) {
mInputMethod = inputMethod; mInputMethod = inputMethod;
mEdgeSlop = inputMethod.getResources().getDimensionPixelSize( mEdgeSlop = inputMethod.getResources().getDimensionPixelSize(
R.dimen.accessibility_edge_slop); R.dimen.accessibility_edge_slop);
@ -70,61 +69,61 @@ public final class AccessibleKeyboardViewProxy extends AccessibilityDelegateComp
* *
* @param view The view to wrap. * @param view The view to wrap.
*/ */
public void setView(MainKeyboardView view) { public void setView(final MainKeyboardView view) {
if (view == null) { if (view == null) {
// Ignore null views. // Ignore null views.
return; return;
} }
mView = view; mView = view;
// Ensure that the view has an accessibility delegate. // Ensure that the view has an accessibility delegate.
ViewCompat.setAccessibilityDelegate(view, this); ViewCompat.setAccessibilityDelegate(view, this);
if (mAccessibilityNodeProvider != null) { if (mAccessibilityNodeProvider == null) {
mAccessibilityNodeProvider.setView(view); return;
} }
mAccessibilityNodeProvider.setView(view);
} }
public void setKeyboard(Keyboard keyboard) { public void setKeyboard() {
if (mAccessibilityNodeProvider != null) { if (mAccessibilityNodeProvider == null) {
mAccessibilityNodeProvider.setKeyboard(keyboard); return;
} }
mAccessibilityNodeProvider.setKeyboard();
} }
/** /**
* Proxy method for View.getAccessibilityNodeProvider(). This method is * Proxy method for View.getAccessibilityNodeProvider(). This method is called in SDK
* called in SDK version 15 and higher to obtain the virtual node hierarchy * version 15 (Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) and higher to obtain the virtual
* provider. * node hierarchy provider.
* *
* @return The accessibility node provider for the current keyboard. * @return The accessibility node provider for the current keyboard.
*/ */
@Override @Override
public AccessibilityEntityProvider getAccessibilityNodeProvider(View host) { public AccessibilityEntityProvider getAccessibilityNodeProvider(final View host) {
return getAccessibilityNodeProvider(); return getAccessibilityNodeProvider();
} }
/** /**
* Intercepts touch events before dispatch when touch exploration is turned * Intercepts touch events before dispatch when touch exploration is turned on in ICS and
* on in ICS and higher. * higher.
* *
* @param event The motion event being dispatched. * @param event The motion event being dispatched.
* @return {@code true} if the event is handled * @return {@code true} if the event is handled
*/ */
public boolean dispatchTouchEvent(MotionEvent event) { public boolean dispatchTouchEvent(final MotionEvent event) {
// To avoid accidental key presses during touch exploration, always drop // To avoid accidental key presses during touch exploration, always drop
// touch events generated by the user. // touch events generated by the user.
return false; return false;
} }
/** /**
* Receives hover events when touch exploration is turned on in SDK versions * Receives hover events when touch exploration is turned on in SDK versions ICS and higher.
* ICS and higher.
* *
* @param event The hover event. * @param event The hover event.
* @return {@code true} if the event is handled * @return {@code true} if the event is handled
*/ */
public boolean dispatchHoverEvent(MotionEvent event, PointerTracker tracker) { public boolean dispatchHoverEvent(final MotionEvent event, final PointerTracker tracker) {
final int x = (int) event.getX(); final int x = (int) event.getX();
final int y = (int) event.getY(); final int y = (int) event.getY();
final Key previousKey = mLastHoverKey; final Key previousKey = mLastHoverKey;
@ -135,7 +134,6 @@ public final class AccessibleKeyboardViewProxy extends AccessibilityDelegateComp
} else { } else {
key = null; key = null;
} }
mLastHoverKey = key; mLastHoverKey = key;
switch (event.getAction()) { switch (event.getAction()) {
@ -173,30 +171,29 @@ public final class AccessibleKeyboardViewProxy extends AccessibilityDelegateComp
} }
/** /**
* Utility method to determine whether the given point, in local * Utility method to determine whether the given point, in local coordinates, is inside the
* coordinates, is inside the view, where the area of the view is contracted * view, where the area of the view is contracted by the edge slop factor.
* by the edge slop factor.
* *
* @param localX The local x-coordinate. * @param localX The local x-coordinate.
* @param localY The local y-coordinate. * @param localY The local y-coordinate.
*/ */
private boolean pointInView(int localX, int localY) { private boolean pointInView(final int localX, final int localY) {
return (localX >= mEdgeSlop) && (localY >= mEdgeSlop) return (localX >= mEdgeSlop) && (localY >= mEdgeSlop)
&& (localX < (mView.getWidth() - mEdgeSlop)) && (localX < (mView.getWidth() - mEdgeSlop))
&& (localY < (mView.getHeight() - mEdgeSlop)); && (localY < (mView.getHeight() - mEdgeSlop));
} }
/** /**
* Simulates a transition between two {@link Key}s by sending a HOVER_EXIT * Simulates a transition between two {@link Key}s by sending a HOVER_EXIT on the previous key,
* on the previous key, a HOVER_ENTER on the current key, and a HOVER_MOVE * a HOVER_ENTER on the current key, and a HOVER_MOVE on the current key.
* on the current key.
* *
* @param currentKey The currently hovered key. * @param currentKey The currently hovered key.
* @param previousKey The previously hovered key. * @param previousKey The previously hovered key.
* @param event The event that triggered the transition. * @param event The event that triggered the transition.
* @return {@code true} if the event was handled. * @return {@code true} if the event was handled.
*/ */
private boolean onTransitionKey(Key currentKey, Key previousKey, MotionEvent event) { private boolean onTransitionKey(final Key currentKey, final Key previousKey,
final MotionEvent event) {
final int savedAction = event.getAction(); final int savedAction = event.getAction();
event.setAction(MotionEvent.ACTION_HOVER_EXIT); event.setAction(MotionEvent.ACTION_HOVER_EXIT);
@ -214,19 +211,18 @@ public final class AccessibleKeyboardViewProxy extends AccessibilityDelegateComp
} }
/** /**
* Handles a hover event on a key. If {@link Key} extended View, this would * Handles a hover event on a key. If {@link Key} extended View, this would be analogous to
* be analogous to calling View.onHoverEvent(MotionEvent). * calling View.onHoverEvent(MotionEvent).
* *
* @param key The currently hovered key. * @param key The currently hovered key.
* @param event The hover event. * @param event The hover event.
* @return {@code true} if the event was handled. * @return {@code true} if the event was handled.
*/ */
private boolean onHoverKey(Key key, MotionEvent event) { private boolean onHoverKey(final Key key, final MotionEvent event) {
// Null keys can't receive events. // Null keys can't receive events.
if (key == null) { if (key == null) {
return false; return false;
} }
final AccessibilityEntityProvider provider = getAccessibilityNodeProvider(); final AccessibilityEntityProvider provider = getAccessibilityNodeProvider();
switch (event.getAction()) { switch (event.getAction()) {
@ -241,7 +237,6 @@ public final class AccessibleKeyboardViewProxy extends AccessibilityDelegateComp
key, AccessibilityEventCompat.TYPE_VIEW_HOVER_EXIT); key, AccessibilityEventCompat.TYPE_VIEW_HOVER_EXIT);
break; break;
} }
return true; return true;
} }
@ -268,7 +263,6 @@ public final class AccessibleKeyboardViewProxy extends AccessibilityDelegateComp
default: default:
text = context.getText(R.string.spoken_description_shiftmode_off); text = context.getText(R.string.spoken_description_shiftmode_off);
} }
AccessibilityUtils.getInstance().announceForAccessibility(mView, text); AccessibilityUtils.getInstance().announceForAccessibility(mView, text);
} }
@ -307,7 +301,6 @@ public final class AccessibleKeyboardViewProxy extends AccessibilityDelegateComp
if (resId < 0) { if (resId < 0) {
return; return;
} }
final String text = context.getString(resId); final String text = context.getString(resId);
AccessibilityUtils.getInstance().announceForAccessibility(mView, text); AccessibilityUtils.getInstance().announceForAccessibility(mView, text);
} }

View File

@ -93,17 +93,17 @@ public final class KeyCodeDescriptionMapper {
* @param keyboard The keyboard on which the key resides. * @param keyboard The keyboard on which the key resides.
* @param key The key from which to obtain a description. * @param key The key from which to obtain a description.
* @param shouldObscure {@true} if text (e.g. non-control) characters should be obscured. * @param shouldObscure {@true} if text (e.g. non-control) characters should be obscured.
* @return a character sequence describing the action performed by pressing * @return a character sequence describing the action performed by pressing the key
* the key
*/ */
public String getDescriptionForKey(Context context, Keyboard keyboard, Key key, public String getDescriptionForKey(final Context context, final Keyboard keyboard,
boolean shouldObscure) { final Key key, final boolean shouldObscure) {
final int code = key.mCode; final int code = key.mCode;
if (code == Constants.CODE_SWITCH_ALPHA_SYMBOL) { if (code == Constants.CODE_SWITCH_ALPHA_SYMBOL) {
final String description = getDescriptionForSwitchAlphaSymbol(context, keyboard); final String description = getDescriptionForSwitchAlphaSymbol(context, keyboard);
if (description != null) if (description != null) {
return description; return description;
}
} }
if (code == Constants.CODE_SHIFT) { if (code == Constants.CODE_SHIFT) {
@ -127,7 +127,6 @@ public final class KeyCodeDescriptionMapper {
if (key.mCode != Constants.CODE_UNSPECIFIED) { if (key.mCode != Constants.CODE_UNSPECIFIED) {
return getDescriptionForKeyCode(context, keyboard, key, shouldObscure); return getDescriptionForKeyCode(context, keyboard, key, shouldObscure);
} }
return null; return null;
} }
@ -138,10 +137,10 @@ public final class KeyCodeDescriptionMapper {
* *
* @param context The package's context. * @param context The package's context.
* @param keyboard The keyboard on which the key resides. * @param keyboard The keyboard on which the key resides.
* @return a character sequence describing the action performed by pressing * @return a character sequence describing the action performed by pressing the key
* the key
*/ */
private String getDescriptionForSwitchAlphaSymbol(Context context, Keyboard keyboard) { private String getDescriptionForSwitchAlphaSymbol(final Context context,
final Keyboard keyboard) {
final KeyboardId keyboardId = keyboard.mId; final KeyboardId keyboardId = keyboard.mId;
final int elementId = keyboardId.mElementId; final int elementId = keyboardId.mElementId;
final int resId; final int resId;
@ -168,7 +167,6 @@ public final class KeyCodeDescriptionMapper {
Log.e(TAG, "Missing description for keyboard element ID:" + elementId); Log.e(TAG, "Missing description for keyboard element ID:" + elementId);
return null; return null;
} }
return context.getString(resId); return context.getString(resId);
} }
@ -179,7 +177,7 @@ public final class KeyCodeDescriptionMapper {
* @param keyboard The keyboard on which the key resides. * @param keyboard The keyboard on which the key resides.
* @return A context-sensitive description of the "Shift" key. * @return A context-sensitive description of the "Shift" key.
*/ */
private String getDescriptionForShiftKey(Context context, Keyboard keyboard) { private String getDescriptionForShiftKey(final Context context, final Keyboard keyboard) {
final KeyboardId keyboardId = keyboard.mId; final KeyboardId keyboardId = keyboard.mId;
final int elementId = keyboardId.mElementId; final int elementId = keyboardId.mElementId;
final int resId; final int resId;
@ -197,7 +195,6 @@ public final class KeyCodeDescriptionMapper {
default: default:
resId = R.string.spoken_description_shift; resId = R.string.spoken_description_shift;
} }
return context.getString(resId); return context.getString(resId);
} }
@ -207,10 +204,10 @@ public final class KeyCodeDescriptionMapper {
* @param context The package's context. * @param context The package's context.
* @param keyboard The keyboard on which the key resides. * @param keyboard The keyboard on which the key resides.
* @param key The key to describe. * @param key The key to describe.
* @return Returns a context-sensitive description of the "Enter" action * @return Returns a context-sensitive description of the "Enter" action key.
* key.
*/ */
private String getDescriptionForActionKey(Context context, Keyboard keyboard, Key key) { private String getDescriptionForActionKey(final Context context, final Keyboard keyboard,
final Key key) {
final KeyboardId keyboardId = keyboard.mId; final KeyboardId keyboardId = keyboard.mId;
final int actionId = keyboardId.imeActionId(); final int actionId = keyboardId.imeActionId();
final int resId; final int resId;
@ -243,7 +240,6 @@ public final class KeyCodeDescriptionMapper {
default: default:
resId = R.string.spoken_description_return; resId = R.string.spoken_description_return;
} }
return context.getString(resId); return context.getString(resId);
} }
@ -265,11 +261,10 @@ public final class KeyCodeDescriptionMapper {
* @param keyboard The keyboard on which the key resides. * @param keyboard The keyboard on which the key resides.
* @param key The key from which to obtain a description. * @param key The key from which to obtain a description.
* @param shouldObscure {@true} if text (e.g. non-control) characters should be obscured. * @param shouldObscure {@true} if text (e.g. non-control) characters should be obscured.
* @return a character sequence describing the action performed by pressing * @return a character sequence describing the action performed by pressing the key
* the key
*/ */
private String getDescriptionForKeyCode(Context context, Keyboard keyboard, Key key, private String getDescriptionForKeyCode(final Context context, final Keyboard keyboard,
boolean shouldObscure) { final Key key, final boolean shouldObscure) {
final int code = key.mCode; final int code = key.mCode;
// If the key description should be obscured, now is the time to do it. // If the key description should be obscured, now is the time to do it.
@ -277,15 +272,15 @@ public final class KeyCodeDescriptionMapper {
if (shouldObscure && isDefinedNonCtrl) { if (shouldObscure && isDefinedNonCtrl) {
return context.getString(OBSCURED_KEY_RES_ID); return context.getString(OBSCURED_KEY_RES_ID);
} }
if (mKeyCodeMap.indexOfKey(code) >= 0) { if (mKeyCodeMap.indexOfKey(code) >= 0) {
return context.getString(mKeyCodeMap.get(code)); return context.getString(mKeyCodeMap.get(code));
} else if (isDefinedNonCtrl) {
return Character.toString((char) code);
} else if (!TextUtils.isEmpty(key.mLabel)) {
return key.mLabel;
} else {
return context.getString(R.string.spoken_description_unknown, code);
} }
if (isDefinedNonCtrl) {
return Character.toString((char) code);
}
if (!TextUtils.isEmpty(key.mLabel)) {
return key.mLabel;
}
return context.getString(R.string.spoken_description_unknown, code);
} }
} }

View File

@ -31,8 +31,8 @@ public final class CompatUtils {
private static final String INPUT_METHOD_SUBTYPE_SETTINGS = private static final String INPUT_METHOD_SUBTYPE_SETTINGS =
"android.settings.INPUT_METHOD_SUBTYPE_SETTINGS"; "android.settings.INPUT_METHOD_SUBTYPE_SETTINGS";
public static Intent getInputLanguageSelectionIntent(String inputMethodId, public static Intent getInputLanguageSelectionIntent(final String inputMethodId,
int flagsForSubtypeSettings) { final int flagsForSubtypeSettings) {
// Refer to android.provider.Settings.ACTION_INPUT_METHOD_SUBTYPE_SETTINGS // Refer to android.provider.Settings.ACTION_INPUT_METHOD_SUBTYPE_SETTINGS
final String action = INPUT_METHOD_SUBTYPE_SETTINGS; final String action = INPUT_METHOD_SUBTYPE_SETTINGS;
final Intent intent = new Intent(action); final Intent intent = new Intent(action);
@ -45,7 +45,7 @@ public final class CompatUtils {
return intent; return intent;
} }
public static Class<?> getClass(String className) { public static Class<?> getClass(final String className) {
try { try {
return Class.forName(className); return Class.forName(className);
} catch (ClassNotFoundException e) { } catch (ClassNotFoundException e) {
@ -53,8 +53,8 @@ public final class CompatUtils {
} }
} }
public static Method getMethod(Class<?> targetClass, String name, public static Method getMethod(final Class<?> targetClass, final String name,
Class<?>... parameterTypes) { final Class<?>... parameterTypes) {
if (targetClass == null || TextUtils.isEmpty(name)) return null; if (targetClass == null || TextUtils.isEmpty(name)) return null;
try { try {
return targetClass.getMethod(name, parameterTypes); return targetClass.getMethod(name, parameterTypes);
@ -66,7 +66,7 @@ public final class CompatUtils {
return null; return null;
} }
public static Field getField(Class<?> targetClass, String name) { public static Field getField(final Class<?> targetClass, final String name) {
if (targetClass == null || TextUtils.isEmpty(name)) return null; if (targetClass == null || TextUtils.isEmpty(name)) return null;
try { try {
return targetClass.getField(name); return targetClass.getField(name);
@ -78,7 +78,8 @@ public final class CompatUtils {
return null; return null;
} }
public static Constructor<?> getConstructor(Class<?> targetClass, Class<?> ... types) { public static Constructor<?> getConstructor(final Class<?> targetClass,
final Class<?> ... types) {
if (targetClass == null || types == null) return null; if (targetClass == null || types == null) return null;
try { try {
return targetClass.getConstructor(types); return targetClass.getConstructor(types);
@ -90,7 +91,7 @@ public final class CompatUtils {
return null; return null;
} }
public static Object newInstance(Constructor<?> constructor, Object ... args) { public static Object newInstance(final Constructor<?> constructor, final Object ... args) {
if (constructor == null) return null; if (constructor == null) return null;
try { try {
return constructor.newInstance(args); return constructor.newInstance(args);
@ -100,8 +101,8 @@ public final class CompatUtils {
return null; return null;
} }
public static Object invoke( public static Object invoke(final Object receiver, final Object defaultValue,
Object receiver, Object defaultValue, Method method, Object... args) { final Method method, final Object... args) {
if (method == null) return defaultValue; if (method == null) return defaultValue;
try { try {
return method.invoke(receiver, args); return method.invoke(receiver, args);
@ -111,7 +112,8 @@ public final class CompatUtils {
return defaultValue; return defaultValue;
} }
public static Object getFieldValue(Object receiver, Object defaultValue, Field field) { public static Object getFieldValue(final Object receiver, final Object defaultValue,
final Field field) {
if (field == null) return defaultValue; if (field == null) return defaultValue;
try { try {
return field.get(receiver); return field.get(receiver);
@ -121,7 +123,7 @@ public final class CompatUtils {
return defaultValue; return defaultValue;
} }
public static void setFieldValue(Object receiver, Field field, Object value) { public static void setFieldValue(final Object receiver, final Field field, final Object value) {
if (field == null) return; if (field == null) return;
try { try {
field.set(receiver, value); field.set(receiver, value);

View File

@ -21,23 +21,23 @@ import android.view.inputmethod.EditorInfo;
import java.lang.reflect.Field; import java.lang.reflect.Field;
public final class EditorInfoCompatUtils { public final class EditorInfoCompatUtils {
// EditorInfo.IME_FLAG_FORCE_ASCII has been introduced since API#16 (JellyBean). // Note that EditorInfo.IME_FLAG_FORCE_ASCII has been introduced
// in API level 16 (Build.VERSION_CODES.JELLY_BEAN).
private static final Field FIELD_IME_FLAG_FORCE_ASCII = CompatUtils.getField( private static final Field FIELD_IME_FLAG_FORCE_ASCII = CompatUtils.getField(
EditorInfo.class, "IME_FLAG_FORCE_ASCII"); EditorInfo.class, "IME_FLAG_FORCE_ASCII");
private static final Integer OBJ_IME_FLAG_FORCE_ASCII = (Integer) CompatUtils private static final Integer OBJ_IME_FLAG_FORCE_ASCII = (Integer) CompatUtils.getFieldValue(
.getFieldValue(null, null, FIELD_IME_FLAG_FORCE_ASCII); null /* receiver */, null /* defaultValue */, FIELD_IME_FLAG_FORCE_ASCII);
private EditorInfoCompatUtils() { private EditorInfoCompatUtils() {
// This utility class is not publicly instantiable. // This utility class is not publicly instantiable.
} }
public static boolean hasFlagForceAscii(int imeOptions) { public static boolean hasFlagForceAscii(final int imeOptions) {
if (OBJ_IME_FLAG_FORCE_ASCII == null) if (OBJ_IME_FLAG_FORCE_ASCII == null) return false;
return false;
return (imeOptions & OBJ_IME_FLAG_FORCE_ASCII) != 0; return (imeOptions & OBJ_IME_FLAG_FORCE_ASCII) != 0;
} }
public static String imeActionName(int imeOptions) { public static String imeActionName(final int imeOptions) {
final int actionId = imeOptions & EditorInfo.IME_MASK_ACTION; final int actionId = imeOptions & EditorInfo.IME_MASK_ACTION;
switch (actionId) { switch (actionId) {
case EditorInfo.IME_ACTION_UNSPECIFIED: case EditorInfo.IME_ACTION_UNSPECIFIED:
@ -61,7 +61,7 @@ public final class EditorInfoCompatUtils {
} }
} }
public static String imeOptionsName(int imeOptions) { public static String imeOptionsName(final int imeOptions) {
final String action = imeActionName(imeOptions); final String action = imeActionName(imeOptions);
final StringBuilder flags = new StringBuilder(); final StringBuilder flags = new StringBuilder();
if ((imeOptions & EditorInfo.IME_FLAG_NO_ENTER_ACTION) != 0) { if ((imeOptions & EditorInfo.IME_FLAG_NO_ENTER_ACTION) != 0) {

View File

@ -23,6 +23,8 @@ import android.view.inputmethod.InputMethodManager;
import java.lang.reflect.Method; import java.lang.reflect.Method;
public final class InputMethodManagerCompatWrapper { public final class InputMethodManagerCompatWrapper {
// Note that InputMethodManager.switchToNextInputMethod() has been introduced
// in API level 16 (Build.VERSION_CODES.JELLY_BEAN).
private static final Method METHOD_switchToNextInputMethod = CompatUtils.getMethod( private static final Method METHOD_switchToNextInputMethod = CompatUtils.getMethod(
InputMethodManager.class, "switchToNextInputMethod", IBinder.class, Boolean.TYPE); InputMethodManager.class, "switchToNextInputMethod", IBinder.class, Boolean.TYPE);
@ -33,7 +35,7 @@ public final class InputMethodManagerCompatWrapper {
} }
public boolean switchToNextInputMethod(final IBinder token, final boolean onlyCurrentIme) { public boolean switchToNextInputMethod(final IBinder token, final boolean onlyCurrentIme) {
return (Boolean)CompatUtils.invoke(mImm, false, METHOD_switchToNextInputMethod, token, return (Boolean)CompatUtils.invoke(mImm, false /* defaultValue */,
onlyCurrentIme); METHOD_switchToNextInputMethod, token, onlyCurrentIme);
} }
} }

View File

@ -21,6 +21,8 @@ import android.inputmethodservice.InputMethodService;
import java.lang.reflect.Method; import java.lang.reflect.Method;
public final class InputMethodServiceCompatUtils { public final class InputMethodServiceCompatUtils {
// Note that InputMethodService.enableHardwareAcceleration() has been introduced
// in API level 17 (Build.VERSION_CODES.JELLY_BEAN_MR1).
private static final Method METHOD_enableHardwareAcceleration = private static final Method METHOD_enableHardwareAcceleration =
CompatUtils.getMethod(InputMethodService.class, "enableHardwareAcceleration"); CompatUtils.getMethod(InputMethodService.class, "enableHardwareAcceleration");
@ -28,7 +30,8 @@ public final class InputMethodServiceCompatUtils {
// This utility class is not publicly instantiable. // This utility class is not publicly instantiable.
} }
public static boolean enableHardwareAcceleration(InputMethodService ims) { public static boolean enableHardwareAcceleration(final InputMethodService ims) {
return (Boolean)CompatUtils.invoke(ims, false, METHOD_enableHardwareAcceleration); return (Boolean)CompatUtils.invoke(ims, false /* defaultValue */,
METHOD_enableHardwareAcceleration);
} }
} }

View File

@ -19,6 +19,8 @@ package com.android.inputmethod.compat;
import java.lang.reflect.Field; import java.lang.reflect.Field;
public final class SettingsSecureCompatUtils { public final class SettingsSecureCompatUtils {
// Note that Settings.Secure.ACCESSIBILITY_SPEAK_PASSWORD has been introduced
// in API level 15 (Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1).
private static final Field FIELD_ACCESSIBILITY_SPEAK_PASSWORD = CompatUtils.getField( private static final Field FIELD_ACCESSIBILITY_SPEAK_PASSWORD = CompatUtils.getField(
android.provider.Settings.Secure.class, "ACCESSIBILITY_SPEAK_PASSWORD"); android.provider.Settings.Secure.class, "ACCESSIBILITY_SPEAK_PASSWORD");
@ -30,5 +32,5 @@ public final class SettingsSecureCompatUtils {
* Whether to speak passwords while in accessibility mode. * Whether to speak passwords while in accessibility mode.
*/ */
public static final String ACCESSIBILITY_SPEAK_PASSWORD = (String) CompatUtils.getFieldValue( public static final String ACCESSIBILITY_SPEAK_PASSWORD = (String) CompatUtils.getFieldValue(
null, null, FIELD_ACCESSIBILITY_SPEAK_PASSWORD); null /* receiver */, null /* defaultValue */, FIELD_ACCESSIBILITY_SPEAK_PASSWORD);
} }

View File

@ -34,11 +34,12 @@ import java.util.ArrayList;
public final class SuggestionSpanUtils { public final class SuggestionSpanUtils {
private static final String TAG = SuggestionSpanUtils.class.getSimpleName(); private static final String TAG = SuggestionSpanUtils.class.getSimpleName();
// Note that SuggestionSpan.FLAG_AUTO_CORRECTION was added in API level 15. // Note that SuggestionSpan.FLAG_AUTO_CORRECTION has been introduced
public static final Field FIELD_FLAG_AUTO_CORRECTION = // in API level 15 (Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1).
CompatUtils.getField(SuggestionSpan.class, "FLAG_AUTO_CORRECTION"); public static final Field FIELD_FLAG_AUTO_CORRECTION = CompatUtils.getField(
public static final Integer OBJ_FLAG_AUTO_CORRECTION = SuggestionSpan.class, "FLAG_AUTO_CORRECTION");
(Integer) CompatUtils.getFieldValue(null, null, FIELD_FLAG_AUTO_CORRECTION); public static final Integer OBJ_FLAG_AUTO_CORRECTION = (Integer) CompatUtils.getFieldValue(
null /* receiver */, null /* defaultValue */, FIELD_FLAG_AUTO_CORRECTION);
static { static {
if (LatinImeLogger.sDBG) { if (LatinImeLogger.sDBG) {
@ -58,8 +59,9 @@ public final class SuggestionSpanUtils {
return text; return text;
} }
final Spannable spannable = new SpannableString(text); final Spannable spannable = new SpannableString(text);
final SuggestionSpan suggestionSpan = new SuggestionSpan(context, null, new String[] {}, final SuggestionSpan suggestionSpan = new SuggestionSpan(context, null /* locale */,
(int)OBJ_FLAG_AUTO_CORRECTION, SuggestionSpanPickedNotificationReceiver.class); new String[] {} /* suggestions */, (int)OBJ_FLAG_AUTO_CORRECTION,
SuggestionSpanPickedNotificationReceiver.class);
spannable.setSpan(suggestionSpan, 0, text.length(), spannable.setSpan(suggestionSpan, 0, text.length(),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE | Spanned.SPAN_COMPOSING); Spanned.SPAN_EXCLUSIVE_EXCLUSIVE | Spanned.SPAN_COMPOSING);
return spannable; return spannable;
@ -87,8 +89,8 @@ public final class SuggestionSpanUtils {
// TODO: We should avoid adding suggestion span candidates that came from the bigram // TODO: We should avoid adding suggestion span candidates that came from the bigram
// prediction. // prediction.
final SuggestionSpan suggestionSpan = new SuggestionSpan(context, null, final SuggestionSpan suggestionSpan = new SuggestionSpan(context, null /* locale */,
suggestionsList.toArray(new String[suggestionsList.size()]), 0, suggestionsList.toArray(new String[suggestionsList.size()]), 0 /* flags */,
SuggestionSpanPickedNotificationReceiver.class); SuggestionSpanPickedNotificationReceiver.class);
spannable.setSpan(suggestionSpan, 0, pickedWord.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); spannable.setSpan(suggestionSpan, 0, pickedWord.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
return spannable; return spannable;

View File

@ -21,10 +21,13 @@ import android.view.textservice.SuggestionsInfo;
import java.lang.reflect.Field; import java.lang.reflect.Field;
public final class SuggestionsInfoCompatUtils { public final class SuggestionsInfoCompatUtils {
private static final Field FIELD_RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS = CompatUtils.getField( // Note that SuggestionsInfo.RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS has been introduced
SuggestionsInfo.class, "RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS"); // in API level 15 (Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1).
private static final Integer OBJ_RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS = (Integer) CompatUtils private static final Field FIELD_RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS =
.getFieldValue(null, null, FIELD_RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS); CompatUtils.getField(SuggestionsInfo.class, "RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS");
private static final Integer OBJ_RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS =
(Integer) CompatUtils.getFieldValue(null /* receiver */, null /* defaultValue */,
FIELD_RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS);
private static final int RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS = private static final int RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS =
OBJ_RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS != null OBJ_RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS != null
? OBJ_RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS : 0; ? OBJ_RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS : 0;

View File

@ -530,7 +530,7 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
// This always needs to be set since the accessibility state can // This always needs to be set since the accessibility state can
// potentially change without the keyboard being set again. // potentially change without the keyboard being set again.
AccessibleKeyboardViewProxy.getInstance().setKeyboard(keyboard); AccessibleKeyboardViewProxy.getInstance().setKeyboard();
} }
// Note that this method is called from a non-UI thread. // Note that this method is called from a non-UI thread.

View File

@ -45,7 +45,7 @@ public final class AdditionalSubtype {
final String keyboardLayoutSetName, final String extraValue) { final String keyboardLayoutSetName, final String extraValue) {
final String layoutExtraValue = KEYBOARD_LAYOUT_SET + "=" + keyboardLayoutSetName; final String layoutExtraValue = KEYBOARD_LAYOUT_SET + "=" + keyboardLayoutSetName;
final String layoutDisplayNameExtraValue; final String layoutDisplayNameExtraValue;
if (Build.VERSION.SDK_INT >= /* JELLY_BEAN */ 15 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN
&& SubtypeLocale.isExceptionalLocale(localeString)) { && SubtypeLocale.isExceptionalLocale(localeString)) {
final String layoutDisplayName = SubtypeLocale.getKeyboardLayoutSetDisplayName( final String layoutDisplayName = SubtypeLocale.getKeyboardLayoutSetDisplayName(
keyboardLayoutSetName); keyboardLayoutSetName);

View File

@ -111,7 +111,7 @@ public final class Constants {
} }
} }
public static class TextUtils { public static final class TextUtils {
/** /**
* Capitalization mode for {@link android.text.TextUtils#getCapsMode}: don't capitalize * Capitalization mode for {@link android.text.TextUtils#getCapsMode}: don't capitalize
* characters. This value may be used with * characters. This value may be used with
@ -126,7 +126,7 @@ public final class Constants {
} }
} }
public static class Dictionary { public static final class Dictionary {
public static final int MAX_WORD_LENGTH = 48; public static final int MAX_WORD_LENGTH = 48;
private Dictionary() { private Dictionary() {

View File

@ -38,7 +38,7 @@ public final class DictionaryCollection extends Dictionary {
mDictionaries = CollectionUtils.newCopyOnWriteArrayList(); mDictionaries = CollectionUtils.newCopyOnWriteArrayList();
} }
public DictionaryCollection(final String dictType, Dictionary... dictionaries) { public DictionaryCollection(final String dictType, final Dictionary... dictionaries) {
super(dictType); super(dictType);
if (null == dictionaries) { if (null == dictionaries) {
mDictionaries = CollectionUtils.newCopyOnWriteArrayList(); mDictionaries = CollectionUtils.newCopyOnWriteArrayList();
@ -48,7 +48,7 @@ public final class DictionaryCollection extends Dictionary {
} }
} }
public DictionaryCollection(final String dictType, Collection<Dictionary> dictionaries) { public DictionaryCollection(final String dictType, final Collection<Dictionary> dictionaries) {
super(dictType); super(dictType);
mDictionaries = CollectionUtils.newCopyOnWriteArrayList(dictionaries); mDictionaries = CollectionUtils.newCopyOnWriteArrayList(dictionaries);
mDictionaries.removeAll(Collections.singleton(null)); mDictionaries.removeAll(Collections.singleton(null));

View File

@ -35,6 +35,7 @@ import android.graphics.Rect;
import android.inputmethodservice.InputMethodService; import android.inputmethodservice.InputMethodService;
import android.media.AudioManager; import android.media.AudioManager;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import android.os.Build.VERSION_CODES;
import android.os.Debug; import android.os.Debug;
import android.os.Handler; import android.os.Handler;
import android.os.HandlerThread; import android.os.HandlerThread;
@ -1318,10 +1319,8 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
return; return;
} }
// 16 is android.os.Build.VERSION_CODES.JELLY_BEAN but we can't write it because
// we want to be able to compile against the Ice Cream Sandwich SDK.
if (Constants.CODE_ENTER == code && mTargetApplicationInfo != null if (Constants.CODE_ENTER == code && mTargetApplicationInfo != null
&& mTargetApplicationInfo.targetSdkVersion < 16) { && mTargetApplicationInfo.targetSdkVersion < VERSION_CODES.JELLY_BEAN) {
// Backward compatibility mode. Before Jelly bean, the keyboard would simulate // Backward compatibility mode. Before Jelly bean, the keyboard would simulate
// a hardware keyboard event on pressing enter or delete. This is bad for many // a hardware keyboard event on pressing enter or delete. This is bad for many
// reasons (there are race conditions with commits) but some applications are // reasons (there are race conditions with commits) but some applications are
@ -1736,10 +1735,8 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
// This should never happen. // This should never happen.
Log.e(TAG, "Backspace when we don't know the selection position"); Log.e(TAG, "Backspace when we don't know the selection position");
} }
// 16 is android.os.Build.VERSION_CODES.JELLY_BEAN but we can't write it because
// we want to be able to compile against the Ice Cream Sandwich SDK.
if (mTargetApplicationInfo != null if (mTargetApplicationInfo != null
&& mTargetApplicationInfo.targetSdkVersion < 16) { && mTargetApplicationInfo.targetSdkVersion < VERSION_CODES.JELLY_BEAN) {
// Backward compatibility mode. Before Jelly bean, the keyboard would simulate // Backward compatibility mode. Before Jelly bean, the keyboard would simulate
// a hardware keyboard event on pressing enter or delete. This is bad for many // a hardware keyboard event on pressing enter or delete. This is bad for many
// reasons (there are race conditions with commits) but some applications are // reasons (there are race conditions with commits) but some applications are

View File

@ -29,7 +29,7 @@ import android.view.inputmethod.EditorInfo;
* the IME needs to take a note of what it has to replace and where it is. * the IME needs to take a note of what it has to replace and where it is.
* This class encapsulates this data. * This class encapsulates this data.
*/ */
public class PositionalInfoForUserDictPendingAddition { public final class PositionalInfoForUserDictPendingAddition {
final private String mOriginalWord; final private String mOriginalWord;
final private int mCursorPos; // Position of the cursor after the word final private int mCursorPos; // Position of the cursor after the word
final private EditorInfo mEditorInfo; // On what binding this has been added final private EditorInfo mEditorInfo; // On what binding this has been added

View File

@ -284,40 +284,40 @@ public final class RichInputConnection {
if (DEBUG_BATCH_NESTING) checkBatchEdit(); if (DEBUG_BATCH_NESTING) checkBatchEdit();
if (keyEvent.getAction() == KeyEvent.ACTION_DOWN) { if (keyEvent.getAction() == KeyEvent.ACTION_DOWN) {
if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug(); if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug();
// This method is only called for enter or backspace when speaking to old // This method is only called for enter or backspace when speaking to old applications
// applications (target SDK <= 15), or for digits. // (target SDK <= 15 (Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1)), or for digits.
// When talking to new applications we never use this method because it's inherently // When talking to new applications we never use this method because it's inherently
// racy and has unpredictable results, but for backward compatibility we continue // racy and has unpredictable results, but for backward compatibility we continue
// sending the key events for only Enter and Backspace because some applications // sending the key events for only Enter and Backspace because some applications
// mistakenly catch them to do some stuff. // mistakenly catch them to do some stuff.
switch (keyEvent.getKeyCode()) { switch (keyEvent.getKeyCode()) {
case KeyEvent.KEYCODE_ENTER: case KeyEvent.KEYCODE_ENTER:
mCommittedTextBeforeComposingText.append("\n"); mCommittedTextBeforeComposingText.append("\n");
mCurrentCursorPosition += 1; mCurrentCursorPosition += 1;
break; break;
case KeyEvent.KEYCODE_DEL: case KeyEvent.KEYCODE_DEL:
if (0 == mComposingText.length()) { if (0 == mComposingText.length()) {
if (mCommittedTextBeforeComposingText.length() > 0) { if (mCommittedTextBeforeComposingText.length() > 0) {
mCommittedTextBeforeComposingText.delete( mCommittedTextBeforeComposingText.delete(
mCommittedTextBeforeComposingText.length() - 1, mCommittedTextBeforeComposingText.length() - 1,
mCommittedTextBeforeComposingText.length()); mCommittedTextBeforeComposingText.length());
}
} else {
mComposingText.delete(mComposingText.length() - 1, mComposingText.length());
} }
if (mCurrentCursorPosition > 0) mCurrentCursorPosition -= 1; } else {
break; mComposingText.delete(mComposingText.length() - 1, mComposingText.length());
case KeyEvent.KEYCODE_UNKNOWN: }
if (null != keyEvent.getCharacters()) { if (mCurrentCursorPosition > 0) mCurrentCursorPosition -= 1;
mCommittedTextBeforeComposingText.append(keyEvent.getCharacters()); break;
mCurrentCursorPosition += keyEvent.getCharacters().length(); case KeyEvent.KEYCODE_UNKNOWN:
} if (null != keyEvent.getCharacters()) {
break; mCommittedTextBeforeComposingText.append(keyEvent.getCharacters());
default: mCurrentCursorPosition += keyEvent.getCharacters().length();
final String text = new String(new int[] { keyEvent.getUnicodeChar() }, 0, 1); }
mCommittedTextBeforeComposingText.append(text); break;
mCurrentCursorPosition += text.length(); default:
break; final String text = new String(new int[] { keyEvent.getUnicodeChar() }, 0, 1);
mCommittedTextBeforeComposingText.append(text);
mCurrentCursorPosition += text.length();
break;
} }
} }
if (null != mIC) { if (null != mIC) {

View File

@ -130,7 +130,8 @@ public final class SubtypeLocale {
} }
public static int getSubtypeNameId(String localeString, String keyboardLayoutName) { public static int getSubtypeNameId(String localeString, String keyboardLayoutName) {
if (Build.VERSION.SDK_INT >= /* JELLY_BEAN */ 15 && isExceptionalLocale(localeString)) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN
&& isExceptionalLocale(localeString)) {
return sExceptionalLocaleToWithLayoutNameIdsMap.get(localeString); return sExceptionalLocaleToWithLayoutNameIdsMap.get(localeString);
} }
final String key = localeString.equals(NO_LANGUAGE) final String key = localeString.equals(NO_LANGUAGE)
@ -166,8 +167,9 @@ public final class SubtypeLocale {
// zz azerty T No language (AZERTY) in system locale // zz azerty T No language (AZERTY) in system locale
public static String getSubtypeDisplayName(final InputMethodSubtype subtype, Resources res) { public static String getSubtypeDisplayName(final InputMethodSubtype subtype, Resources res) {
final String replacementString = (Build.VERSION.SDK_INT >= /* JELLY_BEAN */ 15 final String replacementString =
&& subtype.containsExtraValueKey(UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME)) (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN
&& subtype.containsExtraValueKey(UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME))
? subtype.getExtraValueOf(UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME) ? subtype.getExtraValueOf(UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME)
: getSubtypeLocaleDisplayName(subtype.getLocale()); : getSubtypeLocaleDisplayName(subtype.getLocale());
final int nameResId = subtype.getNameResId(); final int nameResId = subtype.getNameResId();

View File

@ -24,6 +24,7 @@ import android.content.Intent;
import android.database.ContentObserver; import android.database.ContentObserver;
import android.database.Cursor; import android.database.Cursor;
import android.net.Uri; import android.net.Uri;
import android.os.Build;
import android.provider.UserDictionary.Words; import android.provider.UserDictionary.Words;
import android.text.TextUtils; import android.text.TextUtils;
@ -43,8 +44,7 @@ public class UserBinaryDictionary extends ExpandableBinaryDictionary {
final static String SHORTCUT = "shortcut"; final static String SHORTCUT = "shortcut";
private static final String[] PROJECTION_QUERY; private static final String[] PROJECTION_QUERY;
static { static {
// 16 is JellyBean, but we want this to compile against ICS. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
if (android.os.Build.VERSION.SDK_INT >= 16) {
PROJECTION_QUERY = new String[] { PROJECTION_QUERY = new String[] {
Words.WORD, Words.WORD,
SHORTCUT, SHORTCUT,
@ -90,13 +90,14 @@ public class UserBinaryDictionary extends ExpandableBinaryDictionary {
mObserver = new ContentObserver(null) { mObserver = new ContentObserver(null) {
@Override @Override
public void onChange(final boolean self) { public void onChange(final boolean self) {
// This hook is deprecated as of API level 16, but should still be supported for // This hook is deprecated as of API level 16 (Build.VERSION_CODES.JELLY_BEAN),
// cases where the IME is running on an older version of the platform. // but should still be supported for cases where the IME is running on an older
// version of the platform.
onChange(self, null); onChange(self, null);
} }
// The following hook is only available as of API level 16, and as such it will only // The following hook is only available as of API level 16
// work on JellyBean+ devices. On older versions of the platform, the hook // (Build.VERSION_CODES.JELLY_BEAN), and as such it will only work on JellyBean+
// above will be called instead. // devices. On older versions of the platform, the hook above will be called instead.
@Override @Override
public void onChange(final boolean self, final Uri uri) { public void onChange(final boolean self, final Uri uri) {
setRequiresReload(true); setRequiresReload(true);
@ -233,8 +234,7 @@ public class UserBinaryDictionary extends ExpandableBinaryDictionary {
} }
private void addWords(final Cursor cursor) { private void addWords(final Cursor cursor) {
// 16 is JellyBean, but we want this to compile against ICS. final boolean hasShortcutColumn = Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN;
final boolean hasShortcutColumn = android.os.Build.VERSION.SDK_INT >= 16;
clearFusionDictionary(); clearFusionDictionary();
if (cursor == null) return; if (cursor == null) return;
if (cursor.moveToFirst()) { if (cursor.moveToFirst()) {

View File

@ -48,6 +48,7 @@ public final class UserHistoryDictIOUtils {
public void setBigram(final String word1, final String word2, final int frequency); public void setBigram(final String word1, final String word2, final int frequency);
} }
@UsedForTesting
public interface BigramDictionaryInterface { public interface BigramDictionaryInterface {
public int getFrequency(final String word1, final String word2); public int getFrequency(final String word1, final String word2);
} }
@ -214,4 +215,4 @@ public final class UserHistoryDictIOUtils {
} }
} }
} }

View File

@ -18,6 +18,8 @@ package com.android.inputmethod.latin;
import android.util.Log; import android.util.Log;
import com.android.inputmethod.annotations.UsedForTesting;
import java.util.HashMap; import java.util.HashMap;
import java.util.Set; import java.util.Set;
@ -26,6 +28,7 @@ import java.util.Set;
* All bigrams including stale ones in SQL DB should be stored in this class to avoid adding stale * All bigrams including stale ones in SQL DB should be stored in this class to avoid adding stale
* bigrams when we write to the SQL DB. * bigrams when we write to the SQL DB.
*/ */
@UsedForTesting
public final class UserHistoryDictionaryBigramList { public final class UserHistoryDictionaryBigramList {
public static final byte FORGETTING_CURVE_INITIAL_VALUE = 0; public static final byte FORGETTING_CURVE_INITIAL_VALUE = 0;
private static final String TAG = UserHistoryDictionaryBigramList.class.getSimpleName(); private static final String TAG = UserHistoryDictionaryBigramList.class.getSimpleName();

View File

@ -61,7 +61,7 @@ public final class Utils {
} }
} }
/* package */ static class RingCharBuffer { /* package */ static final class RingCharBuffer {
private static RingCharBuffer sRingCharBuffer = new RingCharBuffer(); private static RingCharBuffer sRingCharBuffer = new RingCharBuffer();
private static final char PLACEHOLDER_DELIMITER_CHAR = '\uFFFC'; private static final char PLACEHOLDER_DELIMITER_CHAR = '\uFFFC';
private static final int INVALID_COORDINATE = -2; private static final int INVALID_COORDINATE = -2;
@ -203,7 +203,7 @@ public final class Utils {
} }
// Initialization-on-demand holder // Initialization-on-demand holder
private static class OnDemandInitializationHolder { private static final class OnDemandInitializationHolder {
public static final UsabilityStudyLogUtils sInstance = new UsabilityStudyLogUtils(); public static final UsabilityStudyLogUtils sInstance = new UsabilityStudyLogUtils();
} }

View File

@ -56,6 +56,7 @@ public final class BinaryDictInputOutput {
private static final int MAX_PASSES = 24; private static final int MAX_PASSES = 24;
private static final int MAX_JUMPS = 12; private static final int MAX_JUMPS = 12;
@UsedForTesting
public interface FusionDictionaryBufferInterface { public interface FusionDictionaryBufferInterface {
public int readUnsignedByte(); public int readUnsignedByte();
public int readUnsignedShort(); public int readUnsignedShort();

View File

@ -16,6 +16,7 @@
package com.android.inputmethod.latin.makedict; package com.android.inputmethod.latin.makedict;
import com.android.inputmethod.annotations.UsedForTesting;
import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.Constants;
import java.util.ArrayList; import java.util.ArrayList;
@ -29,6 +30,7 @@ import java.util.LinkedList;
/** /**
* A dictionary that can fusion heads and tails of words for more compression. * A dictionary that can fusion heads and tails of words for more compression.
*/ */
@UsedForTesting
public final class FusionDictionary implements Iterable<Word> { public final class FusionDictionary implements Iterable<Word> {
private static final boolean DBG = MakedictLog.DBG; private static final boolean DBG = MakedictLog.DBG;