Merge "Handle the case of Preference lists that have header views inserted at the top."
diff --git a/core/java/android/text/SpannableStringBuilder.java b/core/java/android/text/SpannableStringBuilder.java
index fdbec20..231f913 100644
--- a/core/java/android/text/SpannableStringBuilder.java
+++ b/core/java/android/text/SpannableStringBuilder.java
@@ -710,18 +710,17 @@
for (int i = 0; i < spanCount; i++) {
int spanStart = starts[i];
- int spanEnd = ends[i];
-
if (spanStart > gapstart) {
spanStart -= gaplen;
}
- if (spanEnd > gapstart) {
- spanEnd -= gaplen;
- }
-
if (spanStart > queryEnd) {
continue;
}
+
+ int spanEnd = ends[i];
+ if (spanEnd > gapstart) {
+ spanEnd -= gaplen;
+ }
if (spanEnd < queryStart) {
continue;
}
diff --git a/core/java/android/text/style/SpellCheckSpan.java b/core/java/android/text/style/SpellCheckSpan.java
index caaae99..0d8a103 100644
--- a/core/java/android/text/style/SpellCheckSpan.java
+++ b/core/java/android/text/style/SpellCheckSpan.java
@@ -39,8 +39,8 @@
mSpellCheckInProgress = (src.readInt() != 0);
}
- public void setSpellCheckInProgress() {
- mSpellCheckInProgress = true;
+ public void setSpellCheckInProgress(boolean inProgress) {
+ mSpellCheckInProgress = inProgress;
}
public boolean isSpellCheckInProgress() {
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 75c7592..d0841dd 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -26,6 +26,7 @@
import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
+import android.os.SystemProperties;
import android.util.Slog;
import android.view.accessibility.AccessibilityEvent;
@@ -472,11 +473,14 @@
}
private class LocalWindowManager extends WindowManagerImpl.CompatModeWrapper {
+ private static final String PROPERTY_HARDWARE_UI = "persist.sys.ui.hw";
+
private final boolean mHardwareAccelerated;
LocalWindowManager(WindowManager wm, boolean hardwareAccelerated) {
super(wm, getCompatInfo(mContext));
- mHardwareAccelerated = hardwareAccelerated;
+ mHardwareAccelerated = hardwareAccelerated ||
+ SystemProperties.getBoolean(PROPERTY_HARDWARE_UI, false);
}
public boolean isHardwareAccelerated() {
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 530b230..370cce4 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -4308,7 +4308,7 @@
selectionDone();
}
mOrientation = newConfig.orientation;
- contentInvalidateAll();
+ mWebViewCore.sendMessage(EventHub.CLEAR_CONTENT);
}
/**
diff --git a/core/java/android/widget/GridLayout.java b/core/java/android/widget/GridLayout.java
index ba69288..fb9047b 100644
--- a/core/java/android/widget/GridLayout.java
+++ b/core/java/android/widget/GridLayout.java
@@ -850,32 +850,65 @@
return c.getVisibility() == View.GONE;
}
- private void measureChildWithMargins(View child, int widthMeasureSpec, int heightMeasureSpec) {
- LayoutParams lp = getLayoutParams(child);
- int childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec,
- mPaddingLeft + mPaddingRight + getTotalMargin(child, true), lp.width);
- int childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec,
- mPaddingTop + mPaddingBottom + getTotalMargin(child, false), lp.height);
- child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
+ private void measureChildWithMargins2(View child, int parentWidthSpec, int parentHeightSpec,
+ int childWidth, int childHeight) {
+ int childWidthSpec = getChildMeasureSpec(parentWidthSpec,
+ mPaddingLeft + mPaddingRight + getTotalMargin(child, true), childWidth);
+ int childHeightSpec = getChildMeasureSpec(parentHeightSpec,
+ mPaddingTop + mPaddingBottom + getTotalMargin(child, false), childHeight);
+ child.measure(childWidthSpec, childHeightSpec);
}
- private void measureChildrenWithMargins(int widthMeasureSpec, int heightMeasureSpec) {
+ private void measureChildrenWithMargins(int widthSpec, int heightSpec, boolean firstPass) {
for (int i = 0, N = getChildCount(); i < N; i++) {
View c = getChildAt(i);
if (isGone(c)) continue;
- measureChildWithMargins(c, widthMeasureSpec, heightMeasureSpec);
+ LayoutParams lp = getLayoutParams(c);
+ if (firstPass) {
+ measureChildWithMargins2(c, widthSpec, heightSpec, lp.width, lp.height);
+ } else {
+ Spec spec = (orientation == HORIZONTAL) ? lp.columnSpec : lp.rowSpec;
+ if (spec.alignment == FILL) {
+ Interval span = spec.span;
+ Axis axis = (orientation == HORIZONTAL) ? horizontalAxis : verticalAxis;
+ int[] locations = axis.getLocations();
+ int size = locations[span.max] - locations[span.min];
+ if (orientation == HORIZONTAL) {
+ measureChildWithMargins2(c, widthSpec, heightSpec, size, lp.height);
+ } else {
+ measureChildWithMargins2(c, widthSpec, heightSpec, lp.width, size);
+ }
+ }
+ }
}
}
@Override
protected void onMeasure(int widthSpec, int heightSpec) {
- measureChildrenWithMargins(widthSpec, heightSpec);
+ /** If we have been called by {@link View#measure(int, int)}, one of width or height
+ * is likely to have changed. We must invalidate if so. */
+ invalidateValues();
- int width = getPaddingLeft() + horizontalAxis.getMeasure(widthSpec) + getPaddingRight();
- int height = getPaddingTop() + verticalAxis.getMeasure(heightSpec) + getPaddingBottom();
+ measureChildrenWithMargins(widthSpec, heightSpec, true);
- int measuredWidth = Math.max(width, getSuggestedMinimumWidth());
- int measuredHeight = Math.max(height, getSuggestedMinimumHeight());
+ int width, height;
+
+ // Use the orientation property to decide which axis should be laid out first.
+ if (orientation == HORIZONTAL) {
+ width = horizontalAxis.getMeasure(widthSpec);
+ measureChildrenWithMargins(widthSpec, heightSpec, false);
+ height = verticalAxis.getMeasure(heightSpec);
+ } else {
+ height = verticalAxis.getMeasure(heightSpec);
+ measureChildrenWithMargins(widthSpec, heightSpec, false);
+ width = horizontalAxis.getMeasure(widthSpec);
+ }
+
+ int hPadding = getPaddingLeft() + getPaddingRight();
+ int vPadding = getPaddingTop() + getPaddingBottom();
+
+ int measuredWidth = Math.max(hPadding + width, getSuggestedMinimumWidth());
+ int measuredHeight = Math.max(vPadding + height, getSuggestedMinimumHeight());
setMeasuredDimension(
resolveSizeAndState(measuredWidth, widthSpec, 0),
@@ -1015,8 +1048,6 @@
for the vertical one.
*/
final class Axis {
- private static final int MIN_VALUE = -1000000;
-
private static final int NEW = 0;
private static final int PENDING = 1;
private static final int COMPLETE = 2;
@@ -1024,7 +1055,7 @@
public final boolean horizontal;
public int definedCount = UNDEFINED;
- private int inferredCount = UNDEFINED;
+ private int maxIndex = UNDEFINED;
PackedMap<Spec, Bounds> groupBounds;
public boolean groupBoundsValid = false;
@@ -1056,28 +1087,29 @@
this.horizontal = horizontal;
}
- private int maxIndex() {
- // note the number Integer.MIN_VALUE + 1 comes up in undefined cells
- int count = -1;
+ private int calculateMaxIndex() {
+ // the number Integer.MIN_VALUE + 1 comes up in undefined cells
+ int result = -1;
for (int i = 0, N = getChildCount(); i < N; i++) {
View c = getChildAt(i);
LayoutParams params = getLayoutParams(c);
Spec spec = horizontal ? params.columnSpec : params.rowSpec;
- count = max(count, spec.span.min);
- count = max(count, spec.span.max);
+ Interval span = spec.span;
+ result = max(result, span.min);
+ result = max(result, span.max);
}
- return count == -1 ? UNDEFINED : count;
+ return result == -1 ? UNDEFINED : result;
}
- private int getInferredCount() {
- if (inferredCount == UNDEFINED) {
- inferredCount = max(0, maxIndex()); // if there are no cells, actual count is zero
+ private int getMaxIndex() {
+ if (maxIndex == UNDEFINED) {
+ maxIndex = max(0, calculateMaxIndex()); // use zero when there are no children
}
- return inferredCount;
+ return maxIndex;
}
public int getCount() {
- return max(definedCount, getInferredCount());
+ return max(definedCount, getMaxIndex());
}
public void setCount(int count) {
@@ -1179,7 +1211,7 @@
}
private void include(List<Arc> arcs, Interval key, MutableInt size,
- boolean ignoreIfAlreadyPresent) {
+ boolean ignoreIfAlreadyPresent) {
/*
Remove self referential links.
These appear:
@@ -1341,19 +1373,18 @@
}
private void init(int[] locations) {
- Arrays.fill(locations, MIN_VALUE);
- locations[0] = 0;
+ Arrays.fill(locations, 0);
}
private String arcsToString(List<Arc> arcs) {
- String var = horizontal ? "c" : "r";
+ String var = horizontal ? "x" : "y";
StringBuilder result = new StringBuilder();
- boolean first = false;
- for(Arc arc : arcs) {
- if (!first) {
- first = true;
+ boolean first = true;
+ for (Arc arc : arcs) {
+ if (first) {
+ first = false;
} else {
- result =result.append(", ");
+ result = result.append(", ");
}
int src = arc.span.min;
int dst = arc.span.max;
@@ -1434,10 +1465,6 @@
if (originalCulprits != null) {
logError(axisName, arcs, originalCulprits);
}
- if (DEBUG) {
- Log.v(TAG, axisName + " iteration completed in " +
- (1 + i) + " steps of " + N);
- }
return;
}
}
@@ -1506,6 +1533,18 @@
private void computeLocations(int[] a) {
solve(getArcs(), a);
+ if (!orderPreserved) {
+ // Solve returns the smallest solution to the constraint system for which all
+ // values are positive. One value is therefore zero - though if the row/col
+ // order is not preserved this may not be the first vertex. For consistency,
+ // translate all the values so that they measure the distance from a[0]; the
+ // leading edge of the parent. After this transformation some values may be
+ // negative.
+ int a0 = a[0];
+ for (int i = 0, N = a.length; i < N; i++) {
+ a[i] = a[i] - a0;
+ }
+ }
}
public int[] getLocations() {
@@ -1521,7 +1560,10 @@
}
private int size(int[] locations) {
- return max2(locations, 0) - locations[0];
+ // The parental edges are attached to vertices 0 and N - even when order is not
+ // being preserved and other vertices fall outside this range. Measure the distance
+ // between vertices 0 and N, assuming that locations[0] = 0.
+ return locations[getCount()];
}
private void setParentConstraints(int min, int max) {
@@ -1561,7 +1603,7 @@
}
public void invalidateStructure() {
- inferredCount = UNDEFINED;
+ maxIndex = UNDEFINED;
groupBounds = null;
forwardLinks = null;
@@ -2139,8 +2181,8 @@
/**
* A Spec defines the horizontal or vertical characteristics of a group of
- * cells. Each spec. defines the <em>grid indices</em>, <em>alignment</em> and
- * <em>flexibility</em> along the appropriate axis.
+ * cells. Each spec. defines the <em>grid indices</em> and <em>alignment</em>
+ * along the appropriate axis.
* <p>
* The <em>grid indices</em> are the leading and trailing edges of this cell group.
* See {@link GridLayout} for a description of the conventions used by GridLayout
@@ -2149,6 +2191,15 @@
* The <em>alignment</em> property specifies how cells should be aligned in this group.
* For row groups, this specifies the vertical alignment.
* For column groups, this specifies the horizontal alignment.
+ * <p>
+ * Use the following static methods to create specs:
+ * <ul>
+ * <li>{@link #spec(int)}</li>
+ * <li>{@link #spec(int, int)}</li>
+ * <li>{@link #spec(int, Alignment)}</li>
+ * <li>{@link #spec(int, int, Alignment)}</li>
+ * </ul>
+ *
*/
public static class Spec {
static final Spec UNDEFINED = spec(GridLayout.UNDEFINED);
diff --git a/core/java/android/widget/Space.java b/core/java/android/widget/Space.java
index d7b2ec2..bb53a77 100644
--- a/core/java/android/widget/Space.java
+++ b/core/java/android/widget/Space.java
@@ -32,20 +32,24 @@
*/
public Space(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
+ if (getVisibility() == VISIBLE) {
+ setVisibility(INVISIBLE);
+ }
}
/**
* {@inheritDoc}
*/
public Space(Context context, AttributeSet attrs) {
- super(context, attrs);
+ this(context, attrs, 0);
}
/**
* {@inheritDoc}
*/
public Space(Context context) {
- super(context);
+ //noinspection NullableProblems
+ this(context, null);
}
/**
@@ -58,22 +62,6 @@
}
/**
- * {@inheritDoc}
- */
- @Override
- public ViewGroup.LayoutParams getLayoutParams() {
- return super.getLayoutParams();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void setLayoutParams(ViewGroup.LayoutParams params) {
- super.setLayoutParams(params);
- }
-
- /**
* Compare to: {@link View#getDefaultSize(int, int)}
* If mode is AT_MOST, return the child size instead of the parent size
* (unless it is too big).
diff --git a/core/java/android/widget/SpellChecker.java b/core/java/android/widget/SpellChecker.java
index 6b2f3e4..5d8db2f 100644
--- a/core/java/android/widget/SpellChecker.java
+++ b/core/java/android/widget/SpellChecker.java
@@ -22,7 +22,6 @@
import android.text.Spanned;
import android.text.style.SpellCheckSpan;
import android.text.style.SuggestionSpan;
-import android.util.Log;
import android.view.textservice.SpellCheckerSession;
import android.view.textservice.SpellCheckerSession.SpellCheckerSessionListener;
import android.view.textservice.SuggestionsInfo;
@@ -40,23 +39,21 @@
* @hide
*/
public class SpellChecker implements SpellCheckerSessionListener {
- private static final String LOG_TAG = "SpellChecker";
- private static final boolean DEBUG_SPELL_CHECK = false;
- private static final int DELAY_BEFORE_SPELL_CHECK = 400; // milliseconds
private final TextView mTextView;
final SpellCheckerSession mSpellCheckerSession;
final int mCookie;
- // Paired arrays for the (id, spellCheckSpan) pair. mIndex is the next available position
+ // Paired arrays for the (id, spellCheckSpan) pair. A negative id means the associated
+ // SpellCheckSpan has been recycled and can be-reused.
+ // May contain null SpellCheckSpans after a given index.
private int[] mIds;
private SpellCheckSpan[] mSpellCheckSpans;
- // The actual current number of used slots in the above arrays
+ // The mLength first elements of the above arrays have been initialized
private int mLength;
private int mSpanSequenceCounter = 0;
- private Runnable mChecker;
public SpellChecker(TextView textView) {
mTextView = textView;
@@ -69,7 +66,7 @@
mCookie = hashCode();
// Arbitrary: 4 simultaneous spell check spans. Will automatically double size on demand
- final int size = ArrayUtils.idealObjectArraySize(4);
+ final int size = ArrayUtils.idealObjectArraySize(1);
mIds = new int[size];
mSpellCheckSpans = new SpellCheckSpan[size];
mLength = 0;
@@ -89,73 +86,50 @@
}
}
- public void addSpellCheckSpan(SpellCheckSpan spellCheckSpan) {
- int length = mIds.length;
- if (mLength >= length) {
- final int newSize = length * 2;
+ private int nextSpellCheckSpanIndex() {
+ for (int i = 0; i < mLength; i++) {
+ if (mIds[i] < 0) return i;
+ }
+
+ if (mLength == mSpellCheckSpans.length) {
+ final int newSize = mLength * 2;
int[] newIds = new int[newSize];
SpellCheckSpan[] newSpellCheckSpans = new SpellCheckSpan[newSize];
- System.arraycopy(mIds, 0, newIds, 0, length);
- System.arraycopy(mSpellCheckSpans, 0, newSpellCheckSpans, 0, length);
+ System.arraycopy(mIds, 0, newIds, 0, mLength);
+ System.arraycopy(mSpellCheckSpans, 0, newSpellCheckSpans, 0, mLength);
mIds = newIds;
mSpellCheckSpans = newSpellCheckSpans;
}
- mIds[mLength] = mSpanSequenceCounter++;
- mSpellCheckSpans[mLength] = spellCheckSpan;
+ mSpellCheckSpans[mLength] = new SpellCheckSpan();
mLength++;
+ return mLength - 1;
+ }
- if (DEBUG_SPELL_CHECK) {
- final Editable mText = (Editable) mTextView.getText();
- int start = mText.getSpanStart(spellCheckSpan);
- int end = mText.getSpanEnd(spellCheckSpan);
- if (start >= 0 && end >= 0) {
- Log.d(LOG_TAG, "Schedule check " + mText.subSequence(start, end));
- } else {
- Log.d(LOG_TAG, "Schedule check EMPTY!");
- }
- }
-
- scheduleSpellCheck();
+ public void addSpellCheckSpan(int wordStart, int wordEnd) {
+ final int index = nextSpellCheckSpanIndex();
+ ((Editable) mTextView.getText()).setSpan(mSpellCheckSpans[index], wordStart, wordEnd,
+ Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ mIds[index] = mSpanSequenceCounter++;
}
public void removeSpellCheckSpan(SpellCheckSpan spellCheckSpan) {
for (int i = 0; i < mLength; i++) {
if (mSpellCheckSpans[i] == spellCheckSpan) {
- removeAtIndex(i);
+ mSpellCheckSpans[i].setSpellCheckInProgress(false);
+ mIds[i] = -1;
return;
}
}
}
- private void removeAtIndex(int i) {
- System.arraycopy(mIds, i + 1, mIds, i, mLength - i - 1);
- System.arraycopy(mSpellCheckSpans, i + 1, mSpellCheckSpans, i, mLength - i - 1);
- mLength--;
- }
-
public void onSelectionChanged() {
- scheduleSpellCheck();
+ spellCheck();
}
- private void scheduleSpellCheck() {
- if (mLength == 0) return;
+ public void spellCheck() {
if (mSpellCheckerSession == null) return;
- if (mChecker != null) {
- mTextView.removeCallbacks(mChecker);
- }
- if (mChecker == null) {
- mChecker = new Runnable() {
- public void run() {
- spellCheck();
- }
- };
- }
- mTextView.postDelayed(mChecker, DELAY_BEFORE_SPELL_CHECK);
- }
-
- private void spellCheck() {
final Editable editable = (Editable) mTextView.getText();
final int selectionStart = Selection.getSelectionStart(editable);
final int selectionEnd = Selection.getSelectionEnd(editable);
@@ -164,8 +138,7 @@
int textInfosCount = 0;
for (int i = 0; i < mLength; i++) {
- SpellCheckSpan spellCheckSpan = mSpellCheckSpans[i];
-
+ final SpellCheckSpan spellCheckSpan = mSpellCheckSpans[i];
if (spellCheckSpan.isSpellCheckInProgress()) continue;
final int start = editable.getSpanStart(spellCheckSpan);
@@ -174,7 +147,7 @@
// Do not check this word if the user is currently editing it
if (start >= 0 && end > start && (selectionEnd < start || selectionStart > end)) {
final String word = editable.subSequence(start, end).toString();
- spellCheckSpan.setSpellCheckInProgress();
+ spellCheckSpan.setSpellCheckInProgress(true);
textInfos[textInfosCount++] = new TextInfo(word, mCookie, mIds[i]);
}
}
@@ -196,27 +169,18 @@
for (int i = 0; i < results.length; i++) {
SuggestionsInfo suggestionsInfo = results[i];
if (suggestionsInfo.getCookie() != mCookie) continue;
-
final int sequenceNumber = suggestionsInfo.getSequence();
- // Starting from the end, to limit the number of array copy while removing
- for (int j = mLength - 1; j >= 0; j--) {
+
+ for (int j = 0; j < mLength; j++) {
+ final SpellCheckSpan spellCheckSpan = mSpellCheckSpans[j];
+
if (sequenceNumber == mIds[j]) {
- SpellCheckSpan spellCheckSpan = mSpellCheckSpans[j];
final int attributes = suggestionsInfo.getSuggestionsAttributes();
boolean isInDictionary =
((attributes & SuggestionsInfo.RESULT_ATTR_IN_THE_DICTIONARY) > 0);
boolean looksLikeTypo =
((attributes & SuggestionsInfo.RESULT_ATTR_LOOKS_LIKE_TYPO) > 0);
- if (DEBUG_SPELL_CHECK) {
- final int start = editable.getSpanStart(spellCheckSpan);
- final int end = editable.getSpanEnd(spellCheckSpan);
- Log.d(LOG_TAG, "Result sequence=" + suggestionsInfo.getSequence() + " " +
- editable.subSequence(start, end) +
- "\t" + (isInDictionary?"IN_DICT" : "NOT_DICT") +
- "\t" + (looksLikeTypo?"TYPO" : "NOT_TYPO"));
- }
-
if (!isInDictionary && looksLikeTypo) {
String[] suggestions = getSuggestions(suggestionsInfo);
if (suggestions.length > 0) {
@@ -230,13 +194,6 @@
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
// TODO limit to the word rectangle region
mTextView.invalidate();
-
- if (DEBUG_SPELL_CHECK) {
- String suggestionsString = "";
- for (String s : suggestions) { suggestionsString += s + "|"; }
- Log.d(LOG_TAG, " Suggestions for " + sequenceNumber + " " +
- editable.subSequence(start, end)+ " " + suggestionsString);
- }
}
}
editable.removeSpan(spellCheckSpan);
@@ -246,9 +203,10 @@
}
private static String[] getSuggestions(SuggestionsInfo suggestionsInfo) {
+ // A negative suggestion count is possible
final int len = Math.max(0, suggestionsInfo.getSuggestionsCount());
String[] suggestions = new String[len];
- for (int j = 0; j < len; ++j) {
+ for (int j = 0; j < len; j++) {
suggestions[j] = suggestionsInfo.getSuggestionAt(j);
}
return suggestions;
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index bffdadc..cde36c8 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -5537,7 +5537,7 @@
@Override public boolean onCheckIsTextEditor() {
return mInputType != EditorInfo.TYPE_NULL;
}
-
+
@Override public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
if (onCheckIsTextEditor() && isEnabled()) {
if (mInputMethodState == null) {
@@ -7492,9 +7492,6 @@
*/
protected void onSelectionChanged(int selStart, int selEnd) {
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
- if (mSpellChecker != null) {
- mSpellChecker.onSelectionChanged();
- }
}
/**
@@ -7553,6 +7550,8 @@
for (int i = 0; i < length; i++) {
final int s = text.getSpanStart(spans[i]);
final int e = text.getSpanEnd(spans[i]);
+ // Spans that are adjacent to the edited region will be handled in
+ // updateSpellCheckSpans. Result depends on what will be added (space or text)
if (e == start || s == end) break;
text.removeSpan(spans[i]);
}
@@ -7735,12 +7734,8 @@
}
}
- if (what instanceof SpellCheckSpan) {
- if (newStart < 0) {
- getSpellChecker().removeSpellCheckSpan((SpellCheckSpan) what);
- } else if (oldStart < 0) {
- getSpellChecker().addSpellCheckSpan((SpellCheckSpan) what);
- }
+ if (newStart < 0 && what instanceof SpellCheckSpan) {
+ getSpellChecker().removeSpellCheckSpan((SpellCheckSpan) what);
}
}
@@ -7750,8 +7745,8 @@
private void updateSpellCheckSpans(int start, int end) {
if (!isTextEditable() || !isSuggestionsEnabled() || !getSpellChecker().isSessionActive())
return;
- Editable text = (Editable) mText;
+ Editable text = (Editable) mText;
WordIterator wordIterator = getWordIterator();
wordIterator.setCharSequence(text);
@@ -7770,57 +7765,75 @@
return;
}
+ // We need to expand by one character because we want to include the spans that end/start
+ // at position start/end respectively.
+ SpellCheckSpan[] spellCheckSpans = text.getSpans(start - 1, end + 1, SpellCheckSpan.class);
+ SuggestionSpan[] suggestionSpans = text.getSpans(start - 1, end + 1, SuggestionSpan.class);
+ final int numberOfSpellCheckSpans = spellCheckSpans.length;
+
// Iterate over the newly added text and schedule new SpellCheckSpans
while (wordStart <= end) {
if (wordEnd >= start) {
- // A word across the interval boundaries must remove boundary edition spans
+ // A new word has been created across the interval boundaries. Remove previous spans
if (wordStart < start && wordEnd > start) {
- removeEditionSpansAt(start, text);
+ removeSpansAt(start, spellCheckSpans, text);
+ removeSpansAt(start, suggestionSpans, text);
}
if (wordStart < end && wordEnd > end) {
- removeEditionSpansAt(end, text);
+ removeSpansAt(end, spellCheckSpans, text);
+ removeSpansAt(end, suggestionSpans, text);
}
// Do not create new boundary spans if they already exist
boolean createSpellCheckSpan = true;
if (wordEnd == start) {
- SpellCheckSpan[] spellCheckSpans = text.getSpans(start, start,
- SpellCheckSpan.class);
- if (spellCheckSpans.length > 0) createSpellCheckSpan = false;
+ for (int i = 0; i < numberOfSpellCheckSpans; i++) {
+ final int spanEnd = text.getSpanEnd(spellCheckSpans[i]);
+ if (spanEnd == start) {
+ createSpellCheckSpan = false;
+ break;
+ }
+ }
}
if (wordStart == end) {
- SpellCheckSpan[] spellCheckSpans = text.getSpans(end, end,
- SpellCheckSpan.class);
- if (spellCheckSpans.length > 0) createSpellCheckSpan = false;
+ for (int i = 0; i < numberOfSpellCheckSpans; i++) {
+ final int spanStart = text.getSpanEnd(spellCheckSpans[i]);
+ if (spanStart == end) {
+ createSpellCheckSpan = false;
+ break;
+ }
+ }
}
if (createSpellCheckSpan) {
- text.setSpan(new SpellCheckSpan(), wordStart, wordEnd,
- Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ mSpellChecker.addSpellCheckSpan(wordStart, wordEnd);
}
}
// iterate word by word
wordEnd = wordIterator.following(wordEnd);
- if (wordEnd == BreakIterator.DONE) return;
+ if (wordEnd == BreakIterator.DONE) break;
wordStart = wordIterator.getBeginning(wordEnd);
if (wordStart == BreakIterator.DONE) {
Log.e(LOG_TAG, "Unable to find word beginning from " + wordEnd + "in " + mText);
- return;
+ break;
}
}
+
+ mSpellChecker.spellCheck();
}
- private static void removeEditionSpansAt(int offset, Editable text) {
- SuggestionSpan[] suggestionSpans = text.getSpans(offset, offset, SuggestionSpan.class);
- for (int i = 0; i < suggestionSpans.length; i++) {
- text.removeSpan(suggestionSpans[i]);
- }
- SpellCheckSpan[] spellCheckSpans = text.getSpans(offset, offset, SpellCheckSpan.class);
- for (int i = 0; i < spellCheckSpans.length; i++) {
- text.removeSpan(spellCheckSpans[i]);
+ private static <T> void removeSpansAt(int offset, T[] spans, Editable text) {
+ final int length = spans.length;
+ for (int i = 0; i < length; i++) {
+ final T span = spans[i];
+ final int start = text.getSpanStart(span);
+ if (start > offset) continue;
+ final int end = text.getSpanEnd(span);
+ if (end < offset) continue;
+ text.removeSpan(span);
}
}
@@ -8381,6 +8394,10 @@
boolean selectAllGotFocus = mSelectAllOnFocus && didTouchFocusSelect();
hideControllers();
if (!selectAllGotFocus && mText.length() > 0) {
+ if (mSpellChecker != null) {
+ // When the cursor moves, the word that was typed may need spell check
+ mSpellChecker.onSelectionChanged();
+ }
if (isCursorInsideEasyCorrectionSpan()) {
showSuggestions();
} else if (hasInsertionController()) {
@@ -9596,6 +9613,8 @@
private class SuggestionsPopupWindow extends PinnedPopupWindow implements OnItemClickListener {
private static final int MAX_NUMBER_SUGGESTIONS = SuggestionSpan.SUGGESTIONS_MAX_SIZE;
+ private static final int ADD_TO_DICTIONARY = -1;
+ private static final int DELETE_TEXT = -2;
private SuggestionInfo[] mSuggestionInfos;
private int mNumberOfSuggestions;
private boolean mCursorWasVisibleBeforeSuggestions;
@@ -9647,9 +9666,9 @@
listView.setOnItemClickListener(this);
mContentView = listView;
- // Inflate the suggestion items once and for all. +1 for add to dictionary
- mSuggestionInfos = new SuggestionInfo[MAX_NUMBER_SUGGESTIONS + 1];
- for (int i = 0; i < MAX_NUMBER_SUGGESTIONS + 1; i++) {
+ // Inflate the suggestion items once and for all. + 2 for add to dictionary and delete
+ mSuggestionInfos = new SuggestionInfo[MAX_NUMBER_SUGGESTIONS + 2];
+ for (int i = 0; i < mSuggestionInfos.length; i++) {
mSuggestionInfos[i] = new SuggestionInfo();
}
}
@@ -9700,7 +9719,19 @@
false);
}
- textView.setText(mSuggestionInfos[position].text);
+ final SuggestionInfo suggestionInfo = mSuggestionInfos[position];
+ textView.setText(suggestionInfo.text);
+
+ if (suggestionInfo.suggestionIndex == ADD_TO_DICTIONARY) {
+ textView.setCompoundDrawablesWithIntrinsicBounds(
+ com.android.internal.R.drawable.ic_suggestions_add, 0, 0, 0);
+ } else if (suggestionInfo.suggestionIndex == DELETE_TEXT) {
+ textView.setCompoundDrawablesWithIntrinsicBounds(
+ com.android.internal.R.drawable.ic_suggestions_delete, 0, 0, 0);
+ } else {
+ textView.setCompoundDrawables(null, null, null, null);
+ }
+
return textView;
}
}
@@ -9751,11 +9782,10 @@
public void show() {
if (!(mText instanceof Editable)) return;
- if (updateSuggestions()) {
- mCursorWasVisibleBeforeSuggestions = mCursorVisible;
- setCursorVisible(false);
- super.show();
- }
+ updateSuggestions();
+ mCursorWasVisibleBeforeSuggestions = mCursorVisible;
+ setCursorVisible(false);
+ super.show();
}
@Override
@@ -9811,7 +9841,7 @@
super.hide();
}
- private boolean updateSuggestions() {
+ private void updateSuggestions() {
Spannable spannable = (Spannable) TextView.this.mText;
SuggestionSpan[] suggestionSpans = getSuggestionSpans();
@@ -9860,13 +9890,14 @@
highlightTextDifferences(mSuggestionInfos[i], spanUnionStart, spanUnionEnd);
}
+ // Add to dictionary item is there a span with the misspelled flag
if (misspelledSpan != null) {
final int misspelledStart = spannable.getSpanStart(misspelledSpan);
final int misspelledEnd = spannable.getSpanEnd(misspelledSpan);
if (misspelledStart >= 0 && misspelledEnd > misspelledStart) {
SuggestionInfo suggestionInfo = mSuggestionInfos[mNumberOfSuggestions];
suggestionInfo.suggestionSpan = misspelledSpan;
- suggestionInfo.suggestionIndex = -1;
+ suggestionInfo.suggestionIndex = ADD_TO_DICTIONARY;
suggestionInfo.text.replace(0, suggestionInfo.text.length(),
getContext().getString(com.android.internal.R.string.addToDictionary));
@@ -9874,7 +9905,13 @@
}
}
- if (mNumberOfSuggestions == 0) return false;
+ // Delete item
+ SuggestionInfo suggestionInfo = mSuggestionInfos[mNumberOfSuggestions];
+ suggestionInfo.suggestionSpan = null;
+ suggestionInfo.suggestionIndex = DELETE_TEXT;
+ suggestionInfo.text.replace(0, suggestionInfo.text.length(),
+ getContext().getString(com.android.internal.R.string.deleteText));
+ mNumberOfSuggestions++;
if (mSuggestionRangeSpan == null) mSuggestionRangeSpan = new SuggestionRangeSpan();
if (underlineColor == 0) {
@@ -9890,8 +9927,6 @@
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
mSuggestionsAdapter.notifyDataSetChanged();
-
- return true;
}
private void highlightTextDifferences(SuggestionInfo suggestionInfo, int unionStart,
@@ -9916,77 +9951,94 @@
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- hide();
+ TextView textView = (TextView) view;
+ Editable editable = (Editable) mText;
- if (view instanceof TextView) {
- TextView textView = (TextView) view;
- Editable editable = (Editable) mText;
+ SuggestionInfo suggestionInfo = mSuggestionInfos[position];
- SuggestionInfo suggestionInfo = mSuggestionInfos[position];
- final int spanStart = editable.getSpanStart(suggestionInfo.suggestionSpan);
- final int spanEnd = editable.getSpanEnd(suggestionInfo.suggestionSpan);
- if (spanStart < 0 || spanEnd < 0) return; // Span has been removed
- final String originalText = mText.subSequence(spanStart, spanEnd).toString();
-
- if (suggestionInfo.suggestionIndex < 0) {
- Intent intent = new Intent(Settings.ACTION_USER_DICTIONARY_INSERT);
- intent.putExtra("word", originalText);
- intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
- getContext().startActivity(intent);
- suggestionInfo.removeMisspelledFlag();
- } else {
- // SuggestionSpans are removed by replace: save them before
- SuggestionSpan[] suggestionSpans = editable.getSpans(spanStart, spanEnd,
- SuggestionSpan.class);
- final int length = suggestionSpans.length;
- int[] suggestionSpansStarts = new int[length];
- int[] suggestionSpansEnds = new int[length];
- int[] suggestionSpansFlags = new int[length];
- for (int i = 0; i < length; i++) {
- final SuggestionSpan suggestionSpan = suggestionSpans[i];
- suggestionSpansStarts[i] = editable.getSpanStart(suggestionSpan);
- suggestionSpansEnds[i] = editable.getSpanEnd(suggestionSpan);
- suggestionSpansFlags[i] = editable.getSpanFlags(suggestionSpan);
- }
-
- final int suggestionStart = suggestionInfo.suggestionStart;
- final int suggestionEnd = suggestionInfo.suggestionEnd;
- final String suggestion = textView.getText().subSequence(
- suggestionStart, suggestionEnd).toString();
- editable.replace(spanStart, spanEnd, suggestion);
-
- suggestionInfo.removeMisspelledFlag();
-
- // Notify source IME of the suggestion pick. Do this before swaping texts.
- if (!TextUtils.isEmpty(
- suggestionInfo.suggestionSpan.getNotificationTargetClassName())) {
- InputMethodManager imm = InputMethodManager.peekInstance();
- imm.notifySuggestionPicked(suggestionInfo.suggestionSpan, originalText,
- suggestionInfo.suggestionIndex);
- }
-
- // Swap text content between actual text and Suggestion span
- String[] suggestions = suggestionInfo.suggestionSpan.getSuggestions();
- suggestions[suggestionInfo.suggestionIndex] = originalText;
-
- // Restore previous SuggestionSpans
- final int lengthDifference = suggestion.length() - (spanEnd - spanStart);
- for (int i = 0; i < length; i++) {
- // Only spans that include the modified region make sense after replacement
- // Spans partially included in the replaced region are removed, there is no
- // way to assign them a valid range after replacement
- if (suggestionSpansStarts[i] <= spanStart &&
- suggestionSpansEnds[i] >= spanEnd) {
- editable.setSpan(suggestionSpans[i], suggestionSpansStarts[i],
- suggestionSpansEnds[i] + lengthDifference,
- suggestionSpansFlags[i]);
- }
- }
-
- // Move cursor at the end of the replacement word
- Selection.setSelection(editable, spanEnd + lengthDifference);
+ if (suggestionInfo.suggestionIndex == DELETE_TEXT) {
+ final int spanUnionStart = editable.getSpanStart(mSuggestionRangeSpan);
+ int spanUnionEnd = editable.getSpanEnd(mSuggestionRangeSpan);
+ // Do not leave two adjacent spaces after deletion, or one at beginning of text
+ if (spanUnionEnd < editable.length() &&
+ Character.isSpaceChar(editable.charAt(spanUnionEnd)) &&
+ (spanUnionStart == 0 ||
+ Character.isSpaceChar(editable.charAt(spanUnionStart - 1)))) {
+ spanUnionEnd = spanUnionEnd + 1;
}
+ editable.replace(spanUnionStart, spanUnionEnd, "");
+ hide();
+ return;
}
+
+ final int spanStart = editable.getSpanStart(suggestionInfo.suggestionSpan);
+ final int spanEnd = editable.getSpanEnd(suggestionInfo.suggestionSpan);
+ if (spanStart < 0 || spanEnd < 0) {
+ // Span has been removed
+ hide();
+ return;
+ }
+ final String originalText = mText.subSequence(spanStart, spanEnd).toString();
+
+ if (suggestionInfo.suggestionIndex == ADD_TO_DICTIONARY) {
+ Intent intent = new Intent(Settings.ACTION_USER_DICTIONARY_INSERT);
+ intent.putExtra("word", originalText);
+ intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
+ getContext().startActivity(intent);
+ suggestionInfo.removeMisspelledFlag();
+ } else {
+ // SuggestionSpans are removed by replace: save them before
+ SuggestionSpan[] suggestionSpans = editable.getSpans(spanStart, spanEnd,
+ SuggestionSpan.class);
+ final int length = suggestionSpans.length;
+ int[] suggestionSpansStarts = new int[length];
+ int[] suggestionSpansEnds = new int[length];
+ int[] suggestionSpansFlags = new int[length];
+ for (int i = 0; i < length; i++) {
+ final SuggestionSpan suggestionSpan = suggestionSpans[i];
+ suggestionSpansStarts[i] = editable.getSpanStart(suggestionSpan);
+ suggestionSpansEnds[i] = editable.getSpanEnd(suggestionSpan);
+ suggestionSpansFlags[i] = editable.getSpanFlags(suggestionSpan);
+ }
+
+ final int suggestionStart = suggestionInfo.suggestionStart;
+ final int suggestionEnd = suggestionInfo.suggestionEnd;
+ final String suggestion = textView.getText().subSequence(
+ suggestionStart, suggestionEnd).toString();
+ editable.replace(spanStart, spanEnd, suggestion);
+
+ suggestionInfo.removeMisspelledFlag();
+
+ // Notify source IME of the suggestion pick. Do this before swaping texts.
+ if (!TextUtils.isEmpty(
+ suggestionInfo.suggestionSpan.getNotificationTargetClassName())) {
+ InputMethodManager imm = InputMethodManager.peekInstance();
+ imm.notifySuggestionPicked(suggestionInfo.suggestionSpan, originalText,
+ suggestionInfo.suggestionIndex);
+ }
+
+ // Swap text content between actual text and Suggestion span
+ String[] suggestions = suggestionInfo.suggestionSpan.getSuggestions();
+ suggestions[suggestionInfo.suggestionIndex] = originalText;
+
+ // Restore previous SuggestionSpans
+ final int lengthDifference = suggestion.length() - (spanEnd - spanStart);
+ for (int i = 0; i < length; i++) {
+ // Only spans that include the modified region make sense after replacement
+ // Spans partially included in the replaced region are removed, there is no
+ // way to assign them a valid range after replacement
+ if (suggestionSpansStarts[i] <= spanStart &&
+ suggestionSpansEnds[i] >= spanEnd) {
+ editable.setSpan(suggestionSpans[i], suggestionSpansStarts[i],
+ suggestionSpansEnds[i] + lengthDifference, suggestionSpansFlags[i]);
+ }
+ }
+
+ // Move cursor at the end of the replacement word
+ Selection.setSelection(editable, spanEnd + lengthDifference);
+ }
+
+ hide();
}
}
diff --git a/core/res/res/drawable-hdpi/ic_suggestions_add.png b/core/res/res/drawable-hdpi/ic_suggestions_add.png
new file mode 100644
index 0000000..79c017a
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_suggestions_add.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_suggestions_delete.png b/core/res/res/drawable-hdpi/ic_suggestions_delete.png
new file mode 100644
index 0000000..1ae6b96
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_suggestions_delete.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_suggestions_add.png b/core/res/res/drawable-mdpi/ic_suggestions_add.png
new file mode 100644
index 0000000..f91951b
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_suggestions_add.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_suggestions_delete.png b/core/res/res/drawable-mdpi/ic_suggestions_delete.png
new file mode 100644
index 0000000..98eb565
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_suggestions_delete.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_suggestions_add.png b/core/res/res/drawable-xhdpi/ic_suggestions_add.png
new file mode 100644
index 0000000..aac038c
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_suggestions_add.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_suggestions_delete.png b/core/res/res/drawable-xhdpi/ic_suggestions_delete.png
new file mode 100644
index 0000000..077e9fc
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_suggestions_delete.png
Binary files differ
diff --git a/core/res/res/layout/status_bar_latest_event_content_large_icon.xml b/core/res/res/layout/status_bar_latest_event_content_large_icon.xml
index ac4d1e4..f3f1957 100644
--- a/core/res/res/layout/status_bar_latest_event_content_large_icon.xml
+++ b/core/res/res/layout/status_bar_latest_event_content_large_icon.xml
@@ -4,8 +4,8 @@
android:layout_height="wrap_content"
android:layout_gravity="center"
android:orientation="vertical"
- android:paddingLeft="8dp"
- android:paddingRight="8dp"
+ android:paddingLeft="12dp"
+ android:paddingRight="12dp"
>
<TextView android:id="@+id/title"
android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Title"
diff --git a/core/res/res/layout/text_edit_suggestion_item.xml b/core/res/res/layout/text_edit_suggestion_item.xml
index 0e2b04f..1fdc1bf 100644
--- a/core/res/res/layout/text_edit_suggestion_item.xml
+++ b/core/res/res/layout/text_edit_suggestion_item.xml
@@ -23,6 +23,7 @@
android:paddingBottom="8dip"
android:layout_gravity="left|center_vertical"
android:singleLine="true"
+ android:drawablePadding="8dip"
android:ellipsize="marquee"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="@android:color/dim_foreground_light" />
diff --git a/docs/html/guide/guide_toc.cs b/docs/html/guide/guide_toc.cs
index 5f74e50..464430b 100644
--- a/docs/html/guide/guide_toc.cs
+++ b/docs/html/guide/guide_toc.cs
@@ -791,7 +791,7 @@
<span class="en">App Install Location</span>
</a></li>
<li><a href="<?cs var:toroot ?>guide/appendix/media-formats.html">
- <span class="en">Supported Media Formats</span>
+ <span class="en">Supported Media Formats <span class="new">updated</span></span>
</a></li>
<li><a href="<?cs var:toroot ?>guide/appendix/g-app-intents.html">
<span class="en">Intents List: Google Apps</span>
diff --git a/docs/html/guide/practices/ui_guidelines/widget_design.jd b/docs/html/guide/practices/ui_guidelines/widget_design.jd
index f111394..de20e00 100644
--- a/docs/html/guide/practices/ui_guidelines/widget_design.jd
+++ b/docs/html/guide/practices/ui_guidelines/widget_design.jd
@@ -1,4 +1,4 @@
-page.title=Widget Design Guidelines
+page.title=App Widget Design Guidelines
parent.title=UI Guidelines
parent.link=index.html
@jd:body
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
index 3dae5ad..886997c 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
@@ -31,9 +31,7 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.media.AudioManager;
-import android.media.Ringtone;
-import android.media.RingtoneManager;
-import android.net.Uri;
+import android.media.SoundPool;
import android.os.Handler;
import android.os.LocalPowerManager;
import android.os.Message;
@@ -253,6 +251,11 @@
private boolean mWaitingUntilKeyguardVisible = false;
private LockPatternUtils mLockPatternUtils;
+ private SoundPool mLockSounds;
+ private int mLockSoundId;
+ private int mUnlockSoundId;
+ private int mLockSoundStreamId;
+
public KeyguardViewMediator(Context context, PhoneWindowManager callback,
LocalPowerManager powerManager) {
mContext = context;
@@ -298,6 +301,22 @@
final ContentResolver cr = mContext.getContentResolver();
mShowLockIcon = (Settings.System.getInt(cr, "show_status_bar_lock", 0) == 1);
+
+ mLockSounds = new SoundPool(1, AudioManager.STREAM_SYSTEM, 0);
+ String soundPath = Settings.System.getString(cr, Settings.System.LOCK_SOUND);
+ if (soundPath != null) {
+ mLockSoundId = mLockSounds.load(soundPath, 1);
+ }
+ if (soundPath == null || mLockSoundId == 0) {
+ if (DEBUG) Log.d(TAG, "failed to load sound from " + soundPath);
+ }
+ soundPath = Settings.System.getString(cr, Settings.System.UNLOCK_SOUND);
+ if (soundPath != null) {
+ mUnlockSoundId = mLockSounds.load(soundPath, 1);
+ }
+ if (soundPath == null || mUnlockSoundId == 0) {
+ if (DEBUG) Log.d(TAG, "failed to load sound from " + soundPath);
+ }
}
/**
@@ -1044,29 +1063,11 @@
final ContentResolver cr = mContext.getContentResolver();
if (Settings.System.getInt(cr, Settings.System.LOCKSCREEN_SOUNDS_ENABLED, 1) == 1)
{
- final String whichSound = locked
- ? Settings.System.LOCK_SOUND
- : Settings.System.UNLOCK_SOUND;
- final String soundPath = Settings.System.getString(cr, whichSound);
- if (soundPath != null) {
- final Uri soundUri = Uri.parse("file://" + soundPath);
- if (soundUri != null) {
- final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri);
- if (sfx != null) {
- sfx.setStreamType(AudioManager.STREAM_SYSTEM);
- sfx.setWakeMode(mContext, PowerManager.PARTIAL_WAKE_LOCK);
- sfx.play();
- } else {
- if (DEBUG) Log.d(TAG, "playSounds: failed to load ringtone from uri: "
- + soundUri);
- }
- } else {
- if (DEBUG) Log.d(TAG, "playSounds: could not parse Uri: " + soundPath);
- }
- } else {
- if (DEBUG) Log.d(TAG, "playSounds: whichSound = " + whichSound
- + "; soundPath was null");
- }
+ final int whichSound = locked
+ ? mLockSoundId
+ : mUnlockSoundId;
+ mLockSounds.stop(mLockSoundStreamId);
+ mLockSoundStreamId = mLockSounds.play(whichSound, 1.0f, 1.0f, 1, 0, 1.0f);
}
}
diff --git a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
index 2c7f86d..f970ff3 100644
--- a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
+++ b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
@@ -996,10 +996,14 @@
public boolean handleMessage(Message msg) {
switch (msg.what) {
case MSG_SHOW_FACELOCK_AREA_VIEW:
- mFaceLockAreaView.setVisibility(View.VISIBLE);
+ if (mFaceLockAreaView != null) {
+ mFaceLockAreaView.setVisibility(View.VISIBLE);
+ }
break;
case MSG_HIDE_FACELOCK_AREA_VIEW:
- mFaceLockAreaView.setVisibility(View.GONE);
+ if (mFaceLockAreaView != null) {
+ mFaceLockAreaView.setVisibility(View.GONE);
+ }
break;
default:
Log.w(TAG, "Unhandled message");
diff --git a/services/input/EventHub.cpp b/services/input/EventHub.cpp
index 80ee28e..790b395 100644
--- a/services/input/EventHub.cpp
+++ b/services/input/EventHub.cpp
@@ -639,6 +639,8 @@
sizeof(struct input_event) * capacity);
if (readSize == 0 || (readSize < 0 && errno == ENODEV)) {
// Device was removed before INotify noticed.
+ LOGW("could not get event, removed? (fd: %d size: %d bufferSize: %d capacity: %d errno: %d)\n",
+ device->fd, readSize, bufferSize, capacity, errno);
deviceChanged = true;
closeDeviceLocked(device);
} else if (readSize < 0) {
@@ -1254,6 +1256,7 @@
if(event->mask & IN_CREATE) {
openDeviceLocked(devname);
} else {
+ LOGI("Removing device '%s' due to inotify event\n", devname);
closeDeviceByPathLocked(devname);
}
}
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 991b7da..8112b1d 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -1975,8 +1975,7 @@
Integer pid = (Integer)pids.get(j);
if (pid.intValue() == myPid) {
Collection<InetAddress> dnses = p.getDnses();
- String proto = determineProto(p);
- writePidDns(dnses, myPid, proto);
+ writePidDns(dnses, myPid);
if (doBump) {
bumpDns();
}
@@ -1986,9 +1985,6 @@
}
}
// nothing found - delete
- if (SystemProperties.get("net.dnsproto." + myPid).length() != 0) {
- SystemProperties.set("net.dnsproto." + myPid, "");
- }
for (int i = 1; ; i++) {
String prop = "net.dns" + i + "." + myPid;
if (SystemProperties.get(prop).length() == 0) {
@@ -2002,7 +1998,7 @@
}
// return true if results in a change
- private boolean writePidDns(Collection <InetAddress> dnses, int pid, String proto) {
+ private boolean writePidDns(Collection <InetAddress> dnses, int pid) {
int j = 1;
boolean changed = false;
for (InetAddress dns : dnses) {
@@ -2012,11 +2008,6 @@
SystemProperties.set("net.dns" + j++ + "." + pid, dns.getHostAddress());
}
}
- if (dnses.size() > 0 && (changed || !proto.equals(SystemProperties.get("net.dnsproto." +
- pid)))) {
- changed = true;
- SystemProperties.set("net.dnsproto." + pid, proto);
- }
return changed;
}
@@ -2047,7 +2038,7 @@
// Caller must grab mDnsLock.
private boolean updateDns(String network, String iface,
- Collection<InetAddress> dnses, String domains, String proto) {
+ Collection<InetAddress> dnses, String domains) {
boolean changed = false;
int last = 0;
if (dnses.size() == 0 && mDefaultDns != null) {
@@ -2083,11 +2074,6 @@
}
mNumDnsEntries = last;
- if (changed || !proto.equals(SystemProperties.get("net.dnsproto"))) {
- changed = true;
- SystemProperties.set("net.dnsproto", proto);
- }
-
if (changed) {
try {
mNetd.setDnsServersForInterface(iface, NetworkUtils.makeStrings(dnses));
@@ -2111,14 +2097,11 @@
if (p == null) return;
Collection<InetAddress> dnses = p.getDnses();
boolean changed = false;
- String proto = determineProto(p);
-
if (mNetConfigs[netType].isDefault()) {
String network = nt.getNetworkInfo().getTypeName();
synchronized (mDnsLock) {
if (!mDnsOverridden) {
- changed = updateDns(network, p.getInterfaceName(), dnses, "",
- proto);
+ changed = updateDns(network, p.getInterfaceName(), dnses, "");
}
}
} else {
@@ -2132,35 +2115,13 @@
List pids = mNetRequestersPids[netType];
for (int y=0; y< pids.size(); y++) {
Integer pid = (Integer)pids.get(y);
- changed = writePidDns(dnses, pid.intValue(), proto);
+ changed = writePidDns(dnses, pid.intValue());
}
}
if (changed) bumpDns();
}
}
- private String determineProto(LinkProperties p) {
- boolean v4 = false;
- boolean v6 = false;
- for (RouteInfo r : p.getRoutes()) {
- if (r.getDestination().getAddress() instanceof Inet6Address) {
- v6 = true;
- } else {
- v4 = true;
- }
- }
- // secondary connections often don't have routes and we infer routes
- // to the dns servers. Look at the dns addrs too
- for (InetAddress i : p.getDnses()) {
- if (i instanceof Inet6Address) {
- v6 = true;
- } else {
- v4 = true;
- }
- }
- return (v4 ? "v4" : "") + (v6 ? "v6" : "");
- }
-
private int getRestoreDefaultNetworkDelay(int networkType) {
String restoreDefaultNetworkDelayStr = SystemProperties.get(
NETWORK_RESTORE_DELAY_PROP_NAME);
@@ -2882,7 +2843,7 @@
// Apply DNS changes.
boolean changed = false;
synchronized (mDnsLock) {
- changed = updateDns("VPN", "VPN", addresses, domains, "v4");
+ changed = updateDns("VPN", "VPN", addresses, domains);
mDnsOverridden = true;
}
if (changed) {
diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp
index 178e7fd..413a2dc 100644
--- a/tools/aapt/Command.cpp
+++ b/tools/aapt/Command.cpp
@@ -368,6 +368,7 @@
REQUIRES_SMALLEST_WIDTH_DP_ATTR = 0x01010364,
COMPATIBLE_WIDTH_LIMIT_DP_ATTR = 0x01010365,
LARGEST_WIDTH_LIMIT_DP_ATTR = 0x01010366,
+ PUBLIC_KEY_ATTR = 0x010103a6,
};
const char *getComponentName(String8 &pkgName, String8 &componentName) {
@@ -1021,6 +1022,15 @@
} else if (tag == "compatible-screens") {
printCompatibleScreens(tree);
depth--;
+ } else if (tag == "package-verifier") {
+ String8 name = getAttribute(tree, NAME_ATTR, &error);
+ if (name != "" && error == "") {
+ String8 publicKey = getAttribute(tree, PUBLIC_KEY_ATTR, &error);
+ if (publicKey != "" && error == "") {
+ printf("package-verifier: name='%s' publicKey='%s'\n",
+ name.string(), publicKey.string());
+ }
+ }
}
} else if (depth == 3 && withinApplication) {
withinActivity = false;