Merge "Use the carrier-given dns addrs for tethering."
diff --git a/core/java/android/text/SpannableStringBuilder.java b/core/java/android/text/SpannableStringBuilder.java
index 231f913..b708750 100644
--- a/core/java/android/text/SpannableStringBuilder.java
+++ b/core/java/android/text/SpannableStringBuilder.java
@@ -863,6 +863,17 @@
return new String(buf);
}
+ /**
+ * Return a String containing a copy of the chars in this buffer, limited to the
+ * [start, end[ range.
+ * @hide
+ */
+ public String substring(int start, int end) {
+ char[] buf = new char[end - start];
+ getChars(start, end, buf, 0);
+ return new String(buf);
+ }
+
private TextWatcher[] sendTextWillChange(int start, int before, int after) {
TextWatcher[] recip = getSpans(start, start + before, TextWatcher.class);
int n = recip.length;
diff --git a/core/java/android/text/TextLine.java b/core/java/android/text/TextLine.java
index b73d900..b3df8ff 100644
--- a/core/java/android/text/TextLine.java
+++ b/core/java/android/text/TextLine.java
@@ -59,6 +59,12 @@
private boolean mCharsValid;
private Spanned mSpanned;
private final TextPaint mWorkPaint = new TextPaint();
+ private final SpanSet<MetricAffectingSpan> mMetricAffectingSpanSpanSet =
+ new SpanSet<MetricAffectingSpan>(MetricAffectingSpan.class);
+ private final SpanSet<CharacterStyle> mCharacterStyleSpanSet =
+ new SpanSet<CharacterStyle>(CharacterStyle.class);
+ private final SpanSet<ReplacementSpan> mReplacementSpanSpanSet =
+ new SpanSet<ReplacementSpan>(ReplacementSpan.class);
private static final TextLine[] sCached = new TextLine[3];
@@ -119,7 +125,6 @@
* @param hasTabs true if the line might contain tabs or emoji
* @param tabStops the tabStops. Can be null.
*/
- @SuppressWarnings("null")
void set(TextPaint paint, CharSequence text, int start, int limit, int dir,
Directions directions, boolean hasTabs, TabStops tabStops) {
mPaint = paint;
@@ -135,12 +140,10 @@
mSpanned = null;
boolean hasReplacement = false;
- SpanSet<ReplacementSpan> replacementSpans = null;
if (text instanceof Spanned) {
mSpanned = (Spanned) text;
- replacementSpans = new SpanSet<ReplacementSpan>(mSpanned, start, limit,
- ReplacementSpan.class);
- hasReplacement = replacementSpans.numberOfSpans > 0;
+ mReplacementSpanSpanSet.init(mSpanned, start, limit);
+ hasReplacement = mReplacementSpanSpanSet.numberOfSpans > 0;
}
mCharsValid = hasReplacement || hasTabs || directions != Layout.DIRS_ALL_LEFT_TO_RIGHT;
@@ -158,9 +161,8 @@
// zero-width characters.
char[] chars = mChars;
for (int i = start, inext; i < limit; i = inext) {
- // replacementSpans cannot be null if hasReplacement is true
- inext = replacementSpans.getNextTransition(i, limit);
- if (replacementSpans.hasSpansIntersecting(i, inext)) {
+ inext = mReplacementSpanSpanSet.getNextTransition(i, limit);
+ if (mReplacementSpanSpanSet.hasSpansIntersecting(i, inext)) {
// transition into a span
chars[i - start] = '\ufffc';
for (int j = i - start + 1, e = inext - start; j < e; ++j) {
@@ -854,21 +856,30 @@
}
private static class SpanSet<E> {
- final int numberOfSpans;
- final E[] spans;
- final int[] spanStarts;
- final int[] spanEnds;
- final int[] spanFlags;
+ int numberOfSpans;
+ E[] spans;
+ int[] spanStarts;
+ int[] spanEnds;
+ int[] spanFlags;
+ final Class<? extends E> classType;
+
+ SpanSet(Class<? extends E> type) {
+ classType = type;
+ numberOfSpans = 0;
+ }
@SuppressWarnings("unchecked")
- SpanSet(Spanned spanned, int start, int limit, Class<? extends E> type) {
- final E[] allSpans = spanned.getSpans(start, limit, type);
+ public void init(Spanned spanned, int start, int limit) {
+ final E[] allSpans = spanned.getSpans(start, limit, classType);
final int length = allSpans.length;
- // These arrays may end up being too large because of empty spans
- spans = (E[]) Array.newInstance(type, length);
- spanStarts = new int[length];
- spanEnds = new int[length];
- spanFlags = new int[length];
+
+ if (length > 0 && (spans == null || spans.length < length)) {
+ // These arrays may end up being too large because of empty spans
+ spans = (E[]) Array.newInstance(classType, length);
+ spanStarts = new int[length];
+ spanEnds = new int[length];
+ spanFlags = new int[length];
+ }
int count = 0;
for (int i = 0; i < length; i++) {
@@ -879,30 +890,11 @@
if (spanStart == spanEnd) continue;
final int spanFlag = spanned.getSpanFlags(span);
- final int priority = spanFlag & Spanned.SPAN_PRIORITY;
- if (priority != 0 && count != 0) {
- int j;
- for (j = 0; j < count; j++) {
- final int otherPriority = spanFlags[j] & Spanned.SPAN_PRIORITY;
- if (priority > otherPriority) break;
- }
-
- System.arraycopy(spans, j, spans, j + 1, count - j);
- System.arraycopy(spanStarts, j, spanStarts, j + 1, count - j);
- System.arraycopy(spanEnds, j, spanEnds, j + 1, count - j);
- System.arraycopy(spanFlags, j, spanFlags, j + 1, count - j);
-
- spans[j] = span;
- spanStarts[j] = spanStart;
- spanEnds[j] = spanEnd;
- spanFlags[j] = spanFlag;
- } else {
- spans[i] = span;
- spanStarts[i] = spanStart;
- spanEnds[i] = spanEnd;
- spanFlags[i] = spanFlag;
- }
+ spans[i] = span;
+ spanStarts[i] = spanStart;
+ spanEnds[i] = spanEnd;
+ spanFlags[i] = spanFlag;
count++;
}
@@ -970,10 +962,8 @@
y, bottom, fmi, needWidth || mlimit < measureLimit);
}
- final SpanSet<MetricAffectingSpan> metricAffectingSpans = new SpanSet<MetricAffectingSpan>(
- mSpanned, mStart + start, mStart + limit, MetricAffectingSpan.class);
- final SpanSet<CharacterStyle> characterStyleSpans = new SpanSet<CharacterStyle>(
- mSpanned, mStart + start, mStart + limit, CharacterStyle.class);
+ mMetricAffectingSpanSpanSet.init(mSpanned, mStart + start, mStart + limit);
+ mCharacterStyleSpanSet.init(mSpanned, mStart + start, mStart + limit);
// Shaping needs to take into account context up to metric boundaries,
// but rendering needs to take into account character style boundaries.
@@ -985,17 +975,18 @@
TextPaint wp = mWorkPaint;
wp.set(mPaint);
- inext = metricAffectingSpans.getNextTransition(mStart + i, mStart + limit) - mStart;
+ inext = mMetricAffectingSpanSpanSet.getNextTransition(mStart + i, mStart + limit) -
+ mStart;
int mlimit = Math.min(inext, measureLimit);
ReplacementSpan replacement = null;
- for (int j = 0; j < metricAffectingSpans.numberOfSpans; j++) {
+ for (int j = 0; j < mMetricAffectingSpanSpanSet.numberOfSpans; j++) {
// Both intervals [spanStarts..spanEnds] and [mStart + i..mStart + mlimit] are NOT
// empty by construction. This special case in getSpans() explains the >= & <= tests
- if ((metricAffectingSpans.spanStarts[j] >= mStart + mlimit) ||
- (metricAffectingSpans.spanEnds[j] <= mStart + i)) continue;
- MetricAffectingSpan span = metricAffectingSpans.spans[j];
+ if ((mMetricAffectingSpanSpanSet.spanStarts[j] >= mStart + mlimit) ||
+ (mMetricAffectingSpanSpanSet.spanEnds[j] <= mStart + i)) continue;
+ MetricAffectingSpan span = mMetricAffectingSpanSpanSet.spans[j];
if (span instanceof ReplacementSpan) {
replacement = (ReplacementSpan)span;
} else {
@@ -1016,16 +1007,16 @@
y, bottom, fmi, needWidth || mlimit < measureLimit);
} else {
for (int j = i, jnext; j < mlimit; j = jnext) {
- jnext = characterStyleSpans.getNextTransition(mStart + j, mStart + mlimit) -
+ jnext = mCharacterStyleSpanSet.getNextTransition(mStart + j, mStart + mlimit) -
mStart;
wp.set(mPaint);
- for (int k = 0; k < characterStyleSpans.numberOfSpans; k++) {
+ for (int k = 0; k < mCharacterStyleSpanSet.numberOfSpans; k++) {
// Intentionally using >= and <= as explained above
- if ((characterStyleSpans.spanStarts[k] >= mStart + jnext) ||
- (characterStyleSpans.spanEnds[k] <= mStart + j)) continue;
+ if ((mCharacterStyleSpanSet.spanStarts[k] >= mStart + jnext) ||
+ (mCharacterStyleSpanSet.spanEnds[k] <= mStart + j)) continue;
- CharacterStyle span = characterStyleSpans.spans[k];
+ CharacterStyle span = mCharacterStyleSpanSet.spans[k];
span.updateDrawState(wp);
}
diff --git a/core/java/android/text/format/Formatter.java b/core/java/android/text/format/Formatter.java
index 5ae65df..121c6f2 100644
--- a/core/java/android/text/format/Formatter.java
+++ b/core/java/android/text/format/Formatter.java
@@ -21,7 +21,7 @@
/**
* Utility class to aid in formatting common values that are not covered
- * by {@link java.util.Formatter}
+ * by the {@link java.util.Formatter} class in {@link java.util}
*/
public final class Formatter {
diff --git a/core/java/android/text/format/package.html b/core/java/android/text/format/package.html
new file mode 100644
index 0000000..b9e6a44
--- /dev/null
+++ b/core/java/android/text/format/package.html
@@ -0,0 +1,7 @@
+<HTML>
+<BODY>
+This package contains alternative classes for some text formatting classes
+defined in {@link java.util} and {@link java.text}. It also contains additional text formatting
+classes for situations not covered by {@link java.util} or {@link java.text}.
+</BODY>
+</HTML>
diff --git a/core/java/android/text/method/WordIterator.java b/core/java/android/text/method/WordIterator.java
index 239d9e8..11226a9 100644
--- a/core/java/android/text/method/WordIterator.java
+++ b/core/java/android/text/method/WordIterator.java
@@ -18,6 +18,7 @@
package android.text.method;
import android.text.Selection;
+import android.text.SpannableStringBuilder;
import java.text.BreakIterator;
import java.util.Locale;
@@ -58,7 +59,11 @@
mOffsetShift = Math.max(0, start - WINDOW_WIDTH);
final int windowEnd = Math.min(charSequence.length(), end + WINDOW_WIDTH);
- mString = charSequence.toString().substring(mOffsetShift, windowEnd);
+ if (charSequence instanceof SpannableStringBuilder) {
+ mString = ((SpannableStringBuilder) charSequence).substring(mOffsetShift, windowEnd);
+ } else {
+ mString = charSequence.subSequence(mOffsetShift, windowEnd).toString();
+ }
mIterator.setText(mString);
}
diff --git a/core/java/android/view/VolumePanel.java b/core/java/android/view/VolumePanel.java
index 48fe0df..24a3066 100644
--- a/core/java/android/view/VolumePanel.java
+++ b/core/java/android/view/VolumePanel.java
@@ -400,7 +400,7 @@
if (LOGD) Log.d(TAG, "onVolumeChanged(streamType: " + streamType + ", flags: " + flags + ")");
if ((flags & AudioManager.FLAG_SHOW_UI) != 0) {
- if (mActiveStreamType == -1) {
+ if (mActiveStreamType != streamType) {
reorderSliders(streamType);
}
onShowVolumeChanged(streamType, flags);
diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java
index c194559..d8f08b2 100644
--- a/core/java/android/webkit/BrowserFrame.java
+++ b/core/java/android/webkit/BrowserFrame.java
@@ -410,6 +410,7 @@
mCommitted = false;
// remove pending draw to block update until mFirstLayoutDone is
// set to true in didFirstLayout()
+ mWebViewCore.clearContent();
mWebViewCore.removeMessages(WebViewCore.EventHub.WEBKIT_DRAW);
}
}
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 14da23e..de4949c 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -497,6 +497,13 @@
message.sendToTarget();
}
+ /**
+ * Clear the picture set. To be called only on the WebCore thread.
+ */
+ /* package */ void clearContent() {
+ nativeClearContent();
+ }
+
//-------------------------------------------------------------------------
// JNI methods
//-------------------------------------------------------------------------
@@ -1560,7 +1567,7 @@
// Clear the view so that onDraw() will draw nothing
// but white background
// (See public method WebView.clearView)
- nativeClearContent();
+ clearContent();
break;
case MESSAGE_RELAY:
diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java
index 9d541e0..7d0f98e 100644
--- a/core/java/android/widget/NumberPicker.java
+++ b/core/java/android/widget/NumberPicker.java
@@ -774,6 +774,7 @@
mBeginEditOnUpEvent = false;
mAdjustScrollerOnUpEvent = true;
if (mSelectorWheelState == SELECTOR_WHEEL_STATE_LARGE) {
+ mSelectorWheelPaint.setAlpha(SELECTOR_WHEEL_BRIGHT_ALPHA);
boolean scrollersFinished = mFlingScroller.isFinished()
&& mAdjustScroller.isFinished();
if (!scrollersFinished) {
@@ -1608,23 +1609,11 @@
*/
private void fling(int velocityY) {
mPreviousScrollerY = 0;
- Scroller flingScroller = mFlingScroller;
- if (mWrapSelectorWheel) {
- if (velocityY > 0) {
- flingScroller.fling(0, 0, 0, velocityY, 0, 0, 0, Integer.MAX_VALUE);
- } else {
- flingScroller.fling(0, Integer.MAX_VALUE, 0, velocityY, 0, 0, 0, Integer.MAX_VALUE);
- }
+ if (velocityY > 0) {
+ mFlingScroller.fling(0, 0, 0, velocityY, 0, 0, 0, Integer.MAX_VALUE);
} else {
- if (velocityY > 0) {
- int maxY = mTextSize * (mValue - mMinValue);
- flingScroller.fling(0, 0, 0, velocityY, 0, 0, 0, maxY);
- } else {
- int startY = mTextSize * (mMaxValue - mValue);
- int maxY = startY;
- flingScroller.fling(0, startY, 0, velocityY, 0, 0, 0, maxY);
- }
+ mFlingScroller.fling(0, Integer.MAX_VALUE, 0, velocityY, 0, 0, 0, Integer.MAX_VALUE);
}
invalidate();
diff --git a/core/java/android/widget/SpellChecker.java b/core/java/android/widget/SpellChecker.java
index 4bd7165..31da5b5 100644
--- a/core/java/android/widget/SpellChecker.java
+++ b/core/java/android/widget/SpellChecker.java
@@ -19,6 +19,7 @@
import android.content.Context;
import android.text.Editable;
import android.text.Selection;
+import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.method.WordIterator;
import android.text.style.SpellCheckSpan;
@@ -220,7 +221,6 @@
TextInfo[] textInfos = new TextInfo[mLength];
int textInfosCount = 0;
- final String text = editable.toString();
for (int i = 0; i < mLength; i++) {
final SpellCheckSpan spellCheckSpan = mSpellCheckSpans[i];
if (spellCheckSpan.isSpellCheckInProgress()) continue;
@@ -230,7 +230,9 @@
// Do not check this word if the user is currently editing it
if (start >= 0 && end > start && (selectionEnd < start || selectionStart > end)) {
- final String word = text.substring(start, end);
+ final String word = (editable instanceof SpannableStringBuilder) ?
+ ((SpannableStringBuilder) editable).substring(start, end) :
+ editable.subSequence(start, end).toString();
spellCheckSpan.setSpellCheckInProgress(true);
textInfos[textInfosCount++] = new TextInfo(word, mCookie, mIds[i]);
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index db9629a..90fb106 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -3210,7 +3210,6 @@
}
boolean needEditableForNotification = false;
- boolean startSpellCheck = false;
if (mListeners != null && mListeners.size() != 0) {
needEditableForNotification = true;
@@ -3222,7 +3221,6 @@
setFilters(t, mFilters);
InputMethodManager imm = InputMethodManager.peekInstance();
if (imm != null) imm.restartInput(this);
- startSpellCheck = true;
} else if (type == BufferType.SPANNABLE || mMovement != null) {
text = mSpannableFactory.newSpannable(text);
} else if (!(text instanceof CharWrapper)) {
@@ -3311,11 +3309,6 @@
sendOnTextChanged(text, 0, oldlen, textLength);
onTextChanged(text, 0, oldlen, textLength);
- if (startSpellCheck && mSpellChecker != null) {
- // This view has to have been previously attached for mSpellChecker to exist
- updateSpellCheckSpans(0, textLength);
- }
-
if (needEditableForNotification) {
sendAfterTextChanged((Editable) text);
}
@@ -4482,8 +4475,8 @@
// Resolve drawables as the layout direction has been resolved
resolveDrawables();
-
- updateSpellCheckSpans(0, mText.length());
+
+ updateSpellCheckSpans(0, mText.length(), true /* create the spell checker if needed */);
}
@Override
@@ -5517,7 +5510,7 @@
* call performClick(), but that won't do anything in
* this case.)
*/
- if (hasOnClickListeners()) {
+ if (!hasOnClickListeners()) {
if (mMovement != null && mText instanceof Editable
&& mLayout != null && onCheckIsTextEditor()) {
InputMethodManager imm = InputMethodManager.peekInstance();
@@ -5554,7 +5547,7 @@
* call performClick(), but that won't do anything in
* this case.)
*/
- if (hasOnClickListeners()) {
+ if (!hasOnClickListeners()) {
View v = focusSearch(FOCUS_DOWN);
if (v != null) {
@@ -7636,7 +7629,7 @@
}
}
- updateSpellCheckSpans(start, start + after);
+ updateSpellCheckSpans(start, start + after, false);
// Hide the controllers as soon as text is modified (typing, procedural...)
// We do not hide the span controllers, since they can be added when a new text is
@@ -7794,17 +7787,22 @@
}
}
- if (newStart < 0 && what instanceof SpellCheckSpan) {
- getSpellChecker().removeSpellCheckSpan((SpellCheckSpan) what);
+ if (mSpellChecker != null && newStart < 0 && what instanceof SpellCheckSpan) {
+ mSpellChecker.removeSpellCheckSpan((SpellCheckSpan) what);
}
}
/**
* Create new SpellCheckSpans on the modified region.
*/
- private void updateSpellCheckSpans(int start, int end) {
+ private void updateSpellCheckSpans(int start, int end, boolean createSpellChecker) {
if (isTextEditable() && isSuggestionsEnabled()) {
- getSpellChecker().spellCheck(start, end);
+ if (mSpellChecker == null && createSpellChecker) {
+ mSpellChecker = new SpellChecker(this);
+ }
+ if (mSpellChecker != null) {
+ mSpellChecker.spellCheck(start, end);
+ }
}
}
@@ -8976,13 +8974,6 @@
return packRangeInLong(offset, offset);
}
- private SpellChecker getSpellChecker() {
- if (mSpellChecker == null) {
- mSpellChecker = new SpellChecker(this);
- }
- return mSpellChecker;
- }
-
private long getLastTouchOffsets() {
SelectionModifierCursorController selectionController = getSelectionController();
final int minOffset = selectionController.getMinTouchOffset();
@@ -9937,7 +9928,7 @@
// There is no way to know if the word was indeed added. Re-check.
// TODO The ExtractEditText should remove the span in the original text instead
editable.removeSpan(suggestionInfo.suggestionSpan);
- updateSpellCheckSpans(spanStart, spanEnd);
+ updateSpellCheckSpans(spanStart, spanEnd, false);
} else {
// SuggestionSpans are removed by replace: save them before
SuggestionSpan[] suggestionSpans = editable.getSpans(spanStart, spanEnd,
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_sim_pin_landscape.xml b/core/res/res/layout-sw600dp/keyguard_screen_sim_pin_landscape.xml
index c65dd83..0b94fc1 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_sim_pin_landscape.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_sim_pin_landscape.xml
@@ -93,17 +93,6 @@
android:layout_marginLeft="8dip"
android:layout_marginRight="8dip">
- <Button android:id="@+id/ok"
- android:text="@android:string/ok"
- android:layout_alignParentBottom="true"
- android:layout_width="0dip"
- android:layout_height="wrap_content"
- android:layout_weight="1.0"
- android:layout_marginBottom="8dip"
- android:layout_marginRight="8dip"
- android:textSize="18sp"
- />
-
<Button android:id="@+id/emergencyCallButton"
android:text="@android:string/lockscreen_emergency_call"
android:layout_alignParentBottom="true"
@@ -112,11 +101,22 @@
android:layout_height="wrap_content"
android:layout_weight="1.0"
android:layout_marginBottom="8dip"
- android:layout_marginLeft="8dip"
+ android:layout_marginRight="8dip"
android:textSize="18sp"
android:drawableLeft="@drawable/ic_emergency"
android:drawablePadding="8dip"
/>
+
+ <Button android:id="@+id/ok"
+ android:text="@android:string/ok"
+ android:layout_alignParentBottom="true"
+ android:layout_width="0dip"
+ android:layout_height="wrap_content"
+ android:layout_weight="1.0"
+ android:layout_marginBottom="8dip"
+ android:layout_marginLeft="8dip"
+ android:textSize="18sp"
+ />
</LinearLayout>
</RelativeLayout>
diff --git a/core/res/res/layout/keyguard_screen_sim_pin_landscape.xml b/core/res/res/layout/keyguard_screen_sim_pin_landscape.xml
index 59065e1..3cb19c3 100644
--- a/core/res/res/layout/keyguard_screen_sim_pin_landscape.xml
+++ b/core/res/res/layout/keyguard_screen_sim_pin_landscape.xml
@@ -91,17 +91,6 @@
android:layout_marginLeft="8dip"
android:layout_marginRight="8dip">
- <Button android:id="@+id/ok"
- android:text="@android:string/ok"
- android:layout_alignParentBottom="true"
- android:layout_width="0dip"
- android:layout_height="wrap_content"
- android:layout_weight="1.0"
- android:layout_marginBottom="8dip"
- android:layout_marginRight="8dip"
- android:textSize="18sp"
- />
-
<Button android:id="@+id/emergencyCallButton"
android:text="@android:string/lockscreen_emergency_call"
android:layout_alignParentBottom="true"
@@ -110,11 +99,22 @@
android:layout_height="wrap_content"
android:layout_weight="1.0"
android:layout_marginBottom="8dip"
- android:layout_marginLeft="8dip"
+ android:layout_marginRight="8dip"
android:textSize="18sp"
android:drawableLeft="@drawable/ic_emergency"
android:drawablePadding="4dip"
/>
+
+ <Button android:id="@+id/ok"
+ android:text="@android:string/ok"
+ android:layout_alignParentBottom="true"
+ android:layout_width="0dip"
+ android:layout_height="wrap_content"
+ android:layout_weight="1.0"
+ android:layout_marginBottom="8dip"
+ android:layout_marginLeft="8dip"
+ android:textSize="18sp"
+ />
</LinearLayout>
</RelativeLayout>
diff --git a/core/res/res/layout/keyguard_screen_sim_puk_landscape.xml b/core/res/res/layout/keyguard_screen_sim_puk_landscape.xml
index b662e82..722dc26 100644
--- a/core/res/res/layout/keyguard_screen_sim_puk_landscape.xml
+++ b/core/res/res/layout/keyguard_screen_sim_puk_landscape.xml
@@ -153,17 +153,6 @@
android:layout_marginLeft="8dip"
android:layout_marginRight="8dip">
- <Button android:id="@+id/ok"
- android:text="@android:string/ok"
- android:layout_alignParentBottom="true"
- android:layout_width="0dip"
- android:layout_height="wrap_content"
- android:layout_weight="1.0"
- android:layout_marginBottom="8dip"
- android:layout_marginRight="8dip"
- android:textSize="18sp"
- />
-
<Button android:id="@+id/emergencyCallButton"
android:text="@android:string/lockscreen_emergency_call"
android:layout_alignParentBottom="true"
@@ -172,11 +161,22 @@
android:layout_height="wrap_content"
android:layout_weight="1.0"
android:layout_marginBottom="8dip"
- android:layout_marginLeft="8dip"
+ android:layout_marginRight="8dip"
android:textSize="18sp"
android:drawableLeft="@drawable/ic_emergency"
android:drawablePadding="4dip"
/>
+
+ <Button android:id="@+id/ok"
+ android:text="@android:string/ok"
+ android:layout_alignParentBottom="true"
+ android:layout_width="0dip"
+ android:layout_height="wrap_content"
+ android:layout_weight="1.0"
+ android:layout_marginBottom="8dip"
+ android:layout_marginLeft="8dip"
+ android:textSize="18sp"
+ />
</LinearLayout>
</RelativeLayout>
diff --git a/core/res/res/layout/twelve_key_entry.xml b/core/res/res/layout/twelve_key_entry.xml
index 46301cd..09c749d 100644
--- a/core/res/res/layout/twelve_key_entry.xml
+++ b/core/res/res/layout/twelve_key_entry.xml
@@ -144,7 +144,7 @@
android:layout_marginRight="2dip"
android:orientation="horizontal">
- <Button android:id="@+id/ok"
+ <Button android:id="@+id/cancel"
android:layout_width="0sp"
android:layout_height="fill_parent"
android:layout_weight="1"
@@ -152,7 +152,7 @@
android:layout_marginRight="2dip"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textStyle="bold"
- android:text="@android:string/ok"
+ android:text="@android:string/cancel"
/>
<Button android:id="@+id/zero"
@@ -165,7 +165,7 @@
android:textStyle="bold"
/>
- <Button android:id="@+id/cancel"
+ <Button android:id="@+id/ok"
android:layout_width="0sp"
android:layout_height="fill_parent"
android:layout_weight="1"
@@ -173,7 +173,7 @@
android:layout_marginRight="2dip"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textStyle="bold"
- android:text="@android:string/cancel"
+ android:text="@android:string/ok"
/>
</LinearLayout>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index f702657..80aef215 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1992,7 +1992,7 @@
<string name="save_password_label">Confirm</string>
<!-- Toast for double-tap -->
- <string name="double_tap_toast">Tip: Double-touch to zoom in and out.</string>
+ <string name="double_tap_toast">Tip: Double-tap to zoom in and out.</string>
<!-- Text to show in the auto complete drop down list on a text view when the WebView can auto fill the entire form, and the user has configured an AutoFill profile [CHAR-LIMIT=8] -->
<string name="autofill_this_form">Autofill</string>
diff --git a/libs/hwui/Program.cpp b/libs/hwui/Program.cpp
index 972dd87..4aff23e 100644
--- a/libs/hwui/Program.cpp
+++ b/libs/hwui/Program.cpp
@@ -27,35 +27,47 @@
Program::Program(const char* vertex, const char* fragment) {
mInitialized = false;
+ mHasColorUniform = false;
- vertexShader = buildShader(vertex, GL_VERTEX_SHADER);
+ // No need to cache compiled shaders, rely instead on Android's
+ // persistent shaders cache
+ GLuint vertexShader = buildShader(vertex, GL_VERTEX_SHADER);
if (vertexShader) {
- fragmentShader = buildShader(fragment, GL_FRAGMENT_SHADER);
+ GLuint fragmentShader = buildShader(fragment, GL_FRAGMENT_SHADER);
if (fragmentShader) {
- id = glCreateProgram();
- glAttachShader(id, vertexShader);
- glAttachShader(id, fragmentShader);
- glLinkProgram(id);
+ mProgramId = glCreateProgram();
+ glAttachShader(mProgramId, vertexShader);
+ glAttachShader(mProgramId, fragmentShader);
+ glLinkProgram(mProgramId);
GLint status;
- glGetProgramiv(id, GL_LINK_STATUS, &status);
+ glGetProgramiv(mProgramId, GL_LINK_STATUS, &status);
if (status != GL_TRUE) {
LOGE("Error while linking shaders:");
GLint infoLen = 0;
- glGetProgramiv(id, GL_INFO_LOG_LENGTH, &infoLen);
+ glGetProgramiv(mProgramId, GL_INFO_LOG_LENGTH, &infoLen);
if (infoLen > 1) {
GLchar log[infoLen];
- glGetProgramInfoLog(id, infoLen, 0, &log[0]);
+ glGetProgramInfoLog(mProgramId, infoLen, 0, &log[0]);
LOGE("%s", log);
}
- glDeleteShader(vertexShader);
- glDeleteShader(fragmentShader);
- glDeleteProgram(id);
} else {
mInitialized = true;
}
+
+ glDetachShader(mProgramId, vertexShader);
+ glDetachShader(mProgramId, fragmentShader);
+
+ glDeleteShader(vertexShader);
+ glDeleteShader(fragmentShader);
+
+ if (!mInitialized) {
+ glDeleteProgram(mProgramId);
+ }
+ } else {
+ glDeleteShader(vertexShader);
}
}
@@ -69,36 +81,34 @@
Program::~Program() {
if (mInitialized) {
- glDeleteShader(vertexShader);
- glDeleteShader(fragmentShader);
- glDeleteProgram(id);
+ glDeleteProgram(mProgramId);
}
}
int Program::addAttrib(const char* name) {
- int slot = glGetAttribLocation(id, name);
- attributes.add(name, slot);
+ int slot = glGetAttribLocation(mProgramId, name);
+ mAttributes.add(name, slot);
return slot;
}
int Program::getAttrib(const char* name) {
- ssize_t index = attributes.indexOfKey(name);
+ ssize_t index = mAttributes.indexOfKey(name);
if (index >= 0) {
- return attributes.valueAt(index);
+ return mAttributes.valueAt(index);
}
return addAttrib(name);
}
int Program::addUniform(const char* name) {
- int slot = glGetUniformLocation(id, name);
- uniforms.add(name, slot);
+ int slot = glGetUniformLocation(mProgramId, name);
+ mUniforms.add(name, slot);
return slot;
}
int Program::getUniform(const char* name) {
- ssize_t index = uniforms.indexOfKey(name);
+ ssize_t index = mUniforms.indexOfKey(name);
if (index >= 0) {
- return uniforms.valueAt(index);
+ return mUniforms.valueAt(index);
}
return addUniform(name);
}
@@ -127,10 +137,11 @@
const mat4& transformMatrix, bool offset) {
mat4 t(projectionMatrix);
if (offset) {
- // offset screenspace xy by an amount that compensates for typical precision issues
- // in GPU hardware that tends to paint hor/vert lines in pixels shifted up and to the left.
- // This offset value is based on an assumption that some hardware may use as little
- // as 12.4 precision, so we offset by slightly more than 1/16.
+ // offset screenspace xy by an amount that compensates for typical precision
+ // issues in GPU hardware that tends to paint hor/vert lines in pixels shifted
+ // up and to the left.
+ // This offset value is based on an assumption that some hardware may use as
+ // little as 12.4 precision, so we offset by slightly more than 1/16.
t.translate(.375, .375, 0);
}
t.multiply(transformMatrix);
@@ -140,20 +151,24 @@
}
void Program::setColor(const float r, const float g, const float b, const float a) {
- glUniform4f(getUniform("color"), r, g, b, a);
+ if (!mHasColorUniform) {
+ mColorUniform = getUniform("color");
+ mHasColorUniform = true;
+ }
+ glUniform4f(mColorUniform, r, g, b, a);
}
void Program::use() {
- glUseProgram(id);
+ glUseProgram(mProgramId);
mUse = true;
-
glEnableVertexAttribArray(position);
}
void Program::remove() {
mUse = false;
-
- glDisableVertexAttribArray(position);
+ // TODO: Is this necessary? It should not be since all of our shaders
+ // use slot 0 for the position attrib
+ // glDisableVertexAttribArray(position);
}
}; // namespace uirenderer
diff --git a/libs/hwui/Program.h b/libs/hwui/Program.h
index 764cb05..edd1209 100644
--- a/libs/hwui/Program.h
+++ b/libs/hwui/Program.h
@@ -122,18 +122,17 @@
GLuint buildShader(const char* source, GLenum type);
// Name of the OpenGL program
- GLuint id;
-
- // Name of the shaders
- GLuint vertexShader;
- GLuint fragmentShader;
+ GLuint mProgramId;
// Keeps track of attributes and uniforms slots
- KeyedVector<const char*, int> attributes;
- KeyedVector<const char*, int> uniforms;
+ KeyedVector<const char*, int> mAttributes;
+ KeyedVector<const char*, int> mUniforms;
bool mUse;
bool mInitialized;
+
+ bool mHasColorUniform;
+ int mColorUniform;
}; // class Program
}; // namespace uirenderer
diff --git a/libs/hwui/ProgramCache.h b/libs/hwui/ProgramCache.h
index 5c7197b..441db8c 100644
--- a/libs/hwui/ProgramCache.h
+++ b/libs/hwui/ProgramCache.h
@@ -27,6 +27,7 @@
#include "Debug.h"
#include "Program.h"
+#include "Properties.h"
namespace android {
namespace uirenderer {
@@ -42,8 +43,6 @@
#define PROGRAM_LOGD(...)
#endif
-// TODO: This should be set in properties
-#define PANEL_BIT_DEPTH 20
#define COLOR_COMPONENT_THRESHOLD (1.0f - (0.5f / PANEL_BIT_DEPTH))
#define COLOR_COMPONENT_INV_THRESHOLD (0.5f / PANEL_BIT_DEPTH)
diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h
index 8c01e3a..2eae0f1 100644
--- a/libs/hwui/Properties.h
+++ b/libs/hwui/Properties.h
@@ -73,6 +73,9 @@
#define PROPERTY_TEXT_BLACK_GAMMA_THRESHOLD "ro.text_gamma.black_threshold"
#define PROPERTY_TEXT_WHITE_GAMMA_THRESHOLD "ro.text_gamma.white_threshold"
+// TODO: This should be set by a system property
+#define PANEL_BIT_DEPTH 20
+
// Converts a number of mega-bytes into bytes
#define MB(s) s * 1024 * 1024
diff --git a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
index e72adc4..6d28298 100644
--- a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
@@ -38,7 +38,8 @@
mFlags(0),
mState(DISCONNECTED),
mFinalResult(OK),
- mDisconnectReplyID(0) {
+ mDisconnectReplyID(0),
+ mSeekGeneration(0) {
if (headers) {
mExtraHeaders = *headers;
@@ -146,14 +147,21 @@
}
status_t NuPlayer::RTSPSource::seekTo(int64_t seekTimeUs) {
+ sp<AMessage> msg = new AMessage(kWhatPerformSeek, mReflector->id());
+ msg->setInt32("generation", ++mSeekGeneration);
+ msg->setInt64("timeUs", seekTimeUs);
+ msg->post(200000ll);
+
+ return OK;
+}
+
+void NuPlayer::RTSPSource::performSeek(int64_t seekTimeUs) {
if (mState != CONNECTED) {
- return UNKNOWN_ERROR;
+ return;
}
mState = SEEKING;
mHandler->seek(seekTimeUs);
-
- return OK;
}
bool NuPlayer::RTSPSource::isSeekable() {
@@ -168,6 +176,20 @@
mDisconnectReplyID = replyID;
finishDisconnectIfPossible();
return;
+ } else if (msg->what() == kWhatPerformSeek) {
+ int32_t generation;
+ CHECK(msg->findInt32("generation", &generation));
+
+ if (generation != mSeekGeneration) {
+ // obsolete.
+ return;
+ }
+
+ int64_t seekTimeUs;
+ CHECK(msg->findInt64("timeUs", &seekTimeUs));
+
+ performSeek(seekTimeUs);
+ return;
}
CHECK_EQ(msg->what(), (int)kWhatNotify);
@@ -208,21 +230,32 @@
break;
}
- const TrackInfo &info = mTracks.editItemAt(trackIndex);
- sp<AnotherPacketSource> source = info.mSource;
+ TrackInfo *info = &mTracks.editItemAt(trackIndex);
+
+ sp<AnotherPacketSource> source = info->mSource;
if (source != NULL) {
-#if 1
uint32_t rtpTime;
CHECK(accessUnit->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
+ if (!info->mNPTMappingValid) {
+ // This is a live stream, we didn't receive any normal
+ // playtime mapping. Assume the first packets correspond
+ // to time 0.
+
+ ALOGV("This is a live stream, assuming time = 0");
+
+ info->mRTPTime = rtpTime;
+ info->mNormalPlaytimeUs = 0ll;
+ info->mNPTMappingValid = true;
+ }
+
int64_t nptUs =
- ((double)rtpTime - (double)info.mRTPTime)
- / info.mTimeScale
+ ((double)rtpTime - (double)info->mRTPTime)
+ / info->mTimeScale
* 1000000ll
- + info.mNormalPlaytimeUs;
+ + info->mNormalPlaytimeUs;
accessUnit->meta()->setInt64("timeUs", nptUs);
-#endif
source->queueAccessUnit(accessUnit);
}
@@ -278,6 +311,7 @@
TrackInfo *info = &mTracks.editItemAt(trackIndex);
info->mRTPTime = rtpTime;
info->mNormalPlaytimeUs = nptUs;
+ info->mNPTMappingValid = true;
break;
}
@@ -305,6 +339,7 @@
info.mTimeScale = timeScale;
info.mRTPTime = 0;
info.mNormalPlaytimeUs = 0ll;
+ info.mNPTMappingValid = false;
if ((isAudio && mAudioTrack == NULL)
|| (isVideo && mVideoTrack == NULL)) {
diff --git a/media/libmediaplayerservice/nuplayer/RTSPSource.h b/media/libmediaplayerservice/nuplayer/RTSPSource.h
index 66eab72..59d06ad 100644
--- a/media/libmediaplayerservice/nuplayer/RTSPSource.h
+++ b/media/libmediaplayerservice/nuplayer/RTSPSource.h
@@ -56,6 +56,7 @@
enum {
kWhatNotify = 'noti',
kWhatDisconnect = 'disc',
+ kWhatPerformSeek = 'seek',
};
enum State {
@@ -76,6 +77,7 @@
int32_t mTimeScale;
uint32_t mRTPTime;
int64_t mNormalPlaytimeUs;
+ bool mNPTMappingValid;
};
AString mURL;
@@ -95,12 +97,16 @@
sp<AnotherPacketSource> mAudioTrack;
sp<AnotherPacketSource> mVideoTrack;
+ int32_t mSeekGeneration;
+
sp<AnotherPacketSource> getSource(bool audio);
void onConnected();
void onDisconnected(const sp<AMessage> &msg);
void finishDisconnectIfPossible();
+ void performSeek(int64_t seekTimeUs);
+
DISALLOW_EVIL_CONSTRUCTORS(RTSPSource);
};
diff --git a/media/libstagefright/foundation/ABitReader.cpp b/media/libstagefright/foundation/ABitReader.cpp
index f07dd4f..5499c32 100644
--- a/media/libstagefright/foundation/ABitReader.cpp
+++ b/media/libstagefright/foundation/ABitReader.cpp
@@ -79,7 +79,13 @@
}
void ABitReader::putBits(uint32_t x, size_t n) {
- CHECK_LE(mNumBitsLeft + n, 32u);
+ CHECK_LE(n, 32u);
+
+ while (mNumBitsLeft + n > 32) {
+ mNumBitsLeft -= 8;
+ --mData;
+ ++mSize;
+ }
mReservoir = (mReservoir >> n) | (x << (32 - n));
mNumBitsLeft += n;
diff --git a/media/libstagefright/rtsp/AAMRAssembler.cpp b/media/libstagefright/rtsp/AAMRAssembler.cpp
index 547b202..9d72b1f 100644
--- a/media/libstagefright/rtsp/AAMRAssembler.cpp
+++ b/media/libstagefright/rtsp/AAMRAssembler.cpp
@@ -79,13 +79,17 @@
}
static size_t getFrameSize(bool isWide, unsigned FT) {
- static const size_t kFrameSizeNB[8] = {
- 95, 103, 118, 134, 148, 159, 204, 244
+ static const size_t kFrameSizeNB[9] = {
+ 95, 103, 118, 134, 148, 159, 204, 244, 39
};
- static const size_t kFrameSizeWB[9] = {
- 132, 177, 253, 285, 317, 365, 397, 461, 477
+ static const size_t kFrameSizeWB[10] = {
+ 132, 177, 253, 285, 317, 365, 397, 461, 477, 40
};
+ if (FT == 15) {
+ return 1;
+ }
+
size_t frameSize = isWide ? kFrameSizeWB[FT] : kFrameSizeNB[FT];
// Round up bits to bytes and add 1 for the header byte.
@@ -161,8 +165,8 @@
unsigned FT = (toc >> 3) & 0x0f;
if ((toc & 3) != 0
- || (mIsWide && FT > 8)
- || (!mIsWide && FT > 7)) {
+ || (mIsWide && FT > 9 && FT != 15)
+ || (!mIsWide && FT > 8 && FT != 15)) {
queue->erase(queue->begin());
++mNextExpectedSeqNo;
diff --git a/media/libstagefright/rtsp/ARTSPConnection.cpp b/media/libstagefright/rtsp/ARTSPConnection.cpp
index 0fbbb9e..d8107bc 100644
--- a/media/libstagefright/rtsp/ARTSPConnection.cpp
+++ b/media/libstagefright/rtsp/ARTSPConnection.cpp
@@ -659,6 +659,7 @@
}
AString line;
+ ssize_t lastDictIndex = -1;
for (;;) {
if (!receiveLine(&line)) {
break;
@@ -668,7 +669,21 @@
break;
}
- ALOGV("line: %s", line.c_str());
+ ALOGV("line: '%s'", line.c_str());
+
+ if (line.c_str()[0] == ' ' || line.c_str()[0] == '\t') {
+ // Support for folded header values.
+
+ if (lastDictIndex < 0) {
+ // First line cannot be a continuation of the previous one.
+ return false;
+ }
+
+ AString &value = response->mHeaders.editValueAt(lastDictIndex);
+ value.append(line);
+
+ continue;
+ }
ssize_t colonPos = line.find(":");
if (colonPos < 0) {
@@ -681,9 +696,12 @@
key.tolower();
line.erase(0, colonPos + 1);
- line.trim();
- response->mHeaders.add(key, line);
+ lastDictIndex = response->mHeaders.add(key, line);
+ }
+
+ for (size_t i = 0; i < response->mHeaders.size(); ++i) {
+ response->mHeaders.editValueAt(i).trim();
}
unsigned long contentLength = 0;
diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h
index dd049c2..21ef298 100644
--- a/media/libstagefright/rtsp/MyHandler.h
+++ b/media/libstagefright/rtsp/MyHandler.h
@@ -1100,6 +1100,8 @@
float npt1, npt2;
if (!ASessionDescription::parseNTPRange(val.c_str(), &npt1, &npt2)) {
// This is a live stream and therefore not seekable.
+
+ LOGI("This is a live stream");
return;
}
@@ -1386,12 +1388,14 @@
msg->setInt32("what", kWhatConnected);
msg->post();
- for (size_t i = 0; i < mTracks.size(); ++i) {
- TrackInfo *info = &mTracks.editItemAt(i);
+ if (mSeekable) {
+ for (size_t i = 0; i < mTracks.size(); ++i) {
+ TrackInfo *info = &mTracks.editItemAt(i);
- postNormalPlayTimeMapping(
- i,
- info->mNormalPlayTimeRTP, info->mNormalPlayTimeUs);
+ postNormalPlayTimeMapping(
+ i,
+ info->mNormalPlayTimeRTP, info->mNormalPlayTimeUs);
+ }
}
mFirstAccessUnit = false;
diff --git a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
index 67a6855..088146b 100644
--- a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
+++ b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
@@ -52,6 +52,7 @@
import android.os.Message;
import android.os.IBinder;
import android.os.Parcelable;
+import android.os.PowerManager;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.SystemProperties;
@@ -101,8 +102,8 @@
private View mLockScreen;
private View mUnlockScreen;
- private volatile boolean mScreenOn = false;
- private volatile boolean mWindowFocused = false;
+ private boolean mScreenOn;
+ private boolean mWindowFocused = false;
private boolean mEnableFallback = false; // assume no fallback UI until we know better
private boolean mShowLockBeforeUnlock = false;
@@ -311,6 +312,7 @@
mWindowController = controller;
mHasOverlay = false;
mPluggedIn = mUpdateMonitor.isDevicePluggedIn();
+ mScreenOn = ((PowerManager)context.getSystemService(Context.POWER_SERVICE)).isScreenOn();
mUpdateMonitor.registerInfoCallback(this);
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index 16643ff..aef3426 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -152,8 +152,12 @@
/* Wifi disabled due to airplane mode on */
private static final int WIFI_DISABLED_AIRPLANE_ON = 3;
- private AtomicInteger mWifiState = new AtomicInteger(WIFI_DISABLED);
+ /* Persisted state that tracks the wifi & airplane interaction from settings */
+ private AtomicInteger mPersistWifiState = new AtomicInteger(WIFI_DISABLED);
+ /* Tracks current airplane mode state */
private AtomicBoolean mAirplaneModeOn = new AtomicBoolean(false);
+ /* Tracks whether wifi is enabled from WifiStateMachine's perspective */
+ private boolean mWifiEnabled;
private boolean mIsReceiverRegistered = false;
@@ -373,8 +377,8 @@
mAirplaneModeOn.set(isAirplaneModeOn());
/* On airplane mode disable, restore wifi state if necessary */
if (!mAirplaneModeOn.get() && (testAndClearWifiSavedState() ||
- mWifiState.get() == WIFI_ENABLED_AIRPLANE_OVERRIDE)) {
- persistWifiEnabled(true);
+ mPersistWifiState.get() == WIFI_ENABLED_AIRPLANE_OVERRIDE)) {
+ persistWifiState(true);
}
updateWifiState();
}
@@ -391,7 +395,12 @@
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
- // reset & clear notification on any wifi state change
+ int wifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
+ WifiManager.WIFI_STATE_DISABLED);
+
+ mWifiEnabled = (wifiState == WifiManager.WIFI_STATE_ENABLED);
+
+ // reset & clear notification on any wifi state change
resetNotification();
} else if (intent.getAction().equals(
WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
@@ -435,7 +444,7 @@
*/
public void checkAndStartWifi() {
mAirplaneModeOn.set(isAirplaneModeOn());
- mWifiState.set(getPersistedWifiState());
+ mPersistWifiState.set(getPersistedWifiState());
/* Start if Wi-Fi should be enabled or the saved state indicates Wi-Fi was on */
boolean wifiEnabled = shouldWifiBeEnabled() || testAndClearWifiSavedState();
Slog.i(TAG, "WifiService starting up with Wi-Fi " +
@@ -472,29 +481,30 @@
private boolean shouldWifiBeEnabled() {
if (mAirplaneModeOn.get()) {
- return mWifiState.get() == WIFI_ENABLED_AIRPLANE_OVERRIDE;
+ return mPersistWifiState.get() == WIFI_ENABLED_AIRPLANE_OVERRIDE;
} else {
- return mWifiState.get() != WIFI_DISABLED;
+ return mPersistWifiState.get() != WIFI_DISABLED;
}
}
- private void persistWifiEnabled(boolean enabled) {
+ private void persistWifiState(boolean enabled) {
final ContentResolver cr = mContext.getContentResolver();
boolean airplane = mAirplaneModeOn.get() && isAirplaneToggleable();
if (enabled) {
if (airplane) {
- mWifiState.set(WIFI_ENABLED_AIRPLANE_OVERRIDE);
+ mPersistWifiState.set(WIFI_ENABLED_AIRPLANE_OVERRIDE);
} else {
- mWifiState.set(WIFI_ENABLED);
+ mPersistWifiState.set(WIFI_ENABLED);
}
} else {
if (airplane) {
- mWifiState.set(WIFI_DISABLED_AIRPLANE_ON);
+ mPersistWifiState.set(WIFI_DISABLED_AIRPLANE_ON);
} else {
- mWifiState.set(WIFI_DISABLED);
+ mPersistWifiState.set(WIFI_DISABLED);
}
}
- Settings.Secure.putInt(cr, Settings.Secure.WIFI_ON, mWifiState.get());
+
+ Settings.Secure.putInt(cr, Settings.Secure.WIFI_ON, mPersistWifiState.get());
}
@@ -545,7 +555,6 @@
*/
public synchronized boolean setWifiEnabled(boolean enable) {
enforceChangePermission();
-
if (DBG) {
Slog.e(TAG, "Invoking mWifiStateMachine.setWifiEnabled\n");
}
@@ -559,16 +568,20 @@
* Caller might not have WRITE_SECURE_SETTINGS,
* only CHANGE_WIFI_STATE is enforced
*/
- long ident = Binder.clearCallingIdentity();
- persistWifiEnabled(enable);
- Binder.restoreCallingIdentity(ident);
+
+ /* Avoids overriding of airplane state when wifi is already in the expected state */
+ if (enable != mWifiEnabled) {
+ long ident = Binder.clearCallingIdentity();
+ persistWifiState(enable);
+ Binder.restoreCallingIdentity(ident);
+ }
if (enable) {
if (!mIsReceiverRegistered) {
registerForBroadcasts();
mIsReceiverRegistered = true;
}
- } else if (mIsReceiverRegistered){
+ } else if (mIsReceiverRegistered) {
mContext.unregisterReceiver(mReceiver);
mIsReceiverRegistered = false;
}
@@ -840,7 +853,7 @@
* of WifiLock & device idle status unless wifi enabled status is toggled
*/
- mWifiStateMachine.setDriverStart(true);
+ mWifiStateMachine.setDriverStart(true, mEmergencyCallbackMode);
mWifiStateMachine.reconnectCommand();
}
@@ -854,7 +867,7 @@
* TODO: if a stop is issued, wifi is brought up only by startWifi
* unless wifi enabled status is toggled
*/
- mWifiStateMachine.setDriverStart(false);
+ mWifiStateMachine.setDriverStart(false, mEmergencyCallbackMode);
}
@@ -1074,11 +1087,11 @@
mWifiStateMachine.setWifiEnabled(true);
mWifiStateMachine.setScanOnlyMode(
strongestLockMode == WifiManager.WIFI_MODE_SCAN_ONLY);
- mWifiStateMachine.setDriverStart(true);
+ mWifiStateMachine.setDriverStart(true, mEmergencyCallbackMode);
mWifiStateMachine.setHighPerfModeEnabled(strongestLockMode
== WifiManager.WIFI_MODE_FULL_HIGH_PERF);
} else {
- mWifiStateMachine.setDriverStart(false);
+ mWifiStateMachine.setDriverStart(false, mEmergencyCallbackMode);
}
} else {
mWifiStateMachine.setWifiEnabled(false);
diff --git a/services/java/com/android/server/connectivity/Vpn.java b/services/java/com/android/server/connectivity/Vpn.java
index 55e0678..72cf512 100644
--- a/services/java/com/android/server/connectivity/Vpn.java
+++ b/services/java/com/android/server/connectivity/Vpn.java
@@ -482,6 +482,7 @@
if (state.exists()) {
throw new IllegalStateException("Cannot delete the state");
}
+ new File("/data/misc/vpn/abort").delete();
// Check if we need to restart any of the daemons.
boolean restart = false;
diff --git a/services/java/com/android/server/location/ComprehensiveCountryDetector.java b/services/java/com/android/server/location/ComprehensiveCountryDetector.java
index bb9e60f..f068b44 100755
--- a/services/java/com/android/server/location/ComprehensiveCountryDetector.java
+++ b/services/java/com/android/server/location/ComprehensiveCountryDetector.java
@@ -66,26 +66,12 @@
protected CountryDetectorBase mLocationBasedCountryDetector;
protected Timer mLocationRefreshTimer;
- private final int mPhoneType;
private Country mCountry;
- private TelephonyManager mTelephonyManager;
+ private final TelephonyManager mTelephonyManager;
private Country mCountryFromLocation;
private boolean mStopped = false;
- private ServiceState mLastState;
- private PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
- @Override
- public void onServiceStateChanged(ServiceState serviceState) {
- // TODO: Find out how often we will be notified, if this method is called too
- // many times, let's consider querying the network.
- Slog.d(TAG, "onServiceStateChanged");
- // We only care the state change
- if (mLastState == null || mLastState.getState() != serviceState.getState()) {
- detectCountry(true, true);
- mLastState = new ServiceState(serviceState);
- }
- }
- };
+ private PhoneStateListener mPhoneStateListener;
/**
* The listener for receiving the notification from LocationBasedCountryDetector.
@@ -104,7 +90,6 @@
public ComprehensiveCountryDetector(Context context) {
super(context);
mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
- mPhoneType = mTelephonyManager.getPhoneType();
}
@Override
@@ -115,6 +100,7 @@
@Override
public void stop() {
+ // Note: this method in this subclass called only by tests.
Slog.i(TAG, "Stop the detector.");
cancelLocationRefresh();
removePhoneStateListener();
@@ -141,14 +127,20 @@
return result;
}
+ private boolean isNetworkCountryCodeAvailable() {
+ // On CDMA TelephonyManager.getNetworkCountryIso() just returns SIM country. We don't want
+ // to prioritize it over location based country, so ignore it.
+ final int phoneType = mTelephonyManager.getPhoneType();
+ if (DEBUG) Slog.v(TAG, " phonetype=" + phoneType);
+ return phoneType == TelephonyManager.PHONE_TYPE_GSM;
+ }
+
/**
* @return the country from the mobile network.
*/
protected Country getNetworkBasedCountry() {
String countryIso = null;
- // TODO: The document says the result may be unreliable on CDMA networks. Shall we use
- // it on CDMA phone? We may test the Android primarily used countries.
- if (mPhoneType == TelephonyManager.PHONE_TYPE_GSM) {
+ if (isNetworkCountryCodeAvailable()) {
countryIso = mTelephonyManager.getNetworkCountryIso();
if (!TextUtils.isEmpty(countryIso)) {
return new Country(countryIso, Country.COUNTRY_SOURCE_NETWORK);
@@ -356,20 +348,16 @@
}
protected synchronized void addPhoneStateListener() {
- if (mPhoneStateListener == null && mPhoneType == TelephonyManager.PHONE_TYPE_GSM) {
- mLastState = null;
+ if (mPhoneStateListener == null) {
mPhoneStateListener = new PhoneStateListener() {
@Override
public void onServiceStateChanged(ServiceState serviceState) {
- // TODO: Find out how often we will be notified, if this
- // method is called too
- // many times, let's consider querying the network.
- Slog.d(TAG, "onServiceStateChanged");
- // We only care the state change
- if (mLastState == null || mLastState.getState() != serviceState.getState()) {
- detectCountry(true, true);
- mLastState = new ServiceState(serviceState);
+ if (!isNetworkCountryCodeAvailable()) {
+ return;
}
+ if (DEBUG) Slog.d(TAG, "onServiceStateChanged: " + serviceState.getState());
+
+ detectCountry(true, true);
}
};
mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_SERVICE_STATE);
diff --git a/services/tests/servicestests/src/com/android/server/location/LocationBasedCountryDetectorTest.java b/services/tests/servicestests/src/com/android/server/location/LocationBasedCountryDetectorTest.java
index 60677df..5f5d668 100755
--- a/services/tests/servicestests/src/com/android/server/location/LocationBasedCountryDetectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/location/LocationBasedCountryDetectorTest.java
@@ -213,7 +213,7 @@
// QueryThread should be set to NULL
assertNull(detector.getQueryThread());
assertTrue(countryListener.notified());
- assertEquals(countryListener.getCountry(), country);
+ assertEquals("us", countryListener.getCountry().toLowerCase());
}
public void testFindingCountryCancelled() {
@@ -238,7 +238,7 @@
// QueryThread should be set to NULL
assertNull(detector.getQueryThread());
assertTrue(countryListener.notified());
- assertEquals(countryListener.getCountry(), country);
+ assertEquals("us", countryListener.getCountry().toLowerCase());
}
public void testFindingLocationCancelled() {
@@ -339,7 +339,7 @@
assertNull(detector.getQueryThread());
// CountryListener should be notified
assertTrue(countryListener.notified());
- assertEquals(countryListener.getCountry(), country);
+ assertEquals("us", countryListener.getCountry().toLowerCase());
}
private void waitForTimerReset(TestCountryDetector detector) {
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index b609ba9..5437caa 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -368,6 +368,10 @@
private static final int SUCCESS = 1;
private static final int FAILURE = -1;
+ /* Phone in emergency call back mode */
+ private static final int IN_ECM_STATE = 1;
+ private static final int NOT_IN_ECM_STATE = 0;
+
/**
* The maximum number of times we will retry a connection to an access point
* for which we have failed in acquiring an IP address from DHCP. A value of
@@ -773,11 +777,11 @@
/**
* TODO: doc
*/
- public void setDriverStart(boolean enable) {
+ public void setDriverStart(boolean enable, boolean ecm) {
if (enable) {
sendMessage(CMD_START_DRIVER);
} else {
- sendMessage(CMD_STOP_DRIVER);
+ sendMessage(obtainMessage(CMD_STOP_DRIVER, ecm ? IN_ECM_STATE : NOT_IN_ECM_STATE, 0));
}
}
@@ -2567,16 +2571,25 @@
WifiNative.setBluetoothCoexistenceScanModeCommand(mBluetoothConnectionActive);
break;
case CMD_STOP_DRIVER:
- /* Already doing a delayed stop */
- if (mInDelayedStop) {
+ int mode = message.arg1;
+
+ /* Already doing a delayed stop && not in ecm state */
+ if (mInDelayedStop && mode != IN_ECM_STATE) {
if (DBG) log("Already in delayed stop");
break;
}
mInDelayedStop = true;
mDelayedStopCounter++;
if (DBG) log("Delayed stop message " + mDelayedStopCounter);
- sendMessageDelayed(obtainMessage(CMD_DELAYED_STOP_DRIVER, mDelayedStopCounter,
- 0), DELAYED_DRIVER_STOP_MS);
+
+ if (mode == IN_ECM_STATE) {
+ /* send a shut down immediately */
+ sendMessage(obtainMessage(CMD_DELAYED_STOP_DRIVER, mDelayedStopCounter, 0));
+ } else {
+ /* send regular delayed shut down */
+ sendMessageDelayed(obtainMessage(CMD_DELAYED_STOP_DRIVER,
+ mDelayedStopCounter, 0), DELAYED_DRIVER_STOP_MS);
+ }
break;
case CMD_START_DRIVER:
if (mInDelayedStop) {