Merge "Support for parsing of "folded" RTSP header values and some tweaks to the AMR assembler"
diff --git a/api/current.txt b/api/current.txt
index 9610853..9eb2075 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -4244,6 +4244,7 @@
method public int getProfileConnectionState(int);
method public boolean getProfileProxy(android.content.Context, android.bluetooth.BluetoothProfile.ServiceListener, int);
method public android.bluetooth.BluetoothDevice getRemoteDevice(java.lang.String);
+ method public android.bluetooth.BluetoothDevice getRemoteDevice(byte[]);
method public int getScanMode();
method public int getState();
method public boolean isDiscovering();
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 5f5ba50..e420bfd 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -399,6 +399,25 @@
}
/**
+ * Get a {@link BluetoothDevice} object for the given Bluetooth hardware
+ * address.
+ * <p>Valid Bluetooth hardware addresses must be 6 bytes. This method
+ * expects the address in network byte order (MSB first).
+ * <p>A {@link BluetoothDevice} will always be returned for a valid
+ * hardware address, even if this adapter has never seen that device.
+ *
+ * @param address Bluetooth MAC address (6 bytes)
+ * @throws IllegalArgumentException if address is invalid
+ */
+ public BluetoothDevice getRemoteDevice(byte[] address) {
+ if (address == null || address.length != 6) {
+ throw new IllegalArgumentException("Bluetooth address must have 6 bytes");
+ }
+ return new BluetoothDevice(String.format("%02X:%02X:%02X:%02X:%02X:%02X",
+ address[0], address[1], address[2], address[3], address[4], address[5]));
+ }
+
+ /**
* Return true if Bluetooth is currently enabled and ready for use.
* <p>Equivalent to:
* <code>getBluetoothState() == STATE_ON</code>
@@ -1281,7 +1300,7 @@
}
/**
- * Validate a Bluetooth address, such as "00:43:A8:23:10:F0"
+ * Validate a String Bluetooth address, such as "00:43:A8:23:10:F0"
* <p>Alphabetic characters must be uppercase to be valid.
*
* @param address Bluetooth address as string
diff --git a/core/java/android/inputmethodservice/ExtractEditText.java b/core/java/android/inputmethodservice/ExtractEditText.java
index 72431f3..10c1195 100644
--- a/core/java/android/inputmethodservice/ExtractEditText.java
+++ b/core/java/android/inputmethodservice/ExtractEditText.java
@@ -158,25 +158,46 @@
}
/**
- * Delete the range of text, supposedly valid
+ * {@inheritDoc}
* @hide
*/
@Override
protected void deleteText_internal(int start, int end) {
- // Do not call the super method. This will change the source TextView instead, which
- // will update the ExtractTextView.
+ // Do not call the super method.
+ // This will change the source TextView instead, which will update the ExtractTextView.
mIME.onExtractedDeleteText(start, end);
}
/**
- * Replaces the range of text [start, end[ by replacement text
+ * {@inheritDoc}
* @hide
*/
@Override
protected void replaceText_internal(int start, int end, CharSequence text) {
- // Do not call the super method. This will change the source TextView instead, which
- // will update the ExtractTextView.
+ // Do not call the super method.
+ // This will change the source TextView instead, which will update the ExtractTextView.
mIME.onExtractedReplaceText(start, end, text);
}
+ /**
+ * {@inheritDoc}
+ * @hide
+ */
+ @Override
+ protected void setSpan_internal(Object span, int start, int end, int flags) {
+ // Do not call the super method.
+ // This will change the source TextView instead, which will update the ExtractTextView.
+ mIME.onExtractedSetSpan(span, start, end, flags);
+ }
+
+ /**
+ * {@inheritDoc}
+ * @hide
+ */
+ @Override
+ protected void setCursorPosition_internal(int start, int end) {
+ // Do not call the super method.
+ // This will change the source TextView instead, which will update the ExtractTextView.
+ mIME.onExtractedSelectionChanged(start, end);
+ }
}
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 02839db..53cdf21 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -2006,6 +2006,22 @@
}
/**
+ * @hide
+ */
+ public void onExtractedSetSpan(Object span, int start, int end, int flags) {
+ InputConnection conn = getCurrentInputConnection();
+ if (conn != null) {
+ if (!conn.setSelection(start, end)) return;
+ CharSequence text = conn.getSelectedText(InputConnection.GET_TEXT_WITH_STYLES);
+ if (text instanceof Spannable) {
+ ((Spannable) text).setSpan(span, 0, text.length(), flags);
+ conn.setComposingRegion(start, end);
+ conn.commitText(text, 1);
+ }
+ }
+ }
+
+ /**
* This is called when the user has clicked on the extracted text view,
* when running in fullscreen mode. The default implementation hides
* the candidates view when this happens, but only if the extracted text
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/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/text/style/SuggestionSpan.java b/core/java/android/text/style/SuggestionSpan.java
index ed2af10..0f26a34 100644
--- a/core/java/android/text/style/SuggestionSpan.java
+++ b/core/java/android/text/style/SuggestionSpan.java
@@ -92,11 +92,6 @@
private float mAutoCorrectionUnderlineThickness;
private int mAutoCorrectionUnderlineColor;
- /*
- * TODO: If switching IME is required, needs to add parameters for ids of InputMethodInfo
- * and InputMethodSubtype.
- */
-
/**
* @param context Context for the application
* @param suggestions Suggestions for the string under the span
@@ -146,6 +141,16 @@
}
private void initStyle(Context context) {
+ if (context == null) {
+ mMisspelledUnderlineThickness = 0;
+ mEasyCorrectUnderlineThickness = 0;
+ mAutoCorrectionUnderlineThickness = 0;
+ mMisspelledUnderlineColor = Color.BLACK;
+ mEasyCorrectUnderlineColor = Color.BLACK;
+ mAutoCorrectionUnderlineColor = Color.BLACK;
+ return;
+ }
+
int defStyle = com.android.internal.R.attr.textAppearanceMisspelledSuggestion;
TypedArray typedArray = context.obtainStyledAttributes(
null, com.android.internal.R.styleable.SuggestionSpan, defStyle, 0);
@@ -169,7 +174,6 @@
com.android.internal.R.styleable.SuggestionSpan_textUnderlineThickness, 0);
mAutoCorrectionUnderlineColor = typedArray.getColor(
com.android.internal.R.styleable.SuggestionSpan_textUnderlineColor, Color.BLACK);
-
}
public SuggestionSpan(Parcel src) {
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 7a9d82c..72966ef4 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -3257,8 +3257,9 @@
}
// If the Control modifier is held, try to interpret the key as a shortcut.
- if (event.getAction() == KeyEvent.ACTION_UP
+ if (event.getAction() == KeyEvent.ACTION_DOWN
&& event.isCtrlPressed()
+ && event.getRepeatCount() == 0
&& !KeyEvent.isModifierKey(event.getKeyCode())) {
if (mView.dispatchKeyShortcutEvent(event)) {
finishInputEvent(q, true);
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 babd8e7..5b73a74 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -5517,7 +5517,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 +5554,7 @@
* call performClick(), but that won't do anything in
* this case.)
*/
- if (hasOnClickListeners()) {
+ if (!hasOnClickListeners()) {
View v = focusSearch(FOCUS_DOWN);
if (v != null) {
@@ -9835,7 +9835,7 @@
highlightTextDifferences(mSuggestionInfos[i], spanUnionStart, spanUnionEnd);
}
- // Add to dictionary item is there a span with the misspelled flag
+ // Add to dictionary item if there is a span with the misspelled flag
if (misspelledSpan != null) {
final int misspelledStart = spannable.getSpanStart(misspelledSpan);
final int misspelledEnd = spannable.getSpanEnd(misspelledSpan);
@@ -9921,7 +9921,7 @@
final int spanStart = editable.getSpanStart(suggestionInfo.suggestionSpan);
final int spanEnd = editable.getSpanEnd(suggestionInfo.suggestionSpan);
- if (spanStart < 0 || spanEnd < 0) {
+ if (spanStart < 0 || spanEnd <= spanStart) {
// Span has been removed
hide();
return;
@@ -9989,14 +9989,14 @@
// way to assign them a valid range after replacement
if (suggestionSpansStarts[i] <= spanStart &&
suggestionSpansEnds[i] >= spanEnd) {
- // TODO The ExtractEditText should restore these spans in the original text
- editable.setSpan(suggestionSpans[i], suggestionSpansStarts[i],
+ setSpan_internal(suggestionSpans[i], suggestionSpansStarts[i],
suggestionSpansEnds[i] + lengthDifference, suggestionSpansFlags[i]);
}
}
// Move cursor at the end of the replaced word
- Selection.setSelection(editable, spanEnd + lengthDifference);
+ final int newCursorPosition = spanEnd + lengthDifference;
+ setCursorPosition_internal(newCursorPosition, newCursorPosition);
}
hide();
@@ -11469,6 +11469,22 @@
((Editable) mText).replace(start, end, text);
}
+ /**
+ * Sets a span on the specified range of text
+ * @hide
+ */
+ protected void setSpan_internal(Object span, int start, int end, int flags) {
+ ((Editable) mText).setSpan(span, start, end, flags);
+ }
+
+ /**
+ * Moves the cursor to the specified offset position in text
+ * @hide
+ */
+ protected void setCursorPosition_internal(int start, int end) {
+ Selection.setSelection(((Editable) mText), start, end);
+ }
+
@ViewDebug.ExportedProperty(category = "text")
private CharSequence mText;
private CharSequence mTransformed;
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/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index b18d88f..fe5388b 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -810,7 +810,7 @@
<!-- Special theme for the recent apps dialog, to allow customization
with overlays. -->
- <style name="Theme.Dialog.RecentApplications">
+ <style name="Theme.Dialog.RecentApplications" parent="Theme.DeviceDefault.Dialog">
<item name="windowFrame">@null</item>
<item name="windowBackground">@android:color/transparent</item>
<item name="android:windowAnimationStyle">@android:style/Animation.RecentApplications</item>
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/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 964cb1f..8405264 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -2091,7 +2091,7 @@
String8 mimeType;
float confidence;
sp<AMessage> dummy;
- bool success = SniffDRM(dataSource, &mimeType, &confidence, &dummy);
+ bool success = SniffWVM(dataSource, &mimeType, &confidence, &dummy);
if (!success
|| strcasecmp(
@@ -2099,6 +2099,8 @@
return ERROR_UNSUPPORTED;
}
+ dataSource->DrmInitialization();
+
mWVMExtractor = new WVMExtractor(dataSource);
mWVMExtractor->setAdaptiveStreamingMode(true);
extractor = mWVMExtractor;
diff --git a/media/libstagefright/DRMExtractor.cpp b/media/libstagefright/DRMExtractor.cpp
index 1f3d581..afc4a80 100644
--- a/media/libstagefright/DRMExtractor.cpp
+++ b/media/libstagefright/DRMExtractor.cpp
@@ -282,13 +282,13 @@
if (decryptHandle != NULL) {
if (decryptHandle->decryptApiType == DecryptApiType::CONTAINER_BASED) {
*mimeType = String8("drm+container_based+") + decryptHandle->mimeType;
+ *confidence = 10.0f;
} else if (decryptHandle->decryptApiType == DecryptApiType::ELEMENTARY_STREAM_BASED) {
*mimeType = String8("drm+es_based+") + decryptHandle->mimeType;
- } else if (decryptHandle->decryptApiType == DecryptApiType::WV_BASED) {
- *mimeType = MEDIA_MIMETYPE_CONTAINER_WVM;
- LOGW("SniffWVM: found match\n");
+ *confidence = 10.0f;
+ } else {
+ return false;
}
- *confidence = 10.0f;
return true;
}
diff --git a/media/libstagefright/DataSource.cpp b/media/libstagefright/DataSource.cpp
index e471f73..d0a7880 100644
--- a/media/libstagefright/DataSource.cpp
+++ b/media/libstagefright/DataSource.cpp
@@ -32,6 +32,7 @@
#include "include/DRMExtractor.h"
#include "include/FLACExtractor.h"
#include "include/AACExtractor.h"
+#include "include/WVMExtractor.h"
#include "matroska/MatroskaExtractor.h"
@@ -120,6 +121,7 @@
RegisterSniffer(SniffAAC);
RegisterSniffer(SniffAVI);
RegisterSniffer(SniffMPEG2PS);
+ RegisterSniffer(SniffWVM);
char value[PROPERTY_VALUE_MAX];
if (property_get("drm.service.enabled", value, NULL)
diff --git a/media/libstagefright/WVMExtractor.cpp b/media/libstagefright/WVMExtractor.cpp
index 26eda0c..79dedca 100644
--- a/media/libstagefright/WVMExtractor.cpp
+++ b/media/libstagefright/WVMExtractor.cpp
@@ -45,17 +45,12 @@
static Mutex gWVMutex;
WVMExtractor::WVMExtractor(const sp<DataSource> &source)
- : mDataSource(source) {
- {
- Mutex::Autolock autoLock(gWVMutex);
- if (gVendorLibHandle == NULL) {
- gVendorLibHandle = dlopen("libwvm.so", RTLD_NOW);
- }
+ : mDataSource(source)
+{
+ Mutex::Autolock autoLock(gWVMutex);
- if (gVendorLibHandle == NULL) {
- LOGE("Failed to open libwvm.so");
- return;
- }
+ if (!getVendorLibHandle()) {
+ return;
}
typedef WVMLoadableExtractor *(*GetInstanceFunc)(sp<DataSource>);
@@ -71,6 +66,19 @@
}
}
+bool WVMExtractor::getVendorLibHandle()
+{
+ if (gVendorLibHandle == NULL) {
+ gVendorLibHandle = dlopen("libwvm.so", RTLD_NOW);
+ }
+
+ if (gVendorLibHandle == NULL) {
+ LOGE("Failed to open libwvm.so");
+ }
+
+ return gVendorLibHandle != NULL;
+}
+
WVMExtractor::~WVMExtractor() {
}
@@ -113,5 +121,33 @@
}
}
+bool SniffWVM(
+ const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ sp<AMessage> *) {
+
+ Mutex::Autolock autoLock(gWVMutex);
+
+ if (!WVMExtractor::getVendorLibHandle()) {
+ return false;
+ }
+
+ typedef WVMLoadableExtractor *(*SnifferFunc)(sp<DataSource>);
+ SnifferFunc snifferFunc =
+ (SnifferFunc) dlsym(gVendorLibHandle,
+ "_ZN7android15IsWidevineMediaENS_2spINS_10DataSourceEEE");
+
+ if (snifferFunc) {
+ if ((*snifferFunc)(source)) {
+ *mimeType = MEDIA_MIMETYPE_CONTAINER_WVM;
+ *confidence = 10.0f;
+ return true;
+ }
+ } else {
+ LOGE("IsWidevineMedia not found in libwvm.so");
+ }
+
+ return false;
+}
+
} //namespace android
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/include/WVMExtractor.h b/media/libstagefright/include/WVMExtractor.h
index deecd25..9f763f9 100644
--- a/media/libstagefright/include/WVMExtractor.h
+++ b/media/libstagefright/include/WVMExtractor.h
@@ -23,6 +23,8 @@
namespace android {
+struct AMessage;
+class String8;
class DataSource;
class WVMLoadableExtractor : public MediaExtractor {
@@ -58,6 +60,8 @@
// is used.
void setAdaptiveStreamingMode(bool adaptive);
+ static bool getVendorLibHandle();
+
protected:
virtual ~WVMExtractor();
@@ -69,6 +73,10 @@
WVMExtractor &operator=(const WVMExtractor &);
};
+bool SniffWVM(
+ const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ sp<AMessage> *);
+
} // namespace android
#endif // DRM_EXTRACTOR_H_
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/nfc-extras/tests/src/com/android/nfc_extras/BasicNfcEeTest.java b/nfc-extras/tests/src/com/android/nfc_extras/tests/BasicNfcEeTest.java
similarity index 97%
rename from nfc-extras/tests/src/com/android/nfc_extras/BasicNfcEeTest.java
rename to nfc-extras/tests/src/com/android/nfc_extras/tests/BasicNfcEeTest.java
index e1025aa..389dfbe 100644
--- a/nfc-extras/tests/src/com/android/nfc_extras/BasicNfcEeTest.java
+++ b/nfc-extras/tests/src/com/android/nfc_extras/tests/BasicNfcEeTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.nfc_extras;
+package com.android.nfc_extras.tests;
import android.content.Context;
import android.nfc.NfcAdapter;
@@ -48,7 +48,7 @@
@Override
protected void setUp() throws Exception {
super.setUp();
- mContext = getInstrumentation().getContext();
+ mContext = getInstrumentation().getTargetContext();
mAdapterExtras = NfcAdapterExtras.get(NfcAdapter.getDefaultAdapter(mContext));
mEe = mAdapterExtras.getEmbeddedExecutionEnvironment();
}
diff --git a/opengl/libs/ETC1/etc1.cpp b/opengl/libs/ETC1/etc1.cpp
index 5ed2c3c..97d1085 100644
--- a/opengl/libs/ETC1/etc1.cpp
+++ b/opengl/libs/ETC1/etc1.cpp
@@ -149,13 +149,13 @@
static
inline int convert8To4(int b) {
int c = b & 0xff;
- return divideBy255(b * 15);
+ return divideBy255(c * 15);
}
static
inline int convert8To5(int b) {
int c = b & 0xff;
- return divideBy255(b * 31);
+ return divideBy255(c * 31);
}
static
diff --git a/policy/src/com/android/internal/policy/impl/IconUtilities.java b/policy/src/com/android/internal/policy/impl/IconUtilities.java
index 4564f90..e997355 100644
--- a/policy/src/com/android/internal/policy/impl/IconUtilities.java
+++ b/policy/src/com/android/internal/policy/impl/IconUtilities.java
@@ -38,6 +38,8 @@
import android.text.TextPaint;
import android.util.DisplayMetrics;
import android.util.Log;
+import android.util.TypedValue;
+import android.view.ContextThemeWrapper;
import android.content.res.Resources;
import android.content.Context;
@@ -74,9 +76,13 @@
mIconTextureWidth = mIconTextureHeight = mIconWidth + (int)(blurPx*2);
mBlurPaint.setMaskFilter(new BlurMaskFilter(blurPx, BlurMaskFilter.Blur.NORMAL));
- mGlowColorPressedPaint.setColor(0xffffc300);
+
+ TypedValue value = new TypedValue();
+ mGlowColorPressedPaint.setColor(context.getTheme().resolveAttribute(
+ android.R.attr.colorPressedHighlight, value, true) ? value.data : 0xffffc300);
mGlowColorPressedPaint.setMaskFilter(TableMaskFilter.CreateClipTable(0, 30));
- mGlowColorFocusedPaint.setColor(0xffff8e00);
+ mGlowColorFocusedPaint.setColor(context.getTheme().resolveAttribute(
+ android.R.attr.colorFocusedHighlight, value, true) ? value.data : 0xffff8e00);
mGlowColorFocusedPaint.setMaskFilter(TableMaskFilter.CreateClipTable(0, 30));
ColorMatrix cm = new ColorMatrix();
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/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index af86ae9..535f039 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -1816,22 +1816,42 @@
@Override
public boolean dispatchKeyShortcutEvent(KeyEvent ev) {
- // Perform the shortcut (mPreparedPanel can be null since
- // global shortcuts (such as search) don't rely on a
- // prepared panel or menu).
- boolean handled = performPanelShortcut(mPreparedPanel, ev.getKeyCode(), ev,
- Menu.FLAG_PERFORM_NO_CLOSE);
- if (handled) {
- if (mPreparedPanel != null) {
- mPreparedPanel.isHandled = true;
+ // If the panel is already prepared, then perform the shortcut using it.
+ boolean handled;
+ if (mPreparedPanel != null) {
+ handled = performPanelShortcut(mPreparedPanel, ev.getKeyCode(), ev,
+ Menu.FLAG_PERFORM_NO_CLOSE);
+ if (handled) {
+ if (mPreparedPanel != null) {
+ mPreparedPanel.isHandled = true;
+ }
+ return true;
}
- return true;
}
// Shortcut not handled by the panel. Dispatch to the view hierarchy.
final Callback cb = getCallback();
- return cb != null && !isDestroyed() && mFeatureId < 0 ? cb.dispatchKeyShortcutEvent(ev)
- : super.dispatchKeyShortcutEvent(ev);
+ handled = cb != null && !isDestroyed() && mFeatureId < 0
+ ? cb.dispatchKeyShortcutEvent(ev) : super.dispatchKeyShortcutEvent(ev);
+ if (handled) {
+ return true;
+ }
+
+ // If the panel is not prepared, then we may be trying to handle a shortcut key
+ // combination such as Control+C. Temporarily prepare the panel then mark it
+ // unprepared again when finished to ensure that the panel will again be prepared
+ // the next time it is shown for real.
+ if (mPreparedPanel == null) {
+ PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, true);
+ preparePanel(st, ev);
+ handled = performPanelShortcut(st, ev.getKeyCode(), ev,
+ Menu.FLAG_PERFORM_NO_CLOSE);
+ st.isPrepared = false;
+ if (handled) {
+ return true;
+ }
+ }
+ return false;
}
@Override
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 92260d6..0a5a765 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -301,9 +301,15 @@
GlobalActions mGlobalActions;
volatile boolean mPowerKeyHandled; // accessed from input reader and handler thread
boolean mPendingPowerKeyUpCanceled;
- RecentApplicationsDialog mRecentAppsDialog;
Handler mHandler;
+ static final int RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS = 0;
+ static final int RECENT_APPS_BEHAVIOR_EXIT_TOUCH_MODE_AND_SHOW = 1;
+ static final int RECENT_APPS_BEHAVIOR_DISMISS_AND_SWITCH = 2;
+
+ RecentApplicationsDialog mRecentAppsDialog;
+ int mRecentAppsDialogHeldModifiers;
+
private static final int LID_ABSENT = -1;
private static final int LID_CLOSED = 0;
private static final int LID_OPEN = 1;
@@ -715,7 +721,7 @@
}
if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_DIALOG) {
- showOrHideRecentAppsDialog(0, true /*dismissIfShown*/);
+ showOrHideRecentAppsDialog(RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS);
} else if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_SYSTEM_UI) {
try {
mStatusBarService.toggleRecentApps();
@@ -726,10 +732,10 @@
}
/**
- * Create (if necessary) and launch the recent apps dialog, or hide it if it is
- * already shown.
+ * Create (if necessary) and show or dismiss the recent apps dialog according
+ * according to the requested behavior.
*/
- void showOrHideRecentAppsDialog(final int heldModifiers, final boolean dismissIfShown) {
+ void showOrHideRecentAppsDialog(final int behavior) {
mHandler.post(new Runnable() {
@Override
public void run() {
@@ -737,12 +743,33 @@
mRecentAppsDialog = new RecentApplicationsDialog(mContext);
}
if (mRecentAppsDialog.isShowing()) {
- if (dismissIfShown) {
- mRecentAppsDialog.dismiss();
+ switch (behavior) {
+ case RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS:
+ mRecentAppsDialog.dismiss();
+ break;
+ case RECENT_APPS_BEHAVIOR_DISMISS_AND_SWITCH:
+ mRecentAppsDialog.dismissAndSwitch();
+ break;
+ case RECENT_APPS_BEHAVIOR_EXIT_TOUCH_MODE_AND_SHOW:
+ default:
+ break;
}
} else {
- mRecentAppsDialog.setHeldModifiers(heldModifiers);
- mRecentAppsDialog.show();
+ switch (behavior) {
+ case RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS:
+ mRecentAppsDialog.show();
+ break;
+ case RECENT_APPS_BEHAVIOR_EXIT_TOUCH_MODE_AND_SHOW:
+ try {
+ mWindowManager.setInTouchMode(false);
+ } catch (RemoteException e) {
+ }
+ mRecentAppsDialog.show();
+ break;
+ case RECENT_APPS_BEHAVIOR_DISMISS_AND_SWITCH:
+ default:
+ break;
+ }
}
}
});
@@ -1649,7 +1676,7 @@
return 0;
} else if (keyCode == KeyEvent.KEYCODE_APP_SWITCH) {
if (down && repeatCount == 0) {
- showOrHideRecentAppsDialog(0, true /*dismissIfShown*/);
+ showOrHideRecentAppsDialog(RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS);
}
return -1;
}
@@ -1685,6 +1712,26 @@
}
}
+ // Invoke shortcuts using Meta.
+ if (down && repeatCount == 0
+ && (metaState & KeyEvent.META_META_ON) != 0) {
+ final KeyCharacterMap kcm = event.getKeyCharacterMap();
+ Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode,
+ metaState & ~(KeyEvent.META_META_ON
+ | KeyEvent.META_META_LEFT_ON | KeyEvent.META_META_RIGHT_ON));
+ if (shortcutIntent != null) {
+ shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ try {
+ mContext.startActivity(shortcutIntent);
+ } catch (ActivityNotFoundException ex) {
+ Slog.w(TAG, "Dropping shortcut key combination because "
+ + "the activity to which it is registered was not found: "
+ + "META+" + KeyEvent.keyCodeToString(keyCode), ex);
+ }
+ return -1;
+ }
+ }
+
// Handle application launch keys.
if (down && repeatCount == 0) {
String category = sApplicationLaunchKeyCategories.get(keyCode);
@@ -1698,9 +1745,29 @@
+ "the activity to which it is registered was not found: "
+ "keyCode=" + keyCode + ", category=" + category, ex);
}
+ return -1;
}
}
+ // Display task switcher for ALT-TAB or Meta-TAB.
+ if (down && repeatCount == 0 && keyCode == KeyEvent.KEYCODE_TAB) {
+ if (mRecentAppsDialogHeldModifiers == 0) {
+ final int shiftlessModifiers = event.getModifiers() & ~KeyEvent.META_SHIFT_MASK;
+ if (KeyEvent.metaStateHasModifiers(shiftlessModifiers, KeyEvent.META_ALT_ON)
+ || KeyEvent.metaStateHasModifiers(
+ shiftlessModifiers, KeyEvent.META_META_ON)) {
+ mRecentAppsDialogHeldModifiers = shiftlessModifiers;
+ showOrHideRecentAppsDialog(RECENT_APPS_BEHAVIOR_EXIT_TOUCH_MODE_AND_SHOW);
+ return -1;
+ }
+ }
+ } else if (!down && mRecentAppsDialogHeldModifiers != 0
+ && (metaState & mRecentAppsDialogHeldModifiers) == 0) {
+ mRecentAppsDialogHeldModifiers = 0;
+ showOrHideRecentAppsDialog(RECENT_APPS_BEHAVIOR_DISMISS_AND_SWITCH);
+ }
+
+ // Let the application handle the key.
return 0;
}
@@ -1722,39 +1789,6 @@
final KeyCharacterMap kcm = event.getKeyCharacterMap();
final int keyCode = event.getKeyCode();
final int metaState = event.getMetaState();
- final boolean initialDown = event.getAction() == KeyEvent.ACTION_DOWN
- && event.getRepeatCount() == 0;
-
- if (initialDown) {
- // Invoke shortcuts using Meta as a fallback.
- if ((metaState & KeyEvent.META_META_ON) != 0) {
- Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode,
- metaState & ~(KeyEvent.META_META_ON
- | KeyEvent.META_META_LEFT_ON | KeyEvent.META_META_RIGHT_ON));
- if (shortcutIntent != null) {
- shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- try {
- mContext.startActivity(shortcutIntent);
- } catch (ActivityNotFoundException ex) {
- Slog.w(TAG, "Dropping shortcut key combination because "
- + "the activity to which it is registered was not found: "
- + "META+" + KeyEvent.keyCodeToString(keyCode), ex);
- }
- return null;
- }
- }
-
- // Display task switcher for ALT-TAB or Meta-TAB.
- if (keyCode == KeyEvent.KEYCODE_TAB) {
- final int shiftlessModifiers = event.getModifiers() & ~KeyEvent.META_SHIFT_MASK;
- if (KeyEvent.metaStateHasModifiers(shiftlessModifiers, KeyEvent.META_ALT_ON)
- || KeyEvent.metaStateHasModifiers(
- shiftlessModifiers, KeyEvent.META_META_ON)) {
- showOrHideRecentAppsDialog(shiftlessModifiers, false /*dismissIfShown*/);
- return null;
- }
- }
- }
// Check for fallback actions specified by the key character map.
if (getFallbackAction(kcm, keyCode, metaState, mFallbackAction)) {
diff --git a/policy/src/com/android/internal/policy/impl/RecentApplicationsDialog.java b/policy/src/com/android/internal/policy/impl/RecentApplicationsDialog.java
index aa00fbdd..b9903dd 100644
--- a/policy/src/com/android/internal/policy/impl/RecentApplicationsDialog.java
+++ b/policy/src/com/android/internal/policy/impl/RecentApplicationsDialog.java
@@ -71,8 +71,6 @@
}
};
- private int mHeldModifiers;
-
public RecentApplicationsDialog(Context context) {
super(context, com.android.internal.R.style.Theme_Dialog_RecentApplications);
@@ -124,17 +122,6 @@
}
}
- /**
- * Sets the modifier keys that are being held to keep the dialog open, or 0 if none.
- * Used to make the recent apps dialog automatically dismiss itself when the modifiers
- * all go up.
- * @param heldModifiers The held key modifiers, such as {@link KeyEvent#META_ALT_ON}.
- * Should exclude shift.
- */
- public void setHeldModifiers(int heldModifiers) {
- mHeldModifiers = heldModifiers;
- }
-
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_TAB) {
@@ -174,30 +161,27 @@
return super.onKeyDown(keyCode, event);
}
- @Override
- public boolean onKeyUp(int keyCode, KeyEvent event) {
- if (mHeldModifiers != 0 && (event.getModifiers() & mHeldModifiers) == 0) {
- final int numIcons = mIcons.length;
- RecentTag tag = null;
- for (int i = 0; i < numIcons; i++) {
- if (mIcons[i].getVisibility() != View.VISIBLE) {
+ /**
+ * Dismiss the dialog and switch to the selected application.
+ */
+ public void dismissAndSwitch() {
+ final int numIcons = mIcons.length;
+ RecentTag tag = null;
+ for (int i = 0; i < numIcons; i++) {
+ if (mIcons[i].getVisibility() != View.VISIBLE) {
+ break;
+ }
+ if (i == 0 || mIcons[i].hasFocus()) {
+ tag = (RecentTag) mIcons[i].getTag();
+ if (mIcons[i].hasFocus()) {
break;
}
- if (i == 0 || mIcons[i].hasFocus()) {
- tag = (RecentTag) mIcons[i].getTag();
- if (mIcons[i].hasFocus()) {
- break;
- }
- }
}
- if (tag != null) {
- switchTo(tag);
- }
- dismiss();
- return true;
}
-
- return super.onKeyUp(keyCode, event);
+ if (tag != null) {
+ switchTo(tag);
+ }
+ dismiss();
}
/**
diff --git a/services/input/InputDispatcher.cpp b/services/input/InputDispatcher.cpp
index 382f4d9..5f31f05 100644
--- a/services/input/InputDispatcher.cpp
+++ b/services/input/InputDispatcher.cpp
@@ -4312,12 +4312,23 @@
mKeyMementos.removeAt(index);
return true;
}
+ /* FIXME: We can't just drop the key up event because that prevents creating
+ * popup windows that are automatically shown when a key is held and then
+ * dismissed when the key is released. The problem is that the popup will
+ * not have received the original key down, so the key up will be considered
+ * to be inconsistent with its observed state. We could perhaps handle this
+ * by synthesizing a key down but that will cause other problems.
+ *
+ * So for now, allow inconsistent key up events to be dispatched.
+ *
#if DEBUG_OUTBOUND_EVENT_DETAILS
LOGD("Dropping inconsistent key up event: deviceId=%d, source=%08x, "
"keyCode=%d, scanCode=%d",
entry->deviceId, entry->source, entry->keyCode, entry->scanCode);
#endif
return false;
+ */
+ return true;
}
case AKEY_EVENT_ACTION_DOWN: {
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index 16643ff..cb291ce 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -840,7 +840,7 @@
* of WifiLock & device idle status unless wifi enabled status is toggled
*/
- mWifiStateMachine.setDriverStart(true);
+ mWifiStateMachine.setDriverStart(true, mEmergencyCallbackMode);
mWifiStateMachine.reconnectCommand();
}
@@ -854,7 +854,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 +1074,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/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/WifiInfo.java b/wifi/java/android/net/wifi/WifiInfo.java
index d5b404e..7bb927b 100644
--- a/wifi/java/android/net/wifi/WifiInfo.java
+++ b/wifi/java/android/net/wifi/WifiInfo.java
@@ -70,7 +70,6 @@
private InetAddress mIpAddress;
private String mMacAddress;
- private boolean mExplicitConnect;
WifiInfo() {
mSSID = null;
@@ -80,7 +79,6 @@
mRssi = -9999;
mLinkSpeed = -1;
mHiddenSSID = false;
- mExplicitConnect = false;
}
/**
@@ -98,7 +96,6 @@
mLinkSpeed = source.mLinkSpeed;
mIpAddress = source.mIpAddress;
mMacAddress = source.mMacAddress;
- mExplicitConnect = source.mExplicitConnect;
}
}
@@ -175,22 +172,6 @@
mNetworkId = id;
}
-
- /**
- * @hide
- */
- public boolean isExplicitConnect() {
- return mExplicitConnect;
- }
-
- /**
- * @hide
- */
- public void setExplicitConnect(boolean explicitConnect) {
- this.mExplicitConnect = explicitConnect;
- }
-
-
/**
* Each configured network has a unique small integer ID, used to identify
* the network when performing operations on the supplicant. This method
@@ -279,8 +260,7 @@
append(mSupplicantState == null ? none : mSupplicantState).
append(", RSSI: ").append(mRssi).
append(", Link speed: ").append(mLinkSpeed).
- append(", Net ID: ").append(mNetworkId).
- append(", Explicit connect: ").append(mExplicitConnect);
+ append(", Net ID: ").append(mNetworkId);
return sb.toString();
}
@@ -304,7 +284,6 @@
dest.writeString(getSSID());
dest.writeString(mBSSID);
dest.writeString(mMacAddress);
- dest.writeByte(mExplicitConnect ? (byte)1 : (byte)0);
mSupplicantState.writeToParcel(dest, flags);
}
@@ -324,7 +303,6 @@
info.setSSID(in.readString());
info.mBSSID = in.readString();
info.mMacAddress = in.readString();
- info.mExplicitConnect = in.readByte() == 1 ? true : false;
info.mSupplicantState = SupplicantState.CREATOR.createFromParcel(in);
return info;
}
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index 920947f..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
@@ -533,11 +537,6 @@
private final WorkSource mLastRunningWifiUids = new WorkSource();
private final IBatteryStats mBatteryStats;
- private boolean mNextWifiActionExplicit = false;
- private int mLastExplicitNetworkId;
- private long mLastNetworkChoiceTime;
- private static final long EXPLICIT_CONNECT_ALLOWED_DELAY_MS = 2 * 60 * 1000;
-
public WifiStateMachine(Context context, String wlanInterface) {
super(TAG);
@@ -778,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));
}
}
@@ -1637,7 +1636,6 @@
mWifiInfo.setNetworkId(WifiConfiguration.INVALID_NETWORK_ID);
mWifiInfo.setRssi(MIN_RSSI);
mWifiInfo.setLinkSpeed(-1);
- mWifiInfo.setExplicitConnect(false);
/* send event to CM & network change broadcast */
setNetworkDetailedState(DetailedState.DISCONNECTED);
@@ -2573,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) {
@@ -2821,10 +2828,6 @@
mSupplicantStateTracker.sendMessage(CMD_CONNECT_NETWORK);
WifiNative.reconnectCommand();
- mLastExplicitNetworkId = netId;
- mLastNetworkChoiceTime = SystemClock.elapsedRealtime();
- mNextWifiActionExplicit = true;
- if (DBG) log("Setting wifi connect explicit for netid " + netId);
/* Expect a disconnection from the old connection */
transitionTo(mDisconnectingState);
break;
@@ -2846,13 +2849,6 @@
mWifiInfo.setSSID(fetchSSID());
mWifiInfo.setBSSID(mLastBssid);
mWifiInfo.setNetworkId(mLastNetworkId);
- if (mNextWifiActionExplicit &&
- mWifiInfo.getNetworkId() == mLastExplicitNetworkId &&
- SystemClock.elapsedRealtime() < mLastNetworkChoiceTime +
- EXPLICIT_CONNECT_ALLOWED_DELAY_MS) {
- mWifiInfo.setExplicitConnect(true);
- }
- mNextWifiActionExplicit = false;
/* send event to CM & network change broadcast */
setNetworkDetailedState(DetailedState.OBTAINING_IPADDR);
sendNetworkStateChangeBroadcast(mLastBssid);
diff --git a/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java b/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java
index b27c60f..0ca3852 100644
--- a/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java
@@ -1030,7 +1030,7 @@
mHasConnectedWifiManager = true;
}
mWifiManager.disableNetwork(networkId, WifiConfiguration.DISABLED_DNS_FAILURE);
- if (mShowDisabledNotification && mConnectionInfo.isExplicitConnect()) {
+ if (mShowDisabledNotification) {
setDisabledNetworkNotificationVisible(true);
}
transitionTo(mNotConnectedState);