Merge "New API to allow third-party apps to bind widgets"
diff --git a/api/current.txt b/api/current.txt
index d10d4c5..408d044 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5321,6 +5321,7 @@
field public static final int MODE_WORLD_WRITEABLE = 2; // 0x2
field public static final java.lang.String NFC_SERVICE = "nfc";
field public static final java.lang.String NOTIFICATION_SERVICE = "notification";
+ field public static final java.lang.String NSD_SERVICE = "servicediscovery";
field public static final java.lang.String POWER_SERVICE = "power";
field public static final java.lang.String SEARCH_SERVICE = "search";
field public static final java.lang.String SENSOR_SERVICE = "sensor";
@@ -24082,11 +24083,7 @@
field public static final int ACCESSIBILITY_FOCUS_BACKWARD = 4097; // 0x1001
field public static final int ACCESSIBILITY_FOCUS_DOWN = 4226; // 0x1082
field public static final int ACCESSIBILITY_FOCUS_FORWARD = 4098; // 0x1002
- field public static final int ACCESSIBILITY_FOCUS_IN = 4100; // 0x1004
field public static final int ACCESSIBILITY_FOCUS_LEFT = 4113; // 0x1011
- field public static final int ACCESSIBILITY_FOCUS_NEXT = 4112; // 0x1010
- field public static final int ACCESSIBILITY_FOCUS_OUT = 4104; // 0x1008
- field public static final int ACCESSIBILITY_FOCUS_PREVIOUS = 4128; // 0x1020
field public static final int ACCESSIBILITY_FOCUS_RIGHT = 4162; // 0x1042
field public static final int ACCESSIBILITY_FOCUS_UP = 4129; // 0x1021
field public static final android.util.Property ALPHA;
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 1abb7de..0519d3e 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -1538,6 +1538,9 @@
FragmentManagerImpl.VIEW_STATE_TAG, f.mSavedViewState);
}
if (!f.mUserVisibleHint) {
+ if (result == null) {
+ result = new Bundle();
+ }
// Only add this if it's not the default value
result.putBoolean(FragmentManagerImpl.USER_VISIBLE_HINT_TAG, f.mUserVisibleHint);
}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 381daa3..4c169d38 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -1770,12 +1770,11 @@
/**
* Use with {@link #getSystemService} to retrieve a {@link
- * android.net.NsdManager} for handling management of network service
+ * android.net.nsd.NsdManager} for handling management of network service
* discovery
*
- * @hide
* @see #getSystemService
- * @see android.net.NsdManager
+ * @see android.net.nsd.NsdManager
*/
public static final String NSD_SERVICE = "servicediscovery";
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 0ba7b88..1df53e8 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -92,6 +92,12 @@
public static final int MEDIA_UID = 1013;
/**
+ * Defines the UID/GID for the DRM process.
+ * @hide
+ */
+ public static final int DRM_UID = 1019;
+
+ /**
* Defines the GID for the group that allows write access to the SD card.
* @hide
*/
diff --git a/core/java/android/provider/CalendarContract.java b/core/java/android/provider/CalendarContract.java
index 593762a..09bf42b 100644
--- a/core/java/android/provider/CalendarContract.java
+++ b/core/java/android/provider/CalendarContract.java
@@ -1354,6 +1354,8 @@
GUESTS_CAN_INVITE_OTHERS);
DatabaseUtils.cursorIntToContentValuesIfPresent(cursor, cv, GUESTS_CAN_MODIFY);
DatabaseUtils.cursorIntToContentValuesIfPresent(cursor, cv, GUESTS_CAN_SEE_GUESTS);
+ DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, CUSTOM_APP_PACKAGE);
+ DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, CUSTOM_APP_URI);
DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, ORGANIZER);
DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, _SYNC_ID);
DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, cv, DIRTY);
@@ -1556,6 +1558,8 @@
* <li>{@link #GUESTS_CAN_MODIFY}</li>
* <li>{@link #GUESTS_CAN_INVITE_OTHERS}</li>
* <li>{@link #GUESTS_CAN_SEE_GUESTS}</li>
+ * <li>{@link #CUSTOM_APP_PACKAGE}</li>
+ * <li>{@link #CUSTOM_APP_URI}</li>
* </ul>
* The following Events columns are writable only by a sync adapter
* <ul>
diff --git a/core/java/android/text/SpannableStringBuilder.java b/core/java/android/text/SpannableStringBuilder.java
index ea9f650..c5e2c42 100644
--- a/core/java/android/text/SpannableStringBuilder.java
+++ b/core/java/android/text/SpannableStringBuilder.java
@@ -428,6 +428,12 @@
final int origLen = end - start;
final int newLen = tbend - tbstart;
+ if (origLen == 0 && newLen == 0 && !hasNonExclusiveExclusiveSpanAt(tb, tbstart)) {
+ // This is a no-op iif there are no spans in tb that would be added (with a 0-length)
+ // Early exit so that the text watchers do not get notified
+ return this;
+ }
+
TextWatcher[] textWatchers = getSpans(start, start + origLen, TextWatcher.class);
sendBeforeTextChanged(textWatchers, start, origLen, newLen);
@@ -470,6 +476,20 @@
return this;
}
+ private static boolean hasNonExclusiveExclusiveSpanAt(CharSequence text, int offset) {
+ if (text instanceof Spanned) {
+ Spanned spanned = (Spanned) text;
+ Object[] spans = spanned.getSpans(offset, offset, Object.class);
+ final int length = spans.length;
+ for (int i = 0; i < length; i++) {
+ Object span = spans[i];
+ int flags = spanned.getSpanFlags(span);
+ if (flags != Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) return true;
+ }
+ }
+ return false;
+ }
+
private void sendToSpanWatchers(int replaceStart, int replaceEnd, int nbNewChars) {
for (int i = 0; i < mSpanCountBeforeAdd; i++) {
int spanStart = mSpanStarts[i];
diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java
index 7d569ad..6387148 100644
--- a/core/java/android/view/AccessibilityInteractionController.java
+++ b/core/java/android/view/AccessibilityInteractionController.java
@@ -662,29 +662,31 @@
ViewGroup parentGroup = (ViewGroup) parent;
ChildListForAccessibility children = ChildListForAccessibility.obtain(parentGroup,
false);
- final int childCount = children.getChildCount();
- for (int i = 0; i < childCount; i++) {
- if (outInfos.size() >= MAX_ACCESSIBILITY_NODE_INFO_BATCH_SIZE) {
- children.recycle();
- return;
- }
- View child = children.getChildAt(i);
- if (child.getAccessibilityViewId() != current.getAccessibilityViewId()
- && child.isDisplayedOnScreen()) {
- AccessibilityNodeInfo info = null;
- AccessibilityNodeProvider provider = child.getAccessibilityNodeProvider();
- if (provider == null) {
- info = child.createAccessibilityNodeInfo();
- } else {
- info = provider.createAccessibilityNodeInfo(
- AccessibilityNodeInfo.UNDEFINED);
+ try {
+ final int childCount = children.getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ if (outInfos.size() >= MAX_ACCESSIBILITY_NODE_INFO_BATCH_SIZE) {
+ return;
}
- if (info != null) {
- outInfos.add(info);
+ View child = children.getChildAt(i);
+ if (child.getAccessibilityViewId() != current.getAccessibilityViewId()
+ && child.isDisplayedOnScreen()) {
+ AccessibilityNodeInfo info = null;
+ AccessibilityNodeProvider provider = child.getAccessibilityNodeProvider();
+ if (provider == null) {
+ info = child.createAccessibilityNodeInfo();
+ } else {
+ info = provider.createAccessibilityNodeInfo(
+ AccessibilityNodeInfo.UNDEFINED);
+ }
+ if (info != null) {
+ outInfos.add(info);
+ }
}
}
+ } finally {
+ children.recycle();
}
- children.recycle();
}
}
@@ -697,32 +699,34 @@
HashMap<View, AccessibilityNodeInfo> addedChildren =
new HashMap<View, AccessibilityNodeInfo>();
ChildListForAccessibility children = ChildListForAccessibility.obtain(rootGroup, false);
- final int childCount = children.getChildCount();
- for (int i = 0; i < childCount; i++) {
- if (outInfos.size() >= MAX_ACCESSIBILITY_NODE_INFO_BATCH_SIZE) {
- children.recycle();
- return;
- }
- View child = children.getChildAt(i);
- if (child.isDisplayedOnScreen()) {
- AccessibilityNodeProvider provider = child.getAccessibilityNodeProvider();
- if (provider == null) {
- AccessibilityNodeInfo info = child.createAccessibilityNodeInfo();
- if (info != null) {
- outInfos.add(info);
- addedChildren.put(child, null);
- }
- } else {
- AccessibilityNodeInfo info = provider.createAccessibilityNodeInfo(
- AccessibilityNodeInfo.UNDEFINED);
- if (info != null) {
- outInfos.add(info);
- addedChildren.put(child, info);
+ try {
+ final int childCount = children.getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ if (outInfos.size() >= MAX_ACCESSIBILITY_NODE_INFO_BATCH_SIZE) {
+ return;
+ }
+ View child = children.getChildAt(i);
+ if (child.isDisplayedOnScreen()) {
+ AccessibilityNodeProvider provider = child.getAccessibilityNodeProvider();
+ if (provider == null) {
+ AccessibilityNodeInfo info = child.createAccessibilityNodeInfo();
+ if (info != null) {
+ outInfos.add(info);
+ addedChildren.put(child, null);
+ }
+ } else {
+ AccessibilityNodeInfo info = provider.createAccessibilityNodeInfo(
+ AccessibilityNodeInfo.UNDEFINED);
+ if (info != null) {
+ outInfos.add(info);
+ addedChildren.put(child, info);
+ }
}
}
}
+ } finally {
+ children.recycle();
}
- children.recycle();
if (outInfos.size() < MAX_ACCESSIBILITY_NODE_INFO_BATCH_SIZE) {
for (Map.Entry<View, AccessibilityNodeInfo> entry : addedChildren.entrySet()) {
View addedChild = entry.getKey();
diff --git a/core/java/android/view/FocusFinder.java b/core/java/android/view/FocusFinder.java
index 8a01c15..98375ae 100644
--- a/core/java/android/view/FocusFinder.java
+++ b/core/java/android/view/FocusFinder.java
@@ -17,12 +17,10 @@
package android.view;
import android.graphics.Rect;
-import android.view.ViewGroup.ChildListForAccessibility;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
-import java.util.Stack;
/**
* The algorithm used for finding the next focusable view in a given direction
@@ -30,7 +28,7 @@
*/
public class FocusFinder {
- private static ThreadLocal<FocusFinder> tlFocusFinder =
+ private static final ThreadLocal<FocusFinder> tlFocusFinder =
new ThreadLocal<FocusFinder>() {
@Override
protected FocusFinder initialValue() {
@@ -45,15 +43,13 @@
return tlFocusFinder.get();
}
- Rect mFocusedRect = new Rect();
- Rect mOtherRect = new Rect();
- Rect mBestCandidateRect = new Rect();
- SequentialFocusComparator mSequentialFocusComparator = new SequentialFocusComparator();
+ final Rect mFocusedRect = new Rect();
+ final Rect mOtherRect = new Rect();
+ final Rect mBestCandidateRect = new Rect();
+ final SequentialFocusComparator mSequentialFocusComparator = new SequentialFocusComparator();
private final ArrayList<View> mTempList = new ArrayList<View>();
- private Stack<View> mTempStack;
-
// enforce thread local access
private FocusFinder() {}
@@ -78,149 +74,116 @@
* @return The next focusable view, or null if none exists.
*/
public View findNextFocusFromRect(ViewGroup root, Rect focusedRect, int direction) {
- return findNextFocus(root, null, focusedRect, direction);
+ mFocusedRect.set(focusedRect);
+ return findNextFocus(root, null, mFocusedRect, direction);
}
private View findNextFocus(ViewGroup root, View focused, Rect focusedRect, int direction) {
if ((direction & View.FOCUS_ACCESSIBILITY) != View.FOCUS_ACCESSIBILITY) {
return findNextInputFocus(root, focused, focusedRect, direction);
} else {
- return findNextAccessibilityFocus(root, focused, direction);
+ return findNextAccessibilityFocus(root, focused, focusedRect, direction);
}
}
private View findNextInputFocus(ViewGroup root, View focused, Rect focusedRect, int direction) {
+ View next = null;
if (focused != null) {
- // check for user specified next focus
- View userSetNextFocus = focused.findUserSetNextFocus(root, direction);
- if (userSetNextFocus != null &&
- userSetNextFocus.isFocusable() &&
- (!userSetNextFocus.isInTouchMode() ||
- userSetNextFocus.isFocusableInTouchMode())) {
- return userSetNextFocus;
+ next = findNextUserSpecifiedInputFocus(root, focused, direction);
+ }
+ if (next != null) {
+ return next;
+ }
+ ArrayList<View> focusables = mTempList;
+ try {
+ focusables.clear();
+ root.addFocusables(focusables, direction);
+ if (!focusables.isEmpty()) {
+ next = findNextFocus(root, focused, focusedRect, direction, focusables);
}
+ } finally {
+ focusables.clear();
+ }
+ return next;
+ }
+ private View findNextUserSpecifiedInputFocus(ViewGroup root, View focused, int direction) {
+ // check for user specified next focus
+ View userSetNextFocus = focused.findUserSetNextFocus(root, direction);
+ if (userSetNextFocus != null && userSetNextFocus.isFocusable()
+ && (!userSetNextFocus.isInTouchMode()
+ || userSetNextFocus.isFocusableInTouchMode())) {
+ return userSetNextFocus;
+ }
+ return null;
+ }
+
+ private View findNextFocus(ViewGroup root, View focused, Rect focusedRect,
+ int direction, ArrayList<View> focusables) {
+ final int directionMasked = (direction & ~View.FOCUS_ACCESSIBILITY);
+ if (focused != null) {
// fill in interesting rect from focused
- focused.getFocusedRect(mFocusedRect);
- root.offsetDescendantRectToMyCoords(focused, mFocusedRect);
+ focused.getFocusedRect(focusedRect);
+ root.offsetDescendantRectToMyCoords(focused, focusedRect);
} else {
// make up a rect at top left or bottom right of root
- switch (direction) {
+ switch (directionMasked) {
case View.FOCUS_RIGHT:
case View.FOCUS_DOWN:
- setFocusTopLeft(root);
+ setFocusTopLeft(root, focusedRect);
break;
case View.FOCUS_FORWARD:
if (root.isLayoutRtl()) {
- setFocusBottomRight(root);
+ setFocusBottomRight(root, focusedRect);
} else {
- setFocusTopLeft(root);
+ setFocusTopLeft(root, focusedRect);
}
break;
case View.FOCUS_LEFT:
case View.FOCUS_UP:
- setFocusBottomRight(root);
+ setFocusBottomRight(root, focusedRect);
break;
case View.FOCUS_BACKWARD:
if (root.isLayoutRtl()) {
- setFocusTopLeft(root);
+ setFocusTopLeft(root, focusedRect);
} else {
- setFocusBottomRight(root);
+ setFocusBottomRight(root, focusedRect);
break;
}
}
}
- ArrayList<View> focusables = mTempList;
- focusables.clear();
- root.addFocusables(focusables, direction);
- if (focusables.isEmpty()) {
- // The focus cannot change.
- return null;
+ switch (directionMasked) {
+ case View.FOCUS_FORWARD:
+ case View.FOCUS_BACKWARD:
+ return findNextInputFocusInRelativeDirection(focusables, root, focused, focusedRect,
+ directionMasked);
+ case View.FOCUS_UP:
+ case View.FOCUS_DOWN:
+ case View.FOCUS_LEFT:
+ case View.FOCUS_RIGHT:
+ return findNextInputFocusInAbsoluteDirection(focusables, root, focused,
+ focusedRect, directionMasked);
+ default:
+ throw new IllegalArgumentException("Unknown direction: " + directionMasked);
}
+ }
+ private View findNextAccessibilityFocus(ViewGroup root, View focused,
+ Rect focusedRect, int direction) {
+ ArrayList<View> focusables = mTempList;
try {
- switch (direction) {
- case View.FOCUS_FORWARD:
- case View.FOCUS_BACKWARD:
- return findNextInputFocusInRelativeDirection(focusables, root, focused,
- focusedRect, direction);
- case View.FOCUS_UP:
- case View.FOCUS_DOWN:
- case View.FOCUS_LEFT:
- case View.FOCUS_RIGHT:
- return findNextInputFocusInAbsoluteDirection(focusables, root, focused,
- focusedRect, direction);
- default:
- throw new IllegalArgumentException("Unknown direction: " + direction);
- }
+ focusables.clear();
+ root.addFocusables(focusables, direction, View.FOCUSABLES_ACCESSIBILITY);
+ View next = findNextFocus(root, focused, focusedRect, direction,
+ focusables);
+ return next;
} finally {
focusables.clear();
}
}
- /**
- * Find the next view to take accessibility focus in root's descendants,
- * starting from the view that currently is accessibility focused.
- *
- * @param root The root which also contains the focused view.
- * @param focused The current accessibility focused view.
- * @param direction Direction to look.
- * @return The next focusable view, or null if none exists.
- */
- private View findNextAccessibilityFocus(ViewGroup root, View focused, int direction) {
- switch (direction) {
- case View.ACCESSIBILITY_FOCUS_IN:
- case View.ACCESSIBILITY_FOCUS_OUT:
- case View.ACCESSIBILITY_FOCUS_FORWARD:
- case View.ACCESSIBILITY_FOCUS_BACKWARD: {
- return findNextHierarchicalAcessibilityFocus(root, focused, direction);
- }
- case View.ACCESSIBILITY_FOCUS_LEFT:
- case View.ACCESSIBILITY_FOCUS_RIGHT:
- case View.ACCESSIBILITY_FOCUS_UP:
- case View.ACCESSIBILITY_FOCUS_DOWN: {
- return findNextDirectionalAccessibilityFocus(root, focused, direction);
- }
- default:
- throw new IllegalArgumentException("Unknown direction: " + direction);
- }
- }
-
- private View findNextHierarchicalAcessibilityFocus(ViewGroup root, View focused,
- int direction) {
- View current = (focused != null) ? focused : root;
- switch (direction) {
- case View.ACCESSIBILITY_FOCUS_IN: {
- return findNextAccessibilityFocusIn(current);
- }
- case View.ACCESSIBILITY_FOCUS_OUT: {
- return findNextAccessibilityFocusOut(current);
- }
- case View.ACCESSIBILITY_FOCUS_FORWARD: {
- return findNextAccessibilityFocusForward(current);
- }
- case View.ACCESSIBILITY_FOCUS_BACKWARD: {
- return findNextAccessibilityFocusBackward(current);
- }
- }
- return null;
- }
-
- private View findNextDirectionalAccessibilityFocus(ViewGroup root, View focused,
- int direction) {
- ArrayList<View> focusables = mTempList;
- focusables.clear();
- root.addFocusables(focusables, direction, View.FOCUSABLES_ACCESSIBILITY);
- Rect focusedRect = getFocusedRect(root, focused, direction);
- final int inputFocusDirection = getCorrespondingInputFocusDirection(direction);
- View next = findNextInputFocusInAbsoluteDirection(focusables, root,
- focused, focusedRect, inputFocusDirection);
- focusables.clear();
- return next;
- }
-
private View findNextInputFocusInRelativeDirection(ArrayList<View> focusables, ViewGroup root,
View focused, Rect focusedRect, int direction) {
try {
@@ -241,17 +204,16 @@
return focusables.get(count - 1);
}
- private void setFocusBottomRight(ViewGroup root) {
+ private void setFocusBottomRight(ViewGroup root, Rect focusedRect) {
final int rootBottom = root.getScrollY() + root.getHeight();
final int rootRight = root.getScrollX() + root.getWidth();
- mFocusedRect.set(rootRight, rootBottom,
- rootRight, rootBottom);
+ focusedRect.set(rootRight, rootBottom, rootRight, rootBottom);
}
- private void setFocusTopLeft(ViewGroup root) {
+ private void setFocusTopLeft(ViewGroup root, Rect focusedRect) {
final int rootTop = root.getScrollY();
final int rootLeft = root.getScrollX();
- mFocusedRect.set(rootLeft, rootTop, rootLeft, rootTop);
+ focusedRect.set(rootLeft, rootTop, rootLeft, rootTop);
}
View findNextInputFocusInAbsoluteDirection(ArrayList<View> focusables, ViewGroup root, View focused,
@@ -294,140 +256,6 @@
return closest;
}
- private View findNextAccessibilityFocusIn(View view) {
- // We have to traverse the full view tree to make sure
- // we consider views in the order specified by their
- // parent layout managers since some managers could be
- // LTR while some could be RTL.
- if (mTempStack == null) {
- mTempStack = new Stack<View>();
- }
- Stack<View> fringe = mTempStack;
- fringe.clear();
- fringe.add(view);
- while (!fringe.isEmpty()) {
- View current = fringe.pop();
- if (current.getAccessibilityNodeProvider() != null) {
- fringe.clear();
- return current;
- }
- if (current != view && current.includeForAccessibility()) {
- fringe.clear();
- return current;
- }
- if (current instanceof ViewGroup) {
- ViewGroup currentGroup = (ViewGroup) current;
- ChildListForAccessibility children = ChildListForAccessibility.obtain(
- currentGroup, true);
- final int childCount = children.getChildCount();
- for (int i = childCount - 1; i >= 0; i--) {
- fringe.push(children.getChildAt(i));
- }
- children.recycle();
- }
- }
- return null;
- }
-
- private View findNextAccessibilityFocusOut(View view) {
- ViewParent parent = view.getParentForAccessibility();
- if (parent instanceof View) {
- return (View) parent;
- }
- return null;
- }
-
- private View findNextAccessibilityFocusForward(View view) {
- // We have to traverse the full view tree to make sure
- // we consider views in the order specified by their
- // parent layout managers since some managers could be
- // LTR while some could be RTL.
- View current = view;
- while (current != null) {
- ViewParent parent = current.getParent();
- if (!(parent instanceof ViewGroup)) {
- return null;
- }
- ViewGroup parentGroup = (ViewGroup) parent;
- // Ask the parent to find a sibling after the current view
- // that can take accessibility focus.
- ChildListForAccessibility children = ChildListForAccessibility.obtain(
- parentGroup, true);
- final int fromIndex = children.getChildIndex(current) + 1;
- final int childCount = children.getChildCount();
- for (int i = fromIndex; i < childCount; i++) {
- View child = children.getChildAt(i);
- View next = null;
- if (child.getAccessibilityNodeProvider() != null) {
- next = child;
- } else if (child.includeForAccessibility()) {
- next = child;
- } else {
- next = findNextAccessibilityFocusIn(child);
- }
- if (next != null) {
- children.recycle();
- return next;
- }
- }
- children.recycle();
- // Reaching a regarded for accessibility predecessor without
- // finding a next view to take focus means that at this level
- // there is no next accessibility focusable sibling.
- if (parentGroup.includeForAccessibility()) {
- return null;
- }
- // Try asking a predecessor to find a focusable.
- current = parentGroup;
- }
- return null;
- }
-
- private View findNextAccessibilityFocusBackward(View view) {
- // We have to traverse the full view tree to make sure
- // we consider views in the order specified by their
- // parent layout managers since some managers could be
- // LTR while some could be RTL.
- View current = view;
- while (current != null) {
- ViewParent parent = current.getParent();
- if (!(parent instanceof ViewGroup)) {
- return null;
- }
- ViewGroup parentGroup = (ViewGroup) parent;
- // Ask the parent to find a sibling after the current view
- // to take accessibility focus
- ChildListForAccessibility children = ChildListForAccessibility.obtain(
- parentGroup, true);
- final int fromIndex = children.getChildIndex(current) - 1;
- for (int i = fromIndex; i >= 0; i--) {
- View child = children.getChildAt(i);
- View next = null;
- if (child.getAccessibilityNodeProvider() != null) {
- next = child;
- } else if (child.includeForAccessibility()) {
- next = child;
- } else {
- next = findNextAccessibilityFocusIn(child);
- }
- if (next != null) {
- children.recycle();
- return next;
- }
- }
- children.recycle();
- // Reaching a regarded for accessibility predecessor without
- // finding a previous view to take focus means that at this level
- // there is no previous accessibility focusable sibling.
- if (parentGroup.includeForAccessibility()) {
- return null;
- }
- // Try asking a predecessor to find a focusable.
- current = parentGroup;
- }
- return null;
- }
-
private static View getForwardFocusable(ViewGroup root, View focused,
ArrayList<View> focusables, int count) {
return (root.isLayoutRtl()) ?
@@ -462,47 +290,6 @@
return focusables.get(count - 1);
}
- private Rect getFocusedRect(ViewGroup root, View focused, int direction) {
- Rect focusedRect = mFocusedRect;
- if (focused != null) {
- focused.getFocusedRect(focusedRect);
- root.offsetDescendantRectToMyCoords(focused, focusedRect);
- } else {
- switch (direction) {
- case View.FOCUS_RIGHT:
- case View.FOCUS_DOWN:
- final int rootTop = root.getScrollY();
- final int rootLeft = root.getScrollX();
- focusedRect.set(rootLeft, rootTop, rootLeft, rootTop);
- break;
-
- case View.FOCUS_LEFT:
- case View.FOCUS_UP:
- final int rootBottom = root.getScrollY() + root.getHeight();
- final int rootRight = root.getScrollX() + root.getWidth();
- focusedRect.set(rootRight, rootBottom, rootRight, rootBottom);
- break;
- }
- }
- return focusedRect;
- }
-
- private int getCorrespondingInputFocusDirection(int accessFocusDirection) {
- switch (accessFocusDirection) {
- case View.ACCESSIBILITY_FOCUS_LEFT:
- return View.FOCUS_LEFT;
- case View.ACCESSIBILITY_FOCUS_RIGHT:
- return View.FOCUS_RIGHT;
- case View.ACCESSIBILITY_FOCUS_UP:
- return View.FOCUS_UP;
- case View.ACCESSIBILITY_FOCUS_DOWN:
- return View.FOCUS_DOWN;
- default:
- throw new IllegalArgumentException("Cannot map accessiblity focus"
- + " direction: " + accessFocusDirection);
- }
- }
-
/**
* Is rect1 a better candidate than rect2 for a focus search in a particular
* direction from a source rect? This is the core routine that determines
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index eb80290d..53af3c5 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -323,6 +323,15 @@
return mSurfaceGenerationId;
}
+
+ /**
+ * Whether the consumer of this Surface is running behind the producer;
+ * that is, isConsumerRunningBehind() returns true if the consumer is more
+ * than one buffer ahead of the producer.
+ * @hide
+ */
+ public native boolean isConsumerRunningBehind();
+
/**
* A Canvas class that can handle the compatibility mode. This does two
* things differently.
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 0e6af61..b65bf8f 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -1056,26 +1056,6 @@
public static final int ACCESSIBILITY_FOCUS_BACKWARD = FOCUS_BACKWARD | FOCUS_ACCESSIBILITY;
/**
- * Use with {@link #focusSearch(int)}. Move acessibility focus in a view.
- */
- public static final int ACCESSIBILITY_FOCUS_IN = 0x00000004 | FOCUS_ACCESSIBILITY;
-
- /**
- * Use with {@link #focusSearch(int)}. Move acessibility focus out of a view.
- */
- public static final int ACCESSIBILITY_FOCUS_OUT = 0x00000008 | FOCUS_ACCESSIBILITY;
-
- /**
- * Use with {@link #focusSearch(int)}. Move acessibility focus to the next view.
- */
- public static final int ACCESSIBILITY_FOCUS_NEXT = 0x00000010 | FOCUS_ACCESSIBILITY;
-
- /**
- * Use with {@link #focusSearch(int)}. Move acessibility focus to the previous view.
- */
- public static final int ACCESSIBILITY_FOCUS_PREVIOUS = 0x00000020 | FOCUS_ACCESSIBILITY;
-
- /**
* Bits of {@link #getMeasuredWidthAndState()} and
* {@link #getMeasuredWidthAndState()} that provide the actual measured size.
*/
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 6ecd767..343ae4c 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -1622,18 +1622,22 @@
@Override
public void addChildrenForAccessibility(ArrayList<View> childrenForAccessibility) {
- View[] children = mChildren;
- final int childrenCount = mChildrenCount;
- for (int i = 0; i < childrenCount; i++) {
- View child = children[i];
- if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE
- && (child.mPrivateFlags & IS_ROOT_NAMESPACE) == 0) {
- if (child.includeForAccessibility()) {
- childrenForAccessibility.add(child);
- } else {
- child.addChildrenForAccessibility(childrenForAccessibility);
+ ChildListForAccessibility children = ChildListForAccessibility.obtain(this, true);
+ try {
+ final int childrenCount = children.getChildCount();
+ for (int i = 0; i < childrenCount; i++) {
+ View child = children.getChildAt(i);
+ if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE
+ && (child.mPrivateFlags & IS_ROOT_NAMESPACE) == 0) {
+ if (child.includeForAccessibility()) {
+ childrenForAccessibility.add(child);
+ } else {
+ child.addChildrenForAccessibility(childrenForAccessibility);
+ }
}
}
+ } finally {
+ children.recycle();
}
}
@@ -2424,18 +2428,21 @@
}
// Let our children have a shot in populating the event.
ChildListForAccessibility children = ChildListForAccessibility.obtain(this, true);
- final int childCount = children.getChildCount();
- for (int i = 0; i < childCount; i++) {
- View child = children.getChildAt(i);
- if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE) {
- handled = child.dispatchPopulateAccessibilityEvent(event);
- if (handled) {
- children.recycle();
- return handled;
+ try {
+ final int childCount = children.getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ View child = children.getChildAt(i);
+ if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE) {
+ handled = child.dispatchPopulateAccessibilityEvent(event);
+ if (handled) {
+ children.recycle();
+ return handled;
+ }
}
}
+ } finally {
+ children.recycle();
}
- children.recycle();
return false;
}
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index bc310b0..d62f513 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -429,6 +429,12 @@
public static final int TYPE_DREAM = FIRST_SYSTEM_WINDOW+23;
/**
+ * Window type: Navigation bar panel (when navigation bar is distinct from status bar)
+ * @hide
+ */
+ public static final int TYPE_NAVIGATION_BAR_PANEL = FIRST_SYSTEM_WINDOW+24;
+
+ /**
* End of types of system windows.
*/
public static final int LAST_SYSTEM_WINDOW = 2999;
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index cdb9e77..3cb3b54 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -391,8 +391,6 @@
* {@link View#FOCUS_RIGHT},
* {@link View#FOCUS_FORWARD},
* {@link View#FOCUS_BACKWARD},
- * {@link View#ACCESSIBILITY_FOCUS_IN},
- * {@link View#ACCESSIBILITY_FOCUS_OUT},
* {@link View#ACCESSIBILITY_FOCUS_FORWARD},
* {@link View#ACCESSIBILITY_FOCUS_BACKWARD},
* {@link View#ACCESSIBILITY_FOCUS_UP},
diff --git a/core/java/android/view/accessibility/AccessibilityNodeProvider.java b/core/java/android/view/accessibility/AccessibilityNodeProvider.java
index ba6433f..a2e0d88 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeProvider.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeProvider.java
@@ -168,8 +168,6 @@
*
* @param direction The direction in which to search for a focus candidate.
* Values are
- * {@link View#ACCESSIBILITY_FOCUS_IN},
- * {@link View#ACCESSIBILITY_FOCUS_OUT},
* {@link View#ACCESSIBILITY_FOCUS_FORWARD},
* {@link View#ACCESSIBILITY_FOCUS_BACKWARD},
* {@link View#ACCESSIBILITY_FOCUS_UP},
diff --git a/core/java/android/webkit/WebViewClassic.java b/core/java/android/webkit/WebViewClassic.java
index fa18dce..05b3e64 100644
--- a/core/java/android/webkit/WebViewClassic.java
+++ b/core/java/android/webkit/WebViewClassic.java
@@ -7825,6 +7825,12 @@
// This provides a hook for ProfiledWebView to observe the tile page swaps.
((PageSwapDelegate) mWebView).onPageSwapOccurred(notifyAnimationStarted);
}
+
+ if (mPictureListener != null) {
+ // trigger picture listener for hardware layers. Software layers are
+ // triggered in setNewPicture
+ mPictureListener.onNewPicture(getWebView(), capturePicture());
+ }
}
void setNewPicture(final WebViewCore.DrawData draw, boolean updateBaseLayer) {
@@ -7894,7 +7900,12 @@
scrollEditWithCursor();
if (mPictureListener != null) {
- mPictureListener.onNewPicture(getWebView(), capturePicture());
+ if (!mWebView.isHardwareAccelerated()
+ || mWebView.getLayerType() == View.LAYER_TYPE_SOFTWARE) {
+ // trigger picture listener for software layers. Hardware layers are
+ // triggered in pageSwapCallback
+ mPictureListener.onNewPicture(getWebView(), capturePicture());
+ }
}
}
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 2f72e4a..214775a 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -16,13 +16,7 @@
package android.widget;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-
+import android.app.ActivityOptions;
import android.app.PendingIntent;
import android.appwidget.AppWidgetHostView;
import android.content.Context;
@@ -40,13 +34,20 @@
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
+import android.view.LayoutInflater.Filter;
import android.view.RemotableViewMethod;
import android.view.View;
-import android.view.ViewGroup;
-import android.view.LayoutInflater.Filter;
import android.view.View.OnClickListener;
+import android.view.ViewGroup;
import android.widget.AdapterView.OnItemClickListener;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+
/**
* A class that describes a view hierarchy that can be displayed in
@@ -140,14 +141,18 @@
return;
}
- protected boolean startIntentSafely(Context context, PendingIntent pendingIntent,
+ protected boolean startIntentSafely(View view, PendingIntent pendingIntent,
Intent fillInIntent) {
try {
// TODO: Unregister this handler if PendingIntent.FLAG_ONE_SHOT?
+ Context context = view.getContext();
+ ActivityOptions opts = ActivityOptions.makeScaleUpAnimation(view,
+ 0, 0,
+ view.getMeasuredWidth(), view.getMeasuredHeight());
context.startIntentSender(
pendingIntent.getIntentSender(), fillInIntent,
Intent.FLAG_ACTIVITY_NEW_TASK,
- Intent.FLAG_ACTIVITY_NEW_TASK, 0);
+ Intent.FLAG_ACTIVITY_NEW_TASK, 0, opts.toBundle());
} catch (IntentSender.SendIntentException e) {
android.util.Log.e(LOG_TAG, "Cannot send pending intent: ", e);
return false;
@@ -263,7 +268,7 @@
rect.bottom = (int) ((pos[1] + v.getHeight()) * appScale + 0.5f);
fillInIntent.setSourceBounds(rect);
- startIntentSafely(v.getContext(), pendingIntent, fillInIntent);
+ startIntentSafely(v, pendingIntent, fillInIntent);
}
};
@@ -341,7 +346,7 @@
final Intent intent = new Intent();
intent.setSourceBounds(rect);
- startIntentSafely(view.getContext(), pendingIntentTemplate, fillInIntent);
+ startIntentSafely(view, pendingIntentTemplate, fillInIntent);
}
}
};
@@ -479,7 +484,7 @@
final Intent intent = new Intent();
intent.setSourceBounds(rect);
- startIntentSafely(v.getContext(), pendingIntent, intent);
+ startIntentSafely(v, pendingIntent, intent);
}
};
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index eba580d..36b1cd6 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -799,22 +799,22 @@
case com.android.internal.R.styleable.TextView_imeOptions:
createEditorIfNeeded("IME options specified in constructor");
- getEditor().createInputContentTypeIfNeeded();
- getEditor().mInputContentType.imeOptions = a.getInt(attr,
- getEditor().mInputContentType.imeOptions);
+ mEditor.createInputContentTypeIfNeeded();
+ mEditor.mInputContentType.imeOptions = a.getInt(attr,
+ mEditor.mInputContentType.imeOptions);
break;
case com.android.internal.R.styleable.TextView_imeActionLabel:
createEditorIfNeeded("IME action label specified in constructor");
- getEditor().createInputContentTypeIfNeeded();
- getEditor().mInputContentType.imeActionLabel = a.getText(attr);
+ mEditor.createInputContentTypeIfNeeded();
+ mEditor.mInputContentType.imeActionLabel = a.getText(attr);
break;
case com.android.internal.R.styleable.TextView_imeActionId:
createEditorIfNeeded("IME action id specified in constructor");
- getEditor().createInputContentTypeIfNeeded();
- getEditor().mInputContentType.imeActionId = a.getInt(attr,
- getEditor().mInputContentType.imeActionId);
+ mEditor.createInputContentTypeIfNeeded();
+ mEditor.mInputContentType.imeActionId = a.getInt(attr,
+ mEditor.mInputContentType.imeActionId);
break;
case com.android.internal.R.styleable.TextView_privateImeOptions:
@@ -884,26 +884,26 @@
try {
createEditorIfNeeded("inputMethod in ctor");
- getEditor().mKeyListener = (KeyListener) c.newInstance();
+ mEditor.mKeyListener = (KeyListener) c.newInstance();
} catch (InstantiationException ex) {
throw new RuntimeException(ex);
} catch (IllegalAccessException ex) {
throw new RuntimeException(ex);
}
try {
- getEditor().mInputType = inputType != EditorInfo.TYPE_NULL
+ mEditor.mInputType = inputType != EditorInfo.TYPE_NULL
? inputType
- : getEditor().mKeyListener.getInputType();
+ : mEditor.mKeyListener.getInputType();
} catch (IncompatibleClassChangeError e) {
- getEditor().mInputType = EditorInfo.TYPE_CLASS_TEXT;
+ mEditor.mInputType = EditorInfo.TYPE_CLASS_TEXT;
}
} else if (digits != null) {
createEditorIfNeeded("digits in ctor");
- getEditor().mKeyListener = DigitsKeyListener.getInstance(digits.toString());
+ mEditor.mKeyListener = DigitsKeyListener.getInstance(digits.toString());
// If no input type was specified, we will default to generic
// text, since we can't tell the IME about the set of digits
// that was selected.
- getEditor().mInputType = inputType != EditorInfo.TYPE_NULL
+ mEditor.mInputType = inputType != EditorInfo.TYPE_NULL
? inputType : EditorInfo.TYPE_CLASS_TEXT;
} else if (inputType != EditorInfo.TYPE_NULL) {
setInputType(inputType, true);
@@ -911,11 +911,11 @@
singleLine = !isMultilineInputType(inputType);
} else if (phone) {
createEditorIfNeeded("dialer in ctor");
- getEditor().mKeyListener = DialerKeyListener.getInstance();
- getEditor().mInputType = inputType = EditorInfo.TYPE_CLASS_PHONE;
+ mEditor.mKeyListener = DialerKeyListener.getInstance();
+ mEditor.mInputType = inputType = EditorInfo.TYPE_CLASS_PHONE;
} else if (numeric != 0) {
createEditorIfNeeded("numeric in ctor");
- getEditor().mKeyListener = DigitsKeyListener.getInstance((numeric & SIGNED) != 0,
+ mEditor.mKeyListener = DigitsKeyListener.getInstance((numeric & SIGNED) != 0,
(numeric & DECIMAL) != 0);
inputType = EditorInfo.TYPE_CLASS_NUMBER;
if ((numeric & SIGNED) != 0) {
@@ -924,7 +924,7 @@
if ((numeric & DECIMAL) != 0) {
inputType |= EditorInfo.TYPE_NUMBER_FLAG_DECIMAL;
}
- getEditor().mInputType = inputType;
+ mEditor.mInputType = inputType;
} else if (autotext || autocap != -1) {
TextKeyListener.Capitalize cap;
@@ -952,23 +952,23 @@
}
createEditorIfNeeded("text input in ctor");
- getEditor().mKeyListener = TextKeyListener.getInstance(autotext, cap);
- getEditor().mInputType = inputType;
+ mEditor.mKeyListener = TextKeyListener.getInstance(autotext, cap);
+ mEditor.mInputType = inputType;
} else if (isTextSelectable()) {
// Prevent text changes from keyboard.
if (mEditor != null) {
- getEditor().mKeyListener = null;
- getEditor().mInputType = EditorInfo.TYPE_NULL;
+ mEditor.mKeyListener = null;
+ mEditor.mInputType = EditorInfo.TYPE_NULL;
}
bufferType = BufferType.SPANNABLE;
// So that selection can be changed using arrow keys and touch is handled.
setMovementMethod(ArrowKeyMovementMethod.getInstance());
} else if (editable) {
createEditorIfNeeded("editable input in ctor");
- getEditor().mKeyListener = TextKeyListener.getInstance();
- getEditor().mInputType = EditorInfo.TYPE_CLASS_TEXT;
+ mEditor.mKeyListener = TextKeyListener.getInstance();
+ mEditor.mInputType = EditorInfo.TYPE_CLASS_TEXT;
} else {
- if (mEditor != null) getEditor().mKeyListener = null;
+ if (mEditor != null) mEditor.mKeyListener = null;
switch (buffertype) {
case 0:
@@ -983,12 +983,12 @@
}
}
- if (mEditor != null) getEditor().adjustInputType(password, passwordInputType, webPasswordInputType,
- numberPasswordInputType);
+ if (mEditor != null) mEditor.adjustInputType(password, passwordInputType,
+ webPasswordInputType, numberPasswordInputType);
if (selectallonfocus) {
createEditorIfNeeded("selectallonfocus in constructor");
- getEditor().mSelectAllOnFocus = true;
+ mEditor.mSelectAllOnFocus = true;
if (bufferType == BufferType.NORMAL)
bufferType = BufferType.SPANNABLE;
@@ -1045,7 +1045,8 @@
if (password || passwordInputType || webPasswordInputType || numberPasswordInputType) {
setTransformationMethod(PasswordTransformationMethod.getInstance());
typefaceIndex = MONOSPACE;
- } else if (mEditor != null && (getEditor().mInputType & (EditorInfo.TYPE_MASK_CLASS | EditorInfo.TYPE_MASK_VARIATION))
+ } else if (mEditor != null &&
+ (mEditor.mInputType & (EditorInfo.TYPE_MASK_CLASS | EditorInfo.TYPE_MASK_VARIATION))
== (EditorInfo.TYPE_CLASS_TEXT | EditorInfo.TYPE_TEXT_VARIATION_PASSWORD)) {
typefaceIndex = MONOSPACE;
}
@@ -1189,11 +1190,11 @@
// Will change text color
if (mEditor != null) {
- getEditor().invalidateTextDisplayList();
- getEditor().prepareCursorControllers();
+ mEditor.invalidateTextDisplayList();
+ mEditor.prepareCursorControllers();
// start or stop the cursor blinking as appropriate
- getEditor().makeBlink();
+ mEditor.makeBlink();
}
}
@@ -1295,7 +1296,7 @@
* This will frequently be null for non-EditText TextViews.
*/
public final KeyListener getKeyListener() {
- return mEditor == null ? null : getEditor().mKeyListener;
+ return mEditor == null ? null : mEditor.mKeyListener;
}
/**
@@ -1327,15 +1328,15 @@
if (input != null) {
createEditorIfNeeded("input is not null");
try {
- getEditor().mInputType = getEditor().mKeyListener.getInputType();
+ mEditor.mInputType = mEditor.mKeyListener.getInputType();
} catch (IncompatibleClassChangeError e) {
- getEditor().mInputType = EditorInfo.TYPE_CLASS_TEXT;
+ mEditor.mInputType = EditorInfo.TYPE_CLASS_TEXT;
}
// Change inputType, without affecting transformation.
// No need to applySingleLine since mSingleLine is unchanged.
setInputTypeSingleLine(mSingleLine);
} else {
- if (mEditor != null) getEditor().mInputType = EditorInfo.TYPE_NULL;
+ if (mEditor != null) mEditor.mInputType = EditorInfo.TYPE_NULL;
}
InputMethodManager imm = InputMethodManager.peekInstance();
@@ -1346,8 +1347,8 @@
if (mEditor == null && input == null) return; // null is the default value
createEditorIfNeeded("setKeyListenerOnly");
- if (getEditor().mKeyListener != input) {
- getEditor().mKeyListener = input;
+ if (mEditor.mKeyListener != input) {
+ mEditor.mKeyListener = input;
if (input != null && !(mText instanceof Editable)) {
setText(mText);
}
@@ -1385,13 +1386,14 @@
fixFocusableAndClickableSettings();
- // SelectionModifierCursorController depends on textCanBeSelected, which depends on mMovement
- if (mEditor != null) getEditor().prepareCursorControllers();
+ // SelectionModifierCursorController depends on textCanBeSelected, which depends on
+ // mMovement
+ if (mEditor != null) mEditor.prepareCursorControllers();
}
}
private void fixFocusableAndClickableSettings() {
- if (mMovement != null || (mEditor != null && getEditor().mKeyListener != null)) {
+ if (mMovement != null || (mEditor != null && mEditor.mKeyListener != null)) {
setFocusable(true);
setClickable(true);
setLongClickable(true);
@@ -2096,7 +2098,8 @@
ColorStateList colors;
int ts;
- color = appearance.getColor(com.android.internal.R.styleable.TextAppearance_textColorHighlight, 0);
+ color = appearance.getColor(
+ com.android.internal.R.styleable.TextAppearance_textColorHighlight, 0);
if (color != 0) {
setHighlightColor(color);
}
@@ -2349,7 +2352,7 @@
mShadowDy = dy;
// Will change text clip region
- if (mEditor != null) getEditor().invalidateTextDisplayList();
+ if (mEditor != null) mEditor.invalidateTextDisplayList();
invalidate();
}
@@ -2842,7 +2845,7 @@
}
if (inval) {
// Text needs to be redrawn with the new color
- if (mEditor != null) getEditor().invalidateTextDisplayList();
+ if (mEditor != null) mEditor.invalidateTextDisplayList();
invalidate();
}
}
@@ -2921,7 +2924,7 @@
if (mEditor != null) {
removeMisspelledSpans(sp);
- sp.removeSpan(getEditor().mSuggestionRangeSpan);
+ sp.removeSpan(mEditor.mSuggestionRangeSpan);
}
ss.text = sp;
@@ -2987,7 +2990,7 @@
if (ss.frozenWithFocus) {
createEditorIfNeeded("restore instance with focus");
- getEditor().mFrozenWithFocus = true;
+ mEditor.mFrozenWithFocus = true;
}
}
}
@@ -3145,7 +3148,8 @@
needEditableForNotification = true;
}
- if (type == BufferType.EDITABLE || getKeyListener() != null || needEditableForNotification) {
+ if (type == BufferType.EDITABLE || getKeyListener() != null ||
+ needEditableForNotification) {
createEditorIfNeeded("setText with BufferType.EDITABLE or non null mInput");
Editable t = mEditableFactory.newEditable(text);
text = t;
@@ -3226,7 +3230,7 @@
* selection, so reset mSelectionMoved to keep that from
* interfering with the normal on-focus selection-setting.
*/
- if (mEditor != null) getEditor().mSelectionMoved = false;
+ if (mEditor != null) mEditor.mSelectionMoved = false;
}
}
@@ -3242,7 +3246,7 @@
}
// SelectionModifierCursorController depends on textCanBeSelected, which depends on text
- if (mEditor != null) getEditor().prepareCursorControllers();
+ if (mEditor != null) mEditor.prepareCursorControllers();
}
/**
@@ -3332,7 +3336,7 @@
// Invalidate display list if hint is currently used
if (mEditor != null && mText.length() == 0 && mHint != null) {
- getEditor().invalidateTextDisplayList();
+ mEditor.invalidateTextDisplayList();
}
}
@@ -3425,9 +3429,9 @@
forceUpdate = true;
}
}
-
+
boolean singleLine = !isMultilineInputType(type);
-
+
// We need to update the single line mode if it has changed or we
// were previously in password mode.
if (mSingleLine != singleLine || forceUpdate) {
@@ -3435,7 +3439,7 @@
// we are not in password mode.
applySingleLine(singleLine, !isPassword, true);
}
-
+
if (!isSuggestionsEnabled()) {
mText = removeSuggestionSpans(mText);
}
@@ -3491,7 +3495,7 @@
public void setRawInputType(int type) {
if (type == InputType.TYPE_NULL && mEditor == null) return; //TYPE_NULL is the default value
createEditorIfNeeded("non null input type");
- getEditor().mInputType = type;
+ mEditor.mInputType = type;
}
private void setInputType(int type, boolean direct) {
@@ -3534,7 +3538,7 @@
setRawInputType(type);
if (direct) {
createEditorIfNeeded("setInputType");
- getEditor().mKeyListener = input;
+ mEditor.mKeyListener = input;
} else {
setKeyListenerOnly(input);
}
@@ -3547,7 +3551,7 @@
* @see android.text.InputType
*/
public int getInputType() {
- return mEditor == null ? EditorInfo.TYPE_NULL : getEditor().mInputType;
+ return mEditor == null ? EditorInfo.TYPE_NULL : mEditor.mInputType;
}
/**
@@ -3560,8 +3564,8 @@
*/
public void setImeOptions(int imeOptions) {
createEditorIfNeeded("IME options specified");
- getEditor().createInputContentTypeIfNeeded();
- getEditor().mInputContentType.imeOptions = imeOptions;
+ mEditor.createInputContentTypeIfNeeded();
+ mEditor.mInputContentType.imeOptions = imeOptions;
}
/**
@@ -3571,8 +3575,8 @@
* @see android.view.inputmethod.EditorInfo
*/
public int getImeOptions() {
- return mEditor != null && getEditor().mInputContentType != null
- ? getEditor().mInputContentType.imeOptions : EditorInfo.IME_NULL;
+ return mEditor != null && mEditor.mInputContentType != null
+ ? mEditor.mInputContentType.imeOptions : EditorInfo.IME_NULL;
}
/**
@@ -3587,9 +3591,9 @@
*/
public void setImeActionLabel(CharSequence label, int actionId) {
createEditorIfNeeded("IME action label specified");
- getEditor().createInputContentTypeIfNeeded();
- getEditor().mInputContentType.imeActionLabel = label;
- getEditor().mInputContentType.imeActionId = actionId;
+ mEditor.createInputContentTypeIfNeeded();
+ mEditor.mInputContentType.imeActionLabel = label;
+ mEditor.mInputContentType.imeActionId = actionId;
}
/**
@@ -3599,8 +3603,8 @@
* @see android.view.inputmethod.EditorInfo
*/
public CharSequence getImeActionLabel() {
- return mEditor != null && getEditor().mInputContentType != null
- ? getEditor().mInputContentType.imeActionLabel : null;
+ return mEditor != null && mEditor.mInputContentType != null
+ ? mEditor.mInputContentType.imeActionLabel : null;
}
/**
@@ -3610,8 +3614,8 @@
* @see android.view.inputmethod.EditorInfo
*/
public int getImeActionId() {
- return mEditor != null && getEditor().mInputContentType != null
- ? getEditor().mInputContentType.imeActionId : 0;
+ return mEditor != null && mEditor.mInputContentType != null
+ ? mEditor.mInputContentType.imeActionId : 0;
}
/**
@@ -3624,8 +3628,8 @@
*/
public void setOnEditorActionListener(OnEditorActionListener l) {
createEditorIfNeeded("Editor action listener set");
- getEditor().createInputContentTypeIfNeeded();
- getEditor().mInputContentType.onEditorActionListener = l;
+ mEditor.createInputContentTypeIfNeeded();
+ mEditor.mInputContentType.onEditorActionListener = l;
}
/**
@@ -3638,18 +3642,18 @@
* EditorInfo.IME_ACTION_NEXT}, {@link EditorInfo#IME_ACTION_PREVIOUS
* EditorInfo.IME_ACTION_PREVIOUS}, or {@link EditorInfo#IME_ACTION_DONE
* EditorInfo.IME_ACTION_DONE}.
- *
+ *
* <p>For backwards compatibility, if no IME options have been set and the
* text view would not normally advance focus on enter, then
* the NEXT and DONE actions received here will be turned into an enter
* key down/up pair to go through the normal key handling.
- *
+ *
* @param actionCode The code of the action being performed.
- *
+ *
* @see #setOnEditorActionListener
*/
public void onEditorAction(int actionCode) {
- final Editor.InputContentType ict = mEditor == null ? null : getEditor().mInputContentType;
+ final Editor.InputContentType ict = mEditor == null ? null : mEditor.mInputContentType;
if (ict != null) {
if (ict.onEditorActionListener != null) {
if (ict.onEditorActionListener.onEditorAction(this,
@@ -3721,8 +3725,8 @@
*/
public void setPrivateImeOptions(String type) {
createEditorIfNeeded("Private IME option set");
- getEditor().createInputContentTypeIfNeeded();
- getEditor().mInputContentType.privateImeOptions = type;
+ mEditor.createInputContentTypeIfNeeded();
+ mEditor.mInputContentType.privateImeOptions = type;
}
/**
@@ -3732,8 +3736,8 @@
* @see EditorInfo#privateImeOptions
*/
public String getPrivateImeOptions() {
- return mEditor != null && getEditor().mInputContentType != null
- ? getEditor().mInputContentType.privateImeOptions : null;
+ return mEditor != null && mEditor.mInputContentType != null
+ ? mEditor.mInputContentType.privateImeOptions : null;
}
/**
@@ -3743,16 +3747,16 @@
* given integer is the resource ID of an XML resource holding an
* {@link android.R.styleable#InputExtras <input-extras>} XML tree.
*
- * @see #getInputExtras(boolean)
+ * @see #getInputExtras(boolean)
* @see EditorInfo#extras
* @attr ref android.R.styleable#TextView_editorExtras
*/
public void setInputExtras(int xmlResId) throws XmlPullParserException, IOException {
createEditorIfNeeded("Input extra set");
XmlResourceParser parser = getResources().getXml(xmlResId);
- getEditor().createInputContentTypeIfNeeded();
- getEditor().mInputContentType.extras = new Bundle();
- getResources().parseBundleExtras(parser, getEditor().mInputContentType.extras);
+ mEditor.createInputContentTypeIfNeeded();
+ mEditor.mInputContentType.extras = new Bundle();
+ getResources().parseBundleExtras(parser, mEditor.mInputContentType.extras);
}
/**
@@ -3768,15 +3772,15 @@
public Bundle getInputExtras(boolean create) {
if (mEditor == null && !create) return null;
createEditorIfNeeded("get Input extra");
- if (getEditor().mInputContentType == null) {
+ if (mEditor.mInputContentType == null) {
if (!create) return null;
- getEditor().createInputContentTypeIfNeeded();
+ mEditor.createInputContentTypeIfNeeded();
}
- if (getEditor().mInputContentType.extras == null) {
+ if (mEditor.mInputContentType.extras == null) {
if (!create) return null;
- getEditor().mInputContentType.extras = new Bundle();
+ mEditor.mInputContentType.extras = new Bundle();
}
- return getEditor().mInputContentType.extras;
+ return mEditor.mInputContentType.extras;
}
/**
@@ -3785,7 +3789,7 @@
* or if it the error was cleared by the widget after user input.
*/
public CharSequence getError() {
- return mEditor == null ? null : getEditor().mError;
+ return mEditor == null ? null : mEditor.mError;
}
/**
@@ -3820,14 +3824,14 @@
*/
public void setError(CharSequence error, Drawable icon) {
createEditorIfNeeded("setError");
- getEditor().setError(error, icon);
+ mEditor.setError(error, icon);
}
@Override
protected boolean setFrame(int l, int t, int r, int b) {
boolean result = super.setFrame(l, t, r, b);
- if (mEditor != null) getEditor().setFrame();
+ if (mEditor != null) mEditor.setFrame();
restartMarqueeIfNeeded();
@@ -3864,11 +3868,11 @@
* and includes mInput in the list if it is an InputFilter.
*/
private void setFilters(Editable e, InputFilter[] filters) {
- if (mEditor != null && getEditor().mKeyListener instanceof InputFilter) {
+ if (mEditor != null && mEditor.mKeyListener instanceof InputFilter) {
InputFilter[] nf = new InputFilter[filters.length + 1];
System.arraycopy(filters, 0, nf, 0, filters.length);
- nf[filters.length] = (InputFilter) getEditor().mKeyListener;
+ nf[filters.length] = (InputFilter) mEditor.mKeyListener;
e.setFilters(nf);
} else {
@@ -3954,7 +3958,7 @@
final int horizontalPadding = getCompoundPaddingLeft();
final int verticalPadding = getExtendedPaddingTop() + getVerticalOffset(true);
- if (getEditor().mCursorCount == 0) {
+ if (mEditor.mCursorCount == 0) {
synchronized (TEMP_RECTF) {
/*
* The reason for this concern about the thickness of the
@@ -3981,8 +3985,8 @@
(int) FloatMath.ceil(verticalPadding + TEMP_RECTF.bottom + thick));
}
} else {
- for (int i = 0; i < getEditor().mCursorCount; i++) {
- Rect bounds = getEditor().mCursorDrawable[i].getBounds();
+ for (int i = 0; i < mEditor.mCursorCount; i++) {
+ Rect bounds = mEditor.mCursorDrawable[i].getBounds();
invalidate(bounds.left + horizontalPadding, bounds.top + verticalPadding,
bounds.right + horizontalPadding, bounds.bottom + verticalPadding);
}
@@ -4035,8 +4039,8 @@
// mEditor can be null in case selection is set programmatically.
if (invalidateCursor && mEditor != null) {
- for (int i = 0; i < getEditor().mCursorCount; i++) {
- Rect bounds = getEditor().mCursorDrawable[i].getBounds();
+ for (int i = 0; i < mEditor.mCursorCount; i++) {
+ Rect bounds = mEditor.mCursorDrawable[i].getBounds();
top = Math.min(top, bounds.top);
bottom = Math.max(bottom, bounds.bottom);
}
@@ -4086,8 +4090,8 @@
*/
int curs = getSelectionEnd();
// Do not create the controller if it is not already created.
- if (mEditor != null && getEditor().mSelectionModifierCursorController != null &&
- getEditor().mSelectionModifierCursorController.isSelectionStartDragged()) {
+ if (mEditor != null && mEditor.mSelectionModifierCursorController != null &&
+ mEditor.mSelectionModifierCursorController.isSelectionStartDragged()) {
curs = getSelectionStart();
}
@@ -4110,16 +4114,16 @@
// This has to be checked here since:
// - onFocusChanged cannot start it when focus is given to a view with selected text (after
// a screen rotation) since layout is not yet initialized at that point.
- if (mEditor != null && getEditor().mCreatedWithASelection) {
- getEditor().startSelectionActionMode();
- getEditor().mCreatedWithASelection = false;
+ if (mEditor != null && mEditor.mCreatedWithASelection) {
+ mEditor.startSelectionActionMode();
+ mEditor.mCreatedWithASelection = false;
}
// Phone specific code (there is no ExtractEditText on tablets).
// ExtractEditText does not call onFocus when it is displayed, and mHasSelectionOnFocus can
// not be set. Do the test here instead.
if (this instanceof ExtractEditText && hasSelection() && mEditor != null) {
- getEditor().startSelectionActionMode();
+ mEditor.startSelectionActionMode();
}
getViewTreeObserver().removeOnPreDrawListener(this);
@@ -4133,11 +4137,11 @@
super.onAttachedToWindow();
mTemporaryDetach = false;
-
+
// Resolve drawables as the layout direction has been resolved
resolveDrawables();
- if (mEditor != null) getEditor().onAttachedToWindow();
+ if (mEditor != null) mEditor.onAttachedToWindow();
}
@Override
@@ -4151,13 +4155,13 @@
resetResolvedDrawables();
- if (mEditor != null) getEditor().onDetachedFromWindow();
+ if (mEditor != null) mEditor.onDetachedFromWindow();
}
@Override
public void onScreenStateChanged(int screenState) {
super.onScreenStateChanged(screenState);
- if (mEditor != null) getEditor().onScreenStateChanged(screenState);
+ if (mEditor != null) mEditor.onScreenStateChanged(screenState);
}
@Override
@@ -4308,7 +4312,7 @@
* @attr ref android.R.styleable#TextView_textIsSelectable
*/
public boolean isTextSelectable() {
- return mEditor == null ? false : getEditor().mTextIsSelectable;
+ return mEditor == null ? false : mEditor.mTextIsSelectable;
}
/**
@@ -4327,9 +4331,9 @@
if (!selectable && mEditor == null) return; // false is default value with no edit data
createEditorIfNeeded("setTextIsSelectable");
- if (getEditor().mTextIsSelectable == selectable) return;
+ if (mEditor.mTextIsSelectable == selectable) return;
- getEditor().mTextIsSelectable = selectable;
+ mEditor.mTextIsSelectable = selectable;
setFocusableInTouchMode(selectable);
setFocusable(selectable);
setClickable(selectable);
@@ -4341,7 +4345,7 @@
setText(getText(), selectable ? BufferType.SPANNABLE : BufferType.NORMAL);
// Called by setText above, but safer in case of future code changes
- getEditor().prepareCursorControllers();
+ mEditor.prepareCursorControllers();
}
@Override
@@ -4382,14 +4386,14 @@
final int selEnd = getSelectionEnd();
if (mMovement != null && (isFocused() || isPressed()) && selStart >= 0) {
if (selStart == selEnd) {
- if (mEditor != null && getEditor().isCursorVisible() &&
- (SystemClock.uptimeMillis() - getEditor().mShowCursor) %
+ if (mEditor != null && mEditor.isCursorVisible() &&
+ (SystemClock.uptimeMillis() - mEditor.mShowCursor) %
(2 * Editor.BLINK) < Editor.BLINK) {
if (mHighlightPathBogus) {
if (mHighlightPath == null) mHighlightPath = new Path();
mHighlightPath.reset();
mLayout.getCursorPath(selStart, mHighlightPath, mText);
- getEditor().updateCursorsPositions();
+ mEditor.updateCursorsPositions();
mHighlightPathBogus = false;
}
@@ -4469,8 +4473,8 @@
// Make sure to update invalidateDrawable() when changing this code.
if (dr.mDrawableTop != null) {
canvas.save();
- canvas.translate(scrollX + compoundPaddingLeft + (hspace - dr.mDrawableWidthTop) / 2,
- scrollY + mPaddingTop);
+ canvas.translate(scrollX + compoundPaddingLeft +
+ (hspace - dr.mDrawableWidthTop) / 2, scrollY + mPaddingTop);
dr.mDrawableTop.draw(canvas);
canvas.restore();
}
@@ -4563,7 +4567,7 @@
Path highlight = getUpdatedHighlightPath();
if (mEditor != null) {
- getEditor().onDraw(canvas, layout, highlight, mHighlightPaint, cursorOffsetVertical);
+ mEditor.onDraw(canvas, layout, highlight, mHighlightPaint, cursorOffsetVertical);
} else {
layout.draw(canvas, highlight, mHighlightPaint, cursorOffsetVertical);
}
@@ -4695,7 +4699,7 @@
if ((mGravity & Gravity.VERTICAL_GRAVITY_MASK) != Gravity.TOP) {
voffset = getVerticalOffset(true);
}
-
+
if (offsetRequired) voffset += getTopPaddingOffset();
return getExtendedPaddingTop() + voffset;
@@ -4712,7 +4716,7 @@
@Override
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
- boolean isInSelectionMode = mEditor != null && getEditor().mSelectionActionMode != null;
+ boolean isInSelectionMode = mEditor != null && mEditor.mSelectionActionMode != null;
if (isInSelectionMode) {
if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) {
@@ -4762,7 +4766,7 @@
}
repeatCount--;
-
+
// We are going to dispatch the remaining events to either the input
// or movement method. To do this, we will just send a repeated stream
// of down and up events until we have done the complete repeatCount.
@@ -4770,11 +4774,11 @@
// but adding that is a more complicated change.
KeyEvent up = KeyEvent.changeAction(event, KeyEvent.ACTION_UP);
if (which == 1) {
- // mEditor and getEditor().mInput are not null from doKeyDown
- getEditor().mKeyListener.onKeyUp(this, (Editable)mText, keyCode, up);
+ // mEditor and mEditor.mInput are not null from doKeyDown
+ mEditor.mKeyListener.onKeyUp(this, (Editable)mText, keyCode, up);
while (--repeatCount > 0) {
- getEditor().mKeyListener.onKeyDown(this, (Editable)mText, keyCode, down);
- getEditor().mKeyListener.onKeyUp(this, (Editable)mText, keyCode, up);
+ mEditor.mKeyListener.onKeyDown(this, (Editable)mText, keyCode, down);
+ mEditor.mKeyListener.onKeyUp(this, (Editable)mText, keyCode, up);
}
hideErrorIfUnchanged();
@@ -4805,8 +4809,9 @@
return true;
}
- if (mEditor != null && (getEditor().mInputType & EditorInfo.TYPE_MASK_CLASS) == EditorInfo.TYPE_CLASS_TEXT) {
- int variation = getEditor().mInputType & EditorInfo.TYPE_MASK_VARIATION;
+ if (mEditor != null &&
+ (mEditor.mInputType & EditorInfo.TYPE_MASK_CLASS) == EditorInfo.TYPE_CLASS_TEXT) {
+ int variation = mEditor.mInputType & EditorInfo.TYPE_MASK_VARIATION;
if (variation == EditorInfo.TYPE_TEXT_VARIATION_EMAIL_ADDRESS
|| variation == EditorInfo.TYPE_TEXT_VARIATION_EMAIL_SUBJECT) {
return true;
@@ -4821,13 +4826,12 @@
* of inserting the character. Insert tabs only in multi-line editors.
*/
private boolean shouldAdvanceFocusOnTab() {
- if (getKeyListener() != null && !mSingleLine) {
- if (mEditor != null && (getEditor().mInputType & EditorInfo.TYPE_MASK_CLASS) == EditorInfo.TYPE_CLASS_TEXT) {
- int variation = getEditor().mInputType & EditorInfo.TYPE_MASK_VARIATION;
- if (variation == EditorInfo.TYPE_TEXT_FLAG_IME_MULTI_LINE
- || variation == EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE) {
- return false;
- }
+ if (getKeyListener() != null && !mSingleLine && mEditor != null &&
+ (mEditor.mInputType & EditorInfo.TYPE_MASK_CLASS) == EditorInfo.TYPE_CLASS_TEXT) {
+ int variation = mEditor.mInputType & EditorInfo.TYPE_MASK_VARIATION;
+ if (variation == EditorInfo.TYPE_TEXT_FLAG_IME_MULTI_LINE
+ || variation == EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE) {
+ return false;
}
}
return true;
@@ -4845,13 +4849,13 @@
// running in a "modern" cupcake environment, so don't need
// to worry about the application trying to capture
// enter key events.
- if (mEditor != null && getEditor().mInputContentType != null) {
+ if (mEditor != null && mEditor.mInputContentType != null) {
// If there is an action listener, given them a
// chance to consume the event.
- if (getEditor().mInputContentType.onEditorActionListener != null &&
- getEditor().mInputContentType.onEditorActionListener.onEditorAction(
+ if (mEditor.mInputContentType.onEditorActionListener != null &&
+ mEditor.mInputContentType.onEditorActionListener.onEditorAction(
this, EditorInfo.IME_NULL, event)) {
- getEditor().mInputContentType.enterDown = true;
+ mEditor.mInputContentType.enterDown = true;
// We are consuming the enter key for them.
return -1;
}
@@ -4869,7 +4873,7 @@
}
}
break;
-
+
case KeyEvent.KEYCODE_DPAD_CENTER:
if (event.hasNoModifiers()) {
if (shouldAdvanceFocusOnEnter()) {
@@ -4888,21 +4892,22 @@
// Has to be done on key down (and not on key up) to correctly be intercepted.
case KeyEvent.KEYCODE_BACK:
- if (mEditor != null && getEditor().mSelectionActionMode != null) {
+ if (mEditor != null && mEditor.mSelectionActionMode != null) {
stopSelectionActionMode();
return -1;
}
break;
}
- if (mEditor != null && getEditor().mKeyListener != null) {
+ if (mEditor != null && mEditor.mKeyListener != null) {
resetErrorChangedFlag();
boolean doDown = true;
if (otherEvent != null) {
try {
beginBatchEdit();
- final boolean handled = getEditor().mKeyListener.onKeyOther(this, (Editable) mText, otherEvent);
+ final boolean handled = mEditor.mKeyListener.onKeyOther(this, (Editable) mText,
+ otherEvent);
hideErrorIfUnchanged();
doDown = false;
if (handled) {
@@ -4915,10 +4920,11 @@
endBatchEdit();
}
}
-
+
if (doDown) {
beginBatchEdit();
- final boolean handled = getEditor().mKeyListener.onKeyDown(this, (Editable) mText, keyCode, event);
+ final boolean handled = mEditor.mKeyListener.onKeyDown(this, (Editable) mText,
+ keyCode, event);
endBatchEdit();
hideErrorIfUnchanged();
if (handled) return 1;
@@ -4964,14 +4970,14 @@
* that error showing. Otherwise, we take down whatever
* error was showing when the user types something.
*/
- if (mEditor != null) getEditor().mErrorWasChanged = false;
+ if (mEditor != null) mEditor.mErrorWasChanged = false;
}
/**
* @hide
*/
public void hideErrorIfUnchanged() {
- if (mEditor != null && getEditor().mError != null && !getEditor().mErrorWasChanged) {
+ if (mEditor != null && mEditor.mError != null && !mEditor.mErrorWasChanged) {
setError(null, null);
}
}
@@ -5009,11 +5015,11 @@
case KeyEvent.KEYCODE_ENTER:
if (event.hasNoModifiers()) {
- if (mEditor != null && getEditor().mInputContentType != null
- && getEditor().mInputContentType.onEditorActionListener != null
- && getEditor().mInputContentType.enterDown) {
- getEditor().mInputContentType.enterDown = false;
- if (getEditor().mInputContentType.onEditorActionListener.onEditorAction(
+ if (mEditor != null && mEditor.mInputContentType != null
+ && mEditor.mInputContentType.onEditorActionListener != null
+ && mEditor.mInputContentType.enterDown) {
+ mEditor.mInputContentType.enterDown = false;
+ if (mEditor.mInputContentType.onEditorActionListener.onEditorAction(
this, EditorInfo.IME_NULL, event)) {
return true;
}
@@ -5064,8 +5070,8 @@
break;
}
- if (mEditor != null && getEditor().mKeyListener != null)
- if (getEditor().mKeyListener.onKeyUp(this, (Editable) mText, keyCode, event))
+ if (mEditor != null && mEditor.mKeyListener != null)
+ if (mEditor.mKeyListener.onKeyUp(this, (Editable) mText, keyCode, event))
return true;
if (mMovement != null && mLayout != null)
@@ -5077,20 +5083,20 @@
@Override
public boolean onCheckIsTextEditor() {
- return mEditor != null && getEditor().mInputType != EditorInfo.TYPE_NULL;
+ return mEditor != null && mEditor.mInputType != EditorInfo.TYPE_NULL;
}
@Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
if (onCheckIsTextEditor() && isEnabled()) {
- getEditor().createInputMethodStateIfNeeded();
+ mEditor.createInputMethodStateIfNeeded();
outAttrs.inputType = getInputType();
- if (getEditor().mInputContentType != null) {
- outAttrs.imeOptions = getEditor().mInputContentType.imeOptions;
- outAttrs.privateImeOptions = getEditor().mInputContentType.privateImeOptions;
- outAttrs.actionLabel = getEditor().mInputContentType.imeActionLabel;
- outAttrs.actionId = getEditor().mInputContentType.imeActionId;
- outAttrs.extras = getEditor().mInputContentType.extras;
+ if (mEditor.mInputContentType != null) {
+ outAttrs.imeOptions = mEditor.mInputContentType.imeOptions;
+ outAttrs.privateImeOptions = mEditor.mInputContentType.privateImeOptions;
+ outAttrs.actionLabel = mEditor.mInputContentType.imeActionLabel;
+ outAttrs.actionId = mEditor.mInputContentType.imeActionId;
+ outAttrs.extras = mEditor.mInputContentType.extras;
} else {
outAttrs.imeOptions = EditorInfo.IME_NULL;
}
@@ -5138,7 +5144,7 @@
*/
public boolean extractText(ExtractedTextRequest request, ExtractedText outText) {
createEditorIfNeeded("extractText");
- return getEditor().extractText(request, outText);
+ return mEditor.extractText(request, outText);
}
/**
@@ -5177,7 +5183,7 @@
content.replace(start, end, text.text);
}
}
-
+
// Now set the selection position... make sure it is in range, to
// avoid crashes. If this is a partial update, it is possible that
// the underlying text may have changed, causing us problems here.
@@ -5191,7 +5197,7 @@
if (end < 0) end = 0;
else if (end > N) end = N;
Selection.setSelection(sp, start, end);
-
+
// Finally, update the selection mode.
if ((text.flags&ExtractedText.FLAG_SELECTING) != 0) {
MetaKeyKeyListener.startSelecting(this, sp);
@@ -5204,13 +5210,13 @@
* @hide
*/
public void setExtracting(ExtractedTextRequest req) {
- if (getEditor().mInputMethodState != null) {
- getEditor().mInputMethodState.mExtractedTextRequest = req;
+ if (mEditor.mInputMethodState != null) {
+ mEditor.mInputMethodState.mExtractedTextRequest = req;
}
// This would stop a possible selection mode, but no such mode is started in case
// extracted mode will start. Some text is selected though, and will trigger an action mode
// in the extracted view.
- getEditor().hideControllers();
+ mEditor.hideControllers();
}
/**
@@ -5236,17 +5242,17 @@
* @param info The auto correct info about the text that was corrected.
*/
public void onCommitCorrection(CorrectionInfo info) {
- if (mEditor != null) getEditor().onCommitCorrection(info);
+ if (mEditor != null) mEditor.onCommitCorrection(info);
}
public void beginBatchEdit() {
- if (mEditor != null) getEditor().beginBatchEdit();
+ if (mEditor != null) mEditor.beginBatchEdit();
}
-
+
public void endBatchEdit() {
- if (mEditor != null) getEditor().endBatchEdit();
+ if (mEditor != null) mEditor.endBatchEdit();
}
-
+
/**
* Called by the framework in response to a request to begin a batch
* of edit operations through a call to link {@link #beginBatchEdit()}.
@@ -5262,7 +5268,7 @@
public void onEndBatchEdit() {
// intentionally empty
}
-
+
/**
* Called by the framework in response to a private command from the
* current method, provided by it calling
@@ -5290,7 +5296,7 @@
mBoring = mHintBoring = null;
// Since it depends on the value of mLayout
- if (mEditor != null) getEditor().prepareCursorControllers();
+ if (mEditor != null) mEditor.prepareCursorControllers();
}
/**
@@ -5511,7 +5517,7 @@
}
// CursorControllers need a non-null mLayout
- if (mEditor != null) getEditor().prepareCursorControllers();
+ if (mEditor != null) mEditor.prepareCursorControllers();
}
private Layout makeSingleLayout(int wantWidth, BoringLayout.Metrics boring, int ellipsisWidth,
@@ -5587,7 +5593,7 @@
private boolean compressText(float width) {
if (isHardwareAccelerated()) return false;
-
+
// Only compress the text if it hasn't been compressed by the previous pass
if (width > 0.0f && mLayout != null && getLineCount() == 1 && !mUserSetTextScaleX &&
mTextPaint.getTextScaleX() == 1.0f) {
@@ -5953,7 +5959,7 @@
invalidate();
return;
}
-
+
// Dynamic height, but height has stayed the same,
// so use our new text layout.
if (mLayout.getHeight() == oldht &&
@@ -5979,7 +5985,7 @@
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
- if (changed && mEditor != null) getEditor().invalidateTextDisplayList();
+ if (changed && mEditor != null) mEditor.invalidateTextDisplayList();
}
private boolean isShowingHint() {
@@ -6246,9 +6252,9 @@
if (start != end) {
return false;
}
-
+
// First: make sure the line is visible on screen:
-
+
int line = mLayout.getLineForOffset(start);
final int top = mLayout.getLineTop(line);
@@ -6264,14 +6270,14 @@
} else if (bottom > (vspace+vs-vslack)) {
line = mLayout.getLineForVertical(vspace+vs-vslack-(bottom-top));
}
-
+
// Next: make sure the character is visible on screen:
-
+
final int hspace = mRight - mLeft - getCompoundPaddingLeft() - getCompoundPaddingRight();
final int hs = mScrollX;
final int leftChar = mLayout.getOffsetForHorizontal(line, hs);
final int rightChar = mLayout.getOffsetForHorizontal(line, hspace+hs);
-
+
// line might contain bidirectional text
final int lowChar = leftChar < rightChar ? leftChar : rightChar;
final int highChar = leftChar > rightChar ? leftChar : rightChar;
@@ -6282,12 +6288,12 @@
} else if (newStart > highChar) {
newStart = highChar;
}
-
+
if (newStart != start) {
Selection.setSelection((Spannable)mText, newStart);
return true;
}
-
+
return false;
}
@@ -6436,11 +6442,12 @@
* @param singleLine
*/
private void setInputTypeSingleLine(boolean singleLine) {
- if (mEditor != null && (getEditor().mInputType & EditorInfo.TYPE_MASK_CLASS) == EditorInfo.TYPE_CLASS_TEXT) {
+ if (mEditor != null &&
+ (mEditor.mInputType & EditorInfo.TYPE_MASK_CLASS) == EditorInfo.TYPE_CLASS_TEXT) {
if (singleLine) {
- getEditor().mInputType &= ~EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE;
+ mEditor.mInputType &= ~EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE;
} else {
- getEditor().mInputType |= EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE;
+ mEditor.mInputType |= EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE;
}
}
}
@@ -6520,7 +6527,7 @@
@android.view.RemotableViewMethod
public void setSelectAllOnFocus(boolean selectAllOnFocus) {
createEditorIfNeeded("setSelectAllOnFocus");
- getEditor().mSelectAllOnFocus = selectAllOnFocus;
+ mEditor.mSelectAllOnFocus = selectAllOnFocus;
if (selectAllOnFocus && !(mText instanceof Spannable)) {
setText(mText, BufferType.SPANNABLE);
@@ -6536,14 +6543,14 @@
public void setCursorVisible(boolean visible) {
if (visible && mEditor == null) return; // visible is the default value with no edit data
createEditorIfNeeded("setCursorVisible");
- if (getEditor().mCursorVisible != visible) {
- getEditor().mCursorVisible = visible;
+ if (mEditor.mCursorVisible != visible) {
+ mEditor.mCursorVisible = visible;
invalidate();
- getEditor().makeBlink();
+ mEditor.makeBlink();
// InsertionPointCursorController depends on mCursorVisible
- getEditor().prepareCursorControllers();
+ mEditor.prepareCursorControllers();
}
}
@@ -6628,7 +6635,7 @@
/**
* This method is called when the selection has changed, in case any
* subclasses would like to know.
- *
+ *
* @param selStart The new selection start location.
* @param selEnd The new selection end location.
*/
@@ -6712,7 +6719,7 @@
}
}
- if (mEditor != null) getEditor().sendOnTextChanged(start, after);
+ if (mEditor != null) mEditor.sendOnTextChanged(start, after);
}
/**
@@ -6739,7 +6746,7 @@
if (curs >= 0) {
mHighlightPathBogus = true;
- if (mEditor != null) getEditor().makeBlink();
+ if (mEditor != null) mEditor.makeBlink();
bringPointIntoView(curs);
}
@@ -6751,7 +6758,7 @@
* through a thunk.
*/
void handleTextChanged(CharSequence buffer, int start, int before, int after) {
- final Editor.InputMethodState ims = mEditor == null ? null : getEditor().mInputMethodState;
+ final Editor.InputMethodState ims = mEditor == null ? null : mEditor.mInputMethodState;
if (ims == null || ims.mBatchEditNesting == 0) {
updateAfterEdit();
}
@@ -6782,7 +6789,7 @@
boolean selChanged = false;
int newSelStart=-1, newSelEnd=-1;
- final Editor.InputMethodState ims = mEditor == null ? null : getEditor().mInputMethodState;
+ final Editor.InputMethodState ims = mEditor == null ? null : mEditor.mInputMethodState;
if (what == Selection.SELECTION_END) {
selChanged = true;
@@ -6791,7 +6798,7 @@
if (oldStart >= 0 || newStart >= 0) {
invalidateCursor(Selection.getSelectionStart(buf), oldStart, newStart);
registerForPreDraw();
- if (mEditor != null) getEditor().makeBlink();
+ if (mEditor != null) mEditor.makeBlink();
}
}
@@ -6807,7 +6814,7 @@
if (selChanged) {
mHighlightPathBogus = true;
- if (mEditor != null && !isFocused()) getEditor().mSelectionMoved = true;
+ if (mEditor != null && !isFocused()) mEditor.mSelectionMoved = true;
if ((buf.getSpanFlags(what)&Spanned.SPAN_INTERMEDIATE) == 0) {
if (newSelStart < 0) {
@@ -6830,8 +6837,8 @@
ims.mContentChanged = true;
}
if (mEditor != null) {
- if (oldStart >= 0) getEditor().invalidateTextDisplayList(mLayout, oldStart, oldEnd);
- if (newStart >= 0) getEditor().invalidateTextDisplayList(mLayout, newStart, newEnd);
+ if (oldStart >= 0) mEditor.invalidateTextDisplayList(mLayout, oldStart, oldEnd);
+ if (newStart >= 0) mEditor.invalidateTextDisplayList(mLayout, newStart, newEnd);
}
}
@@ -6880,8 +6887,9 @@
}
}
- if (mEditor != null && getEditor().mSpellChecker != null && newStart < 0 && what instanceof SpellCheckSpan) {
- getEditor().mSpellChecker.removeSpellCheckSpan((SpellCheckSpan) what);
+ if (mEditor != null && mEditor.mSpellChecker != null && newStart < 0 &&
+ what instanceof SpellCheckSpan) {
+ mEditor.mSpellChecker.removeSpellCheckSpan((SpellCheckSpan) what);
}
}
@@ -6905,7 +6913,7 @@
// Because of View recycling in ListView, there is no easy way to know when a TextView with
// selection becomes visible again. Until a better solution is found, stop text selection
// mode (if any) as soon as this TextView is recycled.
- if (mEditor != null) getEditor().hideControllers();
+ if (mEditor != null) mEditor.hideControllers();
}
@Override
@@ -6924,7 +6932,7 @@
return;
}
- if (mEditor != null) getEditor().onFocusChanged(focused, direction);
+ if (mEditor != null) mEditor.onFocusChanged(focused, direction);
if (focused) {
if (mText instanceof Spannable) {
@@ -6946,7 +6954,7 @@
public void onWindowFocusChanged(boolean hasWindowFocus) {
super.onWindowFocusChanged(hasWindowFocus);
- if (mEditor != null) getEditor().onWindowFocusChanged(hasWindowFocus);
+ if (mEditor != null) mEditor.onWindowFocusChanged(hasWindowFocus);
startStopMarquee(hasWindowFocus);
}
@@ -6955,7 +6963,7 @@
protected void onVisibilityChanged(View changedView, int visibility) {
super.onVisibilityChanged(changedView, visibility);
if (mEditor != null && visibility != VISIBLE) {
- getEditor().hideControllers();
+ mEditor.hideControllers();
}
}
@@ -6969,7 +6977,7 @@
BaseInputConnection.removeComposingSpans((Spannable)mText);
}
}
-
+
@Override
public void setSelected(boolean selected) {
boolean wasSelected = isSelected();
@@ -6989,7 +6997,7 @@
public boolean onTouchEvent(MotionEvent event) {
final int action = event.getActionMasked();
- if (mEditor != null) getEditor().onTouchEvent(event);
+ if (mEditor != null) mEditor.onTouchEvent(event);
final boolean superResult = super.onTouchEvent(event);
@@ -6998,13 +7006,13 @@
* move the selection away from whatever the menu action was
* trying to affect.
*/
- if (mEditor != null && getEditor().mDiscardNextActionUp && action == MotionEvent.ACTION_UP) {
- getEditor().mDiscardNextActionUp = false;
+ if (mEditor != null && mEditor.mDiscardNextActionUp && action == MotionEvent.ACTION_UP) {
+ mEditor.mDiscardNextActionUp = false;
return superResult;
}
final boolean touchIsFinished = (action == MotionEvent.ACTION_UP) &&
- (mEditor == null || !getEditor().mIgnoreActionUpEvent) && isFocused();
+ (mEditor == null || !mEditor.mIgnoreActionUpEvent) && isFocused();
if ((mMovement != null || onCheckIsTextEditor()) && isEnabled()
&& mText instanceof Spannable && mLayout != null) {
@@ -7037,7 +7045,7 @@
}
// The above condition ensures that the mEditor is not null
- getEditor().onTouchUpEvent(event);
+ mEditor.onTouchUpEvent(event);
handled = true;
}
@@ -7081,13 +7089,13 @@
* of interest, in an editable text view.
*/
public boolean didTouchFocusSelect() {
- return mEditor != null && getEditor().mTouchFocusSelected;
+ return mEditor != null && mEditor.mTouchFocusSelected;
}
-
+
@Override
public void cancelLongPress() {
super.cancelLongPress();
- if (mEditor != null) getEditor().mIgnoreActionUpEvent = true;
+ if (mEditor != null) mEditor.mIgnoreActionUpEvent = true;
}
@Override
@@ -7281,16 +7289,17 @@
/**
* Unlike {@link #textCanBeSelected()}, this method is based on the <i>current</i> state of the
* TextView. {@link #textCanBeSelected()} has to be true (this is one of the conditions to have
- * a selection controller (see {@link Editor#prepareCursorControllers()}), but this is not sufficient.
+ * a selection controller (see {@link Editor#prepareCursorControllers()}), but this is not
+ * sufficient.
*/
private boolean canSelectText() {
- return mText.length() != 0 && mEditor != null && getEditor().hasSelectionController();
+ return mText.length() != 0 && mEditor != null && mEditor.hasSelectionController();
}
/**
* Test based on the <i>intrinsic</i> charateristics of the TextView.
* The text must be spannable and the movement method must allow for arbitary selection.
- *
+ *
* See also {@link #canSelectText()}.
*/
boolean textCanBeSelected() {
@@ -7298,7 +7307,8 @@
// If you change this condition, make sure prepareCursorController is called anywhere
// the value of this condition might be changed.
if (mMovement == null || !mMovement.canSelectArbitrarily()) return false;
- return isTextEditable() || (isTextSelectable() && mText instanceof Spannable && isEnabled());
+ return isTextEditable() ||
+ (isTextSelectable() && mText instanceof Spannable && isEnabled());
}
/**
@@ -7322,7 +7332,7 @@
void onLocaleChanged() {
// Will be re-created on demand in getWordIterator with the proper new locale
- getEditor().mWordIterator = null;
+ mEditor.mWordIterator = null;
}
/**
@@ -7331,8 +7341,8 @@
* @hide
*/
public WordIterator getWordIterator() {
- if (getEditor() != null) {
- return mEditor.getWordIterator();
+ if (mEditor != null) {
+ return mEditor.getWordIterator();
} else {
return null;
}
@@ -7423,7 +7433,7 @@
InputMethodManager imm = InputMethodManager.peekInstance();
return imm != null && imm.isActive(this);
}
-
+
static final int ID_SELECT_ALL = android.R.id.selectAll;
static final int ID_CUT = android.R.id.cut;
static final int ID_COPY = android.R.id.copy;
@@ -7486,12 +7496,12 @@
}
if (mEditor != null) {
- handled |= getEditor().performLongClick(handled);
+ handled |= mEditor.performLongClick(handled);
}
if (handled) {
performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
- if (mEditor != null) getEditor().mDiscardNextActionUp = true;
+ if (mEditor != null) mEditor.mDiscardNextActionUp = true;
}
return handled;
@@ -7501,7 +7511,7 @@
protected void onScrollChanged(int horiz, int vert, int oldHoriz, int oldVert) {
super.onScrollChanged(horiz, vert, oldHoriz, oldVert);
if (mEditor != null) {
- getEditor().onScrollChanged();
+ mEditor.onScrollChanged();
}
}
@@ -7529,10 +7539,12 @@
*/
public boolean isSuggestionsEnabled() {
if (mEditor == null) return false;
- if ((getEditor().mInputType & InputType.TYPE_MASK_CLASS) != InputType.TYPE_CLASS_TEXT) return false;
- if ((getEditor().mInputType & InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS) > 0) return false;
+ if ((mEditor.mInputType & InputType.TYPE_MASK_CLASS) != InputType.TYPE_CLASS_TEXT) {
+ return false;
+ }
+ if ((mEditor.mInputType & InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS) > 0) return false;
- final int variation = getEditor().mInputType & EditorInfo.TYPE_MASK_VARIATION;
+ final int variation = mEditor.mInputType & EditorInfo.TYPE_MASK_VARIATION;
return (variation == EditorInfo.TYPE_TEXT_VARIATION_NORMAL ||
variation == EditorInfo.TYPE_TEXT_VARIATION_EMAIL_SUBJECT ||
variation == EditorInfo.TYPE_TEXT_VARIATION_LONG_MESSAGE ||
@@ -7566,7 +7578,7 @@
*/
public void setCustomSelectionActionModeCallback(ActionMode.Callback actionModeCallback) {
createEditorIfNeeded("custom selection action mode set");
- getEditor().mCustomSelectionActionModeCallback = actionModeCallback;
+ mEditor.mCustomSelectionActionModeCallback = actionModeCallback;
}
/**
@@ -7575,14 +7587,14 @@
* @return The current custom selection callback.
*/
public ActionMode.Callback getCustomSelectionActionModeCallback() {
- return mEditor == null ? null : getEditor().mCustomSelectionActionModeCallback;
+ return mEditor == null ? null : mEditor.mCustomSelectionActionModeCallback;
}
/**
* @hide
*/
protected void stopSelectionActionMode() {
- getEditor().stopSelectionActionMode();
+ mEditor.stopSelectionActionMode();
}
boolean canCut() {
@@ -7590,7 +7602,8 @@
return false;
}
- if (mText.length() > 0 && hasSelection() && mText instanceof Editable && mEditor != null && getEditor().mKeyListener != null) {
+ if (mText.length() > 0 && hasSelection() && mText instanceof Editable && mEditor != null &&
+ mEditor.mKeyListener != null) {
return true;
}
@@ -7611,7 +7624,7 @@
boolean canPaste() {
return (mText instanceof Editable &&
- mEditor != null && getEditor().mKeyListener != null &&
+ mEditor != null && mEditor.mKeyListener != null &&
getSelectionStart() >= 0 &&
getSelectionEnd() >= 0 &&
((ClipboardManager)getContext().getSystemService(Context.CLIPBOARD_SERVICE)).
@@ -7755,7 +7768,7 @@
public boolean onDragEvent(DragEvent event) {
switch (event.getAction()) {
case DragEvent.ACTION_DRAG_STARTED:
- return mEditor != null && getEditor().hasInsertionController();
+ return mEditor != null && mEditor.hasInsertionController();
case DragEvent.ACTION_DRAG_ENTERED:
TextView.this.requestFocus();
@@ -7767,7 +7780,7 @@
return true;
case DragEvent.ACTION_DROP:
- if (mEditor != null) getEditor().onDrop(event);
+ if (mEditor != null) mEditor.onDrop(event);
return true;
case DragEvent.ACTION_DRAG_ENDED:
@@ -7779,11 +7792,11 @@
boolean isInBatchEditMode() {
if (mEditor == null) return false;
- final Editor.InputMethodState ims = getEditor().mInputMethodState;
+ final Editor.InputMethodState ims = mEditor.mInputMethodState;
if (ims != null) {
return ims.mBatchEditNesting > 0;
}
- return getEditor().mInBatchEditControllers;
+ return mEditor.mInBatchEditControllers;
}
@Override
@@ -7938,7 +7951,7 @@
private void createEditorIfNeeded(String reason) {
if (mEditor == null) {
if (!(this instanceof EditText)) {
- Log.e(LOG_TAG + " EDITOR", "Creating Editor on TextView. " + reason);
+ Log.e(LOG_TAG + " EDITOR", "Creating an Editor on a regular TextView. " + reason);
}
mEditor = new Editor(this);
} else {
@@ -7948,14 +7961,6 @@
}
}
- private Editor getEditor() {
- if (mEditor == null) {
- //createEditorIfNeeded("Problem: mEditor is not initialized!");
- Log.e(LOG_TAG, "mEditor not initialized. Please send a bug report to debunne@");
- }
- return mEditor;
- }
-
/**
* User interface state that is stored by TextView for implementing
* {@link View#onSaveInstanceState}.
diff --git a/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java b/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
index f2b6e45..624dea8 100644
--- a/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
+++ b/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
@@ -27,7 +27,6 @@
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.RectF;
-import android.graphics.drawable.Drawable;
import android.os.Vibrator;
import android.text.TextUtils;
import android.util.AttributeSet;
@@ -142,6 +141,7 @@
private int mTargetResourceId;
private int mTargetDescriptionsResourceId;
private int mDirectionDescriptionsResourceId;
+ private boolean mAlwaysTrackFinger;
public MultiWaveView(Context context) {
this(context, null);
@@ -168,6 +168,7 @@
mTapRadius = mHandleDrawable.getWidth()/2;
mOuterRing = new TargetDrawable(res,
a.peekValue(R.styleable.MultiWaveView_waveDrawable).resourceId);
+ mAlwaysTrackFinger = a.getBoolean(R.styleable.MultiWaveView_alwaysTrackFinger, false);
// Read chevron animation drawables
final int chevrons[] = { R.styleable.MultiWaveView_leftChevronDrawable,
@@ -634,7 +635,6 @@
@Override
public boolean onTouchEvent(MotionEvent event) {
final int action = event.getAction();
-
boolean handled = false;
switch (action) {
case MotionEvent.ACTION_DOWN:
@@ -805,7 +805,7 @@
final float y = event.getY();
final float dx = x - mWaveCenterX;
final float dy = y - mWaveCenterY;
- if (dist2(dx,dy) <= getScaledTapRadiusSquared()) {
+ if (mAlwaysTrackFinger || dist2(dx,dy) <= getScaledTapRadiusSquared()) {
if (DEBUG) Log.v(TAG, "** Handle HIT");
switchToState(STATE_FIRST_TOUCH, x, y);
moveHandleTo(x, y, false);
diff --git a/core/jni/android/graphics/TextLayoutCache.cpp b/core/jni/android/graphics/TextLayoutCache.cpp
index a97c710..684cc87 100644
--- a/core/jni/android/graphics/TextLayoutCache.cpp
+++ b/core/jni/android/graphics/TextLayoutCache.cpp
@@ -550,6 +550,10 @@
return;
}
+ // To be filled in later
+ for (size_t i = 0; i < count; i++) {
+ outAdvances->add(0);
+ }
UErrorCode error = U_ZERO_ERROR;
bool useNormalizedString = false;
for (ssize_t i = count - 1; i >= 0; --i) {
@@ -691,23 +695,11 @@
logGlyphs(mShaperItem);
#endif
- if (isRTL) {
- endScriptRun = startScriptRun;
-#if DEBUG_GLYPHS
- ALOGD("Updated endScriptRun = %d", int(endScriptRun));
-#endif
- } else {
- startScriptRun = endScriptRun;
-#if DEBUG_GLYPHS
- ALOGD("Updated startScriptRun = %d", int(startScriptRun));
-#endif
- }
if (mShaperItem.advances == NULL || mShaperItem.num_glyphs == 0) {
#if DEBUG_GLYPHS
ALOGD("Advances array is empty or num_glypth = 0");
#endif
- outAdvances->insertAt(0, outAdvances->size(), countScriptRun);
continue;
}
@@ -721,15 +713,13 @@
// Get Advances and their total
jfloat currentAdvance = HBFixedToFloat(mShaperItem.advances[mShaperItem.log_clusters[0]]);
jfloat totalFontRunAdvance = currentAdvance;
- outAdvances->add(currentAdvance);
+ outAdvances->replaceAt(currentAdvance, startScriptRun);
for (size_t i = 1; i < countScriptRun; i++) {
size_t clusterPrevious = mShaperItem.log_clusters[i - 1];
size_t cluster = mShaperItem.log_clusters[i];
- if (cluster == clusterPrevious) {
- outAdvances->add(0);
- } else {
+ if (cluster != clusterPrevious) {
currentAdvance = HBFixedToFloat(mShaperItem.advances[mShaperItem.log_clusters[i]]);
- outAdvances->add(currentAdvance);
+ outAdvances->replaceAt(currentAdvance, startScriptRun + i);
}
}
// TODO: can be removed and go back in the previous loop when Harfbuzz log clusters are fixed
@@ -746,6 +736,7 @@
(*outAdvances)[i], mShaperItem.log_clusters[i], totalFontRunAdvance);
}
#endif
+
// Get Glyphs and reverse them in place if RTL
if (outGlyphs) {
size_t countGlyphs = mShaperItem.num_glyphs;
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 31b914a..a60467b 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -316,6 +316,19 @@
return Surface::isValid(surface) ? JNI_TRUE : JNI_FALSE;
}
+static jboolean Surface_isConsumerRunningBehind(JNIEnv* env, jobject clazz)
+{
+ int value = 0;
+ const sp<Surface>& surface(getSurface(env, clazz));
+ if (!Surface::isValid(surface)) {
+ doThrowIAE(env);
+ return 0;
+ }
+ ANativeWindow* anw = static_cast<ANativeWindow *>(surface.get());
+ anw->query(anw, NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND, &value);
+ return (jboolean)value;
+}
+
static inline SkBitmap::Config convertPixelFormat(PixelFormat format)
{
/* note: if PIXEL_FORMAT_RGBX_8888 means that all alpha bytes are 0xFF, then
@@ -875,6 +888,7 @@
{"setFreezeTint", "(I)V", (void*)Surface_setFreezeTint },
{"readFromParcel", "(Landroid/os/Parcel;)V", (void*)Surface_readFromParcel },
{"writeToParcel", "(Landroid/os/Parcel;I)V", (void*)Surface_writeToParcel },
+ {"isConsumerRunningBehind", "()Z", (void*)Surface_isConsumerRunningBehind },
};
void nativeClassInit(JNIEnv* env, jclass clazz)
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index e522371..e1b9d55 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -732,14 +732,22 @@
android:description="@string/permdesc_expandStatusBar" />
<!-- Allows an application to get information about the currently
- or recently running tasks: a thumbnail representation of the tasks,
- what activities are running in it, etc. -->
+ or recently running tasks. -->
<permission android:name="android.permission.GET_TASKS"
android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
android:protectionLevel="dangerous"
android:label="@string/permlab_getTasks"
android:description="@string/permdesc_getTasks" />
+ <!-- Allows an application to get full detailed information about
+ recently running tasks, with full fidelity to the real state.
+ @hide -->
+ <permission android:name="android.permission.GET_DETAILED_TASKS"
+ android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
+ android:protectionLevel="signature"
+ android:label="@string/permlab_getDetailedTasks"
+ android:description="@string/permdesc_getDetailedTasks" />
+
<!-- Allows an application to change the Z-order of tasks -->
<permission android:name="android.permission.REORDER_TASKS"
android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
diff --git a/core/res/res/anim/activity_close_enter.xml b/core/res/res/anim/activity_close_enter.xml
index c759a83..84e4a19 100644
--- a/core/res/res/anim/activity_close_enter.xml
+++ b/core/res/res/anim/activity_close_enter.xml
@@ -20,12 +20,5 @@
<set xmlns:android="http://schemas.android.com/apk/res/android" android:zAdjustment="normal">
<alpha android:fromAlpha="1.0" android:toAlpha="1.0"
android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
- android:duration="@android:integer/config_shortAnimTime"/>
- <scale android:fromXScale=".95" android:toXScale="1.0"
- android:fromYScale=".95" android:toYScale="1.0"
- android:pivotX="50%p" android:pivotY="50%p"
- android:interpolator="@interpolator/accelerate_quint"
- android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
- android:duration="@android:integer/config_shortAnimTime"/>
-
+ android:duration="300"/>
</set>
\ No newline at end of file
diff --git a/core/res/res/anim/activity_close_exit.xml b/core/res/res/anim/activity_close_exit.xml
index 384810f2..32f6d38 100644
--- a/core/res/res/anim/activity_close_exit.xml
+++ b/core/res/res/anim/activity_close_exit.xml
@@ -22,11 +22,11 @@
<alpha android:fromAlpha="1.0" android:toAlpha="0.0"
android:interpolator="@interpolator/decelerate_cubic"
android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
- android:duration="@android:integer/config_shortAnimTime"/>
- <scale android:fromXScale="1.0" android:toXScale="1.1"
- android:fromYScale="1.0" android:toYScale="1.1"
+ android:duration="300"/>
+ <scale android:fromXScale="1.0" android:toXScale=".8"
+ android:fromYScale="1.0" android:toYScale=".8"
android:pivotX="50%p" android:pivotY="50%p"
- android:interpolator="@interpolator/decelerate_quint"
+ android:interpolator="@interpolator/decelerate_cubic"
android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
- android:duration="@android:integer/config_shortAnimTime"/>
+ android:duration="300"/>
</set>
\ No newline at end of file
diff --git a/core/res/res/anim/activity_open_enter.xml b/core/res/res/anim/activity_open_enter.xml
index 744153d..c92f000 100644
--- a/core/res/res/anim/activity_open_enter.xml
+++ b/core/res/res/anim/activity_open_enter.xml
@@ -24,12 +24,12 @@
android:interpolator="@interpolator/decelerate_cubic"
android:fillEnabled="true"
android:fillBefore="false" android:fillAfter="false"
- android:duration="@android:integer/config_shortAnimTime"/>
- <scale android:fromXScale="1.1" android:toXScale="1.0"
- android:fromYScale="1.1" android:toYScale="1.0"
+ android:duration="300"/>
+ <scale android:fromXScale=".8" android:toXScale="1.0"
+ android:fromYScale=".8" android:toYScale="1.0"
android:pivotX="50%p" android:pivotY="50%p"
- android:interpolator="@interpolator/decelerate_quint"
+ android:interpolator="@interpolator/decelerate_cubic"
android:fillEnabled="true"
android:fillBefore="false" android:fillAfter="false"
- android:duration="@android:integer/config_shortAnimTime"/>
+ android:duration="300"/>
</set>
\ No newline at end of file
diff --git a/core/res/res/anim/activity_open_exit.xml b/core/res/res/anim/activity_open_exit.xml
index 58e8816..d7bfe82 100644
--- a/core/res/res/anim/activity_open_exit.xml
+++ b/core/res/res/anim/activity_open_exit.xml
@@ -18,15 +18,8 @@
-->
<set xmlns:android="http://schemas.android.com/apk/res/android" android:zAdjustment="normal">
- <alpha android:fromAlpha="1.0" android:toAlpha="1.0"
+ <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
android:fillEnabled="true" android:fillBefore="false" android:fillAfter="false"
- android:duration="@android:integer/config_shortAnimTime"/>
- <scale android:fromXScale="1.0" android:toXScale=".95"
- android:fromYScale="1.0" android:toYScale=".95"
- android:pivotX="50%p" android:pivotY="50%p"
android:interpolator="@interpolator/decelerate_quint"
- android:fillEnabled="true"
- android:fillBefore="false" android:fillAfter="false"
- android:duration="@android:integer/config_shortAnimTime"/>
-
+ android:duration="300"/>
</set>
\ No newline at end of file
diff --git a/core/res/res/anim/lock_screen_behind_enter.xml b/core/res/res/anim/lock_screen_behind_enter.xml
index 78b7d29..cb47b3c 100644
--- a/core/res/res/anim/lock_screen_behind_enter.xml
+++ b/core/res/res/anim/lock_screen_behind_enter.xml
@@ -19,14 +19,6 @@
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:background="#ff000000" android:shareInterpolator="false">
- <scale
- android:fromXScale="0.90" android:toXScale="1.0"
- android:fromYScale="0.90" android:toYScale="1.0"
- android:pivotX="50%p" android:pivotY="50%p"
- android:fillEnabled="true" android:fillBefore="true"
- android:interpolator="@interpolator/decelerate_cubic"
- android:startOffset="@android:integer/config_shortAnimTime"
- android:duration="@android:integer/config_shortAnimTime" />
<alpha
android:fromAlpha="0.0" android:toAlpha="1.0"
android:fillEnabled="true" android:fillBefore="true"
diff --git a/core/res/res/anim/lock_screen_exit.xml b/core/res/res/anim/lock_screen_exit.xml
index a186126..37383d9 100644
--- a/core/res/res/anim/lock_screen_exit.xml
+++ b/core/res/res/anim/lock_screen_exit.xml
@@ -22,8 +22,8 @@
android:zAdjustment="top"
android:shareInterpolator="false">
<scale
- android:fromXScale="1.0" android:toXScale="1.15"
- android:fromYScale="1.0" android:toYScale="1.15"
+ android:fromXScale="1.0" android:toXScale="1.10"
+ android:fromYScale="1.0" android:toYScale="1.10"
android:pivotX="50%p" android:pivotY="50%p"
android:fillEnabled="true" android:fillAfter="true"
android:interpolator="@interpolator/accelerate_quint"
diff --git a/core/res/res/anim/lock_screen_wallpaper_behind_enter.xml b/core/res/res/anim/lock_screen_wallpaper_behind_enter.xml
index a354fae..c29fd1a 100644
--- a/core/res/res/anim/lock_screen_wallpaper_behind_enter.xml
+++ b/core/res/res/anim/lock_screen_wallpaper_behind_enter.xml
@@ -19,14 +19,6 @@
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:detachWallpaper="true" android:shareInterpolator="false">
- <scale
- android:fromXScale="0.95" android:toXScale="1.0"
- android:fromYScale="0.95" android:toYScale="1.0"
- android:pivotX="50%p" android:pivotY="50%p"
- android:fillEnabled="true" android:fillBefore="true"
- android:interpolator="@interpolator/decelerate_cubic"
- android:startOffset="@android:integer/config_shortAnimTime"
- android:duration="@android:integer/config_shortAnimTime" />
<alpha
android:fromAlpha="0.0" android:toAlpha="1.0"
android:fillEnabled="true" android:fillBefore="true"
diff --git a/core/res/res/anim/task_close_enter.xml b/core/res/res/anim/task_close_enter.xml
index b39d551..dad8c1f 100644
--- a/core/res/res/anim/task_close_enter.xml
+++ b/core/res/res/anim/task_close_enter.xml
@@ -19,16 +19,21 @@
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:background="#ff000000" android:shareInterpolator="false" android:zAdjustment="normal">
- <scale android:fromXScale="0.95" android:toXScale="1.0"
- android:fromYScale="0.95" android:toYScale="1.0"
+ <alpha android:fromAlpha="0" android:toAlpha="1"
+ android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
+ android:interpolator="@interpolator/decelerate_cubic"
+ android:startOffset="600"
+ android:duration="200"/>
+ <scale android:fromXScale="0.6" android:toXScale="1.0"
+ android:fromYScale="0.6" android:toYScale="1.0"
android:pivotX="50%p" android:pivotY="50%p"
android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
- android:interpolator="@interpolator/decelerate_quint"
- android:startOffset="200"
- android:duration="300" />
- <alpha android:fromAlpha="0" android:toAlpha="1.0"
+ android:interpolator="@interpolator/decelerate_cubic"
+ android:startOffset="350"
+ android:duration="400" />
+ <translate android:fromYDelta="-100%" android:toYDelta="0"
android:interpolator="@interpolator/decelerate_cubic"
android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
- android:startOffset="200"
- android:duration="300"/>
+ android:startOffset="350"
+ android:duration="400"/>
</set>
\ No newline at end of file
diff --git a/core/res/res/anim/task_close_exit.xml b/core/res/res/anim/task_close_exit.xml
index ffbd38a..485c91d 100644
--- a/core/res/res/anim/task_close_exit.xml
+++ b/core/res/res/anim/task_close_exit.xml
@@ -19,17 +19,18 @@
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:background="#ff000000" android:shareInterpolator="false" android:zAdjustment="top">
- <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
- android:interpolator="@interpolator/accelerate_cubic"
- android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
- android:duration="200" />
- <scale android:fromXScale="1.0" android:toXScale="1.2"
- android:fromYScale="1.0" android:toYScale="0.8"
- android:pivotX="50%p" android:pivotY="50%p"
- android:interpolator="@interpolator/accelerate_quint"
- android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
- android:duration="200" />
- <!-- This is needed to keep the animation running while task_close_enter completes -->
- <alpha android:fromAlpha="1.0" android:toAlpha="1.0"
- android:duration="500" />
+ <scale android:fromXScale="1.0" android:toXScale=".8"
+ android:fromYScale="1.0" android:toYScale=".8"
+ android:pivotX="50%p" android:pivotY="50%p"
+ android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
+ android:interpolator="@interpolator/decelerate_cubic"
+ android:duration="300" />
+ <alpha android:fromAlpha="1.0" android:toAlpha="0"
+ android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
+ android:interpolator="@interpolator/decelerate_cubic"
+ android:duration="300"/>
+
+ <!-- This is needed to keep the animation running while task_close_enter completes -->
+ <alpha android:fromAlpha="1.0" android:toAlpha="1.0"
+ android:duration="600" />
</set>
\ No newline at end of file
diff --git a/core/res/res/anim/task_open_enter.xml b/core/res/res/anim/task_open_enter.xml
index d64f856..8341806 100644
--- a/core/res/res/anim/task_open_enter.xml
+++ b/core/res/res/anim/task_open_enter.xml
@@ -19,16 +19,16 @@
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:background="#ff000000" android:shareInterpolator="false" android:zAdjustment="top">
- <scale android:fromXScale="1.2" android:toXScale="1.0"
+ <scale android:fromXScale=".8" android:toXScale="1.0"
android:fromYScale=".8" android:toYScale="1.0"
android:pivotX="50%p" android:pivotY="50%p"
android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
- android:interpolator="@interpolator/decelerate_quint"
- android:startOffset="300"
- android:duration="240" />
+ android:interpolator="@interpolator/decelerate_quad"
+ android:startOffset="400"
+ android:duration="300" />
<alpha android:fromAlpha="0" android:toAlpha="1.0"
android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
android:interpolator="@interpolator/decelerate_quad"
- android:startOffset="300"
+ android:startOffset="400"
android:duration="300"/>
</set>
\ No newline at end of file
diff --git a/core/res/res/anim/task_open_exit.xml b/core/res/res/anim/task_open_exit.xml
index 19f92c0..af1a4a9 100644
--- a/core/res/res/anim/task_open_exit.xml
+++ b/core/res/res/anim/task_open_exit.xml
@@ -22,14 +22,19 @@
<alpha android:fromAlpha="1.0" android:toAlpha="0"
android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
android:interpolator="@interpolator/decelerate_cubic"
- android:duration="200"/>
- <scale android:fromXScale="1.0" android:toXScale="0.95"
- android:fromYScale="1.0" android:toYScale="0.95"
+ android:duration="300"/>
+ <scale android:fromXScale="1.0" android:toXScale="0.6"
+ android:fromYScale="1.0" android:toYScale="0.6"
android:pivotX="50%p" android:pivotY="50%p"
android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
- android:interpolator="@interpolator/decelerate_quint"
- android:duration="300" />
+ android:interpolator="@interpolator/accelerate_quad"
+ android:duration="500" />
+ <translate android:fromYDelta="0" android:toYDelta="-100%"
+ android:interpolator="@interpolator/accelerate_quad"
+ android:duration="500"/>
+
<!-- This is needed to keep the animation running while task_open_enter completes -->
<alpha android:fromAlpha="1.0" android:toAlpha="1.0"
- android:duration="540" />
+ android:interpolator="@interpolator/accelerate_quad"
+ android:duration="700" />
</set>
\ No newline at end of file
diff --git a/core/res/res/anim/wallpaper_close_enter.xml b/core/res/res/anim/wallpaper_close_enter.xml
index 1ca5c0c..981923a 100644
--- a/core/res/res/anim/wallpaper_close_enter.xml
+++ b/core/res/res/anim/wallpaper_close_enter.xml
@@ -19,16 +19,14 @@
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false" android:zAdjustment="top">
- <scale android:fromXScale="1.2" android:toXScale="1.0"
- android:fromYScale=".8" android:toYScale="1.0"
+ <scale android:fromXScale=".2" android:toXScale="1.0"
+ android:fromYScale=".2" android:toYScale="1.0"
android:pivotX="50%p" android:pivotY="50%p"
android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
- android:interpolator="@interpolator/decelerate_quint"
- android:startOffset="300"
- android:duration="240" />
+ android:interpolator="@interpolator/decelerate_cubic"
+ android:duration="300" />
<alpha android:fromAlpha="0" android:toAlpha="1.0"
android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
- android:interpolator="@interpolator/decelerate_quad"
- android:startOffset="300"
+ android:interpolator="@interpolator/decelerate_cubic"
android:duration="300"/>
</set>
\ No newline at end of file
diff --git a/core/res/res/anim/wallpaper_close_exit.xml b/core/res/res/anim/wallpaper_close_exit.xml
index 987fd89..a91eb49 100644
--- a/core/res/res/anim/wallpaper_close_exit.xml
+++ b/core/res/res/anim/wallpaper_close_exit.xml
@@ -19,17 +19,6 @@
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:detachWallpaper="true" android:shareInterpolator="false" android:zAdjustment="normal">
- <alpha android:fromAlpha="1.0" android:toAlpha="0"
- android:fillEnabled="true" android:fillAfter="true"
- android:interpolator="@interpolator/decelerate_cubic"
- android:duration="200"/>
- <scale android:fromXScale="1.0" android:toXScale="0.95"
- android:fromYScale="1.0" android:toYScale="0.95"
- android:pivotX="50%p" android:pivotY="50%p"
- android:fillEnabled="true" android:fillAfter="true"
- android:interpolator="@interpolator/decelerate_quint"
- android:duration="300" />
- <!-- This is needed to keep the animation running while wallpaper_close_enter completes -->
<alpha android:fromAlpha="1.0" android:toAlpha="1.0"
- android:duration="600" />
+ android:duration="300" />
</set>
\ No newline at end of file
diff --git a/core/res/res/anim/wallpaper_open_enter.xml b/core/res/res/anim/wallpaper_open_enter.xml
index 6fdbd40..ee7ab60 100644
--- a/core/res/res/anim/wallpaper_open_enter.xml
+++ b/core/res/res/anim/wallpaper_open_enter.xml
@@ -19,16 +19,7 @@
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:detachWallpaper="true" android:shareInterpolator="false" android:zAdjustment="normal">
- <scale android:fromXScale="0.95" android:toXScale="1.0"
- android:fromYScale="0.95" android:toYScale="1.0"
- android:pivotX="50%p" android:pivotY="50%p"
+ <alpha android:fromAlpha="1.0" android:toAlpha="1.0"
android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
- android:interpolator="@interpolator/decelerate_quint"
- android:startOffset="200"
- android:duration="300" />
- <alpha android:fromAlpha="0" android:toAlpha="1.0"
- android:interpolator="@interpolator/decelerate_cubic"
- android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
- android:startOffset="200"
android:duration="300"/>
</set>
\ No newline at end of file
diff --git a/core/res/res/anim/wallpaper_open_exit.xml b/core/res/res/anim/wallpaper_open_exit.xml
index 1804fa8..8a2582e 100644
--- a/core/res/res/anim/wallpaper_open_exit.xml
+++ b/core/res/res/anim/wallpaper_open_exit.xml
@@ -20,16 +20,13 @@
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false" android:zAdjustment="top">
<alpha android:fromAlpha="1.0" android:toAlpha="0.0"
- android:interpolator="@interpolator/accelerate_cubic"
+ android:interpolator="@interpolator/decelerate_cubic"
android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
android:duration="200" />
- <scale android:fromXScale="1.0" android:toXScale="1.2"
- android:fromYScale="1.0" android:toYScale="0.8"
+ <scale android:fromXScale="1.0" android:toXScale="0.4"
+ android:fromYScale="1.0" android:toYScale="0.4"
android:pivotX="50%p" android:pivotY="50%p"
- android:interpolator="@interpolator/accelerate_quint"
+ android:interpolator="@interpolator/decelerate_cubic"
android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
- android:duration="200" />
- <!-- This is needed to keep the animation running while wallpaper_open_enter completes -->
- <alpha android:fromAlpha="1.0" android:toAlpha="1.0"
- android:duration="500" />
+ android:duration="300" />
</set>
\ No newline at end of file
diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_google_activated.png b/core/res/res/drawable-hdpi/ic_lockscreen_google_activated.png
new file mode 100644
index 0000000..2c4847c
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_lockscreen_google_activated.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_google_focused.png b/core/res/res/drawable-hdpi/ic_lockscreen_google_focused.png
new file mode 100644
index 0000000..d98557d
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_lockscreen_google_focused.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_google_normal.png b/core/res/res/drawable-hdpi/ic_lockscreen_google_normal.png
new file mode 100644
index 0000000..656f3ba
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_lockscreen_google_normal.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lockscreen_google_activated.png b/core/res/res/drawable-mdpi/ic_lockscreen_google_activated.png
new file mode 100644
index 0000000..32a68e0
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_lockscreen_google_activated.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lockscreen_google_focused.png b/core/res/res/drawable-mdpi/ic_lockscreen_google_focused.png
new file mode 100644
index 0000000..3f96d03
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_lockscreen_google_focused.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lockscreen_google_normal.png b/core/res/res/drawable-mdpi/ic_lockscreen_google_normal.png
new file mode 100644
index 0000000..2f7efcf
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_lockscreen_google_normal.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lockscreen_google_activated.png b/core/res/res/drawable-xhdpi/ic_lockscreen_google_activated.png
new file mode 100644
index 0000000..d643f83
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_lockscreen_google_activated.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lockscreen_google_focused.png b/core/res/res/drawable-xhdpi/ic_lockscreen_google_focused.png
new file mode 100644
index 0000000..51863f4
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_lockscreen_google_focused.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lockscreen_google_normal.png b/core/res/res/drawable-xhdpi/ic_lockscreen_google_normal.png
new file mode 100644
index 0000000..9a9bf68
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_lockscreen_google_normal.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lockscreen_search_activated.png b/core/res/res/drawable-xhdpi/ic_lockscreen_search_activated.png
deleted file mode 100644
index c625a36..0000000
--- a/core/res/res/drawable-xhdpi/ic_lockscreen_search_activated.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lockscreen_search_normal.png b/core/res/res/drawable-xhdpi/ic_lockscreen_search_normal.png
deleted file mode 100644
index c625a36..0000000
--- a/core/res/res/drawable-xhdpi/ic_lockscreen_search_normal.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable/ic_lockscreen_search.xml b/core/res/res/drawable/ic_lockscreen_search.xml
index b103922..2c0091a 100644
--- a/core/res/res/drawable/ic_lockscreen_search.xml
+++ b/core/res/res/drawable/ic_lockscreen_search.xml
@@ -19,12 +19,12 @@
android:state_enabled="true"
android:state_active="false"
android:state_focused="false"
- android:drawable="@drawable/ic_lockscreen_search_normal" />
+ android:drawable="@drawable/ic_lockscreen_google_normal" />
<item
android:state_enabled="true"
android:state_active="true"
android:state_focused="false"
- android:drawable="@drawable/ic_lockscreen_search_activated" />
+ android:drawable="@drawable/ic_lockscreen_google_activated" />
</selector>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 0ac381d..9fa666e 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -5383,6 +5383,9 @@
<!-- Used to shift center of pattern horizontally. -->
<attr name="horizontalOffset" format="dimension" />
+
+ <!-- Used when the handle shouldn't wait to be hit before following the finger -->
+ <attr name="alwaysTrackFinger" format="boolean" />
</declare-styleable>
<!-- =============================== -->
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index a589015..213f692 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -542,6 +542,13 @@
information about currently and recently running tasks. Malicious apps may
discover private information about other apps.</string>
+ <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=50] -->
+ <string name="permlab_getDetailedTasks">retrieve details of running apps</string>
+ <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=NONE] -->
+ <string name="permdesc_getDetailedTasks">Allows the app to retrieve
+ detailed information about currently and recently running tasks. Malicious apps may
+ discover private information about other apps.</string>
+
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permlab_reorderTasks">reorder running apps</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
diff --git a/packages/InputDevices/res/raw/keyboard_layout_french.kcm b/packages/InputDevices/res/raw/keyboard_layout_french.kcm
new file mode 100644
index 0000000..89e83da
--- /dev/null
+++ b/packages/InputDevices/res/raw/keyboard_layout_french.kcm
@@ -0,0 +1,336 @@
+# Copyright (C) 2012 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#
+# French keyboard layout, AZERTY style.
+#
+
+type OVERLAY
+
+map key 16 A
+map key 17 Z
+map key 30 Q
+map key 39 M
+map key 44 W
+map key 50 COMMA
+map key 51 SEMICOLON
+map key 86 PLUS
+
+### ROW 1
+
+key GRAVE {
+ label: '\u00b2'
+ base: '\u00b2'
+}
+
+key 1 {
+ label: '1'
+ base: '&'
+ shift: '1'
+}
+
+key 2 {
+ label: '2'
+ base: '\u00e9'
+ shift: '2'
+ ralt: '~'
+}
+
+key 3 {
+ label: '3'
+ base: '"'
+ shift: '3'
+ ralt: '#'
+}
+
+key 4 {
+ label: '4'
+ base: '\''
+ shift: '4'
+ ralt: '{'
+}
+
+key 5 {
+ label: '5'
+ base: '('
+ shift: '5'
+ ralt: '['
+}
+
+key 6 {
+ label: '6'
+ base: '-'
+ shift: '6'
+ ralt: '|'
+}
+
+key 7 {
+ label: '7'
+ base: '\u00e8'
+ shift: '7'
+ ralt: '`'
+}
+
+key 8 {
+ label: '8'
+ base: '_'
+ shift: '8'
+ ralt: '\\'
+}
+
+key 9 {
+ label: '9'
+ base: '\u00e7'
+ shift: '9'
+ ralt: '^'
+}
+
+key 0 {
+ label: '0'
+ base: '\u00e0'
+ shift: '0'
+ ralt: '@'
+}
+
+key MINUS {
+ label: ')'
+ base: ')'
+ shift: '\u00b0'
+ ralt: ']'
+}
+
+key EQUALS {
+ label: '='
+ base: '='
+ shift: '+'
+ ralt: '}'
+}
+
+### ROW 2
+
+key A {
+ label: 'A'
+ base: 'a'
+ shift, capslock: 'A'
+}
+
+key Z {
+ label: 'Z'
+ base: 'z'
+ shift, capslock: 'Z'
+}
+
+key E {
+ label: 'E'
+ base: 'e'
+ shift, capslock: 'E'
+ ralt: '\u20ac'
+}
+
+key R {
+ label: 'R'
+ base: 'r'
+ shift, capslock: 'R'
+}
+
+key T {
+ label: 'T'
+ base: 't'
+ shift, capslock: 'T'
+}
+
+key Y {
+ label: 'Y'
+ base: 'y'
+ shift, capslock: 'Y'
+}
+
+key U {
+ label: 'U'
+ base: 'u'
+ shift, capslock: 'U'
+}
+
+key I {
+ label: 'I'
+ base: 'i'
+ shift, capslock: 'I'
+}
+
+key O {
+ label: 'O'
+ base: 'o'
+ shift, capslock: 'O'
+}
+
+key P {
+ label: 'P'
+ base: 'p'
+ shift, capslock: 'P'
+}
+
+key LEFT_BRACKET {
+ label: '\u02c6'
+ base: '\u0302'
+ shift: '\u0308'
+}
+
+key RIGHT_BRACKET {
+ label: '$'
+ base: '$'
+ shift: '\u00a3'
+ ralt: '\u00a4'
+}
+
+### ROW 3
+
+key Q {
+ label: 'Q'
+ base: 'q'
+ shift, capslock: 'Q'
+}
+
+key S {
+ label: 'S'
+ base: 's'
+ shift, capslock: 'S'
+}
+
+key D {
+ label: 'D'
+ base: 'd'
+ shift, capslock: 'D'
+}
+
+key F {
+ label: 'F'
+ base: 'f'
+ shift, capslock: 'F'
+}
+
+key G {
+ label: 'G'
+ base: 'g'
+ shift, capslock: 'G'
+}
+
+key H {
+ label: 'H'
+ base: 'h'
+ shift, capslock: 'H'
+}
+
+key J {
+ label: 'J'
+ base: 'j'
+ shift, capslock: 'J'
+}
+
+key K {
+ label: 'K'
+ base: 'k'
+ shift, capslock: 'K'
+}
+
+key L {
+ label: 'L'
+ base: 'l'
+ shift, capslock: 'L'
+}
+
+key M {
+ label: 'M'
+ base: 'm'
+ shift, capslock: 'M'
+}
+
+key APOSTROPHE {
+ label: '\u00f9'
+ base: '\u00f9'
+ shift: '%'
+}
+
+key BACKSLASH {
+ label: '*'
+ base: '*'
+ shift: '\u00b5'
+}
+
+### ROW 4
+
+key PLUS {
+ label: '<'
+ base: '<'
+ shift: '>'
+}
+
+key W {
+ label: 'W'
+ base: 'w'
+ shift, capslock: 'W'
+}
+
+key X {
+ label: 'X'
+ base: 'x'
+ shift, capslock: 'X'
+}
+
+key C {
+ label: 'C'
+ base: 'c'
+ shift, capslock: 'C'
+}
+
+key V {
+ label: 'V'
+ base: 'v'
+ shift, capslock: 'V'
+}
+
+key B {
+ label: 'B'
+ base: 'b'
+ shift, capslock: 'B'
+}
+
+key N {
+ label: 'N'
+ base: 'n'
+ shift, capslock: 'N'
+}
+
+key COMMA {
+ label: ','
+ base: ','
+ shift: '?'
+}
+
+key SEMICOLON {
+ label: ';'
+ base: ';'
+ shift: '.'
+}
+
+key PERIOD {
+ label: ':'
+ base: ':'
+ shift: '/'
+}
+
+key SLASH {
+ label: '!'
+ base: '!'
+ shift: '\u00a7'
+}
diff --git a/packages/InputDevices/res/raw/keyboard_layout_french_ca.kcm b/packages/InputDevices/res/raw/keyboard_layout_french_ca.kcm
new file mode 100644
index 0000000..55ddd60
--- /dev/null
+++ b/packages/InputDevices/res/raw/keyboard_layout_french_ca.kcm
@@ -0,0 +1,339 @@
+# Copyright (C) 2012 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#
+# French (Canada) keyboard layout.
+#
+
+type OVERLAY
+
+map key 86 PLUS
+
+### ROW 1
+
+key GRAVE {
+ label: '#'
+ base: '#'
+ shift: '|'
+ ralt: '\\'
+}
+
+key 1 {
+ label: '1'
+ base: '1'
+ shift: '!'
+ ralt: '\u00b1'
+}
+
+key 2 {
+ label: '2'
+ base: '2'
+ shift: '"'
+ ralt: '@'
+}
+
+key 3 {
+ label: '3'
+ base: '3'
+ shift: '/'
+ ralt: '\u00a3'
+}
+
+key 4 {
+ label: '4'
+ base: '4'
+ shift: '$'
+ ralt: '\u00a2'
+}
+
+key 5 {
+ label: '5'
+ base: '5'
+ shift: '%'
+ ralt: '\u00a4'
+}
+
+key 6 {
+ label: '6'
+ base: '6'
+ shift: '?'
+ ralt: '\u00ac'
+}
+
+key 7 {
+ label: '7'
+ base: '7'
+ shift: '&'
+ ralt: '\u00a6'
+}
+
+key 8 {
+ label: '8'
+ base: '8'
+ shift: '*'
+ ralt: '\u00b2'
+}
+
+key 9 {
+ label: '9'
+ base: '9'
+ shift: '('
+ ralt: '\u00b3'
+}
+
+key 0 {
+ label: '0'
+ base: '0'
+ shift: ')'
+ ralt: '\u00bc'
+}
+
+key MINUS {
+ label: '-'
+ base: '-'
+ shift: '_'
+ ralt: '\u00bd'
+}
+
+key EQUALS {
+ label: '='
+ base: '='
+ shift: '+'
+ ralt: '\u00be'
+}
+
+### ROW 2
+
+key Q {
+ label: 'Q'
+ base: 'q'
+ shift, capslock: 'Q'
+}
+
+key W {
+ label: 'W'
+ base: 'w'
+ shift, capslock: 'W'
+}
+
+key E {
+ label: 'E'
+ base: 'e'
+ shift, capslock: 'E'
+}
+
+key R {
+ label: 'R'
+ base: 'r'
+ shift, capslock: 'R'
+}
+
+key T {
+ label: 'T'
+ base: 't'
+ shift, capslock: 'T'
+}
+
+key Y {
+ label: 'Y'
+ base: 'y'
+ shift, capslock: 'Y'
+}
+
+key U {
+ label: 'U'
+ base: 'u'
+ shift, capslock: 'U'
+}
+
+key I {
+ label: 'I'
+ base: 'i'
+ shift, capslock: 'I'
+}
+
+key O {
+ label: 'O'
+ base: 'o'
+ shift, capslock: 'O'
+ ralt: '\u00a7'
+}
+
+key P {
+ label: 'P'
+ base: 'p'
+ shift, capslock: 'P'
+ ralt: '\u00b6'
+}
+
+key LEFT_BRACKET {
+ label: '\u02c6'
+ base: '\u0302'
+ ralt: '['
+}
+
+key RIGHT_BRACKET {
+ label: '\u00b8'
+ base: '\u0327'
+ shift: '\u0308'
+ ralt: ']'
+}
+
+### ROW 3
+
+key A {
+ label: 'A'
+ base: 'a'
+ shift, capslock: 'A'
+}
+
+key S {
+ label: 'S'
+ base: 's'
+ shift, capslock: 'S'
+}
+
+key D {
+ label: 'D'
+ base: 'd'
+ shift, capslock: 'D'
+}
+
+key F {
+ label: 'F'
+ base: 'f'
+ shift, capslock: 'F'
+}
+
+key G {
+ label: 'G'
+ base: 'g'
+ shift, capslock: 'G'
+}
+
+key H {
+ label: 'H'
+ base: 'h'
+ shift, capslock: 'H'
+}
+
+key J {
+ label: 'J'
+ base: 'j'
+ shift, capslock: 'J'
+}
+
+key K {
+ label: 'K'
+ base: 'k'
+ shift, capslock: 'K'
+}
+
+key L {
+ label: 'L'
+ base: 'l'
+ shift, capslock: 'L'
+}
+
+key SEMICOLON {
+ label: ';'
+ base: ';'
+ shift: ':'
+ ralt: '~'
+}
+
+key APOSTROPHE {
+ label: '\u02cb'
+ base: '\u0300'
+ ralt: '{'
+}
+
+key BACKSLASH {
+ label: '<'
+ base: '<'
+ shift: '>'
+ ralt: '}'
+}
+
+### ROW 4
+
+key PLUS {
+ label: '\u00ab'
+ base: '\u00ab'
+ shift: '\u00bb'
+ ralt: '\u00b0'
+}
+
+key Z {
+ label: 'Z'
+ base: 'z'
+ shift, capslock: 'Z'
+}
+
+key X {
+ label: 'X'
+ base: 'x'
+ shift, capslock: 'X'
+}
+
+key C {
+ label: 'C'
+ base: 'c'
+ shift, capslock: 'C'
+}
+
+key V {
+ label: 'V'
+ base: 'v'
+ shift, capslock: 'V'
+}
+
+key B {
+ label: 'B'
+ base: 'b'
+ shift, capslock: 'B'
+}
+
+key N {
+ label: 'N'
+ base: 'n'
+ shift, capslock: 'N'
+}
+
+key M {
+ label: 'M'
+ base: 'm'
+ shift, capslock: 'M'
+ ralt: '\u00b5'
+}
+
+key COMMA {
+ label: ','
+ base: ','
+ shift: '\''
+ ralt: '_'
+}
+
+key PERIOD {
+ label: '.'
+ base: '.'
+ ralt: '-'
+}
+
+key SLASH {
+ label: '\u00c9'
+ base: '\u00e9'
+ shift, capslock: '\u00c9'
+ ralt: '\u0301'
+}
diff --git a/packages/InputDevices/res/raw/keyboard_layout_german.kcm b/packages/InputDevices/res/raw/keyboard_layout_german.kcm
index 9c75973..d9caa32 100644
--- a/packages/InputDevices/res/raw/keyboard_layout_german.kcm
+++ b/packages/InputDevices/res/raw/keyboard_layout_german.kcm
@@ -178,7 +178,7 @@
key LEFT_BRACKET {
label: '\u00dc'
base: '\u00fc'
- shift: '\u00dc'
+ shift, capslock: '\u00dc'
}
key RIGHT_BRACKET {
@@ -247,13 +247,13 @@
key SEMICOLON {
label: '\u00d6'
base: '\u00f6'
- shift: '\u00d6'
+ shift, capslock: '\u00d6'
}
key APOSTROPHE {
label: '\u00c4'
base: '\u00e4'
- shift: '\u00c4'
+ shift, capslock: '\u00c4'
}
key BACKSLASH {
diff --git a/packages/InputDevices/res/raw/keyboard_layout_russian.kcm b/packages/InputDevices/res/raw/keyboard_layout_russian.kcm
new file mode 100644
index 0000000..73646d2
--- /dev/null
+++ b/packages/InputDevices/res/raw/keyboard_layout_russian.kcm
@@ -0,0 +1,396 @@
+# Copyright (C) 2012 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#
+# Russian keyboard layout.
+# This is a typical Russian PC keyboard layout.
+# English characters are accessible using ralt (Alt Gr).
+#
+
+type OVERLAY
+
+map key 86 BACKSLASH
+
+### ROW 1
+
+key GRAVE {
+ label: '\u0401'
+ base: '\u0451'
+ shift, capslock: '\u0401'
+ ralt: '`'
+ ralt+shift: '~'
+}
+
+key 1 {
+ label: '1'
+ base: '1'
+ shift: '!'
+ ralt: '!'
+}
+
+key 2 {
+ label: '2'
+ base: '2'
+ shift: '"'
+ ralt: '@'
+}
+
+key 3 {
+ label: '3'
+ base: '3'
+ shift: '\u2116'
+ ralt: '#'
+}
+
+key 4 {
+ label: '4'
+ base: '4'
+ shift: ';'
+ ralt: '$'
+}
+
+key 5 {
+ label: '5'
+ base: '5'
+ shift: '%'
+ ralt: '%'
+}
+
+key 6 {
+ label: '6'
+ base: '6'
+ shift: ':'
+ ralt: '^'
+}
+
+key 7 {
+ label: '7'
+ base: '7'
+ shift: '?'
+ ralt: '&'
+}
+
+key 8 {
+ label: '8'
+ base: '8'
+ shift: '*'
+ ralt: '*'
+}
+
+key 9 {
+ label: '9'
+ base: '9'
+ shift: '('
+ ralt: '('
+}
+
+key 0 {
+ label: '0'
+ base: '0'
+ shift: ')'
+ ralt: ')'
+}
+
+key MINUS {
+ label: '-'
+ base: '-'
+ shift: '_'
+ ralt: '-'
+ ralt+shift: '_'
+}
+
+key EQUALS {
+ label: '='
+ base: '='
+ shift: '+'
+ ralt: '='
+ ralt+shift: '+'
+}
+
+### ROW 2
+
+key Q {
+ label: '\u0419'
+ base: '\u0439'
+ shift, capslock: '\u0419'
+ ralt: 'q'
+ ralt+shift, ralt+capslock: 'Q'
+}
+
+key W {
+ label: '\u0426'
+ base: '\u0446'
+ shift, capslock: '\u0426'
+ ralt: 'w'
+ ralt+shift, ralt+capslock: 'W'
+}
+
+key E {
+ label: '\u0423'
+ base: '\u0443'
+ shift, capslock: '\u0423'
+ ralt: 'e'
+ ralt+shift, ralt+capslock: 'E'
+}
+
+key R {
+ label: '\u041a'
+ base: '\u043a'
+ shift, capslock: '\u041a'
+ ralt: 'r'
+ ralt+shift, ralt+capslock: 'R'
+}
+
+key T {
+ label: '\u0415'
+ base: '\u0435'
+ shift, capslock: '\u0415'
+ ralt: 't'
+ ralt+shift, ralt+capslock: 'T'
+}
+
+key Y {
+ label: '\u041d'
+ base: '\u043d'
+ shift, capslock: '\u041d'
+ ralt: 'y'
+ ralt+shift, ralt+capslock: 'Y'
+}
+
+key U {
+ label: '\u0413'
+ base: '\u0433'
+ shift, capslock: '\u0413'
+ ralt: 'u'
+ ralt+shift, ralt+capslock: 'U'
+}
+
+key I {
+ label: '\u0428'
+ base: '\u0448'
+ shift, capslock: '\u0428'
+ ralt: 'i'
+ ralt+shift, ralt+capslock: 'I'
+}
+
+key O {
+ label: '\u0429'
+ base: '\u0449'
+ shift, capslock: '\u0429'
+ ralt: 'o'
+ ralt+shift, ralt+capslock: 'O'
+}
+
+key P {
+ label: '\u0417'
+ base: '\u0437'
+ shift, capslock: '\u0417'
+ ralt: 'p'
+ ralt+shift, ralt+capslock: 'P'
+}
+
+key LEFT_BRACKET {
+ label: '\u0425'
+ base: '\u0445'
+ shift, capslock: '\u0425'
+ ralt: '['
+ ralt+shift: '{'
+}
+
+key RIGHT_BRACKET {
+ label: '\u042a'
+ base: '\u044a'
+ shift, capslock: '\u042a'
+ ralt: ']'
+ ralt+shift: '}'
+}
+
+### ROW 3
+
+key A {
+ label: '\u0424'
+ base: '\u0444'
+ shift, capslock: '\u0424'
+ ralt: 'a'
+ ralt+shift, ralt+capslock: 'A'
+}
+
+key S {
+ label: '\u042b'
+ base: '\u044b'
+ shift, capslock: '\u042b'
+ ralt: 's'
+ ralt+shift, ralt+capslock: 'S'
+}
+
+key D {
+ label: '\u0412'
+ base: '\u0432'
+ shift, capslock: '\u0412'
+ ralt: 'd'
+ ralt+shift, ralt+capslock: 'D'
+}
+
+key F {
+ label: '\u0410'
+ base: '\u0430'
+ shift, capslock: '\u0410'
+ ralt: 'f'
+ ralt+shift, ralt+capslock: 'F'
+}
+
+key G {
+ label: '\u041f'
+ base: '\u043f'
+ shift, capslock: '\u041f'
+ ralt: 'g'
+ ralt+shift, ralt+capslock: 'G'
+}
+
+key H {
+ label: '\u0420'
+ base: '\u0440'
+ shift, capslock: '\u0420'
+ ralt: 'h'
+ ralt+shift, ralt+capslock: 'H'
+}
+
+key J {
+ label: '\u041e'
+ base: '\u043e'
+ shift, capslock: '\u041e'
+ ralt: 'j'
+ ralt+shift, ralt+capslock: 'J'
+}
+
+key K {
+ label: '\u041b'
+ base: '\u043b'
+ shift, capslock: '\u041b'
+ ralt: 'k'
+ ralt+shift, ralt+capslock: 'K'
+}
+
+key L {
+ label: '\u0414'
+ base: '\u0434'
+ shift, capslock: '\u0414'
+ ralt: 'l'
+ ralt+shift, ralt+capslock: 'L'
+}
+
+key SEMICOLON {
+ label: '\u0416'
+ base: '\u0436'
+ shift, capslock: '\u0416'
+ ralt: ';'
+ ralt+shift: ':'
+}
+
+key APOSTROPHE {
+ label: '\u042d'
+ base: '\u044d'
+ shift, capslock: '\u042d'
+ ralt: '\''
+ ralt+shift: '"'
+}
+
+key BACKSLASH {
+ label: '\\'
+ base: '\\'
+ shift: '/'
+ ralt: '|'
+}
+
+### ROW 4
+
+key Z {
+ label: '\u042f'
+ base: '\u044f'
+ shift, capslock: '\u042f'
+ ralt: 'z'
+ ralt+shift, ralt+capslock: 'Z'
+}
+
+key X {
+ label: '\u0427'
+ base: '\u0447'
+ shift, capslock: '\u0427'
+ ralt: 'x'
+ ralt+shift, ralt+capslock: 'X'
+}
+
+key C {
+ label: '\u0421'
+ base: '\u0441'
+ shift, capslock: '\u0421'
+ ralt: 'c'
+ ralt+shift, ralt+capslock: 'C'
+}
+
+key V {
+ label: '\u041c'
+ base: '\u043c'
+ shift, capslock: '\u041c'
+ ralt: 'v'
+ ralt+shift, ralt+capslock: 'V'
+}
+
+key B {
+ label: '\u0418'
+ base: '\u0438'
+ shift, capslock: '\u0418'
+ ralt: 'b'
+ ralt+shift, ralt+capslock: 'B'
+}
+
+key N {
+ label: '\u0422'
+ base: '\u0442'
+ shift, capslock: '\u0422'
+ ralt: 'n'
+ ralt+shift, ralt+capslock: 'N'
+}
+
+key M {
+ label: '\u042c'
+ base: '\u044c'
+ shift, capslock: '\u042c'
+ ralt: 'm'
+ ralt+shift, ralt+capslock: 'M'
+}
+
+key COMMA {
+ label: '\u0411'
+ base: '\u0431'
+ shift, capslock: '\u0411'
+ ralt: ','
+ ralt+shift: '<'
+}
+
+key PERIOD {
+ label: '\u042e'
+ base: '\u044e'
+ shift, capslock: '\u042e'
+ ralt: '.'
+ ralt+shift: '>'
+}
+
+key SLASH {
+ label: '.'
+ base: '.'
+ shift: ','
+ ralt: '/'
+ ralt+shift: '?'
+}
diff --git a/packages/InputDevices/res/raw/keyboard_layout_russian_apple.kcm b/packages/InputDevices/res/raw/keyboard_layout_russian_apple.kcm
new file mode 100644
index 0000000..18893fe
--- /dev/null
+++ b/packages/InputDevices/res/raw/keyboard_layout_russian_apple.kcm
@@ -0,0 +1,407 @@
+# Copyright (C) 2012 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#
+# Russian keyboard layout.
+# This is a variant of the typical Russian PC keyboard layout that is presented
+# on Apple keyboards. In contrast with the standard layout, some of the symbols and
+# punctuation characters have been rearranged.
+# English characters are accessible using ralt (Alt Gr).
+#
+
+type OVERLAY
+
+map key 86 PLUS
+
+### ROW 1
+
+key GRAVE {
+ label: '>'
+ base: '>'
+ shift: '<'
+ ralt: '\u00a7'
+ ralt+shift: '\u00b1'
+}
+
+key 1 {
+ label: '1'
+ base: '1'
+ shift: '!'
+ ralt: '!'
+}
+
+key 2 {
+ label: '2'
+ base: '2'
+ shift: '"'
+ ralt: '@'
+}
+
+key 3 {
+ label: '3'
+ base: '3'
+ shift: '\u2116'
+ ralt: '#'
+}
+
+key 4 {
+ label: '4'
+ base: '4'
+ shift: '%'
+ ralt: '$'
+}
+
+key 5 {
+ label: '5'
+ base: '5'
+ shift: ':'
+ ralt: '%'
+}
+
+key 6 {
+ label: '6'
+ base: '6'
+ shift: ','
+ ralt: '^'
+}
+
+key 7 {
+ label: '7'
+ base: '7'
+ shift: '.'
+ ralt: '&'
+}
+
+key 8 {
+ label: '8'
+ base: '8'
+ shift: ';'
+ ralt: '*'
+}
+
+key 9 {
+ label: '9'
+ base: '9'
+ shift: '('
+ ralt: '('
+}
+
+key 0 {
+ label: '0'
+ base: '0'
+ shift: ')'
+ ralt: ')'
+}
+
+key MINUS {
+ label: '-'
+ base: '-'
+ shift: '_'
+ ralt: '-'
+ ralt+shift: '_'
+}
+
+key EQUALS {
+ label: '='
+ base: '='
+ shift: '+'
+ ralt: '='
+ ralt+shift: '+'
+}
+
+### ROW 2
+
+key Q {
+ label: '\u0419'
+ base: '\u0439'
+ shift, capslock: '\u0419'
+ ralt: 'q'
+ ralt+shift, ralt+capslock: 'Q'
+}
+
+key W {
+ label: '\u0426'
+ base: '\u0446'
+ shift, capslock: '\u0426'
+ ralt: 'w'
+ ralt+shift, ralt+capslock: 'W'
+}
+
+key E {
+ label: '\u0423'
+ base: '\u0443'
+ shift, capslock: '\u0423'
+ ralt: 'e'
+ ralt+shift, ralt+capslock: 'E'
+}
+
+key R {
+ label: '\u041a'
+ base: '\u043a'
+ shift, capslock: '\u041a'
+ ralt: 'r'
+ ralt+shift, ralt+capslock: 'R'
+}
+
+key T {
+ label: '\u0415'
+ base: '\u0435'
+ shift, capslock: '\u0415'
+ ralt: 't'
+ ralt+shift, ralt+capslock: 'T'
+}
+
+key Y {
+ label: '\u041d'
+ base: '\u043d'
+ shift, capslock: '\u041d'
+ ralt: 'y'
+ ralt+shift, ralt+capslock: 'Y'
+}
+
+key U {
+ label: '\u0413'
+ base: '\u0433'
+ shift, capslock: '\u0413'
+ ralt: 'u'
+ ralt+shift, ralt+capslock: 'U'
+}
+
+key I {
+ label: '\u0428'
+ base: '\u0448'
+ shift, capslock: '\u0428'
+ ralt: 'i'
+ ralt+shift, ralt+capslock: 'I'
+}
+
+key O {
+ label: '\u0429'
+ base: '\u0449'
+ shift, capslock: '\u0429'
+ ralt: 'o'
+ ralt+shift, ralt+capslock: 'O'
+}
+
+key P {
+ label: '\u0417'
+ base: '\u0437'
+ shift, capslock: '\u0417'
+ ralt: 'p'
+ ralt+shift, ralt+capslock: 'P'
+}
+
+key LEFT_BRACKET {
+ label: '\u0425'
+ base: '\u0445'
+ shift, capslock: '\u0425'
+ ralt: '['
+ ralt+shift: '{'
+}
+
+key RIGHT_BRACKET {
+ label: '\u042a'
+ base: '\u044a'
+ shift, capslock: '\u042a'
+ ralt: ']'
+ ralt+shift: '}'
+}
+
+### ROW 3
+
+key A {
+ label: '\u0424'
+ base: '\u0444'
+ shift, capslock: '\u0424'
+ ralt: 'a'
+ ralt+shift, ralt+capslock: 'A'
+}
+
+key S {
+ label: '\u042b'
+ base: '\u044b'
+ shift, capslock: '\u042b'
+ ralt: 's'
+ ralt+shift, ralt+capslock: 'S'
+}
+
+key D {
+ label: '\u0412'
+ base: '\u0432'
+ shift, capslock: '\u0412'
+ ralt: 'd'
+ ralt+shift, ralt+capslock: 'D'
+}
+
+key F {
+ label: '\u0410'
+ base: '\u0430'
+ shift, capslock: '\u0410'
+ ralt: 'f'
+ ralt+shift, ralt+capslock: 'F'
+}
+
+key G {
+ label: '\u041f'
+ base: '\u043f'
+ shift, capslock: '\u041f'
+ ralt: 'g'
+ ralt+shift, ralt+capslock: 'G'
+}
+
+key H {
+ label: '\u0420'
+ base: '\u0440'
+ shift, capslock: '\u0420'
+ ralt: 'h'
+ ralt+shift, ralt+capslock: 'H'
+}
+
+key J {
+ label: '\u041e'
+ base: '\u043e'
+ shift, capslock: '\u041e'
+ ralt: 'j'
+ ralt+shift, ralt+capslock: 'J'
+}
+
+key K {
+ label: '\u041b'
+ base: '\u043b'
+ shift, capslock: '\u041b'
+ ralt: 'k'
+ ralt+shift, ralt+capslock: 'K'
+}
+
+key L {
+ label: '\u0414'
+ base: '\u0434'
+ shift, capslock: '\u0414'
+ ralt: 'l'
+ ralt+shift, ralt+capslock: 'L'
+}
+
+key SEMICOLON {
+ label: '\u0416'
+ base: '\u0436'
+ shift, capslock: '\u0416'
+ ralt: ';'
+ ralt+shift: ':'
+}
+
+key APOSTROPHE {
+ label: '\u042d'
+ base: '\u044d'
+ shift, capslock: '\u042d'
+ ralt: '\''
+ ralt+shift: '"'
+}
+
+key BACKSLASH {
+ label: '\u0401'
+ base: '\u0451'
+ shift, capslock: '\u0401'
+ ralt: '\\'
+ ralt+shift: '|'
+}
+
+### ROW 4
+
+key PLUS {
+ label: '['
+ base: '['
+ shift: ']'
+ ralt: '`'
+ ralt+shift: '~'
+}
+
+key Z {
+ label: '\u042f'
+ base: '\u044f'
+ shift, capslock: '\u042f'
+ ralt: 'z'
+ ralt+shift, ralt+capslock: 'Z'
+}
+
+key X {
+ label: '\u0427'
+ base: '\u0447'
+ shift, capslock: '\u0427'
+ ralt: 'x'
+ ralt+shift, ralt+capslock: 'X'
+}
+
+key C {
+ label: '\u0421'
+ base: '\u0441'
+ shift, capslock: '\u0421'
+ ralt: 'c'
+ ralt+shift, ralt+capslock: 'C'
+}
+
+key V {
+ label: '\u041c'
+ base: '\u043c'
+ shift, capslock: '\u041c'
+ ralt: 'v'
+ ralt+shift, ralt+capslock: 'V'
+}
+
+key B {
+ label: '\u0418'
+ base: '\u0438'
+ shift, capslock: '\u0418'
+ ralt: 'b'
+ ralt+shift, ralt+capslock: 'B'
+}
+
+key N {
+ label: '\u0422'
+ base: '\u0442'
+ shift, capslock: '\u0422'
+ ralt: 'n'
+ ralt+shift, ralt+capslock: 'N'
+}
+
+key M {
+ label: '\u042c'
+ base: '\u044c'
+ shift, capslock: '\u042c'
+ ralt: 'm'
+ ralt+shift, ralt+capslock: 'M'
+}
+
+key COMMA {
+ label: '\u0411'
+ base: '\u0431'
+ shift, capslock: '\u0411'
+ ralt: ','
+ ralt+shift: '<'
+}
+
+key PERIOD {
+ label: '\u042e'
+ base: '\u044e'
+ shift, capslock: '\u042e'
+ ralt: '.'
+ ralt+shift: '>'
+}
+
+key SLASH {
+ label: '/'
+ base: '/'
+ shift: '?'
+ ralt: '/'
+ ralt+shift: '?'
+}
diff --git a/packages/InputDevices/res/raw/keyboard_layout_spanish.kcm b/packages/InputDevices/res/raw/keyboard_layout_spanish.kcm
new file mode 100644
index 0000000..da9159b
--- /dev/null
+++ b/packages/InputDevices/res/raw/keyboard_layout_spanish.kcm
@@ -0,0 +1,329 @@
+# Copyright (C) 2012 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#
+# Spanish (Spain) keyboard layout.
+#
+
+type OVERLAY
+
+map key 86 PLUS
+
+### ROW 1
+
+key GRAVE {
+ label: '\u00ba'
+ base: '\u00ba'
+ shift: '\u00aa'
+ ralt: '\\'
+}
+
+key 1 {
+ label: '1'
+ base: '1'
+ shift: '!'
+ ralt: '|'
+}
+
+key 2 {
+ label: '2'
+ base: '2'
+ shift: '"'
+ ralt: '@'
+}
+
+key 3 {
+ label: '3'
+ base: '3'
+ shift: '\u00b7'
+ ralt: '#'
+}
+
+key 4 {
+ label: '4'
+ base: '4'
+ shift: '$'
+ ralt: '\u0303'
+}
+
+key 5 {
+ label: '5'
+ base: '5'
+ shift: '%'
+ ralt: '\u20ac'
+}
+
+key 6 {
+ label: '6'
+ base: '6'
+ shift: '&'
+ ralt: '\u00ac'
+}
+
+key 7 {
+ label: '7'
+ base: '7'
+ shift: '/'
+}
+
+key 8 {
+ label: '8'
+ base: '8'
+ shift: '('
+}
+
+key 9 {
+ label: '9'
+ base: '9'
+ shift: ')'
+}
+
+key 0 {
+ label: '0'
+ base: '0'
+ shift: '='
+}
+
+key MINUS {
+ label: '\''
+ base: '\''
+ shift: '?'
+}
+
+key EQUALS {
+ label: '\u00a1'
+ base: '\u00a1'
+ shift: '\u00bf'
+}
+
+### ROW 2
+
+key Q {
+ label: 'Q'
+ base: 'q'
+ shift, capslock: 'Q'
+}
+
+key W {
+ label: 'W'
+ base: 'w'
+ shift, capslock: 'W'
+}
+
+key E {
+ label: 'E'
+ base: 'e'
+ shift, capslock: 'E'
+ ralt: '\u20ac'
+}
+
+key R {
+ label: 'R'
+ base: 'r'
+ shift, capslock: 'R'
+}
+
+key T {
+ label: 'T'
+ base: 't'
+ shift, capslock: 'T'
+}
+
+key Y {
+ label: 'Y'
+ base: 'y'
+ shift, capslock: 'Y'
+}
+
+key U {
+ label: 'U'
+ base: 'u'
+ shift, capslock: 'U'
+}
+
+key I {
+ label: 'I'
+ base: 'i'
+ shift, capslock: 'I'
+}
+
+key O {
+ label: 'O'
+ base: 'o'
+ shift, capslock: 'O'
+}
+
+key P {
+ label: 'P'
+ base: 'p'
+ shift, capslock: 'P'
+}
+
+key LEFT_BRACKET {
+ label: '\u02cb'
+ base: '\u0300'
+ shift: '\u0302'
+ ralt: '['
+}
+
+key RIGHT_BRACKET {
+ label: '+'
+ base: '+'
+ shift: '*'
+ ralt: ']'
+}
+
+### ROW 3
+
+key A {
+ label: 'A'
+ base: 'a'
+ shift, capslock: 'A'
+}
+
+key S {
+ label: 'S'
+ base: 's'
+ shift, capslock: 'S'
+}
+
+key D {
+ label: 'D'
+ base: 'd'
+ shift, capslock: 'D'
+}
+
+key F {
+ label: 'F'
+ base: 'f'
+ shift, capslock: 'F'
+}
+
+key G {
+ label: 'G'
+ base: 'g'
+ shift, capslock: 'G'
+}
+
+key H {
+ label: 'H'
+ base: 'h'
+ shift, capslock: 'H'
+}
+
+key J {
+ label: 'J'
+ base: 'j'
+ shift, capslock: 'J'
+}
+
+key K {
+ label: 'K'
+ base: 'k'
+ shift, capslock: 'K'
+}
+
+key L {
+ label: 'L'
+ base: 'l'
+ shift, capslock: 'L'
+}
+
+key SEMICOLON {
+ label: '\u00d1'
+ base: '\u00f1'
+ shift, capslock: '\u00d1'
+}
+
+key APOSTROPHE {
+ label: '\u00b4'
+ base: '\u0301'
+ shift: '\u0308'
+ ralt: '{'
+}
+
+key BACKSLASH {
+ label: '\u00c7'
+ base: '\u00e7'
+ shift, capslock: '\u00c7'
+ ralt: '}'
+}
+
+### ROW 4
+
+key PLUS {
+ label: '<'
+ base: '<'
+ shift: '>'
+}
+
+key Z {
+ label: 'Z'
+ base: 'z'
+ shift, capslock: 'Z'
+}
+
+key X {
+ label: 'X'
+ base: 'x'
+ shift, capslock: 'X'
+}
+
+key C {
+ label: 'C'
+ base: 'c'
+ shift, capslock: 'C'
+}
+
+key V {
+ label: 'V'
+ base: 'v'
+ shift, capslock: 'V'
+}
+
+key B {
+ label: 'B'
+ base: 'b'
+ shift, capslock: 'B'
+}
+
+key N {
+ label: 'N'
+ base: 'n'
+ shift, capslock: 'N'
+}
+
+key M {
+ label: 'M'
+ base: 'm'
+ shift, capslock: 'M'
+}
+
+key COMMA {
+ label: ','
+ base: ','
+ shift: ';'
+}
+
+key PERIOD {
+ label: '.'
+ base: '.'
+ shift: ':'
+}
+
+key SLASH {
+ label: '-'
+ base: '-'
+ shift: '_'
+}
diff --git a/packages/InputDevices/res/raw/keyboard_layout_swiss_french.kcm b/packages/InputDevices/res/raw/keyboard_layout_swiss_french.kcm
new file mode 100644
index 0000000..a75d154
--- /dev/null
+++ b/packages/InputDevices/res/raw/keyboard_layout_swiss_french.kcm
@@ -0,0 +1,334 @@
+# Copyright (C) 2012 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#
+# Swiss French keyboard layout.
+# Same as Swiss German except in the placement of the umlaut / accented keys.
+#
+
+type OVERLAY
+
+map key 21 Z
+map key 44 Y
+map key 86 PLUS
+
+### ROW 1
+
+key GRAVE {
+ label: '\u00a7'
+ base: '\u00a7'
+ shift: '\u00b0'
+}
+
+key 1 {
+ label: '1'
+ base: '1'
+ shift: '+'
+ ralt: '\u00a6'
+}
+
+key 2 {
+ label: '2'
+ base: '2'
+ shift: '"'
+ ralt: '@'
+}
+
+key 3 {
+ label: '3'
+ base: '3'
+ shift: '*'
+ ralt: '#'
+}
+
+key 4 {
+ label: '4'
+ base: '4'
+ shift: '\u00e7'
+}
+
+key 5 {
+ label: '5'
+ base: '5'
+ shift: '%'
+}
+
+key 6 {
+ label: '6'
+ base: '6'
+ shift: '&'
+ ralt: '\u00ac'
+}
+
+key 7 {
+ label: '7'
+ base: '7'
+ shift: '/'
+ ralt: '|'
+}
+
+key 8 {
+ label: '8'
+ base: '8'
+ shift: '('
+ ralt: '\u00a2'
+}
+
+key 9 {
+ label: '9'
+ base: '9'
+ shift: ')'
+}
+
+key 0 {
+ label: '0'
+ base: '0'
+ shift: '='
+}
+
+key MINUS {
+ label: '\''
+ base: '\''
+ shift: '?'
+ ralt: '\u0301'
+}
+
+key EQUALS {
+ label: '\u02c6'
+ base: '\u0302'
+ shift: '\u0300'
+ ralt: '\u0303'
+}
+
+### ROW 2
+
+key Q {
+ label: 'Q'
+ base: 'q'
+ shift, capslock: 'Q'
+}
+
+key W {
+ label: 'W'
+ base: 'w'
+ shift, capslock: 'W'
+}
+
+key E {
+ label: 'E'
+ base: 'e'
+ shift, capslock: 'E'
+ ralt: '\u20ac'
+}
+
+key R {
+ label: 'R'
+ base: 'r'
+ shift, capslock: 'R'
+}
+
+key T {
+ label: 'T'
+ base: 't'
+ shift, capslock: 'T'
+}
+
+key Z {
+ label: 'Z'
+ base: 'z'
+ shift, capslock: 'Z'
+}
+
+key U {
+ label: 'U'
+ base: 'u'
+ shift, capslock: 'U'
+}
+
+key I {
+ label: 'I'
+ base: 'i'
+ shift, capslock: 'I'
+}
+
+key O {
+ label: 'O'
+ base: 'o'
+ shift, capslock: 'O'
+}
+
+key P {
+ label: 'P'
+ base: 'p'
+ shift, capslock: 'P'
+}
+
+key LEFT_BRACKET {
+ label: '\u00e8'
+ base: '\u00e8'
+ shift: '\u00fc'
+ ralt: '['
+}
+
+key RIGHT_BRACKET {
+ label: '\u00a8'
+ base: '\u0308'
+ shift: '!'
+ ralt: ']'
+}
+
+### ROW 3
+
+key A {
+ label: 'A'
+ base: 'a'
+ shift, capslock: 'A'
+}
+
+key S {
+ label: 'S'
+ base: 's'
+ shift, capslock: 'S'
+}
+
+key D {
+ label: 'D'
+ base: 'd'
+ shift, capslock: 'D'
+}
+
+key F {
+ label: 'F'
+ base: 'f'
+ shift, capslock: 'F'
+}
+
+key G {
+ label: 'G'
+ base: 'g'
+ shift, capslock: 'G'
+}
+
+key H {
+ label: 'H'
+ base: 'h'
+ shift, capslock: 'H'
+}
+
+key J {
+ label: 'J'
+ base: 'j'
+ shift, capslock: 'J'
+}
+
+key K {
+ label: 'K'
+ base: 'k'
+ shift, capslock: 'K'
+}
+
+key L {
+ label: 'L'
+ base: 'l'
+ shift, capslock: 'L'
+}
+
+key SEMICOLON {
+ label: '\u00e9'
+ base: '\u00e9'
+ shift: '\u00f6'
+}
+
+key APOSTROPHE {
+ label: '\u00e0'
+ base: '\u00e0'
+ shift: '\u00e4'
+ ralt: '{'
+}
+
+key BACKSLASH {
+ label: '$'
+ base: '$'
+ shift: '\u00a3'
+ ralt: '}'
+}
+
+### ROW 4
+
+key PLUS {
+ label: '<'
+ base: '<'
+ shift: '>'
+ ralt: '\\'
+}
+
+key Y {
+ label: 'Y'
+ base: 'y'
+ shift, capslock: 'Y'
+}
+
+key X {
+ label: 'X'
+ base: 'x'
+ shift, capslock: 'X'
+}
+
+key C {
+ label: 'C'
+ base: 'c'
+ shift, capslock: 'C'
+}
+
+key V {
+ label: 'V'
+ base: 'v'
+ shift, capslock: 'V'
+}
+
+key B {
+ label: 'B'
+ base: 'b'
+ shift, capslock: 'B'
+}
+
+key N {
+ label: 'N'
+ base: 'n'
+ shift, capslock: 'N'
+}
+
+key M {
+ label: 'M'
+ base: 'm'
+ shift, capslock: 'M'
+}
+
+key COMMA {
+ label: ','
+ base: ','
+ shift: ';'
+}
+
+key PERIOD {
+ label: '.'
+ base: '.'
+ shift: ':'
+}
+
+key SLASH {
+ label: '-'
+ base: '-'
+ shift: '_'
+}
diff --git a/packages/InputDevices/res/raw/keyboard_layout_swiss_german.kcm b/packages/InputDevices/res/raw/keyboard_layout_swiss_german.kcm
new file mode 100644
index 0000000..ae93f4b
--- /dev/null
+++ b/packages/InputDevices/res/raw/keyboard_layout_swiss_german.kcm
@@ -0,0 +1,334 @@
+# Copyright (C) 2012 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#
+# Swiss German keyboard layout.
+# Same as Swiss French except in the placement of the umlaut / accented keys.
+#
+
+type OVERLAY
+
+map key 21 Z
+map key 44 Y
+map key 86 PLUS
+
+### ROW 1
+
+key GRAVE {
+ label: '\u00a7'
+ base: '\u00a7'
+ shift: '\u00b0'
+}
+
+key 1 {
+ label: '1'
+ base: '1'
+ shift: '+'
+ ralt: '\u00a6'
+}
+
+key 2 {
+ label: '2'
+ base: '2'
+ shift: '"'
+ ralt: '@'
+}
+
+key 3 {
+ label: '3'
+ base: '3'
+ shift: '*'
+ ralt: '#'
+}
+
+key 4 {
+ label: '4'
+ base: '4'
+ shift: '\u00e7'
+}
+
+key 5 {
+ label: '5'
+ base: '5'
+ shift: '%'
+}
+
+key 6 {
+ label: '6'
+ base: '6'
+ shift: '&'
+ ralt: '\u00ac'
+}
+
+key 7 {
+ label: '7'
+ base: '7'
+ shift: '/'
+ ralt: '|'
+}
+
+key 8 {
+ label: '8'
+ base: '8'
+ shift: '('
+ ralt: '\u00a2'
+}
+
+key 9 {
+ label: '9'
+ base: '9'
+ shift: ')'
+}
+
+key 0 {
+ label: '0'
+ base: '0'
+ shift: '='
+}
+
+key MINUS {
+ label: '\''
+ base: '\''
+ shift: '?'
+ ralt: '\u0301'
+}
+
+key EQUALS {
+ label: '\u02c6'
+ base: '\u0302'
+ shift: '\u0300'
+ ralt: '\u0303'
+}
+
+### ROW 2
+
+key Q {
+ label: 'Q'
+ base: 'q'
+ shift, capslock: 'Q'
+}
+
+key W {
+ label: 'W'
+ base: 'w'
+ shift, capslock: 'W'
+}
+
+key E {
+ label: 'E'
+ base: 'e'
+ shift, capslock: 'E'
+ ralt: '\u20ac'
+}
+
+key R {
+ label: 'R'
+ base: 'r'
+ shift, capslock: 'R'
+}
+
+key T {
+ label: 'T'
+ base: 't'
+ shift, capslock: 'T'
+}
+
+key Z {
+ label: 'Z'
+ base: 'z'
+ shift, capslock: 'Z'
+}
+
+key U {
+ label: 'U'
+ base: 'u'
+ shift, capslock: 'U'
+}
+
+key I {
+ label: 'I'
+ base: 'i'
+ shift, capslock: 'I'
+}
+
+key O {
+ label: 'O'
+ base: 'o'
+ shift, capslock: 'O'
+}
+
+key P {
+ label: 'P'
+ base: 'p'
+ shift, capslock: 'P'
+}
+
+key LEFT_BRACKET {
+ label: '\u00fc'
+ base: '\u00fc'
+ shift: '\u00e8'
+ ralt: '['
+}
+
+key RIGHT_BRACKET {
+ label: '\u00a8'
+ base: '\u0308'
+ shift: '!'
+ ralt: ']'
+}
+
+### ROW 3
+
+key A {
+ label: 'A'
+ base: 'a'
+ shift, capslock: 'A'
+}
+
+key S {
+ label: 'S'
+ base: 's'
+ shift, capslock: 'S'
+}
+
+key D {
+ label: 'D'
+ base: 'd'
+ shift, capslock: 'D'
+}
+
+key F {
+ label: 'F'
+ base: 'f'
+ shift, capslock: 'F'
+}
+
+key G {
+ label: 'G'
+ base: 'g'
+ shift, capslock: 'G'
+}
+
+key H {
+ label: 'H'
+ base: 'h'
+ shift, capslock: 'H'
+}
+
+key J {
+ label: 'J'
+ base: 'j'
+ shift, capslock: 'J'
+}
+
+key K {
+ label: 'K'
+ base: 'k'
+ shift, capslock: 'K'
+}
+
+key L {
+ label: 'L'
+ base: 'l'
+ shift, capslock: 'L'
+}
+
+key SEMICOLON {
+ label: '\u00f6'
+ base: '\u00f6'
+ shift: '\u00e9'
+}
+
+key APOSTROPHE {
+ label: '\u00e4'
+ base: '\u00e4'
+ shift: '\u00e0'
+ ralt: '{'
+}
+
+key BACKSLASH {
+ label: '$'
+ base: '$'
+ shift: '\u00a3'
+ ralt: '}'
+}
+
+### ROW 4
+
+key PLUS {
+ label: '<'
+ base: '<'
+ shift: '>'
+ ralt: '\\'
+}
+
+key Y {
+ label: 'Y'
+ base: 'y'
+ shift, capslock: 'Y'
+}
+
+key X {
+ label: 'X'
+ base: 'x'
+ shift, capslock: 'X'
+}
+
+key C {
+ label: 'C'
+ base: 'c'
+ shift, capslock: 'C'
+}
+
+key V {
+ label: 'V'
+ base: 'v'
+ shift, capslock: 'V'
+}
+
+key B {
+ label: 'B'
+ base: 'b'
+ shift, capslock: 'B'
+}
+
+key N {
+ label: 'N'
+ base: 'n'
+ shift, capslock: 'N'
+}
+
+key M {
+ label: 'M'
+ base: 'm'
+ shift, capslock: 'M'
+}
+
+key COMMA {
+ label: ','
+ base: ','
+ shift: ';'
+}
+
+key PERIOD {
+ label: '.'
+ base: '.'
+ shift: ':'
+}
+
+key SLASH {
+ label: '-'
+ base: '-'
+ shift: '_'
+}
diff --git a/packages/InputDevices/res/values/strings.xml b/packages/InputDevices/res/values/strings.xml
index 6d5ee98..b44bc5c 100644
--- a/packages/InputDevices/res/values/strings.xml
+++ b/packages/InputDevices/res/values/strings.xml
@@ -11,4 +11,25 @@
<!-- German keyboard layout label. [CHAR LIMIT=35] -->
<string name="keyboard_layout_german_label">German</string>
+
+ <!-- French keyboard layout label. [CHAR LIMIT=35] -->
+ <string name="keyboard_layout_french_label">French</string>
+
+ <!-- Canadian French keyboard layout label. [CHAR LIMIT=35] -->
+ <string name="keyboard_layout_french_ca_label">French (Canada)</string>
+
+ <!-- Russian keyboard layout label. [CHAR LIMIT=35] -->
+ <string name="keyboard_layout_russian_label">Russian</string>
+
+ <!-- Russian (Apple style) keyboard layout label. [CHAR LIMIT=35] -->
+ <string name="keyboard_layout_russian_apple_label">Russian, Apple</string>
+
+ <!-- Spanish keyboard layout label. [CHAR LIMIT=35] -->
+ <string name="keyboard_layout_spanish_label">Spanish</string>
+
+ <!-- Swiss French keyboard layout label. [CHAR LIMIT=35] -->
+ <string name="keyboard_layout_swiss_french_label">Swiss French</string>
+
+ <!-- Swiss German keyboard layout label. [CHAR LIMIT=35] -->
+ <string name="keyboard_layout_swiss_german_label">Swiss German</string>
</resources>
diff --git a/packages/InputDevices/res/xml/keyboard_layouts.xml b/packages/InputDevices/res/xml/keyboard_layouts.xml
index 459a0e4..58920dc 100644
--- a/packages/InputDevices/res/xml/keyboard_layouts.xml
+++ b/packages/InputDevices/res/xml/keyboard_layouts.xml
@@ -11,4 +11,32 @@
<keyboard-layout android:name="keyboard_layout_german"
android:label="@string/keyboard_layout_german_label"
android:kcm="@raw/keyboard_layout_german" />
+
+ <keyboard-layout android:name="keyboard_layout_french"
+ android:label="@string/keyboard_layout_french_label"
+ android:kcm="@raw/keyboard_layout_french" />
+
+ <keyboard-layout android:name="keyboard_layout_french_ca"
+ android:label="@string/keyboard_layout_french_ca_label"
+ android:kcm="@raw/keyboard_layout_french_ca" />
+
+ <keyboard-layout android:name="keyboard_layout_russian"
+ android:label="@string/keyboard_layout_russian_label"
+ android:kcm="@raw/keyboard_layout_russian" />
+
+ <keyboard-layout android:name="keyboard_layout_russian_apple"
+ android:label="@string/keyboard_layout_russian_apple_label"
+ android:kcm="@raw/keyboard_layout_russian_apple" />
+
+ <keyboard-layout android:name="keyboard_layout_spanish"
+ android:label="@string/keyboard_layout_spanish_label"
+ android:kcm="@raw/keyboard_layout_spanish" />
+
+ <keyboard-layout android:name="keyboard_layout_swiss_french"
+ android:label="@string/keyboard_layout_swiss_french_label"
+ android:kcm="@raw/keyboard_layout_swiss_french" />
+
+ <keyboard-layout android:name="keyboard_layout_swiss_german"
+ android:label="@string/keyboard_layout_swiss_german_label"
+ android:kcm="@raw/keyboard_layout_swiss_german" />
</keyboard-layouts>
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index f200f43..a31c264 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -29,6 +29,7 @@
<!-- ActivityManager -->
<uses-permission android:name="android.permission.GET_TASKS" />
+ <uses-permission android:name="android.permission.GET_DETAILED_TASKS" />
<uses-permission android:name="android.permission.REORDER_TASKS" />
<uses-permission android:name="android.permission.REMOVE_TASKS" />
<uses-permission android:name="android.permission.STOP_APP_SWITCHES" />
@@ -37,6 +38,7 @@
<!-- WindowManager -->
<uses-permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW" />
+ <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.READ_FRAME_BUFFER" />
<uses-permission android:name="android.permission.MANAGE_APP_TOKENS" />
<uses-permission android:name="android.permission.SET_ORIENTATION" />
diff --git a/packages/SystemUI/res/drawable/navbar_search_bg_scrim.png b/packages/SystemUI/res/drawable/navbar_search_bg_scrim.png
new file mode 100644
index 0000000..d595ed2
--- /dev/null
+++ b/packages/SystemUI/res/drawable/navbar_search_bg_scrim.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable/navbar_search_handle.xml b/packages/SystemUI/res/drawable/navbar_search_handle.xml
new file mode 100644
index 0000000..e40fa2c
--- /dev/null
+++ b/packages/SystemUI/res/drawable/navbar_search_handle.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item
+ android:state_enabled="true"
+ android:state_active="false"
+ android:state_focused="false"
+ android:drawable="@*android:drawable/ic_lockscreen_handle_pressed" />
+
+ <item
+ android:state_enabled="true"
+ android:state_active="true"
+ android:state_focused="false"
+ android:drawable="@*android:drawable/ic_lockscreen_handle_pressed" />
+
+</selector>
diff --git a/packages/SystemUI/res/drawable/navbar_search_outerring.xml b/packages/SystemUI/res/drawable/navbar_search_outerring.xml
new file mode 100644
index 0000000..37b6c1c
--- /dev/null
+++ b/packages/SystemUI/res/drawable/navbar_search_outerring.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="oval">
+ <size android:height="@dimen/navbar_search_outerring_diameter"
+ android:width="@dimen/navbar_search_outerring_diameter" />
+ <solid android:color="#00000000" />
+ <stroke android:color="#1affffff" android:width="2dp" />
+</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout-land/status_bar_search_panel.xml b/packages/SystemUI/res/layout-land/status_bar_search_panel.xml
new file mode 100644
index 0000000..2adee33
--- /dev/null
+++ b/packages/SystemUI/res/layout-land/status_bar_search_panel.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* apps/common/assets/default/default/skins/StatusBar.xml
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<com.android.systemui.SearchPanelView
+ xmlns:prvandroid="http://schemas.android.com/apk/prv/res/android"
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/search_panel_container"
+ android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ android:paddingBottom="0dip">
+
+ <RelativeLayout
+ android:id="@+id/search_bg_protect"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_marginBottom="0dip">
+
+ <RelativeLayout
+ android:id="@+id/search_panel_container"
+ android:layout_width="230dip"
+ android:layout_height="match_parent"
+ android:layout_alignParentRight="true">
+
+ <com.android.internal.widget.multiwaveview.MultiWaveView
+ android:id="@+id/multi_wave_view"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_alignParentBottom="true"
+ android:background="@drawable/navbar_search_bg_scrim"
+
+ prvandroid:targetDrawables="@array/navbar_search_targets"
+ prvandroid:targetDescriptions="@array/navbar_search_target_descriptions"
+ prvandroid:directionDescriptions="@array/navbar_search_direction_descriptions"
+ prvandroid:handleDrawable="@drawable/navbar_search_handle"
+ prvandroid:waveDrawable="@drawable/navbar_search_outerring"
+ prvandroid:outerRadius="@dimen/navbar_search_target_placement_radius"
+ prvandroid:snapMargin="@dimen/navbar_search_snap_margin"
+ prvandroid:hitRadius="@dimen/navbar_search_hit_radius"
+ prvandroid:verticalOffset="0dip"
+ prvandroid:horizontalOffset="60dip"
+ prvandroid:feedbackCount="0"
+ prvandroid:vibrationDuration="0"
+ prvandroid:alwaysTrackFinger="true"/>
+
+ </RelativeLayout>
+
+ </RelativeLayout>
+
+</com.android.systemui.SearchPanelView>
diff --git a/packages/SystemUI/res/layout-port/status_bar_search_panel.xml b/packages/SystemUI/res/layout-port/status_bar_search_panel.xml
new file mode 100644
index 0000000..463fa04
--- /dev/null
+++ b/packages/SystemUI/res/layout-port/status_bar_search_panel.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* apps/common/assets/default/default/skins/StatusBar.xml
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<com.android.systemui.SearchPanelView
+ xmlns:prvandroid="http://schemas.android.com/apk/prv/res/android"
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/search_panel_container"
+ android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ android:paddingBottom="0dip">
+
+ <RelativeLayout
+ android:id="@+id/search_bg_protect"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_marginBottom="0dip">
+
+ <RelativeLayout
+ android:id="@+id/search_panel_container"
+ android:layout_width="match_parent"
+ android:layout_height="230dip"
+ android:layout_alignParentBottom="true">
+
+ <com.android.internal.widget.multiwaveview.MultiWaveView
+ android:id="@+id/multi_wave_view"
+ android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_alignParentBottom="true"
+ android:background="@drawable/navbar_search_bg_scrim"
+
+ prvandroid:targetDrawables="@array/navbar_search_targets"
+ prvandroid:targetDescriptions="@array/navbar_search_target_descriptions"
+ prvandroid:directionDescriptions="@array/navbar_search_direction_descriptions"
+ prvandroid:handleDrawable="@drawable/navbar_search_handle"
+ prvandroid:waveDrawable="@drawable/navbar_search_outerring"
+ prvandroid:outerRadius="@dimen/navbar_search_target_placement_radius"
+ prvandroid:snapMargin="@dimen/navbar_search_snap_margin"
+ prvandroid:hitRadius="@dimen/navbar_search_hit_radius"
+ prvandroid:horizontalOffset="0dip"
+ prvandroid:verticalOffset="60dip"
+ prvandroid:feedbackCount="0"
+ prvandroid:vibrationDuration="0"
+ prvandroid:alwaysTrackFinger="true"/>
+
+ </RelativeLayout>
+
+ </RelativeLayout>
+
+</com.android.systemui.SearchPanelView>
diff --git a/packages/SystemUI/res/values-land/arrays.xml b/packages/SystemUI/res/values-land/arrays.xml
new file mode 100644
index 0000000..53f374d
--- /dev/null
+++ b/packages/SystemUI/res/values-land/arrays.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/assets/res/any/colors.xml
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+ <array name="navbar_search_targets">
+ <item>@null</item>
+ <item>@null</item>
+ <item>@*android:drawable/ic_lockscreen_search</item>
+ <item>@null</item>
+ </array>
+
+ <array name="navbar_search_target_descriptions">
+ <item>@null</item>
+ <item>@null</item>
+ <item>@*android:string/description_target_search</item>
+ <item>@null</item>
+ </array>
+
+ <array name="navbar_search_direction_descriptions">
+ <item>@null</item>
+ <item>@null</item>
+ <item>@*android:string/description_direction_left</item>
+ <item>@null</item>
+ </array>
+
+</resources>
diff --git a/packages/SystemUI/res/values-port/arrays.xml b/packages/SystemUI/res/values-port/arrays.xml
new file mode 100644
index 0000000..f8b1620
--- /dev/null
+++ b/packages/SystemUI/res/values-port/arrays.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/assets/res/any/colors.xml
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+ <array name="navbar_search_targets">
+ <item>@null</item>
+ <item>@*android:drawable/ic_lockscreen_search</item>
+ <item>@null</item>
+ <item>@null</item>
+ </array>
+
+ <array name="navbar_search_target_descriptions">
+ <item>@null</item>
+ <item>@*android:string/description_target_search</item>
+ <item>@null</item>
+ <item>@null</item>
+ </array>
+
+ <array name="navbar_search_direction_descriptions">
+ <item>@null</item>
+ <item>@*android:string/description_direction_up</item>
+ <item>@null</item>
+ <item>@null</item>
+ </array>
+
+</resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index b8e8fe4..531f154 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -105,4 +105,17 @@
<!-- The width of the view containing the menu status bar icon -->
<dimen name="navigation_menu_key_width">40dip</dimen>
+
+ <!-- Default target placement radius for navigation bar search target -->
+ <dimen name="navbar_search_target_placement_radius">150dip</dimen>
+
+ <!-- Default distance beyond which snaps to the target radius -->
+ <dimen name="navbar_search_snap_margin">20dip</dimen>
+
+ <!-- Default distance from each snap target considers a "hit" -->
+ <dimen name="navbar_search_hit_radius">60dip</dimen>
+
+ <!-- Diameter of outer shape drawable shown in navbar search-->
+ <dimen name="navbar_search_outerring_diameter">300dip</dimen>
+
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/SearchPanelView.java b/packages/SystemUI/src/com/android/systemui/SearchPanelView.java
new file mode 100644
index 0000000..369a093
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/SearchPanelView.java
@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui;
+
+import android.animation.Animator;
+import android.animation.LayoutTransition;
+import android.content.ActivityNotFoundException;
+import android.content.Context;
+import android.content.Intent;
+import android.speech.RecognizerIntent;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+
+import com.android.internal.widget.multiwaveview.MultiWaveView;
+import com.android.internal.widget.multiwaveview.MultiWaveView.OnTriggerListener;
+import com.android.systemui.R;
+import com.android.systemui.recent.StatusBarTouchProxy;
+import com.android.systemui.statusbar.BaseStatusBar;
+import com.android.systemui.statusbar.phone.PhoneStatusBar;
+import com.android.systemui.statusbar.tablet.StatusBarPanel;
+import com.android.systemui.statusbar.tablet.TabletStatusBar;
+
+public class SearchPanelView extends FrameLayout implements
+ StatusBarPanel, Animator.AnimatorListener {
+ static final String TAG = "SearchPanelView";
+ static final boolean DEBUG = TabletStatusBar.DEBUG || PhoneStatusBar.DEBUG || false;
+ private Context mContext;
+ private BaseStatusBar mBar;
+ private StatusBarTouchProxy mStatusBarTouchProxy;
+
+ private boolean mShowing;
+ private View mSearchTargetsContainer;
+ private MultiWaveView mMultiWaveView;
+
+
+ public SearchPanelView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public SearchPanelView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ mContext = context;
+ }
+
+ final MultiWaveView.OnTriggerListener mMultiWaveViewListener
+ = new MultiWaveView.OnTriggerListener() {
+
+ public void onGrabbed(View v, int handle) {
+ }
+
+ public void onReleased(View v, int handle) {
+ }
+
+ public void onGrabbedStateChange(View v, int handle) {
+ if (OnTriggerListener.NO_HANDLE == handle) {
+ mBar.hideSearchPanel();
+ }
+ }
+
+ public void onTrigger(View v, int target) {
+ final int resId = mMultiWaveView.getResourceIdForTarget(target);
+ switch (resId) {
+ case com.android.internal.R.drawable.ic_lockscreen_search:
+ Intent intent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
+ intent.setFlags(
+ Intent.FLAG_ACTIVITY_NEW_TASK
+ | Intent.FLAG_ACTIVITY_SINGLE_TOP
+ | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ try {
+ mContext.startActivity(intent);
+ } catch (ActivityNotFoundException e) {
+ Log.w(TAG, "Application not found for action " + intent.getAction());
+ }
+ mBar.hideSearchPanel();
+ break;
+ }
+ }
+ };
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ mSearchTargetsContainer = (ViewGroup) findViewById(R.id.search_panel_container);
+ mStatusBarTouchProxy = (StatusBarTouchProxy) findViewById(R.id.status_bar_touch_proxy);
+ // TODO: fetch views
+ mMultiWaveView = (MultiWaveView) findViewById(R.id.multi_wave_view);
+ mMultiWaveView.setOnTriggerListener(mMultiWaveViewListener);
+ }
+
+ private boolean pointInside(int x, int y, View v) {
+ final int l = v.getLeft();
+ final int r = v.getRight();
+ final int t = v.getTop();
+ final int b = v.getBottom();
+ return x >= l && x < r && y >= t && y < b;
+ }
+
+ public boolean isInContentArea(int x, int y) {
+ if (pointInside(x, y, mSearchTargetsContainer)) {
+ return true;
+ } else if (mStatusBarTouchProxy != null &&
+ pointInside(x, y, mStatusBarTouchProxy)) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public void show(boolean show, boolean animate) {
+ if (animate) {
+ if (mShowing != show) {
+ mShowing = show;
+ // TODO: start animating ring
+ }
+ } else {
+ mShowing = show;
+ onAnimationEnd(null);
+ }
+ setVisibility(show ? View.VISIBLE : View.GONE);
+ if (show) {
+ setFocusable(true);
+ setFocusableInTouchMode(true);
+ requestFocus();
+ }
+ }
+
+ public void hide(boolean animate) {
+ if (!animate) {
+ setVisibility(View.GONE);
+ }
+ if (mBar != null) {
+ // This will indirectly cause show(false, ...) to get called
+ mBar.animateCollapse();
+ }
+ }
+
+ public void onAnimationCancel(Animator animation) {
+ }
+
+ public void onAnimationEnd(Animator animation) {
+ if (mShowing) {
+ final LayoutTransition transitioner = new LayoutTransition();
+ ((ViewGroup)mSearchTargetsContainer).setLayoutTransition(transitioner);
+ createCustomAnimations(transitioner);
+ } else {
+ ((ViewGroup)mSearchTargetsContainer).setLayoutTransition(null);
+ }
+ }
+
+ public void onAnimationRepeat(Animator animation) {
+ }
+
+ public void onAnimationStart(Animator animation) {
+ }
+
+ /**
+ * We need to be aligned at the bottom. LinearLayout can't do this, so instead,
+ * let LinearLayout do all the hard work, and then shift everything down to the bottom.
+ */
+ @Override
+ protected void onLayout(boolean changed, int l, int t, int r, int b) {
+ super.onLayout(changed, l, t, r, b);
+ // setPanelHeight(mSearchTargetsContainer.getHeight());
+ }
+
+ @Override
+ public boolean dispatchHoverEvent(MotionEvent event) {
+ // Ignore hover events outside of this panel bounds since such events
+ // generate spurious accessibility events with the panel content when
+ // tapping outside of it, thus confusing the user.
+ final int x = (int) event.getX();
+ final int y = (int) event.getY();
+ if (x >= 0 && x < getWidth() && y >= 0 && y < getHeight()) {
+ return super.dispatchHoverEvent(event);
+ }
+ return true;
+ }
+
+ /**
+ * Whether the panel is showing, or, if it's animating, whether it will be
+ * when the animation is done.
+ */
+ public boolean isShowing() {
+ return mShowing;
+ }
+
+ public void setBar(BaseStatusBar bar) {
+ mBar = bar;
+ }
+
+ public void setStatusBarView(final View statusBarView) {
+ if (mStatusBarTouchProxy != null) {
+ mStatusBarTouchProxy.setStatusBar(statusBarView);
+// mMultiWaveView.setOnTouchListener(new OnTouchListener() {
+// public boolean onTouch(View v, MotionEvent event) {
+// return statusBarView.onTouchEvent(event);
+// }
+// });
+ }
+ }
+
+ private void createCustomAnimations(LayoutTransition transitioner) {
+ transitioner.setDuration(200);
+ transitioner.setStartDelay(LayoutTransition.CHANGE_DISAPPEARING, 0);
+ transitioner.setAnimator(LayoutTransition.DISAPPEARING, null);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 19306a9..4dd96fa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -55,6 +55,7 @@
import com.android.internal.statusbar.StatusBarIconList;
import com.android.internal.statusbar.StatusBarNotification;
import com.android.internal.widget.SizeAdaptiveLayout;
+import com.android.systemui.SearchPanelView;
import com.android.systemui.SystemUI;
import com.android.systemui.recent.RecentsPanelView;
import com.android.systemui.recent.RecentTasksLoader;
@@ -73,6 +74,8 @@
protected static final int MSG_CLOSE_RECENTS_PANEL = 1021;
protected static final int MSG_PRELOAD_RECENT_APPS = 1022;
protected static final int MSG_CANCEL_PRELOAD_RECENT_APPS = 1023;
+ protected static final int MSG_OPEN_SEARCH_PANEL = 1024;
+ protected static final int MSG_CLOSE_SEARCH_PANEL = 1025;
protected CommandQueue mCommandQueue;
protected IStatusBarService mBarService;
@@ -81,6 +84,9 @@
// used to notify status bar for suppressing notification LED
protected boolean mPanelSlightlyVisible;
+ // Search panel
+ protected SearchPanelView mSearchPanelView;
+
// Recent apps
protected RecentsPanelView mRecentsPanel;
protected RecentTasksLoader mRecentTasksLoader;
@@ -278,12 +284,29 @@
}
@Override
+ public void showSearchPanel() {
+ int msg = MSG_OPEN_SEARCH_PANEL;
+ mHandler.removeMessages(msg);
+ mHandler.sendEmptyMessage(msg);
+ }
+
+ @Override
+ public void hideSearchPanel() {
+ int msg = MSG_CLOSE_SEARCH_PANEL;
+ mHandler.removeMessages(msg);
+ mHandler.sendEmptyMessage(msg);
+ }
+
+ @Override
public void onRecentsPanelVisibilityChanged(boolean visible) {
}
protected abstract WindowManager.LayoutParams getRecentsLayoutParams(
LayoutParams layoutParams);
+ protected abstract WindowManager.LayoutParams getSearchLayoutParams(
+ LayoutParams layoutParams);
+
protected void updateRecentsPanel(int recentsResId) {
// Recents Panel
boolean visible = false;
@@ -319,6 +342,31 @@
}
+ protected void updateSearchPanel() {
+ // Search Panel
+ boolean visible = false;
+ if (mSearchPanelView != null) {
+ visible = mSearchPanelView.isShowing();
+ WindowManagerImpl.getDefault().removeView(mSearchPanelView);
+ }
+
+ // Provide SearchPanel with a temporary parent to allow layout params to work.
+ LinearLayout tmpRoot = new LinearLayout(mContext);
+ mSearchPanelView = (SearchPanelView) LayoutInflater.from(mContext).inflate(
+ R.layout.status_bar_search_panel, tmpRoot, false);
+ mSearchPanelView.setOnTouchListener(
+ new TouchOutsideListener(MSG_CLOSE_SEARCH_PANEL, mSearchPanelView));
+ mSearchPanelView.setVisibility(View.GONE);
+
+ WindowManager.LayoutParams lp = getSearchLayoutParams(mSearchPanelView.getLayoutParams());
+
+ WindowManagerImpl.getDefault().addView(mSearchPanelView, lp);
+ mSearchPanelView.setBar(this);
+ if (visible) {
+ mSearchPanelView.show(true, false);
+ }
+ }
+
protected H createHandler() {
return new H();
}
@@ -346,6 +394,18 @@
if (DEBUG) Slog.d(TAG, "cancel preloading recents");
mRecentsPanel.clearRecentTasksList();
break;
+ case MSG_OPEN_SEARCH_PANEL:
+ if (DEBUG) Slog.d(TAG, "opening search panel");
+ if (mSearchPanelView != null) {
+ mSearchPanelView.show(true, true);
+ }
+ break;
+ case MSG_CLOSE_SEARCH_PANEL:
+ if (DEBUG) Slog.d(TAG, "closing search panel");
+ if (mSearchPanelView != null && mSearchPanelView.isShowing()) {
+ mSearchPanelView.show(false, true);
+ }
+ break;
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index f88a3cc9..4209354 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -59,7 +59,7 @@
private static final int MSG_TOP_APP_WINDOW_CHANGED = 8 << MSG_SHIFT;
private static final int MSG_SHOW_IME_BUTTON = 9 << MSG_SHIFT;
private static final int MSG_SET_HARD_KEYBOARD_STATUS = 10 << MSG_SHIFT;
-
+
private static final int MSG_TOGGLE_RECENT_APPS = 11 << MSG_SHIFT;
private static final int MSG_PRELOAD_RECENT_APPS = 12 << MSG_SHIFT;
private static final int MSG_CANCEL_PRELOAD_RECENT_APPS = 13 << MSG_SHIFT;
@@ -95,6 +95,8 @@
public void setHardKeyboardStatus(boolean available, boolean enabled);
public void toggleRecentApps();
public void preloadRecentApps();
+ public void showSearchPanel();
+ public void hideSearchPanel();
public void cancelPreloadRecentApps();
public void setNavigationIconHints(int hints);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/DelegateViewHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/DelegateViewHelper.java
new file mode 100644
index 0000000..f725724
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/DelegateViewHelper.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar;
+
+import android.view.MotionEvent;
+import android.view.Surface;
+import android.view.VelocityTracker;
+import android.view.View;
+
+public class DelegateViewHelper {
+ private static final int VELOCITY_THRESHOLD = 1000;
+ private VelocityTracker mVelocityTracker;
+ private View mDelegateView;
+ private View mSourceView;
+ private BaseStatusBar mBar;
+ private int[] mTempPoint = new int[2];
+ private int mOrientation;
+
+ public DelegateViewHelper(View sourceView) {
+ mSourceView = sourceView;
+ }
+
+ public void setDelegateView(View view) {
+ mDelegateView = view;
+ }
+
+ public void setBar(BaseStatusBar phoneStatusBar) {
+ mBar = phoneStatusBar;
+ }
+
+ public void setOrientation(int orientation) {
+ mOrientation = orientation;
+ }
+
+ public boolean onInterceptTouchEvent(MotionEvent event) {
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ mVelocityTracker = VelocityTracker.obtain();
+ break;
+ case MotionEvent.ACTION_CANCEL:
+ case MotionEvent.ACTION_UP:
+ mVelocityTracker.recycle();
+ mVelocityTracker = null;
+ break;
+ }
+ if (mVelocityTracker != null) {
+ if (mDelegateView != null && mDelegateView.getVisibility() != View.VISIBLE) {
+ mVelocityTracker.addMovement(event);
+ mVelocityTracker.computeCurrentVelocity(1000);
+ final boolean isVertical = (mOrientation == Surface.ROTATION_90
+ || mOrientation == Surface.ROTATION_270);
+ float velocity = isVertical ? - mVelocityTracker.getXVelocity()
+ : - mVelocityTracker.getYVelocity();
+ if (velocity > VELOCITY_THRESHOLD) {
+ if (mDelegateView != null && mDelegateView.getVisibility() != View.VISIBLE) {
+ mBar.showSearchPanel();
+ }
+ }
+ }
+ }
+ if (mDelegateView != null) {
+ mSourceView.getLocationOnScreen(mTempPoint);
+ float deltaX = mTempPoint[0];
+ float deltaY = mTempPoint[1];
+
+ mDelegateView.getLocationOnScreen(mTempPoint);
+ deltaX -= mTempPoint[0];
+ deltaY -= mTempPoint[1];
+
+ event.offsetLocation(deltaX, deltaY);
+ mDelegateView.dispatchTouchEvent(event);
+ event.offsetLocation(-deltaX, -deltaY);
+ }
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 11e067f..73c5d3a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -31,10 +31,12 @@
import android.view.animation.AccelerateInterpolator;
import android.view.Display;
import android.view.MotionEvent;
+import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewGroup;
import android.view.Surface;
import android.view.WindowManager;
+import android.view.WindowManagerImpl;
import android.widget.ImageView;
import android.widget.LinearLayout;
@@ -43,8 +45,9 @@
import java.lang.StringBuilder;
import com.android.internal.statusbar.IStatusBarService;
-
import com.android.systemui.R;
+import com.android.systemui.statusbar.BaseStatusBar;
+import com.android.systemui.statusbar.DelegateViewHelper;
public class NavigationBarView extends LinearLayout {
final static boolean DEBUG = false;
@@ -68,6 +71,8 @@
int mDisabledFlags = 0;
int mNavigationIconHints = 0;
+ private DelegateViewHelper mDelegateHelper;
+
// workaround for LayoutTransitions leaving the nav buttons in a weird state (bug 5549288)
final static boolean WORKAROUND_INVALID_LAYOUT = true;
final static int MSG_CHECK_INVALID_LAYOUT = 8686;
@@ -95,6 +100,19 @@
}
}
+ public void setDelegateView(View view) {
+ mDelegateHelper.setDelegateView(view);
+ }
+
+ public void setBar(BaseStatusBar phoneStatusBar) {
+ mDelegateHelper.setBar(phoneStatusBar);
+ }
+
+ @Override
+ public boolean onInterceptTouchEvent(MotionEvent event) {
+ return mDelegateHelper.onInterceptTouchEvent(event);
+ }
+
private H mHandler = new H();
public View getRecentsButton() {
@@ -127,6 +145,7 @@
mBarSize = res.getDimensionPixelSize(R.dimen.navigation_bar_size);
mVertical = false;
mShowMenu = false;
+ mDelegateHelper = new DelegateViewHelper(this);
}
View.OnTouchListener mLightsOutListener = new View.OnTouchListener() {
@@ -411,4 +430,5 @@
);
pw.println(" }");
}
+
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 61500e9..80ee64f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -258,7 +258,7 @@
// ================================================================================
// Constructing the view
// ================================================================================
- protected View makeStatusBarView() {
+ protected PhoneStatusBarView makeStatusBarView() {
final Context context = mContext;
Resources res = context.getResources();
@@ -294,6 +294,7 @@
(NavigationBarView) View.inflate(context, R.layout.navigation_bar, null);
mNavigationBarView.setDisabledFlags(mDisabled);
+ mNavigationBarView.setBar(this);
}
} catch (RemoteException ex) {
// no window manager? good luck with that
@@ -389,6 +390,32 @@
return lp;
}
+ @Override
+ protected WindowManager.LayoutParams getSearchLayoutParams(LayoutParams layoutParams) {
+ boolean opaque = false;
+ WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
+ LayoutParams.MATCH_PARENT,
+ LayoutParams.MATCH_PARENT,
+ WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
+ WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+ | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
+ | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
+ (opaque ? PixelFormat.OPAQUE : PixelFormat.TRANSLUCENT));
+ if (ActivityManager.isHighEndGfx(mDisplay)) {
+ lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
+ } else {
+ lp.flags |= WindowManager.LayoutParams.FLAG_DIM_BEHIND;
+ lp.dimAmount = 0.7f;
+ }
+ lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
+ lp.setTitle("SearchPanel");
+ // TODO: Define custom animation for Search panel
+ lp.windowAnimations = com.android.internal.R.style.Animation_RecentApplications;
+ lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED
+ | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
+ return lp;
+ }
+
protected void updateRecentsPanel() {
super.updateRecentsPanel(R.layout.status_bar_recent_panel);
// Make .03 alpha the minimum so you always see the item a bit-- slightly below
@@ -397,6 +424,33 @@
mRecentsPanel.setMinSwipeAlpha(0.03f);
}
+ @Override
+ protected void updateSearchPanel() {
+ super.updateSearchPanel();
+ mSearchPanelView.setStatusBarView(mStatusBarView);
+ mNavigationBarView.setDelegateView(mSearchPanelView);
+ }
+
+ @Override
+ public void showSearchPanel() {
+ super.showSearchPanel();
+ WindowManager.LayoutParams lp =
+ (android.view.WindowManager.LayoutParams) mNavigationBarView.getLayoutParams();
+ lp.flags &= ~WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
+ lp.flags &= ~WindowManager.LayoutParams.FLAG_SLIPPERY;
+ WindowManagerImpl.getDefault().updateViewLayout(mNavigationBarView, lp);
+ }
+
+ @Override
+ public void hideSearchPanel() {
+ super.hideSearchPanel();
+ WindowManager.LayoutParams lp =
+ (android.view.WindowManager.LayoutParams) mNavigationBarView.getLayoutParams();
+ lp.flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
+ lp.flags |= WindowManager.LayoutParams.FLAG_SLIPPERY;
+ WindowManagerImpl.getDefault().updateViewLayout(mNavigationBarView, lp);
+ }
+
protected int getStatusBarGravity() {
return Gravity.TOP | Gravity.FILL_HORIZONTAL;
}
@@ -412,12 +466,30 @@
}
};
private StatusBarNotification mCurrentlyIntrudingNotification;
+ View.OnTouchListener mHomeSearchActionListener = new View.OnTouchListener() {
+ public boolean onTouch(View v, MotionEvent event) {
+ switch(event.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ Slog.d(TAG, "showing search panel");
+ showSearchPanel();
+ break;
+
+ case MotionEvent.ACTION_UP:
+ Slog.d(TAG, "hiding search panel");
+ hideSearchPanel();
+ break;
+ }
+ return false;
+ }
+ };
private void prepareNavigationBarView() {
mNavigationBarView.reorient();
mNavigationBarView.getRecentsButton().setOnClickListener(mRecentsClickListener);
mNavigationBarView.getRecentsButton().setOnTouchListener(mRecentsPanel);
+ updateSearchPanel();
+// mNavigationBarView.getHomeButton().setOnTouchListener(mHomeSearchActionListener);
}
// For small-screen devices (read: phones) that lack hardware navigation buttons
@@ -528,7 +600,7 @@
Slog.d(TAG, "Presenting high-priority notification");
// special new transient ticker mode
// 1. Populate mIntruderAlertView
-
+
if (notification.notification.intruderView == null) {
Slog.e(TAG, notification.notification.toString() + " wanted to intrude but intruderView was null");
return;
@@ -544,7 +616,7 @@
mIntruderAlertView.applyIntruderContent(notification.notification.intruderView, listener);
mCurrentlyIntrudingNotification = notification;
-
+
// 2. Animate mIntruderAlertView in
mHandler.sendEmptyMessage(MSG_SHOW_INTRUDER);
@@ -698,7 +770,7 @@
// Recalculate the position of the sliding windows and the titles.
updateExpandedViewPos(EXPANDED_LEAVE_ALONE);
-
+
if (ENABLE_INTRUDERS && old == mCurrentlyIntrudingNotification) {
mHandler.sendEmptyMessage(MSG_HIDE_INTRUDER);
}
@@ -1672,7 +1744,7 @@
addStatusBarWindow();
addExpandedWindow();
}
-
+
private void addStatusBarWindow() {
// Put up the view
final int height = getStatusBarHeight();
@@ -1697,9 +1769,10 @@
lp.gravity = getStatusBarGravity();
lp.setTitle("StatusBar");
lp.packageName = mContext.getPackageName();
- WindowManagerImpl.getDefault().addView(makeStatusBarView(), lp);
+ mStatusBarView = makeStatusBarView();
+ WindowManagerImpl.getDefault().addView(mStatusBarView, lp);
}
-
+
void addExpandedWindow() {
WindowManager.LayoutParams lp;
int pixelFormat;
@@ -1780,11 +1853,11 @@
panelh = disph;
}
}
-
+
// catch orientation changes and other peculiar cases
if (panelh > disph || (panelh < disph && !mTracking && !mAnimating))
panelh = disph;
-
+
mTrackingPosition = panelh;
// XXX: this is all very WIP
//mNotificationPanel.setY(panelh);
@@ -1796,9 +1869,9 @@
final float frac = (float)panelh / disph;
final int color = ((int)(0xB0 * frac * frac)) << 24;
mExpandedWindowView.setBackgroundColor(color);
-
+
// Slog.d(TAG, String.format("updateExpanded: pos=%d frac=%.2f col=0x%08x", pos, frac, color));
-
+
// if (mExpandedParams != null) {
// if (mCloseView.getWindowVisibility() == View.VISIBLE) {
// mCloseView.getLocationInWindow(mPositionTmp);
@@ -2060,7 +2133,7 @@
// oh well
}
}
-
+
/**
* Reload some of our resources when the configuration changes.
*
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
index 7b3b745..3bdefcb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
@@ -18,6 +18,7 @@
import android.animation.LayoutTransition;
import android.animation.ObjectAnimator;
+import android.app.ActivityManager;
import android.app.ActivityManagerNative;
import android.app.Notification;
import android.app.PendingIntent;
@@ -174,7 +175,7 @@
KeyEvent mSpaceBarKeyEvent = null;
View mCompatibilityHelpDialog = null;
-
+
// for disabling the status bar
int mDisabled = 0;
@@ -192,7 +193,7 @@
addStatusBarWindow();
addPanelWindows();
}
-
+
private void addStatusBarWindow() {
final View sb = makeStatusBarView();
@@ -328,6 +329,10 @@
mRecentTasksLoader = new RecentTasksLoader(context);
updateRecentsPanel();
+ // Search Panel
+ mStatusBarView.setBar(this);
+ updateSearchPanel();
+
// Input methods Panel
mInputMethodsPanel = (InputMethodsPanel) View.inflate(context,
R.layout.system_bar_input_methods_panel, null);
@@ -350,7 +355,7 @@
lp.windowAnimations = R.style.Animation_RecentPanel;
WindowManagerImpl.getDefault().addView(mInputMethodsPanel, lp);
-
+
// Compatibility mode selector panel
mCompatModePanel = (CompatModePanel) View.inflate(context,
R.layout.system_bar_compat_mode_panel, null);
@@ -373,7 +378,7 @@
lp.windowAnimations = android.R.style.Animation_Dialog;
WindowManagerImpl.getDefault().addView(mCompatModePanel, lp);
-
+
mRecentButton.setOnTouchListener(mRecentsPanel);
mPile = (NotificationRowLayout)mNotificationPanel.findViewById(R.id.content);
@@ -646,11 +651,64 @@
return lp;
}
+ @Override
+ protected WindowManager.LayoutParams getSearchLayoutParams(LayoutParams layoutParams) {
+ boolean opaque = false;
+ WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
+ LayoutParams.MATCH_PARENT,
+ LayoutParams.MATCH_PARENT,
+ WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
+ WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+ | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
+ | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
+ (opaque ? PixelFormat.OPAQUE : PixelFormat.TRANSLUCENT));
+ if (ActivityManager.isHighEndGfx(mDisplay)) {
+ lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
+ } else {
+ lp.flags |= WindowManager.LayoutParams.FLAG_DIM_BEHIND;
+ lp.dimAmount = 0.7f;
+ }
+ lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
+ lp.setTitle("SearchPanel");
+ // TODO: Define custom animation for Search panel
+ lp.windowAnimations = com.android.internal.R.style.Animation_RecentApplications;
+ lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED
+ | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
+ return lp;
+ }
+
protected void updateRecentsPanel() {
super.updateRecentsPanel(R.layout.system_bar_recent_panel);
mRecentsPanel.setStatusBarView(mStatusBarView);
}
+ @Override
+ protected void updateSearchPanel() {
+ super.updateSearchPanel();
+ mSearchPanelView.setStatusBarView(mStatusBarView);
+ mStatusBarView.setDelegateView(mSearchPanelView);
+ }
+
+ @Override
+ public void showSearchPanel() {
+ super.showSearchPanel();
+ WindowManager.LayoutParams lp =
+ (android.view.WindowManager.LayoutParams) mStatusBarView.getLayoutParams();
+ lp.flags &= ~WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
+ lp.flags &= ~WindowManager.LayoutParams.FLAG_SLIPPERY;
+ WindowManagerImpl.getDefault().updateViewLayout(mStatusBarView, lp);
+ }
+
+ @Override
+ public void hideSearchPanel() {
+ super.hideSearchPanel();
+ WindowManager.LayoutParams lp =
+ (android.view.WindowManager.LayoutParams) mStatusBarView.getLayoutParams();
+ lp.flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
+ lp.flags |= WindowManager.LayoutParams.FLAG_SLIPPERY;
+ WindowManagerImpl.getDefault().updateViewLayout(mStatusBarView, lp);
+ }
+
public int getStatusBarHeight() {
return mStatusBarView != null ? mStatusBarView.getHeight()
: mContext.getResources().getDimensionPixelSize(
@@ -1191,7 +1249,7 @@
if (mCompatibilityHelpDialog != null) {
return;
}
-
+
mCompatibilityHelpDialog = View.inflate(mContext, R.layout.compat_mode_help, null);
View button = mCompatibilityHelpDialog.findViewById(R.id.button);
@@ -1227,7 +1285,7 @@
mCompatibilityHelpDialog = null;
}
}
-
+
public void setImeWindowStatus(IBinder token, int vis, int backDisposition) {
mInputMethodSwitchButton.setImeWindowStatus(token,
(vis & InputMethodService.IME_ACTIVE) != 0);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarView.java
index 877a40e..a6fc396 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarView.java
@@ -16,6 +16,9 @@
package com.android.systemui.statusbar.tablet;
+import com.android.systemui.statusbar.BaseStatusBar;
+import com.android.systemui.statusbar.DelegateViewHelper;
+
import android.content.Context;
import android.os.Handler;
import android.util.AttributeSet;
@@ -31,13 +34,24 @@
private final View[] mIgnoreChildren = new View[MAX_PANELS];
private final View[] mPanels = new View[MAX_PANELS];
private final int[] mPos = new int[2];
+ private DelegateViewHelper mDelegateHelper;
public TabletStatusBarView(Context context) {
super(context);
+ mDelegateHelper = new DelegateViewHelper(this);
}
public TabletStatusBarView(Context context, AttributeSet attrs) {
super(context, attrs);
+ mDelegateHelper = new DelegateViewHelper(this);
+ }
+
+ public void setDelegateView(View view) {
+ mDelegateHelper.setDelegateView(view);
+ }
+
+ public void setBar(BaseStatusBar phoneStatusBar) {
+ mDelegateHelper.setBar(phoneStatusBar);
}
@Override
@@ -72,6 +86,9 @@
if (TabletStatusBar.DEBUG) {
Slog.d(TabletStatusBar.TAG, "TabletStatusBarView not intercepting event");
}
+ if (mDelegateHelper != null) {
+ return mDelegateHelper.onInterceptTouchEvent(ev);
+ }
return super.onInterceptTouchEvent(ev);
}
@@ -97,7 +114,7 @@
/**
* Let the status bar know that if you tap on ignore while panel is showing, don't do anything.
- *
+ *
* Debounces taps on, say, a popup's trigger when the popup is already showing.
*/
public void setIgnoreChildren(int index, View ignore, View panel) {
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index cc663c2..96eaa28 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -131,6 +131,7 @@
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static android.view.WindowManager.LayoutParams.TYPE_POINTER;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
+import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
import android.view.WindowManagerImpl;
import android.view.WindowManagerPolicy;
@@ -216,16 +217,18 @@
static final int SYSTEM_OVERLAY_LAYER = 18;
// the navigation bar, if available, shows atop most things
static final int NAVIGATION_BAR_LAYER = 19;
+ // some panels (e.g. search) need to show on top of the navigation bar
+ static final int NAVIGATION_BAR_PANEL_LAYER = 20;
// system-level error dialogs
- static final int SYSTEM_ERROR_LAYER = 20;
+ static final int SYSTEM_ERROR_LAYER = 21;
// the drag layer: input for drag-and-drop is associated with this window,
// which sits above all other focusable windows
- static final int DRAG_LAYER = 21;
- static final int SECURE_SYSTEM_OVERLAY_LAYER = 22;
- static final int BOOT_PROGRESS_LAYER = 23;
+ static final int DRAG_LAYER = 22;
+ static final int SECURE_SYSTEM_OVERLAY_LAYER = 23;
+ static final int BOOT_PROGRESS_LAYER = 24;
// the (mouse) pointer layer
- static final int POINTER_LAYER = 24;
- static final int HIDDEN_NAV_CONSUMER_LAYER = 25;
+ static final int POINTER_LAYER = 25;
+ static final int HIDDEN_NAV_CONSUMER_LAYER = 26;
static final int APPLICATION_MEDIA_SUBLAYER = -2;
static final int APPLICATION_MEDIA_OVERLAY_SUBLAYER = -1;
@@ -306,7 +309,6 @@
WindowState mStatusBar = null;
boolean mHasSystemNavBar;
int mStatusBarHeight;
- final ArrayList<WindowState> mStatusBarSubPanels = new ArrayList<WindowState>();
WindowState mNavigationBar = null;
boolean mHasNavigationBar = false;
boolean mCanHideNavigationBar = false;
@@ -1335,6 +1337,8 @@
return POINTER_LAYER;
case TYPE_NAVIGATION_BAR:
return NAVIGATION_BAR_LAYER;
+ case TYPE_NAVIGATION_BAR_PANEL:
+ return NAVIGATION_BAR_PANEL_LAYER;
case TYPE_BOOT_PROGRESS:
return BOOT_PROGRESS_LAYER;
case TYPE_HIDDEN_NAV_CONSUMER:
@@ -1577,6 +1581,11 @@
mNavigationBar = win;
if (DEBUG_LAYOUT) Log.i(TAG, "NAVIGATION BAR: " + mNavigationBar);
break;
+ case TYPE_NAVIGATION_BAR_PANEL:
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.STATUS_BAR_SERVICE,
+ "PhoneWindowManager");
+ break;
case TYPE_STATUS_BAR_PANEL:
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.STATUS_BAR_SERVICE,
@@ -1586,7 +1595,6 @@
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.STATUS_BAR_SERVICE,
"PhoneWindowManager");
- mStatusBarSubPanels.add(win);
break;
case TYPE_KEYGUARD:
if (mKeyguard != null) {
@@ -1606,8 +1614,6 @@
mKeyguard = null;
} else if (mNavigationBar == win) {
mNavigationBar = null;
- } else {
- mStatusBarSubPanels.remove(win);
}
}
@@ -2480,7 +2486,8 @@
"Laying out IN_SCREEN status bar window: (%d,%d - %d,%d)",
pf.left, pf.top, pf.right, pf.bottom));
}
- } else if (attrs.type == TYPE_NAVIGATION_BAR) {
+ } else if (attrs.type == TYPE_NAVIGATION_BAR
+ || attrs.type == TYPE_NAVIGATION_BAR_PANEL) {
// The navigation bar has Real Ultimate Power.
pf.left = df.left = mUnrestrictedScreenLeft;
pf.top = df.top = mUnrestrictedScreenTop;
@@ -2778,25 +2785,6 @@
// behind it.
return false;
}
- if (mStatusBar != null && mStatusBar.isVisibleLw()) {
- RectF rect = new RectF(mStatusBar.getShownFrameLw());
- for (int i=mStatusBarSubPanels.size()-1; i>=0; i--) {
- WindowState w = mStatusBarSubPanels.get(i);
- if (w.isVisibleLw()) {
- rect.union(w.getShownFrameLw());
- }
- }
- final int insetw = mRestrictedScreenWidth/10;
- final int inseth = mRestrictedScreenHeight/10;
- if (rect.contains(insetw, inseth, mRestrictedScreenWidth-insetw,
- mRestrictedScreenHeight-inseth)) {
- // All of the status bar windows put together cover the
- // screen, so the app can't be seen. (Note this test doesn't
- // work if the rects of these windows are at odd offsets or
- // sizes, causing gaps in the rect union we have computed.)
- return false;
- }
- }
return true;
}
diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp
index 6022f10..c6b701f 100644
--- a/services/input/InputReader.cpp
+++ b/services/input/InputReader.cpp
@@ -3143,7 +3143,7 @@
mOrientedRanges.distance.min =
mRawPointerAxes.distance.minValue * mDistanceScale;
mOrientedRanges.distance.max =
- mRawPointerAxes.distance.minValue * mDistanceScale;
+ mRawPointerAxes.distance.maxValue * mDistanceScale;
mOrientedRanges.distance.flat = 0;
mOrientedRanges.distance.fuzz =
mRawPointerAxes.distance.fuzz * mDistanceScale;
diff --git a/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
index e980ccc..b9404f3 100644
--- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -1149,10 +1149,10 @@
AccessibilityNodeInfo next = null;
switch (gestureId) {
case AccessibilityService.GESTURE_SWIPE_UP: {
- next = current.focusSearch(View.ACCESSIBILITY_FOCUS_OUT);
+ // TODO:
} break;
case AccessibilityService.GESTURE_SWIPE_DOWN: {
- next = current.focusSearch(View.ACCESSIBILITY_FOCUS_IN);
+ // TODO:
} break;
case AccessibilityService.GESTURE_SWIPE_LEFT: {
// TODO: Implement the RTL support.
@@ -1694,6 +1694,7 @@
final class SecurityPolicy {
private static final int VALID_ACTIONS =
AccessibilityNodeInfo.ACTION_CLICK
+ | AccessibilityNodeInfo.ACTION_LONG_CLICK
| AccessibilityNodeInfo.ACTION_FOCUS
| AccessibilityNodeInfo.ACTION_CLEAR_FOCUS
| AccessibilityNodeInfo.ACTION_SELECT
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 77bec41..6c99cdb 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -4116,6 +4116,10 @@
public void dismissKeyguardOnNextActivity() {
enforceNotIsolatedCaller("dismissKeyguardOnNextActivity");
synchronized (this) {
+ if (mLockScreenShown) {
+ mLockScreenShown = false;
+ comeOutOfSleepIfNeededLocked();
+ }
mMainStack.dismissKeyguardOnNextActivityLocked();
}
}
@@ -5489,6 +5493,9 @@
synchronized (this) {
enforceCallingPermission(android.Manifest.permission.GET_TASKS,
"getRecentTasks()");
+ final boolean detailed = checkCallingPermission(
+ android.Manifest.permission.GET_DETAILED_TASKS)
+ == PackageManager.PERMISSION_GRANTED;
IPackageManager pm = AppGlobals.getPackageManager();
@@ -5517,6 +5524,9 @@
rti.persistentId = tr.taskId;
rti.baseIntent = new Intent(
tr.intent != null ? tr.intent : tr.affinityIntent);
+ if (!detailed) {
+ rti.baseIntent.replaceExtras((Bundle)null);
+ }
rti.origActivity = tr.origActivity;
rti.description = tr.lastDescription;
@@ -13398,7 +13408,8 @@
@Override
public boolean targetTaskAffinityMatchesActivity(IBinder token, String destAffinity) {
ActivityRecord srec = ActivityRecord.forToken(token);
- return srec.task.affinity != null && srec.task.affinity.equals(destAffinity);
+ return srec != null && srec.task.affinity != null &&
+ srec.task.affinity.equals(destAffinity);
}
public boolean navigateUpTo(IBinder token, Intent destIntent, int resultCode,
@@ -13407,6 +13418,9 @@
synchronized (this) {
ActivityRecord srec = ActivityRecord.forToken(token);
+ if (srec == null) {
+ return false;
+ }
ArrayList<ActivityRecord> history = srec.stack.mHistory;
final int start = history.indexOf(srec);
if (start < 0) {
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
old mode 100644
new mode 100755
index 24bab99..c8e015b
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -1378,7 +1378,10 @@
// If we are sleeping, and there is no resumed activity, and the top
// activity is paused, well that is the state we want.
if ((mService.mSleeping || mService.mShuttingDown)
- && mLastPausedActivity == next && next.state == ActivityState.PAUSED) {
+ && mLastPausedActivity == next
+ && (next.state == ActivityState.PAUSED
+ || next.state == ActivityState.STOPPED
+ || next.state == ActivityState.STOPPING)) {
// Make sure we have executed any pending transitions, since there
// should be nothing left to do at this point.
mService.mWindowManager.executeAppTransition();
diff --git a/services/java/com/android/server/net/NetworkPolicyManagerService.java b/services/java/com/android/server/net/NetworkPolicyManagerService.java
index 52d5019..f873b6c 100644
--- a/services/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -1665,20 +1665,9 @@
updateRulesForAppLocked(appId);
}
- // and catch system UIDs
- // TODO: keep in sync with android_filesystem_config.h
- for (int uid = 1000; uid <= 1025; uid++) {
- updateRulesForUidLocked(uid);
- }
- for (int uid = 2000; uid <= 2002; uid++) {
- updateRulesForUidLocked(uid);
- }
- for (int uid = 3000; uid <= 3007; uid++) {
- updateRulesForUidLocked(uid);
- }
- for (int uid = 9998; uid <= 9999; uid++) {
- updateRulesForUidLocked(uid);
- }
+ // limit data usage for some internal system services
+ updateRulesForUidLocked(android.os.Process.MEDIA_UID);
+ updateRulesForUidLocked(android.os.Process.DRM_UID);
}
private void updateRulesForAppLocked(int appId) {
@@ -1688,7 +1677,19 @@
}
}
+ private static boolean isUidValidForRules(int uid) {
+ // allow rules on specific system services, and any apps
+ if (uid == android.os.Process.MEDIA_UID || uid == android.os.Process.DRM_UID
+ || UserId.isApp(uid)) {
+ return true;
+ }
+
+ return false;
+ }
+
private void updateRulesForUidLocked(int uid) {
+ if (!isUidValidForRules(uid)) return;
+
final int appId = UserId.getAppId(uid);
final int appPolicy = getAppPolicy(appId);
final boolean uidForeground = isUidForeground(uid);
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index 6891b76..00d86e3 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -2737,7 +2737,7 @@
}
}
- if (pi != null && !list.append(pi)) {
+ if (pi != null && list.append(pi)) {
break;
}
}
@@ -2787,7 +2787,7 @@
}
}
- if (ai != null && !list.append(ai)) {
+ if (ai != null && list.append(ai)) {
break;
}
}
diff --git a/services/java/com/android/server/wm/AppWindowAnimator.java b/services/java/com/android/server/wm/AppWindowAnimator.java
index 6964137..d635e8c 100644
--- a/services/java/com/android/server/wm/AppWindowAnimator.java
+++ b/services/java/com/android/server/wm/AppWindowAnimator.java
@@ -54,7 +54,7 @@
public void setAnimation(Animation anim, boolean initialized) {
if (WindowManagerService.localLOGV) Slog.v(
- TAG, "Setting animation in " + this + ": " + anim);
+ TAG, "Setting animation in " + mAppToken + ": " + anim);
animation = anim;
animating = false;
animInitialized = initialized;
@@ -81,7 +81,7 @@
public void setDummyAnimation() {
if (animation == null) {
if (WindowManagerService.localLOGV) Slog.v(
- TAG, "Setting dummy animation in " + this);
+ TAG, "Setting dummy animation in " + mAppToken);
animation = sDummyAnimation;
animInitialized = false;
}
@@ -165,12 +165,12 @@
transformation.clear();
final boolean more = animation.getTransformation(currentTime, transformation);
if (WindowManagerService.DEBUG_ANIM) Slog.v(
- TAG, "Stepped animation in " + this + ": more=" + more + ", xform=" + transformation);
+ TAG, "Stepped animation in " + mAppToken + ": more=" + more + ", xform=" + transformation);
if (!more) {
animation = null;
clearThumbnail();
if (WindowManagerService.DEBUG_ANIM) Slog.v(
- TAG, "Finished animation in " + this + " @ " + currentTime);
+ TAG, "Finished animation in " + mAppToken + " @ " + currentTime);
}
hasTransformation = more;
return more;
@@ -195,7 +195,7 @@
&& animation != null) {
if (!animating) {
if (WindowManagerService.DEBUG_ANIM) Slog.v(
- TAG, "Starting animation in " + this +
+ TAG, "Starting animation in " + mAppToken +
" @ " + currentTime + ": dw=" + dw + " dh=" + dh
+ " scale=" + mService.mTransitionAnimationScale
+ " allDrawn=" + mAppToken.allDrawn + " animating=" + animating);
@@ -248,7 +248,7 @@
}
if (WindowManagerService.DEBUG_ANIM) Slog.v(
- TAG, "Animation done in " + this
+ TAG, "Animation done in " + mAppToken
+ ": reportedVisible=" + mAppToken.reportedVisible);
transformation.clear();
diff --git a/services/java/com/android/server/wm/DimSurface.java b/services/java/com/android/server/wm/DimSurface.java
index c1dbb36..9fca4183 100644
--- a/services/java/com/android/server/wm/DimSurface.java
+++ b/services/java/com/android/server/wm/DimSurface.java
@@ -33,10 +33,17 @@
DimSurface(SurfaceSession session) {
if (mDimSurface == null) {
try {
- mDimSurface = new Surface(session, 0,
+ if (WindowManagerService.DEBUG_SURFACE_TRACE) {
+ mDimSurface = new WindowStateAnimator.SurfaceTrace(session, 0,
"DimSurface",
-1, 16, 16, PixelFormat.OPAQUE,
Surface.FX_SURFACE_DIM);
+ } else {
+ mDimSurface = new Surface(session, 0,
+ "DimSurface",
+ -1, 16, 16, PixelFormat.OPAQUE,
+ Surface.FX_SURFACE_DIM);
+ }
if (WindowManagerService.SHOW_TRANSACTIONS ||
WindowManagerService.SHOW_SURFACE_ALLOC) Slog.i(WindowManagerService.TAG,
" DIM " + mDimSurface + ": CREATE");
diff --git a/services/java/com/android/server/wm/WindowAnimator.java b/services/java/com/android/server/wm/WindowAnimator.java
index f1ad539..e5b1f2c 100644
--- a/services/java/com/android/server/wm/WindowAnimator.java
+++ b/services/java/com/android/server/wm/WindowAnimator.java
@@ -451,9 +451,9 @@
Surface.openTransaction();
try {
- testWallpaperAndBackgroundLocked();
updateWindowsAppsAndRotationAnimationsLocked();
performAnimationsLocked();
+ testWallpaperAndBackgroundLocked();
// THIRD LOOP: Update the surfaces of all windows.
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index defe824..32700cb 100755
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -130,6 +130,7 @@
import android.view.animation.Interpolator;
import android.view.animation.ScaleAnimation;
import android.view.animation.Transformation;
+import android.view.animation.TranslateAnimation;
import java.io.BufferedWriter;
import java.io.DataInputStream;
@@ -3129,13 +3130,13 @@
com.android.internal.R.integer.config_shortAnimTime);
break;
default:
- duration = 500;
+ duration = 300;
break;
}
if (enter) {
// Entering app zooms out from the center of the initial rect.
- float scaleW = mNextAppTransitionStartWidth/(float)mAppDisplayWidth;
- float scaleH = mNextAppTransitionStartHeight/(float)mAppDisplayHeight;
+ float scaleW = mNextAppTransitionStartWidth / (float) mAppDisplayWidth;
+ float scaleH = mNextAppTransitionStartHeight / (float) mAppDisplayHeight;
Animation scale = new ScaleAnimation(scaleW, 1, scaleH, 1,
computePivot(mNextAppTransitionStartX, scaleW),
computePivot(mNextAppTransitionStartY, scaleH));
@@ -3152,7 +3153,7 @@
}
a.setFillAfter(true);
final Interpolator interpolator = AnimationUtils.loadInterpolator(mContext,
- com.android.internal.R.interpolator.decelerate_quad);
+ com.android.internal.R.interpolator.decelerate_cubic);
a.setInterpolator(interpolator);
a.initialize(mAppDisplayWidth, mAppDisplayHeight,
mAppDisplayWidth, mAppDisplayHeight);
@@ -3177,7 +3178,7 @@
com.android.internal.R.integer.config_shortAnimTime);
break;
default:
- duration = 500;
+ duration = 300;
break;
}
if (thumb) {