Merge "Fix for IOOBoundsExc in SpannableStringBuilder"
diff --git a/core/java/android/accounts/AccountManagerService.java b/core/java/android/accounts/AccountManagerService.java
index e6b1c08..8471df9 100644
--- a/core/java/android/accounts/AccountManagerService.java
+++ b/core/java/android/accounts/AccountManagerService.java
@@ -520,6 +520,18 @@
if (account == null) throw new IllegalArgumentException("account is null");
checkManageAccountsPermission();
long identityToken = clearCallingIdentity();
+
+ cancelNotification(getSigninRequiredNotificationId(account));
+ synchronized(mCredentialsPermissionNotificationIds) {
+ for (Pair<Pair<Account, String>, Integer> pair:
+ mCredentialsPermissionNotificationIds.keySet()) {
+ if (account.equals(pair.first.first)) {
+ int id = mCredentialsPermissionNotificationIds.get(pair);
+ cancelNotification(id);
+ }
+ }
+ }
+
try {
new RemoveAccountSession(response, account).bind();
} finally {
diff --git a/core/java/android/content/ContentQueryMap.java b/core/java/android/content/ContentQueryMap.java
index c955094..8aeaa8f 100644
--- a/core/java/android/content/ContentQueryMap.java
+++ b/core/java/android/content/ContentQueryMap.java
@@ -33,7 +33,7 @@
* The cursor data is accessed by row key and column name via getValue().
*/
public class ContentQueryMap extends Observable {
- private Cursor mCursor;
+ private volatile Cursor mCursor;
private String[] mColumnNames;
private int mKeyColumn;
@@ -71,7 +71,7 @@
// ContentProvider then read it once into the cache. Otherwise the cache will be filled
// automatically.
if (!keepUpdated) {
- readCursorIntoCache();
+ readCursorIntoCache(cursor);
}
}
@@ -128,27 +128,35 @@
/** Requeries the cursor and reads the contents into the cache */
public void requery() {
- mDirty = false;
- if (!mCursor.requery()) {
- throw new IllegalStateException("trying to requery an already closed cursor");
+ final Cursor cursor = mCursor;
+ if (cursor == null) {
+ // If mCursor is null then it means there was a requery() in flight
+ // while another thread called close(), which nulls out mCursor.
+ // If this happens ignore the requery() since we are closed anyways.
+ return;
}
- readCursorIntoCache();
+ mDirty = false;
+ if (!cursor.requery()) {
+ // again, don't do anything if the cursor is already closed
+ return;
+ }
+ readCursorIntoCache(cursor);
setChanged();
notifyObservers();
}
- private synchronized void readCursorIntoCache() {
+ private synchronized void readCursorIntoCache(Cursor cursor) {
// Make a new map so old values returned by getRows() are undisturbed.
int capacity = mValues != null ? mValues.size() : 0;
mValues = new HashMap<String, ContentValues>(capacity);
- while (mCursor.moveToNext()) {
+ while (cursor.moveToNext()) {
ContentValues values = new ContentValues();
for (int i = 0; i < mColumnNames.length; i++) {
if (i != mKeyColumn) {
- values.put(mColumnNames[i], mCursor.getString(i));
+ values.put(mColumnNames[i], cursor.getString(i));
}
}
- mValues.put(mCursor.getString(mKeyColumn), values);
+ mValues.put(cursor.getString(mKeyColumn), values);
}
}
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index 97f015b..1fa5af2 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -1276,11 +1276,14 @@
state.mActiveHead = mNext;
}
+ state.mActiveSize--;
+
+ if (LOG_V) Log.d(TAG, "Span finished=" + mName + "; size=" + state.mActiveSize);
+
this.mCreateMillis = -1;
this.mName = null;
this.mPrev = null;
this.mNext = null;
- state.mActiveSize--;
// Add ourselves to the freeList, if it's not already
// too big.
@@ -1367,6 +1370,7 @@
if (span.mNext != null) {
span.mNext.mPrev = span;
}
+ if (LOG_V) Log.d(TAG, "Span enter=" + name + "; size=" + state.mActiveSize);
}
return span;
}
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 06800d5..f987a49 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -4185,9 +4185,8 @@
if (keyCode == KeyEvent.KEYCODE_SHIFT_LEFT
|| keyCode == KeyEvent.KEYCODE_SHIFT_RIGHT) {
- if (pageShouldHandleShiftAndArrows()) {
- mShiftIsPressed = true;
- } else if (!nativeCursorWantsKeyEvents() && !mSelectingText) {
+ if (!pageShouldHandleShiftAndArrows() && !nativeCursorWantsKeyEvents()
+ && !mSelectingText) {
setUpSelect();
}
}
@@ -4206,7 +4205,7 @@
&& keyCode <= KeyEvent.KEYCODE_DPAD_RIGHT) {
switchOutDrawHistory();
if (pageShouldHandleShiftAndArrows()) {
- letPageHandleNavKey(keyCode, event.getEventTime(), true);
+ letPageHandleNavKey(keyCode, event.getEventTime(), true, event.getMetaState());
return true;
}
if (mSelectingText) {
@@ -4248,7 +4247,6 @@
&& keyCode != KeyEvent.KEYCODE_SHIFT_RIGHT) {
// turn off copy select if a shift-key combo is pressed
selectionDone();
- mShiftIsPressed = false;
}
if (getSettings().getNavDump()) {
@@ -4339,9 +4337,7 @@
if (keyCode == KeyEvent.KEYCODE_SHIFT_LEFT
|| keyCode == KeyEvent.KEYCODE_SHIFT_RIGHT) {
- if (pageShouldHandleShiftAndArrows()) {
- mShiftIsPressed = false;
- } else if (copySelection()) {
+ if (!pageShouldHandleShiftAndArrows() && copySelection()) {
selectionDone();
return true;
}
@@ -4350,7 +4346,7 @@
if (keyCode >= KeyEvent.KEYCODE_DPAD_UP
&& keyCode <= KeyEvent.KEYCODE_DPAD_RIGHT) {
if (pageShouldHandleShiftAndArrows()) {
- letPageHandleNavKey(keyCode, event.getEventTime(), false);
+ letPageHandleNavKey(keyCode, event.getEventTime(), false, event.getMetaState());
return true;
}
// always handle the navigation keys in the UI thread
@@ -4592,7 +4588,6 @@
mDrawCursorRing = false;
}
mGotKeyDown = false;
- mShiftIsPressed = false;
mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
mTouchMode = TOUCH_DONE_MODE;
if (mNativeClass != 0) {
@@ -5529,7 +5524,6 @@
private int mSelectX = 0;
private int mSelectY = 0;
private boolean mFocusSizeChanged = false;
- private boolean mShiftIsPressed = false;
private boolean mTrackballDown = false;
private long mTrackballUpTime = 0;
private long mLastCursorTime = 0;
@@ -5600,7 +5594,7 @@
}
return false; // let common code in onKeyUp at it
}
- if ((mMapTrackballToArrowKeys && mShiftIsPressed == false) ||
+ if ((mMapTrackballToArrowKeys && (ev.getMetaState() & KeyEvent.META_SHIFT_ON) == 0) ||
(mAccessibilityInjector != null || mAccessibilityScriptInjected)) {
if (DebugFlags.WEB_VIEW) Log.v(LOGTAG, "onTrackballEvent gmail quit");
return false;
@@ -5629,7 +5623,7 @@
}
mTrackballRemainsX += ev.getX();
mTrackballRemainsY += ev.getY();
- doTrackball(time);
+ doTrackball(time, ev.getMetaState());
return true;
}
@@ -5713,7 +5707,7 @@
"KEYCODE_DPAD_LEFT}.");
}
- private void doTrackball(long time) {
+ private void doTrackball(long time, int metaState) {
int elapsed = (int) (mTrackballLastTime - mTrackballFirstTime);
if (elapsed == 0) {
elapsed = TRACKBALL_TIMEOUT;
@@ -5771,9 +5765,9 @@
}
if (mNativeClass != 0 && nativePageShouldHandleShiftAndArrows()) {
for (int i = 0; i < count; i++) {
- letPageHandleNavKey(selectKeyCode, time, true);
+ letPageHandleNavKey(selectKeyCode, time, true, metaState);
}
- letPageHandleNavKey(selectKeyCode, time, false);
+ letPageHandleNavKey(selectKeyCode, time, false, metaState);
} else if (navHandledKey(selectKeyCode, count, false, time)) {
playSoundEffect(keyCodeToSoundsEffect(selectKeyCode));
}
@@ -7282,7 +7276,7 @@
* Pass the key directly to the page. This assumes that
* nativePageShouldHandleShiftAndArrows() returned true.
*/
- private void letPageHandleNavKey(int keyCode, long time, boolean down) {
+ private void letPageHandleNavKey(int keyCode, long time, boolean down, int metaState) {
int keyEventAction;
int eventHubAction;
if (down) {
@@ -7293,10 +7287,11 @@
keyEventAction = KeyEvent.ACTION_UP;
eventHubAction = EventHub.KEY_UP;
}
+
KeyEvent event = new KeyEvent(time, time, keyEventAction, keyCode,
- 1, (mShiftIsPressed ? KeyEvent.META_SHIFT_ON : 0)
- | (false ? KeyEvent.META_ALT_ON : 0) // FIXME
- | (false ? KeyEvent.META_SYM_ON : 0) // FIXME
+ 1, (metaState & KeyEvent.META_SHIFT_ON)
+ | (metaState & KeyEvent.META_ALT_ON)
+ | (metaState & KeyEvent.META_SYM_ON)
, 0, 0, 0);
mWebViewCore.sendMessage(eventHubAction, event);
}
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 30b1e5d..466e541 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -29,6 +29,7 @@
import android.os.Handler;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.StrictMode;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
@@ -460,6 +461,15 @@
private boolean mFlingProfilingStarted = false;
/**
+ * The StrictMode "critical time span" objects to catch animation
+ * stutters. Non-null when a time-sensitive animation is
+ * in-flight. Must call finish() on them when done animating.
+ * These are no-ops on user builds.
+ */
+ private StrictMode.Span mScrollStrictSpan = null;
+ private StrictMode.Span mFlingStrictSpan = null;
+
+ /**
* The last CheckForLongPress runnable we posted, if any
*/
private CheckForLongPress mPendingCheckForLongPress;
@@ -2089,6 +2099,16 @@
mAdapter.unregisterDataSetObserver(mDataSetObserver);
mDataSetObserver = null;
}
+
+ if (mScrollStrictSpan != null) {
+ mScrollStrictSpan.finish();
+ mScrollStrictSpan = null;
+ }
+
+ if (mFlingStrictSpan != null) {
+ mFlingStrictSpan.finish();
+ mFlingStrictSpan = null;
+ }
}
@Override
@@ -2559,6 +2579,11 @@
}
}
+ if (mScrollStrictSpan == null) {
+ // If it's non-null, we're already in a scroll.
+ mScrollStrictSpan = StrictMode.enterCriticalSpan("AbsListView-scroll");
+ }
+
if (y != mLastY) {
// We may be here after stopping a fling and continuing to scroll.
// If so, we haven't disallowed intercepting touch events yet.
@@ -2722,6 +2747,11 @@
mScrollProfilingStarted = false;
}
}
+
+ if (mScrollStrictSpan != null) {
+ mScrollStrictSpan.finish();
+ mScrollStrictSpan = null;
+ }
break;
}
@@ -2934,6 +2964,10 @@
mFlingProfilingStarted = true;
}
}
+
+ if (mFlingStrictSpan == null) {
+ mFlingStrictSpan = StrictMode.enterCriticalSpan("AbsListView-fling");
+ }
}
void startScroll(int distance, int duration) {
@@ -3012,6 +3046,11 @@
mFlingProfilingStarted = false;
}
}
+
+ if (mFlingStrictSpan != null) {
+ mFlingStrictSpan.finish();
+ mFlingStrictSpan = null;
+ }
}
break;
}
diff --git a/core/java/android/widget/StackView.java b/core/java/android/widget/StackView.java
index 432dd4a..e2d78c0 100644
--- a/core/java/android/widget/StackView.java
+++ b/core/java/android/widget/StackView.java
@@ -100,6 +100,8 @@
private static final int FRAME_PADDING = 4;
+ private final Rect mTouchRect = new Rect();
+
/**
* These variables are all related to the current state of touch interaction
* with the stack
@@ -531,7 +533,6 @@
return true;
}
- private final Rect touchRect = new Rect();
private void onSecondaryPointerUp(MotionEvent ev) {
final int activePointerIndex = ev.getActionIndex();
final int pointerId = ev.getPointerId(activePointerIndex);
@@ -552,8 +553,8 @@
float x = ev.getX(index);
float y = ev.getY(index);
- touchRect.set(v.getLeft(), v.getTop(), v.getRight(), v.getBottom());
- if (touchRect.contains(Math.round(x), Math.round(y))) {
+ mTouchRect.set(v.getLeft(), v.getTop(), v.getRight(), v.getBottom());
+ if (mTouchRect.contains(Math.round(x), Math.round(y))) {
float oldX = ev.getX(activePointerIndex);
float oldY = ev.getY(activePointerIndex);
@@ -1049,18 +1050,23 @@
private static final int RES_OUT = 0;
private static final int CLICK_FEEDBACK = 1;
private float mDensity;
+ private BlurMaskFilter mSmallBlurMaskFilter;
+ private BlurMaskFilter mLargeBlurMaskFilter;
+ private final Canvas mCanvas = new Canvas();
+ private final Canvas mMaskCanvas = new Canvas();
+ private final int[] mTmpXY = new int[2];
+ private final Matrix mIdentityMatrix = new Matrix();
HolographicHelper(Context context) {
- initializePaints(context);
- }
-
- void initializePaints(Context context) {
mDensity = context.getResources().getDisplayMetrics().density;
mHolographicPaint.setFilterBitmap(true);
mHolographicPaint.setMaskFilter(TableMaskFilter.CreateClipTable(0, 30));
mErasePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
mErasePaint.setFilterBitmap(true);
+
+ mSmallBlurMaskFilter = new BlurMaskFilter(2 * mDensity, BlurMaskFilter.Blur.NORMAL);
+ mLargeBlurMaskFilter = new BlurMaskFilter(4 * mDensity, BlurMaskFilter.Blur.NORMAL);
}
Bitmap createOutline(View v) {
@@ -1070,10 +1076,10 @@
Bitmap createOutline(View v, int type) {
if (type == RES_OUT) {
mHolographicPaint.setColor(0xff6699ff);
- mBlurPaint.setMaskFilter(new BlurMaskFilter(2*mDensity, BlurMaskFilter.Blur.NORMAL));
+ mBlurPaint.setMaskFilter(mSmallBlurMaskFilter);
} else if (type == CLICK_FEEDBACK) {
mHolographicPaint.setColor(0x886699ff);
- mBlurPaint.setMaskFilter(new BlurMaskFilter(4*mDensity, BlurMaskFilter.Blur.NORMAL));
+ mBlurPaint.setMaskFilter(mLargeBlurMaskFilter);
}
if (v.getMeasuredWidth() == 0 || v.getMeasuredHeight() == 0) {
@@ -1082,7 +1088,7 @@
Bitmap bitmap = Bitmap.createBitmap(v.getMeasuredWidth(), v.getMeasuredHeight(),
Bitmap.Config.ARGB_8888);
- Canvas canvas = new Canvas(bitmap);
+ mCanvas.setBitmap(bitmap);
float rotationX = v.getRotationX();
float rotation = v.getRotation();
@@ -1090,23 +1096,22 @@
v.setRotationX(0);
v.setRotation(0);
v.setTranslationY(0);
- v.draw(canvas);
+ v.draw(mCanvas);
v.setRotationX(rotationX);
v.setRotation(rotation);
v.setTranslationY(translationY);
- drawOutline(canvas, bitmap);
+ drawOutline(mCanvas, bitmap);
return bitmap;
}
- final Matrix id = new Matrix();
void drawOutline(Canvas dest, Bitmap src) {
- int[] xy = new int[2];
+ final int[] xy = mTmpXY;
Bitmap mask = src.extractAlpha(mBlurPaint, xy);
- Canvas maskCanvas = new Canvas(mask);
- maskCanvas.drawBitmap(src, -xy[0], -xy[1], mErasePaint);
+ mMaskCanvas.setBitmap(mask);
+ mMaskCanvas.drawBitmap(src, -xy[0], -xy[1], mErasePaint);
dest.drawColor(0, PorterDuff.Mode.CLEAR);
- dest.setMatrix(id);
+ dest.setMatrix(mIdentityMatrix);
dest.drawBitmap(mask, xy[0], xy[1], mHolographicPaint);
mask.recycle();
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index fbc8549..aefe8d8 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -6720,7 +6720,8 @@
+ " before=" + before + " after=" + after + ": " + buffer);
if (AccessibilityManager.getInstance(mContext).isEnabled()
- && !isPasswordInputType(mInputType)) {
+ && !isPasswordInputType(mInputType)
+ && !hasPasswordTransformationMethod()) {
mBeforeText = buffer.toString();
}
@@ -7599,7 +7600,7 @@
return false;
}
- final boolean isPassword = isPasswordInputType(mInputType);
+ final boolean isPassword = hasPasswordTransformationMethod();
if (!isPassword) {
CharSequence text = getText();
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index ff9f255..538e7bf 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -84,11 +84,13 @@
OMX_COLOR_FORMATTYPE colorFormat,
const sp<Surface> &surface,
size_t displayWidth, size_t displayHeight,
- size_t decodedWidth, size_t decodedHeight)
+ size_t decodedWidth, size_t decodedHeight,
+ int32_t rotationDegrees)
: mTarget(NULL) {
init(colorFormat, surface,
displayWidth, displayHeight,
- decodedWidth, decodedHeight);
+ decodedWidth, decodedHeight,
+ rotationDegrees);
}
virtual void render(MediaBuffer *buffer) {
@@ -113,7 +115,8 @@
OMX_COLOR_FORMATTYPE colorFormat,
const sp<Surface> &surface,
size_t displayWidth, size_t displayHeight,
- size_t decodedWidth, size_t decodedHeight);
+ size_t decodedWidth, size_t decodedHeight,
+ int32_t rotationDegrees);
AwesomeLocalRenderer(const AwesomeLocalRenderer &);
AwesomeLocalRenderer &operator=(const AwesomeLocalRenderer &);;
@@ -123,15 +126,19 @@
OMX_COLOR_FORMATTYPE colorFormat,
const sp<Surface> &surface,
size_t displayWidth, size_t displayHeight,
- size_t decodedWidth, size_t decodedHeight) {
+ size_t decodedWidth, size_t decodedHeight,
+ int32_t rotationDegrees) {
mTarget = new SoftwareRenderer(
colorFormat, surface, displayWidth, displayHeight,
- decodedWidth, decodedHeight);
+ decodedWidth, decodedHeight, rotationDegrees);
}
struct AwesomeNativeWindowRenderer : public AwesomeRenderer {
- AwesomeNativeWindowRenderer(const sp<ANativeWindow> &nativeWindow)
+ AwesomeNativeWindowRenderer(
+ const sp<ANativeWindow> &nativeWindow,
+ int32_t rotationDegrees)
: mNativeWindow(nativeWindow) {
+ applyRotation(rotationDegrees);
}
virtual void render(MediaBuffer *buffer) {
@@ -153,6 +160,22 @@
private:
sp<ANativeWindow> mNativeWindow;
+ void applyRotation(int32_t rotationDegrees) {
+ uint32_t transform;
+ switch (rotationDegrees) {
+ case 0: transform = 0; break;
+ case 90: transform = HAL_TRANSFORM_ROT_90; break;
+ case 180: transform = HAL_TRANSFORM_ROT_180; break;
+ case 270: transform = HAL_TRANSFORM_ROT_270; break;
+ default: transform = 0; break;
+ }
+
+ if (transform) {
+ CHECK_EQ(0, native_window_set_buffers_transform(
+ mNativeWindow.get(), transform));
+ }
+ }
+
AwesomeNativeWindowRenderer(const AwesomeNativeWindowRenderer &);
AwesomeNativeWindowRenderer &operator=(
const AwesomeNativeWindowRenderer &);
@@ -796,7 +819,19 @@
CHECK(meta->findInt32(kKeyWidth, &decodedWidth));
CHECK(meta->findInt32(kKeyHeight, &decodedHeight));
- notifyListener_l(MEDIA_SET_VIDEO_SIZE, decodedWidth, decodedHeight);
+ int32_t rotationDegrees;
+ if (!mVideoTrack->getFormat()->findInt32(
+ kKeyRotation, &rotationDegrees)) {
+ rotationDegrees = 0;
+ }
+
+ if (rotationDegrees == 90 || rotationDegrees == 270) {
+ notifyListener_l(
+ MEDIA_SET_VIDEO_SIZE, decodedHeight, decodedWidth);
+ } else {
+ notifyListener_l(
+ MEDIA_SET_VIDEO_SIZE, decodedWidth, decodedHeight);
+ }
}
void AwesomePlayer::initRenderer_l() {
@@ -814,6 +849,12 @@
CHECK(meta->findInt32(kKeyWidth, &decodedWidth));
CHECK(meta->findInt32(kKeyHeight, &decodedHeight));
+ int32_t rotationDegrees;
+ if (!mVideoTrack->getFormat()->findInt32(
+ kKeyRotation, &rotationDegrees)) {
+ rotationDegrees = 0;
+ }
+
mVideoRenderer.clear();
// Must ensure that mVideoRenderer's destructor is actually executed
@@ -824,7 +865,8 @@
// Hardware decoders avoid the CPU color conversion by decoding
// directly to ANativeBuffers, so we must use a renderer that
// just pushes those buffers to the ANativeWindow.
- mVideoRenderer = new AwesomeNativeWindowRenderer(mSurface);
+ mVideoRenderer =
+ new AwesomeNativeWindowRenderer(mSurface, rotationDegrees);
} else {
// Other decoders are instantiated locally and as a consequence
// allocate their buffers in local address space. This renderer
@@ -834,7 +876,8 @@
(OMX_COLOR_FORMATTYPE)format,
mSurface,
mVideoWidth, mVideoHeight,
- decodedWidth, decodedHeight);
+ decodedWidth, decodedHeight,
+ rotationDegrees);
}
}
@@ -1819,7 +1862,8 @@
state->mVideoWidth,
state->mVideoHeight,
state->mDecodedWidth,
- state->mDecodedHeight);
+ state->mDecodedHeight,
+ 0);
mVideoRendererIsPreview = true;
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index 2e94a12..bb929fd 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -27,11 +27,11 @@
#include <stdlib.h>
#include <string.h>
+#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/DataSource.h>
#include "include/ESDS.h"
#include <media/stagefright/MediaBuffer.h>
#include <media/stagefright/MediaBufferGroup.h>
-#include <media/stagefright/MediaDebug.h>
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MediaSource.h>
#include <media/stagefright/MetaData.h>
@@ -766,55 +766,11 @@
case FOURCC('t', 'k', 'h', 'd'):
{
- if (chunk_data_size < 4) {
- return ERROR_MALFORMED;
+ status_t err;
+ if ((err = parseTrackHeader(data_offset, chunk_data_size)) != OK) {
+ return err;
}
- uint8_t version;
- if (mDataSource->readAt(data_offset, &version, 1) < 1) {
- return ERROR_IO;
- }
-
- uint64_t ctime, mtime, duration;
- int32_t id;
- uint32_t width, height;
-
- if (version == 1) {
- if (chunk_data_size != 36 + 60) {
- return ERROR_MALFORMED;
- }
-
- uint8_t buffer[36 + 60];
- if (mDataSource->readAt(
- data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
- return ERROR_IO;
- }
-
- ctime = U64_AT(&buffer[4]);
- mtime = U64_AT(&buffer[12]);
- id = U32_AT(&buffer[20]);
- duration = U64_AT(&buffer[28]);
- width = U32_AT(&buffer[88]);
- height = U32_AT(&buffer[92]);
- } else if (version == 0) {
- if (chunk_data_size != 24 + 60) {
- return ERROR_MALFORMED;
- }
-
- uint8_t buffer[24 + 60];
- if (mDataSource->readAt(
- data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
- return ERROR_IO;
- }
- ctime = U32_AT(&buffer[4]);
- mtime = U32_AT(&buffer[8]);
- id = U32_AT(&buffer[12]);
- duration = U32_AT(&buffer[20]);
- width = U32_AT(&buffer[76]);
- height = U32_AT(&buffer[80]);
- }
-
- mLastTrack->meta->setInt32(kKeyTrackID, id);
*offset += chunk_size;
break;
}
@@ -1275,6 +1231,93 @@
return OK;
}
+status_t MPEG4Extractor::parseTrackHeader(
+ off_t data_offset, off_t data_size) {
+ if (data_size < 4) {
+ return ERROR_MALFORMED;
+ }
+
+ uint8_t version;
+ if (mDataSource->readAt(data_offset, &version, 1) < 1) {
+ return ERROR_IO;
+ }
+
+ size_t dynSize = (version == 1) ? 36 : 24;
+
+ uint8_t buffer[36 + 60];
+
+ if (data_size != (off_t)dynSize + 60) {
+ return ERROR_MALFORMED;
+ }
+
+ if (mDataSource->readAt(
+ data_offset, buffer, data_size) < (ssize_t)data_size) {
+ return ERROR_IO;
+ }
+
+ uint64_t ctime, mtime, duration;
+ int32_t id;
+
+ if (version == 1) {
+ ctime = U64_AT(&buffer[4]);
+ mtime = U64_AT(&buffer[12]);
+ id = U32_AT(&buffer[20]);
+ duration = U64_AT(&buffer[28]);
+ } else {
+ CHECK_EQ((unsigned)version, 0u);
+
+ ctime = U32_AT(&buffer[4]);
+ mtime = U32_AT(&buffer[8]);
+ id = U32_AT(&buffer[12]);
+ duration = U32_AT(&buffer[20]);
+ }
+
+ mLastTrack->meta->setInt32(kKeyTrackID, id);
+
+ size_t matrixOffset = dynSize + 16;
+ int32_t a00 = U32_AT(&buffer[matrixOffset]);
+ int32_t a01 = U32_AT(&buffer[matrixOffset + 4]);
+ int32_t dx = U32_AT(&buffer[matrixOffset + 8]);
+ int32_t a10 = U32_AT(&buffer[matrixOffset + 12]);
+ int32_t a11 = U32_AT(&buffer[matrixOffset + 16]);
+ int32_t dy = U32_AT(&buffer[matrixOffset + 20]);
+
+#if 0
+ LOGI("x' = %.2f * x + %.2f * y + %.2f",
+ a00 / 65536.0f, a01 / 65536.0f, dx / 65536.0f);
+ LOGI("y' = %.2f * x + %.2f * y + %.2f",
+ a10 / 65536.0f, a11 / 65536.0f, dy / 65536.0f);
+#endif
+
+ uint32_t rotationDegrees;
+
+ static const int32_t kFixedOne = 0x10000;
+ if (a00 == kFixedOne && a01 == 0 && a10 == 0 && a11 == kFixedOne) {
+ // Identity, no rotation
+ rotationDegrees = 0;
+ } else if (a00 == 0 && a01 == kFixedOne && a10 == -kFixedOne && a11 == 0) {
+ rotationDegrees = 90;
+ } else if (a00 == 0 && a01 == -kFixedOne && a10 == kFixedOne && a11 == 0) {
+ rotationDegrees = 270;
+ } else if (a00 == -kFixedOne && a01 == 0 && a10 == 0 && a11 == -kFixedOne) {
+ rotationDegrees = 180;
+ } else {
+ LOGW("We only support 0,90,180,270 degree rotation matrices");
+ rotationDegrees = 0;
+ }
+
+ if (rotationDegrees != 0) {
+ mLastTrack->meta->setInt32(kKeyRotation, rotationDegrees);
+ }
+
+#if 0
+ uint32_t width = U32_AT(&buffer[dynSize + 52]);
+ uint32_t height = U32_AT(&buffer[dynSize + 56]);
+#endif
+
+ return OK;
+}
+
status_t MPEG4Extractor::parseMetaData(off_t offset, size_t size) {
if (size < 4) {
return ERROR_MALFORMED;
@@ -1588,7 +1631,7 @@
const uint8_t *ptr = (const uint8_t *)data;
CHECK(size >= 7);
- CHECK_EQ(ptr[0], 1); // configurationVersion == 1
+ CHECK_EQ((unsigned)ptr[0], 1u); // configurationVersion == 1
// The number of bytes used to encode the length of a NAL unit.
mNALLengthSize = 1 + (ptr[4] & 3);
@@ -1736,7 +1779,7 @@
}
uint32_t sampleTime;
- CHECK_EQ(OK, mSampleTable->getMetaDataForSample(
+ CHECK_EQ((status_t)OK, mSampleTable->getMetaDataForSample(
sampleIndex, NULL, NULL, &sampleTime));
if (mode == ReadOptions::SEEK_CLOSEST) {
@@ -1783,7 +1826,7 @@
err = mGroup->acquire_buffer(&mBuffer);
if (err != OK) {
- CHECK_EQ(mBuffer, NULL);
+ CHECK(mBuffer == NULL);
return err;
}
}
diff --git a/media/libstagefright/colorconversion/SoftwareRenderer.cpp b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
index 662a84a..3d507ca 100644
--- a/media/libstagefright/colorconversion/SoftwareRenderer.cpp
+++ b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
@@ -35,7 +35,8 @@
OMX_COLOR_FORMATTYPE colorFormat,
const sp<Surface> &surface,
size_t displayWidth, size_t displayHeight,
- size_t decodedWidth, size_t decodedHeight)
+ size_t decodedWidth, size_t decodedHeight,
+ int32_t rotationDegrees)
: mColorFormat(colorFormat),
mConverter(NULL),
mYUVMode(None),
@@ -95,6 +96,20 @@
CHECK_EQ(0, native_window_set_buffers_geometry(
mSurface.get(), mDecodedWidth, mDecodedHeight,
halFormat));
+
+ uint32_t transform;
+ switch (rotationDegrees) {
+ case 0: transform = 0; break;
+ case 90: transform = HAL_TRANSFORM_ROT_90; break;
+ case 180: transform = HAL_TRANSFORM_ROT_180; break;
+ case 270: transform = HAL_TRANSFORM_ROT_270; break;
+ default: transform = 0; break;
+ }
+
+ if (transform) {
+ CHECK_EQ(0, native_window_set_buffers_transform(
+ mSurface.get(), transform));
+ }
}
SoftwareRenderer::~SoftwareRenderer() {
diff --git a/media/libstagefright/include/MPEG4Extractor.h b/media/libstagefright/include/MPEG4Extractor.h
index 4e31059..bc2e4dc 100644
--- a/media/libstagefright/include/MPEG4Extractor.h
+++ b/media/libstagefright/include/MPEG4Extractor.h
@@ -88,6 +88,8 @@
bool mIsDrm;
status_t parseDrmSINF(off_t *offset, off_t data_offset);
+ status_t parseTrackHeader(off_t data_offset, off_t data_size);
+
MPEG4Extractor(const MPEG4Extractor &);
MPEG4Extractor &operator=(const MPEG4Extractor &);
};
diff --git a/media/libstagefright/include/SoftwareRenderer.h b/media/libstagefright/include/SoftwareRenderer.h
index 198bfd6..9cafc68 100644
--- a/media/libstagefright/include/SoftwareRenderer.h
+++ b/media/libstagefright/include/SoftwareRenderer.h
@@ -31,7 +31,8 @@
OMX_COLOR_FORMATTYPE colorFormat,
const sp<Surface> &surface,
size_t displayWidth, size_t displayHeight,
- size_t decodedWidth, size_t decodedHeight);
+ size_t decodedWidth, size_t decodedHeight,
+ int32_t rotationDegrees);
~SoftwareRenderer();
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 35a2c19..290f2c1 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -438,9 +438,9 @@
+ " " + (mCssIndicator ? "CSS supported" : "CSS not supported")
+ " " + mNetworkId
+ " " + mSystemId
- + "RoamInd: " + mCdmaRoamingIndicator
- + "DefRoamInd: " + mCdmaDefaultRoamingIndicator
- + "EmergOnly: " + mIsEmergencyOnly);
+ + " RoamInd=" + mCdmaRoamingIndicator
+ + " DefRoamInd=" + mCdmaDefaultRoamingIndicator
+ + " EmergOnly=" + mIsEmergencyOnly);
}
public void setStateOutOfService() {
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
index 7c652c5..d7ff0c5 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
@@ -240,8 +240,8 @@
mCdmaPhone.mRuimRecords.getRecordsLoaded())) {
reason += " - radioState= " + mPhone.mCM.getRadioState() + " - RUIM not loaded";
}
- if (mPhone.getState() != Phone.State.IDLE &&
- mCdmaPhone.mSST.isConcurrentVoiceAndData()) {
+ if (!(mCdmaPhone.mSST.isConcurrentVoiceAndData() ||
+ mPhone.getState() == Phone.State.IDLE)) {
reason += " - concurrentVoiceAndData not allowed and state= " + mPhone.getState();
}
if (roaming) reason += " - Roaming";
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
index 2aca9ad..effb743 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
@@ -328,8 +328,8 @@
reason += " - PhoneState= " + mPhone.getState();
}
if (!mMasterDataEnabled) reason += " - mMasterDataEnabled= false";
- if (mPhone.getServiceState().getRoaming() && getDataOnRoamingEnabled()) {
- reason += " - Roaming";
+ if (mPhone.getServiceState().getRoaming() && !getDataOnRoamingEnabled()) {
+ reason += " - Roaming and data roaming not enabled";
}
if (mIsPsRestricted) reason += " - mIsPsRestricted= true";
if (!desiredPowerState) reason += " - desiredPowerState= false";
@@ -1037,8 +1037,15 @@
} else {
GsmDataConnection.FailCause cause;
cause = (GsmDataConnection.FailCause) (ar.result);
- if(DBG) log("PDP setup failed " + cause);
- // Log this failure to the Event Logs.
+ if (DBG) {
+ String apnString;
+ try {
+ apnString = mWaitingApns.get(0).apn;
+ } catch (Exception e) {
+ apnString = "<unknown>";
+ }
+ log(String.format("onDataSetupComplete: error apn=%s cause=%s", apnString, cause));
+ }
if (cause.isEventLoggable()) {
GsmCellLocation loc = ((GsmCellLocation)mPhone.getCellLocation());
EventLog.writeEvent(EventLogTags.PDP_SETUP_FAIL,