diff options
35 files changed, 642 insertions, 201 deletions
diff --git a/api/current.txt b/api/current.txt index f6bfd73d2935..9273b712f4a3 100644 --- a/api/current.txt +++ b/api/current.txt @@ -11446,11 +11446,14 @@ package android.net.http { } public class SslError { - ctor public SslError(int, android.net.http.SslCertificate); - ctor public SslError(int, java.security.cert.X509Certificate); + ctor public deprecated SslError(int, android.net.http.SslCertificate); + ctor public deprecated SslError(int, java.security.cert.X509Certificate); + ctor public SslError(int, android.net.http.SslCertificate, java.lang.String); + ctor public SslError(int, java.security.cert.X509Certificate, java.lang.String); method public boolean addError(int); method public android.net.http.SslCertificate getCertificate(); method public int getPrimaryError(); + method public java.lang.String getUrl(); method public boolean hasError(int); field public static final int SSL_EXPIRED = 1; // 0x1 field public static final int SSL_IDMISMATCH = 2; // 0x2 @@ -21426,7 +21429,6 @@ package android.view { field public static final int AXIS_Y = 1; // 0x1 field public static final int AXIS_Z = 11; // 0xb field public static final int BUTTON_BACK = 8; // 0x8 - field public static final int BUTTON_ERASER = 32; // 0x20 field public static final int BUTTON_FORWARD = 16; // 0x10 field public static final int BUTTON_PRIMARY = 1; // 0x1 field public static final int BUTTON_SECONDARY = 2; // 0x2 @@ -22011,6 +22013,7 @@ package android.view { method public void setOnDragListener(android.view.View.OnDragListener); method public void setOnFocusChangeListener(android.view.View.OnFocusChangeListener); method public void setOnGenericMotionListener(android.view.View.OnGenericMotionListener); + method public void setOnHoverListener(android.view.View.OnHoverListener); method public void setOnKeyListener(android.view.View.OnKeyListener); method public void setOnLongClickListener(android.view.View.OnLongClickListener); method public void setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener); diff --git a/cmds/stagefright/sf2.cpp b/cmds/stagefright/sf2.cpp index 289665f51b5d..ddd64ecf0445 100644 --- a/cmds/stagefright/sf2.cpp +++ b/cmds/stagefright/sf2.cpp @@ -29,6 +29,7 @@ #include <media/stagefright/MediaExtractor.h> #include <media/stagefright/MediaSource.h> #include <media/stagefright/MetaData.h> +#include <media/stagefright/NativeWindowWrapper.h> #include <media/stagefright/Utils.h> #include <surfaceflinger/ISurfaceComposer.h> @@ -39,10 +40,12 @@ using namespace android; struct Controller : public AHandler { - Controller(const char *uri, bool decodeAudio, const sp<Surface> &surface) + Controller(const char *uri, bool decodeAudio, + const sp<Surface> &surface, bool renderToSurface) : mURI(uri), mDecodeAudio(decodeAudio), mSurface(surface), + mRenderToSurface(renderToSurface), mCodec(new ACodec) { CHECK(!mDecodeAudio || mSurface == NULL); } @@ -97,7 +100,8 @@ protected: sp<AMessage> format = makeFormat(mSource->getFormat()); if (mSurface != NULL) { - format->setObject("surface", mSurface); + format->setObject( + "native-window", new NativeWindowWrapper(mSurface)); } mCodec->initiateSetup(format); @@ -220,6 +224,7 @@ private: AString mURI; bool mDecodeAudio; sp<Surface> mSurface; + bool mRenderToSurface; sp<ACodec> mCodec; sp<MediaSource> mSource; @@ -451,7 +456,7 @@ private: inBuffer->release(); inBuffer = NULL; - // break; // Don't coalesce + break; // Don't coalesce } LOGV("coalesced %d input buffers", n); @@ -479,6 +484,10 @@ private: sp<AMessage> reply; CHECK(msg->findMessage("reply", &reply)); + if (mRenderToSurface) { + reply->setInt32("render", 1); + } + reply->post(); } @@ -491,7 +500,8 @@ static void usage(const char *me) { fprintf(stderr, " -a(udio)\n"); fprintf(stderr, - " -s(surface) Allocate output buffers on a surface.\n"); + " -S(urface) Allocate output buffers on a surface.\n" + " -R(ender) Render surface-allocated buffers.\n"); } int main(int argc, char **argv) { @@ -499,18 +509,23 @@ int main(int argc, char **argv) { bool decodeAudio = false; bool useSurface = false; + bool renderToSurface = false; int res; - while ((res = getopt(argc, argv, "has")) >= 0) { + while ((res = getopt(argc, argv, "haSR")) >= 0) { switch (res) { case 'a': decodeAudio = true; break; - case 's': + case 'S': useSurface = true; break; + case 'R': + renderToSurface = true; + break; + case '?': case 'h': default: @@ -562,7 +577,9 @@ int main(int argc, char **argv) { CHECK(surface != NULL); } - sp<Controller> controller = new Controller(argv[0], decodeAudio, surface); + sp<Controller> controller = + new Controller(argv[0], decodeAudio, surface, renderToSurface); + looper->registerHandler(controller); controller->startAsync(); diff --git a/core/java/android/net/http/SslError.java b/core/java/android/net/http/SslError.java index e1b9debb8f2b..1e1cb49dabad 100644 --- a/core/java/android/net/http/SslError.java +++ b/core/java/android/net/http/SslError.java @@ -59,36 +59,97 @@ public class SslError { /** * The SSL certificate associated with the error set */ - SslCertificate mCertificate; + final SslCertificate mCertificate; + + /** + * The URL associated with the error set. + */ + final String mUrl; /** * Creates a new SSL error set object * @param error The SSL error * @param certificate The associated SSL certificate + * @deprecated Use {@link #SslError(int, SslCertificate, String)} */ + @Deprecated public SslError(int error, SslCertificate certificate) { addError(error); + if (certificate == null) { + throw new NullPointerException("certificate is null."); + } mCertificate = certificate; + mUrl = ""; } /** * Creates a new SSL error set object * @param error The SSL error * @param certificate The associated SSL certificate + * @deprecated Use {@link #SslError(int, X509Certificate, String)} */ + @Deprecated public SslError(int error, X509Certificate certificate) { addError(error); + if (certificate == null) { + throw new NullPointerException("certificate is null."); + } mCertificate = new SslCertificate(certificate); + mUrl = ""; } /** - * @return The SSL certificate associated with the error set + * Creates a new SSL error set object + * @param error The SSL error + * @param certificate The associated SSL certificate + * @param url The associated URL. + */ + public SslError(int error, SslCertificate certificate, String url) { + addError(error); + if (certificate == null) { + throw new NullPointerException("certificate is null."); + } + mCertificate = certificate; + if (url == null) { + throw new NullPointerException("url is null."); + } + mUrl = url; + } + + /** + * Creates a new SSL error set object + * @param error The SSL error + * @param certificate The associated SSL certificate + * @param url The associated URL. + */ + public SslError(int error, X509Certificate certificate, String url) { + addError(error); + if (certificate == null) { + throw new NullPointerException("certificate is null."); + } + mCertificate = new SslCertificate(certificate); + if (url == null) { + throw new NullPointerException("url is null."); + } + mUrl = url; + } + + /** + * @return The SSL certificate associated with the error set, non-null. */ public SslCertificate getCertificate() { return mCertificate; } /** + * @return The URL associated with the error set, non-null. + * "" if one of the deprecated constructors is used. + */ + public String getUrl() { + return mUrl; + } + + /** * Adds the SSL error to the error set * @param error The SSL error to add * @return True iff the error being added is a known SSL error @@ -137,6 +198,7 @@ public class SslError { */ public String toString() { return "primary error: " + getPrimaryError() + - " certificate: " + getCertificate(); + " certificate: " + getCertificate() + + " on URL: " + getUrl(); } } diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java index 02faf496843e..09331939f616 100644 --- a/core/java/android/provider/CallLog.java +++ b/core/java/android/provider/CallLog.java @@ -24,6 +24,8 @@ import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.net.Uri; +import android.provider.ContactsContract.CommonDataKinds.Phone; +import android.provider.ContactsContract.DataUsageFeedback; import android.text.TextUtils; /** @@ -204,7 +206,44 @@ public class CallLog { } if ((ci != null) && (ci.person_id > 0)) { - ContactsContract.Contacts.markAsContacted(resolver, ci.person_id); + // Update usage information for the number associated with the contact ID. + // We need to use both the number and the ID for obtaining a data ID since other + // contacts may have the same number. + + final Cursor cursor; + + // We should prefer normalized one (probably coming from + // Phone.NORMALIZED_NUMBER column) first. If it isn't available try others. + if (ci.normalizedNumber != null) { + final String normalizedPhoneNumber = ci.normalizedNumber; + cursor = resolver.query(Phone.CONTENT_URI, + new String[] { Phone._ID }, + Phone.CONTACT_ID + " =? AND " + Phone.NORMALIZED_NUMBER + " =?", + new String[] { String.valueOf(ci.person_id), normalizedPhoneNumber}, + null); + } else { + final String phoneNumber = ci.phoneNumber != null ? ci.phoneNumber : number; + cursor = resolver.query(Phone.CONTENT_URI, + new String[] { Phone._ID }, + Phone.CONTACT_ID + " =? AND " + Phone.NUMBER + " =?", + new String[] { String.valueOf(ci.person_id), phoneNumber}, + null); + } + + if (cursor != null) { + try { + if (cursor.getCount() > 0 && cursor.moveToFirst()) { + final Uri feedbackUri = DataUsageFeedback.FEEDBACK_URI.buildUpon() + .appendPath(cursor.getString(0)) + .appendQueryParameter(DataUsageFeedback.USAGE_TYPE, + DataUsageFeedback.USAGE_TYPE_CALL) + .build(); + resolver.update(feedbackUri, new ContentValues(), null, null); + } + } finally { + cursor.close(); + } + } } Uri result = resolver.insert(CONTENT_URI, values); diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java index cb96bfd2c9d1..ad71061f52be 100644 --- a/core/java/android/provider/ContactsContract.java +++ b/core/java/android/provider/ContactsContract.java @@ -174,6 +174,15 @@ public final class ContactsContract { */ public static final String PRIMARY_ACCOUNT_TYPE = "type_for_primary_account"; + /** + * A boolean parameter for {@link Contacts#CONTENT_STREQUENT_URI} and + * {@link Contacts#CONTENT_STREQUENT_FILTER_URI}, which requires the ContactsProvider to + * return only phone-related results. For example, frequently contacted person list should + * include persons contacted via phone (not email, sms, etc.) + * + * @hide + */ + public static final String STREQUENT_PHONE_ONLY = "strequent_phone_only"; /** * @hide diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java index 3436cd1df94f..f45e78bfef10 100644 --- a/core/java/android/view/MotionEvent.java +++ b/core/java/android/view/MotionEvent.java @@ -1130,14 +1130,14 @@ public final class MotionEvent extends InputEvent implements Parcelable { public static final int BUTTON_PRIMARY = 1 << 0; /** - * Button constant: Secondary button (right mouse button, stylus barrel). + * Button constant: Secondary button (right mouse button, stylus first button). * * @see #getButtonState */ public static final int BUTTON_SECONDARY = 1 << 1; /** - * Button constant: Tertiary button (middle mouse button). + * Button constant: Tertiary button (middle mouse button, stylus second button). * * @see #getButtonState */ @@ -1165,13 +1165,6 @@ public final class MotionEvent extends InputEvent implements Parcelable { */ public static final int BUTTON_FORWARD = 1 << 4; - /** - * Button constant: Eraser button pressed (stylus end). - * - * @see #getButtonState - */ - public static final int BUTTON_ERASER = 1 << 5; - // NOTE: If you add a new axis here you must also add it to: // native/include/android/input.h @@ -1183,7 +1176,7 @@ public final class MotionEvent extends InputEvent implements Parcelable { "BUTTON_TERTIARY", "BUTTON_BACK", "BUTTON_FORWARD", - "BUTTON_ERASER", + "0x00000020", "0x00000040", "0x00000080", "0x00000100", @@ -2176,7 +2169,6 @@ public final class MotionEvent extends InputEvent implements Parcelable { * @see #BUTTON_TERTIARY * @see #BUTTON_FORWARD * @see #BUTTON_BACK - * @see #BUTTON_ERASER */ public final int getButtonState() { return nativeGetButtonState(mNativePtr); diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 574313441d15..411b7142a6dc 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -3390,6 +3390,14 @@ public class View implements Drawable.Callback2, KeyEvent.Callback, Accessibilit } /** + * Register a callback to be invoked when a hover event is sent to this view. + * @param l the hover listener to attach to this view + */ + public void setOnHoverListener(OnHoverListener l) { + mOnHoverListener = l; + } + + /** * Register a drag event listener callback object for this View. The parameter is * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a * View, the system calls the diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java index 2f4774f61e17..79a5affffa44 100644 --- a/core/java/android/webkit/BrowserFrame.java +++ b/core/java/android/webkit/BrowserFrame.java @@ -1150,11 +1150,12 @@ class BrowserFrame extends Handler { * {@link #nativeSslCertErrorProceed(int)} or * {@link #nativeSslCertErrorCancel(int, int)}. */ - private void reportSslCertError(final int handle, final int cert_error, byte cert_der[]) { + private void reportSslCertError( + final int handle, final int cert_error, byte cert_der[], String url) { final SslError ssl_error; try { X509Certificate cert = new X509CertImpl(cert_der); - ssl_error = new SslError(cert_error, cert); + ssl_error = new SslError(cert_error, cert, url); } catch (IOException e) { // Can't get the certificate, not much to do. Log.e(LOGTAG, "Can't get the certificate from WebKit, canceling"); diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index 12687a130e3f..7b65964a2fc0 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -41,6 +41,7 @@ import android.util.PrintWriterPrinter; import android.util.Printer; import android.util.Slog; import android.util.SparseArray; +import android.util.TimeUtils; import java.io.BufferedReader; import java.io.File; @@ -4870,8 +4871,8 @@ public final class BatteryStatsImpl extends BatteryStats { return 0; } - void readHistory(Parcel in) { - mHistoryBaseTime = in.readLong(); + void readHistory(Parcel in, boolean andOldHistory) { + final long historyBaseTime = in.readLong(); mHistoryBuffer.setDataSize(0); mHistoryBuffer.setDataPosition(0); @@ -4889,15 +4890,35 @@ public final class BatteryStatsImpl extends BatteryStats { in.setDataPosition(curPos + bufSize); } - long oldnow = SystemClock.elapsedRealtime() - (5*60*1000); - if (oldnow > 0) { - // If the system process has restarted, but not the entire - // system, then the mHistoryBaseTime already accounts for - // much of the elapsed time. We thus want to adjust it back, - // to avoid large gaps in the data. We determine we are - // in this case by arbitrarily saying it is so if at this - // point in boot the elapsed time is already more than 5 minutes. - mHistoryBaseTime -= oldnow; + if (andOldHistory) { + readOldHistory(in); + } + + if (DEBUG_HISTORY) { + StringBuilder sb = new StringBuilder(128); + sb.append("****************** OLD mHistoryBaseTime: "); + TimeUtils.formatDuration(mHistoryBaseTime, sb); + Slog.i(TAG, sb.toString()); + } + mHistoryBaseTime = historyBaseTime; + if (DEBUG_HISTORY) { + StringBuilder sb = new StringBuilder(128); + sb.append("****************** NEW mHistoryBaseTime: "); + TimeUtils.formatDuration(mHistoryBaseTime, sb); + Slog.i(TAG, sb.toString()); + } + + // We are just arbitrarily going to insert 1 minute from the sample of + // the last run until samples in this run. + if (mHistoryBaseTime > 0) { + long oldnow = SystemClock.elapsedRealtime(); + mHistoryBaseTime = (mHistoryBaseTime - oldnow) + 60*1000; + if (DEBUG_HISTORY) { + StringBuilder sb = new StringBuilder(128); + sb.append("****************** ADJUSTED mHistoryBaseTime: "); + TimeUtils.formatDuration(mHistoryBaseTime, sb); + Slog.i(TAG, sb.toString()); + } } } @@ -4910,12 +4931,24 @@ public final class BatteryStatsImpl extends BatteryStats { } } - void writeHistory(Parcel out) { - out.writeLong(mLastHistoryTime); + void writeHistory(Parcel out, boolean andOldHistory) { + if (DEBUG_HISTORY) { + StringBuilder sb = new StringBuilder(128); + sb.append("****************** WRITING mHistoryBaseTime: "); + TimeUtils.formatDuration(mHistoryBaseTime, sb); + sb.append(" mLastHistoryTime: "); + TimeUtils.formatDuration(mLastHistoryTime, sb); + Slog.i(TAG, sb.toString()); + } + out.writeLong(mHistoryBaseTime + mLastHistoryTime); out.writeInt(mHistoryBuffer.dataSize()); if (DEBUG_HISTORY) Slog.i(TAG, "***************** WRITING HISTORY: " + mHistoryBuffer.dataSize() + " bytes at " + out.dataPosition()); out.appendFrom(mHistoryBuffer, 0, mHistoryBuffer.dataSize()); + + if (andOldHistory) { + writeOldHistory(out); + } } void writeOldHistory(Parcel out) { @@ -4935,8 +4968,7 @@ public final class BatteryStatsImpl extends BatteryStats { return; } - readHistory(in); - readOldHistory(in); + readHistory(in, true); mStartCount = in.readInt(); mBatteryUptime = in.readLong(); @@ -5136,8 +5168,7 @@ public final class BatteryStatsImpl extends BatteryStats { out.writeInt(VERSION); - writeHistory(out); - writeOldHistory(out); + writeHistory(out, true); out.writeInt(mStartCount); out.writeLong(computeBatteryUptime(NOW_SYS, STATS_SINCE_CHARGED)); @@ -5340,7 +5371,7 @@ public final class BatteryStatsImpl extends BatteryStats { throw new ParcelFormatException("Bad magic number"); } - readHistory(in); + readHistory(in, false); mStartCount = in.readInt(); mBatteryUptime = in.readLong(); @@ -5461,7 +5492,7 @@ public final class BatteryStatsImpl extends BatteryStats { out.writeInt(MAGIC); - writeHistory(out); + writeHistory(out, false); out.writeInt(mStartCount); out.writeLong(mBatteryUptime); diff --git a/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java b/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java index 3e7b976aedb7..5b3510428f7b 100644 --- a/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java +++ b/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java @@ -224,8 +224,8 @@ public class MultiWaveView extends View implements AnimatorUpdateListener { /** * Animation used to attract user's attention to the target button. - * Assumes mChevronDrawables is an a list with an even number of chevrons filled with left - * followed by right chevrons. + * Assumes mChevronDrawables is an a list with an even number of chevrons filled with + * mFeedbackCount items in the order: left, right, top, bottom. */ private void startChevronAnimation() { final float r = mHandleDrawable.getWidth() / 2; @@ -442,6 +442,7 @@ public class MultiWaveView extends View implements AnimatorUpdateListener { mHandleDrawable.setX(mWaveCenterX); mHandleDrawable.setY(mWaveCenterY); mHandleDrawable.setState(TargetDrawable.STATE_INACTIVE); + Tweener.reset(); } @Override diff --git a/core/java/com/android/internal/widget/multiwaveview/Tweener.java b/core/java/com/android/internal/widget/multiwaveview/Tweener.java index 0cff00a514ab..bc8a62f2ca0b 100644 --- a/core/java/com/android/internal/widget/multiwaveview/Tweener.java +++ b/core/java/com/android/internal/widget/multiwaveview/Tweener.java @@ -18,25 +18,42 @@ package com.android.internal.widget.multiwaveview; import java.util.ArrayList; import java.util.HashMap; +import java.util.Iterator; +import java.util.Map.Entry; import android.animation.Animator.AnimatorListener; +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; import android.animation.ObjectAnimator; import android.animation.PropertyValuesHolder; import android.animation.TimeInterpolator; import android.animation.ValueAnimator.AnimatorUpdateListener; +import android.util.Log; class Tweener { private static final String TAG = "Tweener"; + private static final boolean DEBUG = false; - private Object object; ObjectAnimator animator; private static HashMap<Object, Tweener> sTweens = new HashMap<Object, Tweener>(); - public Tweener(Object obj, ObjectAnimator anim) { - object = obj; + public Tweener(ObjectAnimator anim) { animator = anim; } + private static void remove(Animator animator) { + Iterator<Entry<Object, Tweener>> iter = sTweens.entrySet().iterator(); + while (iter.hasNext()) { + Entry<Object, Tweener> entry = iter.next(); + if (entry.getValue().animator == animator) { + if (DEBUG) Log.v(TAG, "Removing tweener " + sTweens.get(entry.getKey()) + + " sTweens.size() = " + sTweens.size()); + iter.remove(); + break; // an animator can only be attached to one object + } + } + } + public static Tweener to(Object object, long duration, Object... vars) { long delay = 0; AnimatorUpdateListener updateListener = null; @@ -77,32 +94,35 @@ class Tweener { // Re-use existing tween, if present Tweener tween = sTweens.get(object); + ObjectAnimator anim = null; if (tween == null) { - ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(object, + anim = ObjectAnimator.ofPropertyValuesHolder(object, props.toArray(new PropertyValuesHolder[props.size()])); - tween = new Tweener(object, anim); + tween = new Tweener(anim); sTweens.put(object, tween); + if (DEBUG) Log.v(TAG, "Added new Tweener " + tween); } else { - tween.animator.cancel(); - replace(props, object); + anim = sTweens.get(object).animator; + replace(props, object); // Cancel all animators for given object } if (interpolator != null) { - tween.animator.setInterpolator(interpolator); + anim.setInterpolator(interpolator); } // Update animation with properties discovered in loop above - tween.animator.setStartDelay(delay); - tween.animator.setDuration(duration); + anim.setStartDelay(delay); + anim.setDuration(duration); if (updateListener != null) { - tween.animator.removeAllUpdateListeners(); // There should be only one - tween.animator.addUpdateListener(updateListener); + anim.removeAllUpdateListeners(); // There should be only one + anim.addUpdateListener(updateListener); } if (listener != null) { - tween.animator.removeAllListeners(); // There should be only one. - tween.animator.addListener(listener); + anim.removeAllListeners(); // There should be only one. + anim.addListener(listener); } - tween.animator.start(); + anim.addListener(mCleanupListener); + anim.start(); return tween; } @@ -114,18 +134,40 @@ class Tweener { return Tweener.to(object, duration, vars); } - static void replace(ArrayList<PropertyValuesHolder> props, Object... args) { + // Listener to watch for completed animations and remove them. + private static AnimatorListener mCleanupListener = new AnimatorListenerAdapter() { + + @Override + public void onAnimationEnd(Animator animation) { + remove(animation); + } + + @Override + public void onAnimationCancel(Animator animation) { + remove(animation); + } + }; + + public static void reset() { + if (DEBUG) { + Log.v(TAG, "Reset()"); + if (sTweens.size() > 0) { + Log.v(TAG, "Cleaning up " + sTweens.size() + " animations"); + } + } + sTweens.clear(); + } + + private static void replace(ArrayList<PropertyValuesHolder> props, Object... args) { for (final Object killobject : args) { Tweener tween = sTweens.get(killobject); if (tween != null) { - if (killobject == tween.object) { - tween.animator.cancel(); - if (props != null) { - tween.animator.setValues( - props.toArray(new PropertyValuesHolder[props.size()])); - } else { - sTweens.remove(tween); - } + tween.animator.cancel(); + if (props != null) { + tween.animator.setValues( + props.toArray(new PropertyValuesHolder[props.size()])); + } else { + sTweens.remove(tween); } } } diff --git a/core/jni/android/graphics/SurfaceTexture.cpp b/core/jni/android/graphics/SurfaceTexture.cpp index dd8b3780f06c..2de0932e540f 100644 --- a/core/jni/android/graphics/SurfaceTexture.cpp +++ b/core/jni/android/graphics/SurfaceTexture.cpp @@ -233,12 +233,6 @@ static jlong SurfaceTexture_getTimestamp(JNIEnv* env, jobject thiz) return surfaceTexture->getTimestamp(); } -static jint SurfaceTexture_getQueuedCount(JNIEnv* env, jobject thiz) -{ - sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz)); - return surfaceTexture->getQueuedCount(); -} - // ---------------------------------------------------------------------------- static JNINativeMethod gSurfaceTextureMethods[] = { @@ -249,7 +243,6 @@ static JNINativeMethod gSurfaceTextureMethods[] = { {"nativeUpdateTexImage", "()V", (void*)SurfaceTexture_updateTexImage }, {"nativeGetTransformMatrix", "([F)V", (void*)SurfaceTexture_getTransformMatrix }, {"nativeGetTimestamp", "()J", (void*)SurfaceTexture_getTimestamp }, - {"nativeGetQueuedCount", "()I", (void*)SurfaceTexture_getQueuedCount } }; int register_android_graphics_SurfaceTexture(JNIEnv* env) diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_handle_normal.png b/core/res/res/drawable-hdpi/ic_lockscreen_handle_normal.png Binary files differindex e21a87caa40c..0f4bfe6d0d1f 100644 --- a/core/res/res/drawable-hdpi/ic_lockscreen_handle_normal.png +++ b/core/res/res/drawable-hdpi/ic_lockscreen_handle_normal.png diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_handle_pressed.png b/core/res/res/drawable-hdpi/ic_lockscreen_handle_pressed.png Binary files differindex 3283f99a555e..995705dc607e 100644 --- a/core/res/res/drawable-hdpi/ic_lockscreen_handle_pressed.png +++ b/core/res/res/drawable-hdpi/ic_lockscreen_handle_pressed.png diff --git a/core/res/res/drawable-mdpi/ic_lockscreen_handle_normal.png b/core/res/res/drawable-mdpi/ic_lockscreen_handle_normal.png Binary files differindex c10344f83bba..754d7bc830e5 100644 --- a/core/res/res/drawable-mdpi/ic_lockscreen_handle_normal.png +++ b/core/res/res/drawable-mdpi/ic_lockscreen_handle_normal.png diff --git a/core/res/res/drawable-mdpi/ic_lockscreen_handle_pressed.png b/core/res/res/drawable-mdpi/ic_lockscreen_handle_pressed.png Binary files differindex 08c6cfe71bc6..0187a02afc21 100644 --- a/core/res/res/drawable-mdpi/ic_lockscreen_handle_pressed.png +++ b/core/res/res/drawable-mdpi/ic_lockscreen_handle_pressed.png diff --git a/core/res/res/drawable-xhdpi/ic_lockscreen_handle_normal.png b/core/res/res/drawable-xhdpi/ic_lockscreen_handle_normal.png Binary files differnew file mode 100644 index 000000000000..544924e4bcf9 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_lockscreen_handle_normal.png diff --git a/core/res/res/drawable-xhdpi/ic_lockscreen_handle_pressed.png b/core/res/res/drawable-xhdpi/ic_lockscreen_handle_pressed.png Binary files differnew file mode 100644 index 000000000000..2d28009f2235 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_lockscreen_handle_pressed.png diff --git a/core/res/res/values-sw600dp/config.xml b/core/res/res/values-sw600dp/config.xml index d6a0cdd7d4a7..13bbac60f5c8 100644 --- a/core/res/res/values-sw600dp/config.xml +++ b/core/res/res/values-sw600dp/config.xml @@ -23,9 +23,6 @@ <!-- see comment in values/config.xml --> <integer name="config_longPressOnPowerBehavior">2</integer> - <!-- Show sliding tab before lockscreen --> - <bool name="config_enableSlidingTabFirst">false</bool> - <!-- Enable lockscreen rotation --> <bool name="config_enableLockScreenRotation">true</bool> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 0ad3184fabda..827153e7243e 100755 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -3,16 +3,16 @@ /* ** Copyright 2009, The Android Open Source Project ** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at ** -** http://www.apache.org/licenses/LICENSE-2.0 +** http://www.apache.org/licenses/LICENSE-2.0 ** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and ** limitations under the License. */ --> @@ -54,25 +54,25 @@ connected. If you use the ims apn DCT will block any other apn from connecting until ims apn is connected--> <bool name="ImsConnectedDefaultValue">false</bool> - + <!-- Flag indicating whether the surface flinger is inefficient at performing a blur. Used by parts of the UI to turn off the blur effect where it isn't worth the performance hit. --> <bool name="config_sf_slowBlur">false</bool> - + <!-- The duration (in milliseconds) of a short animation. --> <integer name="config_shortAnimTime">200</integer> - + <!-- The duration (in milliseconds) of a medium-length animation. --> <integer name="config_mediumAnimTime">400</integer> - + <!-- The duration (in milliseconds) of a long animation. --> <integer name="config_longAnimTime">500</integer> <!-- The duration (in milliseconds) of the activity open/close and fragment open/close animations. --> <integer name="config_activityShortDur">150</integer> <integer name="config_activityDefaultDur">220</integer> - + <!-- Duration for the dim animation behind a dialog. This may be either a percentage, which is relative to the duration of the enter/open animation of the window being shown that is dimming behind, or it may @@ -83,11 +83,11 @@ maximum (let them grow as large as the screen). Actual values are specified for -large and -xlarge configurations. --> <dimen name="config_prefDialogWidth">320dp</dimen> - + <!-- Whether dialogs should close automatically when the user touches outside of them. This should not normally be modified. --> <bool name="config_closeDialogWhenTouchOutside">false</bool> - + <!-- The duration (in milliseconds) that the radio will scan for a signal when there's no network connection. If the scan doesn't timeout, use zero --> <integer name="config_radioScanningTimeout">0</integer> @@ -202,7 +202,7 @@ the slider is open. This can be set or unset depending how easily the slider can be opened (for example, in a pocket or purse). --> <bool name="config_bypass_keyguard_if_slider_open">true</bool> - + <!-- Flag indicating whether the we should enable the automatic brightness in Settings. Software implementation will be used if config_hardware_auto_brightness_available is not set --> <bool name="config_automatic_brightness_available">false</bool> @@ -212,10 +212,10 @@ <!-- If this is true, the screen will come on when you unplug usb/power/whatever. --> <bool name="config_unplugTurnsOnScreen">false</bool> - + <!-- If this is true, the screen will fade off. --> <bool name="config_animateScreenLights">true</bool> - + <!-- XXXXXX END OF RESOURCES USING WRONG NAMING CONVENTION --> <!-- If true, the screen can be rotated via the accelerometer in all 4 @@ -300,7 +300,7 @@ <item>20</item> <item>21</item> </integer-array> - + <!-- Vibrator pattern for feedback about touching a virtual key --> <integer-array name="config_virtualKeyVibePattern"> <item>0</item> @@ -380,8 +380,8 @@ <!-- Allow the menu hard key to be disabled in LockScreen on some devices --> <bool name="config_disableMenuKeyInLockScreen">false</bool> - <!-- Show sliding tab before lockscreen --> - <bool name="config_enableSlidingTabFirst">true</bool> + <!-- Don't show lock screen before unlock screen (PIN/pattern/password) --> + <bool name="config_enableLockBeforeUnlockScreen">false</bool> <!-- Diable lockscreen rotation by default --> <bool name="config_enableLockScreenRotation">false</bool> @@ -460,7 +460,7 @@ This feature should be disabled for most devices. --> <integer name="config_virtualKeyQuietTimeMillis">0</integer> - <!-- Component name of the default wallpaper. This will be ImageWallpaper if not + <!-- Component name of the default wallpaper. This will be ImageWallpaper if not specified --> <string name="default_wallpaper_component">@null</string> diff --git a/graphics/java/android/graphics/SurfaceTexture.java b/graphics/java/android/graphics/SurfaceTexture.java index adb6eac3e6d5..90a7ac22335b 100644 --- a/graphics/java/android/graphics/SurfaceTexture.java +++ b/graphics/java/android/graphics/SurfaceTexture.java @@ -144,10 +144,6 @@ public class SurfaceTexture { */ public void updateTexImage() { nativeUpdateTexImage(); - if (nativeGetQueuedCount() > 0) { - Message m = mEventHandler.obtainMessage(); - mEventHandler.sendMessage(m); - } } /** diff --git a/include/gui/SurfaceTexture.h b/include/gui/SurfaceTexture.h index e558dfd6c252..c82fb9b77ed4 100644 --- a/include/gui/SurfaceTexture.h +++ b/include/gui/SurfaceTexture.h @@ -46,11 +46,14 @@ public: enum { NUM_BUFFER_SLOTS = 32 }; struct FrameAvailableListener : public virtual RefBase { - // onFrameAvailable() is called from queueBuffer() is the FIFO is - // empty. You can use SurfaceTexture::getQueuedCount() to - // figure out if there are more frames waiting. - // This is called without any lock held can be called concurrently by - // multiple threads. + // onFrameAvailable() is called from queueBuffer() each time an + // additional frame becomes available for consumption. This means that + // frames that are queued while in asynchronous mode only trigger the + // callback if no previous frames are pending. Frames queued while in + // synchronous mode always trigger the callback. + // + // This is called without any lock held and can be called concurrently + // by multiple threads. virtual void onFrameAvailable() = 0; }; @@ -101,11 +104,6 @@ public: // target texture belongs is bound to the calling thread. status_t updateTexImage(); - // getqueuedCount returns the number of queued frames waiting in the - // FIFO. In asynchronous mode, this always returns 0 or 1 since - // frames are not accumulating in the FIFO. - size_t getQueuedCount() const; - // setBufferCountServer set the buffer count. If the client has requested // a buffer count using setBufferCount, the server-buffer count will // take effect once the client sets the count back to zero. diff --git a/include/media/stagefright/MPEG2TSWriter.h b/include/media/stagefright/MPEG2TSWriter.h index f2c65057b809..e4c1c49a72d6 100644 --- a/include/media/stagefright/MPEG2TSWriter.h +++ b/include/media/stagefright/MPEG2TSWriter.h @@ -31,6 +31,10 @@ struct MPEG2TSWriter : public MediaWriter { MPEG2TSWriter(int fd); MPEG2TSWriter(const char *filename); + MPEG2TSWriter( + void *cookie, + ssize_t (*write)(void *cookie, const void *data, size_t size)); + virtual status_t addSource(const sp<MediaSource> &source); virtual status_t start(MetaData *param = NULL); virtual status_t stop(); @@ -51,6 +55,10 @@ private: struct SourceInfo; FILE *mFile; + + void *mWriteCookie; + ssize_t (*mWriteFunc)(void *cookie, const void *data, size_t size); + sp<ALooper> mLooper; sp<AHandlerReflector<MPEG2TSWriter> > mReflector; @@ -69,6 +77,8 @@ private: void writeProgramMap(); void writeAccessUnit(int32_t sourceIndex, const sp<ABuffer> &buffer); + ssize_t internalWrite(const void *data, size_t size); + DISALLOW_EVIL_CONSTRUCTORS(MPEG2TSWriter); }; diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h index 589cefda2038..92331a16f96a 100644 --- a/include/media/stagefright/OMXCodec.h +++ b/include/media/stagefright/OMXCodec.h @@ -79,6 +79,13 @@ struct OMXCodec : public MediaSource, // from MediaBufferObserver virtual void signalBufferReturned(MediaBuffer *buffer); + // for use by ACodec + static void findMatchingCodecs( + const char *mime, + bool createEncoder, const char *matchComponentName, + uint32_t flags, + Vector<String8> *matchingCodecs); + protected: virtual ~OMXCodec(); @@ -311,12 +318,6 @@ private: static uint32_t getComponentQuirks( const char *componentName, bool isEncoder); - static void findMatchingCodecs( - const char *mime, - bool createEncoder, const char *matchComponentName, - uint32_t flags, - Vector<String8> *matchingCodecs); - void restorePatchedDataPointer(BufferInfo *info); status_t applyRotation(); diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp index 37e6d1187db8..0925001965dd 100644 --- a/libs/gui/SurfaceTexture.cpp +++ b/libs/gui/SurfaceTexture.cpp @@ -417,17 +417,22 @@ status_t SurfaceTexture::queueBuffer(int buf, int64_t timestamp) { return -EINVAL; } - if (mQueue.empty()) { - listener = mFrameAvailableListener; - } - if (mSynchronousMode) { - // in synchronous mode we queue all buffers in a FIFO + // In synchronous mode we queue all buffers in a FIFO. mQueue.push_back(buf); + + // Synchronous mode always signals that an additional frame should + // be consumed. + listener = mFrameAvailableListener; } else { - // in asynchronous mode we only keep the most recent buffer + // In asynchronous mode we only keep the most recent buffer. if (mQueue.empty()) { mQueue.push_back(buf); + + // Asynchronous mode only signals that a frame should be + // consumed if no previous frame was pending. If a frame were + // pending then the consumer would have already been notified. + listener = mFrameAvailableListener; } else { Fifo::iterator front(mQueue.begin()); // buffer currently queued is freed @@ -483,24 +488,14 @@ status_t SurfaceTexture::setTransform(uint32_t transform) { status_t SurfaceTexture::updateTexImage() { LOGV("SurfaceTexture::updateTexImage"); - Mutex::Autolock lock(mMutex); - int buf = mCurrentTexture; + // In asynchronous mode the list is guaranteed to be one buffer + // deep, while in synchronous mode we use the oldest buffer. if (!mQueue.empty()) { - // in asynchronous mode the list is guaranteed to be one buffer deep, - // while in synchronous mode we use the oldest buffer Fifo::iterator front(mQueue.begin()); - buf = *front; - mQueue.erase(front); - if (mQueue.isEmpty()) { - mDequeueCondition.signal(); - } - } + int buf = *front; - // Initially both mCurrentTexture and buf are INVALID_BUFFER_SLOT, - // so this check will fail until a buffer gets queued. - if (mCurrentTexture != buf) { // Update the GL texture object. EGLImageKHR image = mSlots[buf].mEglImage; if (image == EGL_NO_IMAGE_KHR) { @@ -538,7 +533,7 @@ status_t SurfaceTexture::updateTexImage() { } if (mCurrentTexture != INVALID_BUFFER_SLOT) { - // the current buffer becomes FREE if it was still in the queued + // The current buffer becomes FREE if it was still in the queued // state. If it has already been given to the client // (synchronous mode), then it stays in DEQUEUED state. if (mSlots[mCurrentTexture].mBufferState == BufferSlot::QUEUED) @@ -553,17 +548,17 @@ status_t SurfaceTexture::updateTexImage() { mCurrentTransform = mSlots[buf].mTransform; mCurrentTimestamp = mSlots[buf].mTimestamp; computeCurrentTransformMatrix(); + + // Now that we've passed the point at which failures can happen, + // it's safe to remove the buffer from the front of the queue. + mQueue.erase(front); mDequeueCondition.signal(); } else { // We always bind the texture even if we don't update its contents. glBindTexture(mCurrentTextureTarget, mTexName); } - return OK; -} -size_t SurfaceTexture::getQueuedCount() const { - Mutex::Autolock lock(mMutex); - return mQueue.size(); + return OK; } bool SurfaceTexture::isExternalFormat(uint32_t format) diff --git a/libs/gui/tests/SurfaceTexture_test.cpp b/libs/gui/tests/SurfaceTexture_test.cpp index f219639a0627..dfa9211afac5 100644 --- a/libs/gui/tests/SurfaceTexture_test.cpp +++ b/libs/gui/tests/SurfaceTexture_test.cpp @@ -419,6 +419,31 @@ protected: ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); } + class FrameWaiter : public SurfaceTexture::FrameAvailableListener { + public: + FrameWaiter(): + mPendingFrames(0) { + } + + void waitForFrame() { + Mutex::Autolock lock(mMutex); + while (mPendingFrames == 0) { + mCondition.wait(mMutex); + } + mPendingFrames--; + } + + virtual void onFrameAvailable() { + Mutex::Autolock lock(mMutex); + mPendingFrames++; + mCondition.signal(); + } + + int mPendingFrames; + Mutex mMutex; + Condition mCondition; + }; + sp<SurfaceTexture> mST; sp<SurfaceTextureClient> mSTC; sp<ANativeWindow> mANW; @@ -648,6 +673,157 @@ TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BufferWithCrop) { } } +// This test is intended to catch synchronization bugs between the CPU-written +// and GPU-read buffers. +TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BuffersRepeatedly) { + enum { texWidth = 16 }; + enum { texHeight = 16 }; + enum { numFrames = 1024 }; + + ASSERT_EQ(NO_ERROR, mST->setSynchronousMode(true)); + ASSERT_EQ(NO_ERROR, mST->setBufferCountServer(2)); + ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(), + texWidth, texHeight, HAL_PIXEL_FORMAT_YV12)); + ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(), + GRALLOC_USAGE_SW_WRITE_OFTEN)); + + struct TestPixel { + int x; + int y; + }; + const TestPixel testPixels[] = { + { 4, 11 }, + { 12, 14 }, + { 7, 2 }, + }; + enum {numTestPixels = sizeof(testPixels) / sizeof(testPixels[0])}; + + class ProducerThread : public Thread { + public: + ProducerThread(const sp<ANativeWindow>& anw, const TestPixel* testPixels): + mANW(anw), + mTestPixels(testPixels) { + } + + virtual ~ProducerThread() { + } + + virtual bool threadLoop() { + for (int i = 0; i < numFrames; i++) { + ANativeWindowBuffer* anb; + if (mANW->dequeueBuffer(mANW.get(), &anb) != NO_ERROR) { + return false; + } + if (anb == NULL) { + return false; + } + + sp<GraphicBuffer> buf(new GraphicBuffer(anb, false)); + if (mANW->lockBuffer(mANW.get(), buf->getNativeBuffer()) + != NO_ERROR) { + return false; + } + + const int yuvTexOffsetY = 0; + int stride = buf->getStride(); + int yuvTexStrideY = stride; + int yuvTexOffsetV = yuvTexStrideY * texHeight; + int yuvTexStrideV = (yuvTexStrideY/2 + 0xf) & ~0xf; + int yuvTexOffsetU = yuvTexOffsetV + yuvTexStrideV * texHeight/2; + int yuvTexStrideU = yuvTexStrideV; + + uint8_t* img = NULL; + buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img)); + + // Gray out all the test pixels first, so we're more likely to + // see a failure if GL is still texturing from the buffer we + // just dequeued. + for (int j = 0; j < numTestPixels; j++) { + int x = mTestPixels[j].x; + int y = mTestPixels[j].y; + uint8_t value = 128; + img[y*stride + x] = value; + } + + // Fill the buffer with gray. + for (int y = 0; y < texHeight; y++) { + for (int x = 0; x < texWidth; x++) { + img[yuvTexOffsetY + y*yuvTexStrideY + x] = 128; + img[yuvTexOffsetU + (y/2)*yuvTexStrideU + x/2] = 128; + img[yuvTexOffsetV + (y/2)*yuvTexStrideV + x/2] = 128; + } + } + + // Set the test pixels to either white or black. + for (int j = 0; j < numTestPixels; j++) { + int x = mTestPixels[j].x; + int y = mTestPixels[j].y; + uint8_t value = 0; + if (j == (i % numTestPixels)) { + value = 255; + } + img[y*stride + x] = value; + } + + buf->unlock(); + if (mANW->queueBuffer(mANW.get(), buf->getNativeBuffer()) + != NO_ERROR) { + return false; + } + } + return false; + } + + sp<ANativeWindow> mANW; + const TestPixel* mTestPixels; + }; + + sp<FrameWaiter> fw(new FrameWaiter); + mST->setFrameAvailableListener(fw); + + sp<Thread> pt(new ProducerThread(mANW, testPixels)); + pt->run(); + + glViewport(0, 0, texWidth, texHeight); + + glClearColor(0.2, 0.2, 0.2, 0.2); + glClear(GL_COLOR_BUFFER_BIT); + + // We wait for the first two frames up front so that the producer will be + // likely to dequeue the buffer that's currently being textured from. + fw->waitForFrame(); + fw->waitForFrame(); + + for (int i = 0; i < numFrames; i++) { + SCOPED_TRACE(String8::format("frame %d", i).string()); + + // We must wait for each frame to come in because if we ever do an + // updateTexImage call that doesn't consume a newly available buffer + // then the producer and consumer will get out of sync, which will cause + // a deadlock. + if (i > 1) { + fw->waitForFrame(); + } + mST->updateTexImage(); + drawTexture(); + + for (int j = 0; j < numTestPixels; j++) { + int x = testPixels[j].x; + int y = testPixels[j].y; + uint8_t value = 0; + if (j == (i % numTestPixels)) { + // We must y-invert the texture coords + EXPECT_TRUE(checkPixel(x, texHeight-y-1, 255, 255, 255, 255)); + } else { + // We must y-invert the texture coords + EXPECT_TRUE(checkPixel(x, texHeight-y-1, 0, 0, 0, 255)); + } + } + } + + pt->requestExitAndWait(); +} + // XXX: This test is disabled because there are currently no drivers that can // handle RGBA textures with the GL_TEXTURE_EXTERNAL_OES target. TEST_F(SurfaceTextureGLTest, DISABLED_TexturingFromCpuFilledRGBABufferNpot) { diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp index e43f6e55fb23..8b1caeeedf59 100644 --- a/libs/hwui/DisplayListRenderer.cpp +++ b/libs/hwui/DisplayListRenderer.cpp @@ -699,9 +699,10 @@ bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, uint32_t level) float* vertices = getFloats(verticesCount); bool hasColors = getInt(); int* colors = hasColors ? getInts(colorsCount) : NULL; + SkPaint* paint = getPaint(); DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]); - renderer.drawBitmapMesh(bitmap, meshWidth, meshHeight, vertices, colors, getPaint()); + renderer.drawBitmapMesh(bitmap, meshWidth, meshHeight, vertices, colors, paint); } break; case DrawPatch: { @@ -718,9 +719,15 @@ bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, uint32_t level) yDivs = getInts(yDivsCount); colors = getUInts(numColors); + float left = getFloat(); + float top = getFloat(); + float right = getFloat(); + float bottom = getFloat(); + SkPaint* paint = getPaint(); + DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]); renderer.drawPatch(bitmap, xDivs, yDivs, colors, xDivsCount, yDivsCount, - numColors, getFloat(), getFloat(), getFloat(), getFloat(), getPaint()); + numColors, left, top, right, bottom, paint); } break; case DrawColor: { @@ -799,15 +806,17 @@ bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, uint32_t level) case DrawLines: { int count = 0; float* points = getFloats(count); + SkPaint* paint = getPaint(); DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]); - renderer.drawLines(points, count, getPaint()); + renderer.drawLines(points, count, paint); } break; case DrawPoints: { int count = 0; float* points = getFloats(count); + SkPaint* paint = getPaint(); DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]); - renderer.drawPoints(points, count, getPaint()); + renderer.drawPoints(points, count, paint); } break; case DrawText: { diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp index d628301b5b71..513eda82f868 100644 --- a/media/libstagefright/ACodec.cpp +++ b/media/libstagefright/ACodec.cpp @@ -29,6 +29,7 @@ #include <media/stagefright/MediaDefs.h> #include <media/stagefright/NativeWindowWrapper.h> #include <media/stagefright/OMXClient.h> +#include <media/stagefright/OMXCodec.h> #include <surfaceflinger/Surface.h> #include <gui/SurfaceTextureClient.h> @@ -401,11 +402,22 @@ status_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) { CHECK(mem.get() != NULL); IOMX::buffer_id buffer; -#if 0 - err = mOMX->allocateBufferWithBackup(mNode, portIndex, mem, &buffer); -#else - err = mOMX->useBuffer(mNode, portIndex, mem, &buffer); -#endif + + if (!strcasecmp( + mComponentName.c_str(), "OMX.TI.DUCATI1.VIDEO.DECODER")) { + if (portIndex == kPortIndexInput && i == 0) { + // Only log this warning once per allocation round. + + LOGW("OMX.TI.DUCATI1.VIDEO.DECODER requires the use of " + "OMX_AllocateBuffer instead of the preferred " + "OMX_UseBuffer. Vendor must fix this."); + } + + err = mOMX->allocateBufferWithBackup( + mNode, portIndex, mem, &buffer); + } else { + err = mOMX->useBuffer(mNode, portIndex, mem, &buffer); + } if (err != OK) { return err; @@ -891,6 +903,7 @@ status_t ACodec::setSupportedOutputFormat() { CHECK(format.eColorFormat == OMX_COLOR_FormatYUV420Planar || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar || format.eColorFormat == OMX_COLOR_FormatCbYCrY + || format.eColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar || format.eColorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar); return mOMX->setParameter( @@ -1639,27 +1652,33 @@ void ACodec::UninitializedState::onSetup( AString mime; CHECK(msg->findString("mime", &mime)); + Vector<String8> matchingCodecs; + OMXCodec::findMatchingCodecs( + mime.c_str(), + false, // createEncoder + NULL, // matchComponentName + 0, // flags + &matchingCodecs); + + sp<CodecObserver> observer = new CodecObserver; + IOMX::node_id node = NULL; + AString componentName; - if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_AVC)) { - componentName = "OMX.Nvidia.h264.decode"; - } else if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_AUDIO_AAC)) { - componentName = "OMX.google.aac.decoder"; - } else if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_AUDIO_MPEG)) { - componentName = "OMX.Nvidia.mp3.decoder"; - } else if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_MPEG2)) { - componentName = "OMX.Nvidia.mpeg2v.decode"; - } else if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_MPEG4)) { - componentName = "OMX.google.mpeg4.decoder"; - } else { - TRESPASS(); - } + for (size_t matchIndex = 0; matchIndex < matchingCodecs.size(); + ++matchIndex) { + componentName = matchingCodecs.itemAt(matchIndex).string(); - sp<CodecObserver> observer = new CodecObserver; + status_t err = omx->allocateNode(componentName.c_str(), observer, &node); - IOMX::node_id node; - CHECK_EQ(omx->allocateNode(componentName.c_str(), observer, &node), - (status_t)OK); + if (err == OK) { + break; + } + + node = NULL; + } + + CHECK(node != NULL); sp<AMessage> notify = new AMessage(kWhatOMXMessage, mCodec->id()); observer->setNotificationMessage(notify); diff --git a/media/libstagefright/MPEG2TSWriter.cpp b/media/libstagefright/MPEG2TSWriter.cpp index 4e4f2898b622..02eeb40030c4 100644 --- a/media/libstagefright/MPEG2TSWriter.cpp +++ b/media/libstagefright/MPEG2TSWriter.cpp @@ -466,6 +466,8 @@ bool MPEG2TSWriter::SourceInfo::eosReceived() const { MPEG2TSWriter::MPEG2TSWriter(int fd) : mFile(fdopen(dup(fd), "wb")), + mWriteCookie(NULL), + mWriteFunc(NULL), mStarted(false), mNumSourcesDone(0), mNumTSPacketsWritten(0), @@ -475,6 +477,21 @@ MPEG2TSWriter::MPEG2TSWriter(int fd) MPEG2TSWriter::MPEG2TSWriter(const char *filename) : mFile(fopen(filename, "wb")), + mWriteCookie(NULL), + mWriteFunc(NULL), + mStarted(false), + mNumSourcesDone(0), + mNumTSPacketsWritten(0), + mNumTSPacketsBeforeMeta(0) { + init(); +} + +MPEG2TSWriter::MPEG2TSWriter( + void *cookie, + ssize_t (*write)(void *cookie, const void *data, size_t size)) + : mFile(NULL), + mWriteCookie(cookie), + mWriteFunc(write), mStarted(false), mNumSourcesDone(0), mNumTSPacketsWritten(0), @@ -483,7 +500,7 @@ MPEG2TSWriter::MPEG2TSWriter(const char *filename) } void MPEG2TSWriter::init() { - CHECK(mFile != NULL); + CHECK(mFile != NULL || mWriteFunc != NULL); mLooper = new ALooper; mLooper->setName("MPEG2TSWriter"); @@ -502,8 +519,10 @@ MPEG2TSWriter::~MPEG2TSWriter() { mLooper->unregisterHandler(mReflector->id()); mLooper->stop(); - fclose(mFile); - mFile = NULL; + if (mFile != NULL) { + fclose(mFile); + mFile = NULL; + } } status_t MPEG2TSWriter::addSource(const sp<MediaSource> &source) { @@ -718,7 +737,7 @@ void MPEG2TSWriter::writeProgramAssociationTable() { static const unsigned kContinuityCounter = 5; buffer->data()[3] |= kContinuityCounter; - CHECK_EQ(fwrite(buffer->data(), 1, buffer->size(), mFile), buffer->size()); + CHECK_EQ(internalWrite(buffer->data(), buffer->size()), buffer->size()); } void MPEG2TSWriter::writeProgramMap() { @@ -794,7 +813,7 @@ void MPEG2TSWriter::writeProgramMap() { *ptr++ = 0x00; *ptr++ = 0x00; - CHECK_EQ(fwrite(buffer->data(), 1, buffer->size(), mFile), buffer->size()); + CHECK_EQ(internalWrite(buffer->data(), buffer->size()), buffer->size()); } void MPEG2TSWriter::writeAccessUnit( @@ -890,7 +909,7 @@ void MPEG2TSWriter::writeAccessUnit( memcpy(ptr, accessUnit->data(), copy); - CHECK_EQ(fwrite(buffer->data(), 1, buffer->size(), mFile), buffer->size()); + CHECK_EQ(internalWrite(buffer->data(), buffer->size()), buffer->size()); size_t offset = copy; while (offset < accessUnit->size()) { @@ -923,7 +942,7 @@ void MPEG2TSWriter::writeAccessUnit( } memcpy(ptr, accessUnit->data() + offset, copy); - CHECK_EQ(fwrite(buffer->data(), 1, buffer->size(), mFile), + CHECK_EQ(internalWrite(buffer->data(), buffer->size()), buffer->size()); offset += copy; @@ -939,5 +958,13 @@ void MPEG2TSWriter::writeTS() { } } +ssize_t MPEG2TSWriter::internalWrite(const void *data, size_t size) { + if (mFile != NULL) { + return fwrite(data, 1, size, mFile); + } + + return (*mWriteFunc)(mWriteCookie, data, size); +} + } // namespace android diff --git a/native/include/android/input.h b/native/include/android/input.h index 26cac50cb169..0d8ea2841ea5 100644 --- a/native/include/android/input.h +++ b/native/include/android/input.h @@ -404,7 +404,6 @@ enum { AMOTION_EVENT_BUTTON_TERTIARY = 1 << 2, AMOTION_EVENT_BUTTON_BACK = 1 << 3, AMOTION_EVENT_BUTTON_FORWARD = 1 << 4, - AMOTION_EVENT_BUTTON_ERASER = 1 << 5, }; /* diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java index a9aa31b61284..946960122565 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java @@ -531,7 +531,12 @@ public class SettingsBackupAgent extends BackupAgentHelper { private void restoreFileData(String filename, BackupDataInput data) { byte[] bytes = new byte[data.getDataSize()]; if (bytes.length <= 0) return; - restoreFileData(filename, bytes, bytes.length); + try { + data.readEntityData(bytes, 0, data.getDataSize()); + restoreFileData(filename, bytes, bytes.length); + } catch (IOException e) { + Log.w(TAG, "Unable to read file data for " + filename); + } } private void restoreFileData(String filename, byte[] bytes, int size) { diff --git a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java index eea30407af55..b60bae7d49eb 100644 --- a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java +++ b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java @@ -682,8 +682,9 @@ public class LockPatternKeyguardView extends KeyguardViewBase { final boolean usingLockPattern = mLockPatternUtils.getKeyguardStoredPasswordQuality() == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING; - boolean showSlidingTab = getResources().getBoolean(R.bool.config_enableSlidingTabFirst); - if (isSecure() && (usingLockPattern || !showSlidingTab)) { + boolean showLockBeforeUnlock = getResources() + .getBoolean(R.bool.config_enableLockBeforeUnlockScreen); + if (isSecure() && (usingLockPattern || !showLockBeforeUnlock)) { return Mode.UnlockScreen; } else { return Mode.LockScreen; diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp index 3e4c66691cb0..5a25f8cc9584 100644 --- a/services/input/InputReader.cpp +++ b/services/input/InputReader.cpp @@ -154,14 +154,15 @@ static uint32_t getButtonStateForScanCode(int32_t scanCode) { case BTN_LEFT: return AMOTION_EVENT_BUTTON_PRIMARY; case BTN_RIGHT: + case BTN_STYLUS: return AMOTION_EVENT_BUTTON_SECONDARY; case BTN_MIDDLE: + case BTN_STYLUS2: return AMOTION_EVENT_BUTTON_TERTIARY; case BTN_SIDE: return AMOTION_EVENT_BUTTON_BACK; - case BTN_EXTRA: - return AMOTION_EVENT_BUTTON_FORWARD; case BTN_FORWARD: + case BTN_EXTRA: return AMOTION_EVENT_BUTTON_FORWARD; case BTN_BACK: return AMOTION_EVENT_BUTTON_BACK; @@ -176,8 +177,7 @@ static uint32_t getButtonStateForScanCode(int32_t scanCode) { static bool isPointerDown(int32_t buttonState) { return buttonState & (AMOTION_EVENT_BUTTON_PRIMARY | AMOTION_EVENT_BUTTON_SECONDARY - | AMOTION_EVENT_BUTTON_TERTIARY - | AMOTION_EVENT_BUTTON_ERASER); + | AMOTION_EVENT_BUTTON_TERTIARY); } static int32_t calculateEdgeFlagsUsingPointerBounds( diff --git a/services/java/com/android/server/am/BatteryStatsService.java b/services/java/com/android/server/am/BatteryStatsService.java index b4fdc9f3c0ff..293702dfe750 100644 --- a/services/java/com/android/server/am/BatteryStatsService.java +++ b/services/java/com/android/server/am/BatteryStatsService.java @@ -446,6 +446,15 @@ public final class BatteryStatsService extends IBatteryStats.Stub { Binder.getCallingPid(), Binder.getCallingUid(), null); } + private void dumpHelp(PrintWriter pw) { + pw.println("Battery stats (batteryinfo) dump options:"); + pw.println(" [--checkin] [--reset] [--write] [-h]"); + pw.println(" --checkin: format output for a checkin report."); + pw.println(" --reset: reset the stats, clearing all current data."); + pw.println(" --write: force write current collected stats to disk."); + pw.println(" -h: print this help text."); + } + @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { boolean isCheckin = false; @@ -466,8 +475,12 @@ public final class BatteryStatsService extends IBatteryStats.Stub { pw.println("Battery stats written."); noOutput = true; } + } else if ("-h".equals(arg)) { + dumpHelp(pw); + return; } else { pw.println("Unknown option: " + arg); + dumpHelp(pw); } } } diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 2bab6a8fe18b..35e29a6315a8 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -101,9 +101,8 @@ Layer::~Layer() } void Layer::onFrameQueued() { - if (android_atomic_or(1, &mQueuedFrames) == 0) { - mFlinger->signalEvent(); - } + android_atomic_inc(&mQueuedFrames); + mFlinger->signalEvent(); } // called with SurfaceFlinger::mStateLock as soon as the layer is entered @@ -406,20 +405,18 @@ bool Layer::isCropped() const { void Layer::lockPageFlip(bool& recomputeVisibleRegions) { - if (android_atomic_and(0, &mQueuedFrames)) { + if (mQueuedFrames > 0) { + // signal another event if we have more frames pending + if (android_atomic_dec(&mQueuedFrames) > 1) { + mFlinger->signalEvent(); + } + if (mSurfaceTexture->updateTexImage() < NO_ERROR) { // something happened! recomputeVisibleRegions = true; return; } - // signal another event if we have more frames waiting - if (mSurfaceTexture->getQueuedCount()) { - if (android_atomic_or(1, &mQueuedFrames) == 0) { - mFlinger->signalEvent(); - } - } - mActiveBuffer = mSurfaceTexture->getCurrentBuffer(); mSurfaceTexture->getTransformMatrix(mTextureMatrix); |