diff options
21 files changed, 337 insertions, 172 deletions
@@ -644,28 +644,6 @@ $(full_target): $(framework_built) $(gen) .PHONY: checkbuild checkbuild: doc-comment-check-docs -# ==== static html in the pdk ================================== -include $(CLEAR_VARS) - -LOCAL_INTERMEDIATE_SOURCES:=$(framework_docs_LOCAL_INTERMEDIATE_SOURCES) -LOCAL_JAVA_LIBRARIES:=$(framework_docs_LOCAL_JAVA_LIBRARIES) -LOCAL_MODULE_CLASS:=$(framework_docs_LOCAL_MODULE_CLASS) -LOCAL_DROIDDOC_SOURCE_PATH:=$(framework_docs_LOCAL_DROIDDOC_SOURCE_PATH) -LOCAL_DROIDDOC_HTML_DIR:=../../vendor/pdk/data/google/docs -LOCAL_ADDITIONAL_JAVA_DIR:=$(framework_docs_LOCAL_ADDITIONAL_JAVA_DIR) -LOCAL_ADDITIONAL_DEPENDENCIES:=$(framework_docs_LOCAL_ADDITIONAL_DEPENDENCIES) - -LOCAL_MODULE := offline-pdk - -LOCAL_DROIDDOC_OPTIONS:=\ - -hdf android.whichdoc offline \ - -hdf android.whichmodule $(LOCAL_MODULE) - -LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=build/tools/droiddoc/templates-pdk - -include $(BUILD_DROIDDOC) - - # ==== static html in the sdk ================================== include $(CLEAR_VARS) diff --git a/api/current.txt b/api/current.txt index a80c27f..262596a 100644 --- a/api/current.txt +++ b/api/current.txt @@ -2951,6 +2951,7 @@ package android.app { field public int id; field public android.content.ComponentName origActivity; field public int persistentId; + field public int stackId; } public static class ActivityManager.RunningAppProcessInfo implements android.os.Parcelable { diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index 729ebd7..1f6f421 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -452,14 +452,21 @@ public class ActivityManager { * Description of the task's last state. */ public CharSequence description; - + + /** + * The id of the ActivityStack this Task was on most recently. + */ + public int stackId; + public RecentTaskInfo() { } + @Override public int describeContents() { return 0; } + @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(id); dest.writeInt(persistentId); @@ -472,6 +479,7 @@ public class ActivityManager { ComponentName.writeToParcel(origActivity, dest); TextUtils.writeToParcel(description, dest, Parcelable.PARCELABLE_WRITE_RETURN_VALUE); + dest.writeInt(stackId); } public void readFromParcel(Parcel source) { @@ -484,8 +492,9 @@ public class ActivityManager { } origActivity = ComponentName.readFromParcel(source); description = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source); + stackId = source.readInt(); } - + public static final Creator<RecentTaskInfo> CREATOR = new Creator<RecentTaskInfo>() { public RecentTaskInfo createFromParcel(Parcel source) { diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java index c41c35e..220b997 100644 --- a/core/java/android/provider/ContactsContract.java +++ b/core/java/android/provider/ContactsContract.java @@ -2383,7 +2383,7 @@ public final class ContactsContract { * parameters. The latter approach is preferable, especially when you can reuse the * URI: * <pre> - * Uri rawContactUri = RawContacts.URI.buildUpon() + * Uri rawContactUri = RawContacts.CONTENT_URI.buildUpon() * .appendQueryParameter(RawContacts.ACCOUNT_NAME, accountName) * .appendQueryParameter(RawContacts.ACCOUNT_TYPE, accountType) * .build(); diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index fc005d1..0c506d8 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -1601,7 +1601,7 @@ public final class ViewRootImpl implements ViewParent, if (mAttachInfo.mHardwareRenderer != null && mAttachInfo.mHardwareRenderer.isEnabled()) { - if (hwInitialized || windowShouldResize || + if (hwInitialized || mWidth != mAttachInfo.mHardwareRenderer.getWidth() || mHeight != mAttachInfo.mHardwareRenderer.getHeight()) { mAttachInfo.mHardwareRenderer.setup(mWidth, mHeight); diff --git a/core/jni/android/graphics/TextLayoutCache.cpp b/core/jni/android/graphics/TextLayoutCache.cpp index be14f58..cd84fff 100644 --- a/core/jni/android/graphics/TextLayoutCache.cpp +++ b/core/jni/android/graphics/TextLayoutCache.cpp @@ -318,6 +318,7 @@ hash_t TextLayoutCacheKey::hash() const { */ TextLayoutValue::TextLayoutValue(size_t contextCount) : mTotalAdvance(0), mElapsedTime(0) { + mBounds.setEmpty(); // Give a hint for advances and glyphs vectors size mAdvances.setCapacity(contextCount); mGlyphs.setCapacity(contextCount); @@ -345,11 +346,11 @@ TextLayoutShaper::~TextLayoutShaper() { hb_buffer_destroy(mBuffer); } -void TextLayoutShaper::computeValues(TextLayoutValue* value, const SkPaint* paint, const UChar* chars, - size_t start, size_t count, size_t contextCount, int dirFlags) { - +void TextLayoutShaper::computeValues(TextLayoutValue* value, const SkPaint* paint, + const UChar* chars, size_t start, size_t count, size_t contextCount, int dirFlags) { computeValues(paint, chars, start, count, contextCount, dirFlags, - &value->mAdvances, &value->mTotalAdvance, &value->mGlyphs, &value->mPos); + &value->mAdvances, &value->mTotalAdvance, &value->mBounds, + &value->mGlyphs, &value->mPos); #if DEBUG_ADVANCES ALOGD("Advances - start = %d, count = %d, contextCount = %d, totalAdvance = %f", start, count, contextCount, value->mTotalAdvance); @@ -358,7 +359,7 @@ void TextLayoutShaper::computeValues(TextLayoutValue* value, const SkPaint* pain void TextLayoutShaper::computeValues(const SkPaint* paint, const UChar* chars, size_t start, size_t count, size_t contextCount, int dirFlags, - Vector<jfloat>* const outAdvances, jfloat* outTotalAdvance, + Vector<jfloat>* const outAdvances, jfloat* outTotalAdvance, SkRect* outBounds, Vector<jchar>* const outGlyphs, Vector<jfloat>* const outPos) { *outTotalAdvance = 0; if (!count) { @@ -454,7 +455,7 @@ void TextLayoutShaper::computeValues(const SkPaint* paint, const UChar* chars, i, startRun, lengthRun, isRTL); #endif computeRunValues(paint, chars, startRun, lengthRun, contextCount, isRTL, - outAdvances, outTotalAdvance, outGlyphs, outPos); + outAdvances, outTotalAdvance, outBounds, outGlyphs, outPos); } } @@ -478,7 +479,7 @@ void TextLayoutShaper::computeValues(const SkPaint* paint, const UChar* chars, "-- run-start = %d, run-len = %d, isRTL = %d", start, count, isRTL); #endif computeRunValues(paint, chars, start, count, contextCount, isRTL, - outAdvances, outTotalAdvance, outGlyphs, outPos); + outAdvances, outTotalAdvance, outBounds, outGlyphs, outPos); } #if DEBUG_GLYPHS @@ -675,7 +676,7 @@ static void logGlyphs(hb_buffer_t* buffer) { void TextLayoutShaper::computeRunValues(const SkPaint* paint, const UChar* contextChars, size_t start, size_t count, size_t contextCount, bool isRTL, - Vector<jfloat>* const outAdvances, jfloat* outTotalAdvance, + Vector<jfloat>* const outAdvances, jfloat* outTotalAdvance, SkRect* outBounds, Vector<jchar>* const outGlyphs, Vector<jfloat>* const outPos) { if (!count) { // We cannot shape an empty run. @@ -749,12 +750,22 @@ void TextLayoutShaper::computeRunValues(const SkPaint* paint, const UChar* conte size_t cluster = info[i].cluster - start; float xAdvance = HBFixedToFloat(positions[i].x_advance); outAdvances->replaceAt(outAdvances->itemAt(cluster) + xAdvance, cluster); - outGlyphs->add(info[i].codepoint + glyphBaseCount); + jchar glyphId = info[i].codepoint + glyphBaseCount; + outGlyphs->add(glyphId); float xo = HBFixedToFloat(positions[i].x_offset); float yo = -HBFixedToFloat(positions[i].y_offset); - outPos->add(totalAdvance + xo + yo * skewX); - outPos->add(yo); + + float xpos = totalAdvance + xo + yo * skewX; + float ypos = yo; + outPos->add(xpos); + outPos->add(ypos); totalAdvance += xAdvance; + + // TODO: consider using glyph cache + const SkGlyph& metrics = mShapingPaint.getGlyphMetrics(glyphId, NULL); + outBounds->join(xpos + metrics.fLeft, ypos + metrics.fTop, + xpos + metrics.fLeft + metrics.fWidth, ypos + metrics.fTop + metrics.fHeight); + } } diff --git a/core/jni/android/graphics/TextLayoutCache.h b/core/jni/android/graphics/TextLayoutCache.h index 5414a11..ab6ac72 100644 --- a/core/jni/android/graphics/TextLayoutCache.h +++ b/core/jni/android/graphics/TextLayoutCache.h @@ -134,6 +134,7 @@ public: inline const jfloat* getAdvances() const { return mAdvances.array(); } inline size_t getAdvancesCount() const { return mAdvances.size(); } inline jfloat getTotalAdvance() const { return mTotalAdvance; } + inline const SkRect& getBounds() const { return mBounds; } inline const jchar* getGlyphs() const { return mGlyphs.array(); } inline size_t getGlyphsCount() const { return mGlyphs.size(); } inline const jfloat* getPos() const { return mPos.array(); } @@ -150,6 +151,11 @@ public: jfloat mTotalAdvance; /** + * Bounds containing all glyphs + */ + SkRect mBounds; + + /** * Glyphs vector */ Vector<jchar> mGlyphs; @@ -208,12 +214,12 @@ private: void computeValues(const SkPaint* paint, const UChar* chars, size_t start, size_t count, size_t contextCount, int dirFlags, - Vector<jfloat>* const outAdvances, jfloat* outTotalAdvance, + Vector<jfloat>* const outAdvances, jfloat* outTotalAdvance, SkRect* outBounds, Vector<jchar>* const outGlyphs, Vector<jfloat>* const outPos); void computeRunValues(const SkPaint* paint, const UChar* chars, size_t start, size_t count, size_t contextCount, bool isRTL, - Vector<jfloat>* const outAdvances, jfloat* outTotalAdvance, + Vector<jfloat>* const outAdvances, jfloat* outTotalAdvance, SkRect* outBounds, Vector<jchar>* const outGlyphs, Vector<jfloat>* const outPos); SkTypeface* setCachedTypeface(SkTypeface** typeface, hb_script_t script, SkTypeface::Style style); diff --git a/core/jni/android_os_SELinux.cpp b/core/jni/android_os_SELinux.cpp index 0a97f39..ca278cf 100644 --- a/core/jni/android_os_SELinux.cpp +++ b/core/jni/android_os_SELinux.cpp @@ -102,7 +102,7 @@ static jstring getPeerCon(JNIEnv *env, jobject, jobject fileDescriptor) { return NULL; } - security_context_t tmp; + security_context_t tmp = NULL; int ret = getpeercon(fd, &tmp); Unique_SecurityContext context(tmp); @@ -111,7 +111,7 @@ static jstring getPeerCon(JNIEnv *env, jobject, jobject fileDescriptor) { contextStr.reset(env->NewStringUTF(context.get())); } - ALOGV("getPeerCon(%d) => %s", fd, contextStr.get()); + ALOGV("getPeerCon(%d) => %s", fd, context.get()); return contextStr.release(); } @@ -198,7 +198,7 @@ static jstring getFileCon(JNIEnv *env, jobject, jstring pathStr) { return NULL; } - security_context_t tmp; + security_context_t tmp = NULL; int ret = getfilecon(path.c_str(), &tmp); Unique_SecurityContext context(tmp); @@ -224,7 +224,7 @@ static jstring getCon(JNIEnv *env, jobject) { return NULL; } - security_context_t tmp; + security_context_t tmp = NULL; int ret = getcon(&tmp); Unique_SecurityContext context(tmp); @@ -251,7 +251,7 @@ static jstring getPidCon(JNIEnv *env, jobject, jint pid) { return NULL; } - security_context_t tmp; + security_context_t tmp = NULL; int ret = getpidcon(static_cast<pid_t>(pid), &tmp); Unique_SecurityContext context(tmp); diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp index cd7a032..983a838 100644 --- a/core/jni/android_view_GLES20Canvas.cpp +++ b/core/jni/android_view_GLES20Canvas.cpp @@ -574,6 +574,20 @@ static void android_view_GLES20Canvas_resetPaintFilter(JNIEnv* env, jobject claz // Text // ---------------------------------------------------------------------------- +static float xOffsetForTextAlign(SkPaint* paint, float totalAdvance) { + switch (paint->getTextAlign()) { + case SkPaint::kCenter_Align: + return -totalAdvance / 2.0f; + break; + case SkPaint::kRight_Align: + return -totalAdvance; + break; + default: + break; + } + return 0; +} + static void renderText(OpenGLRenderer* renderer, const jchar* text, int count, jfloat x, jfloat y, int flags, SkPaint* paint) { sp<TextLayoutValue> value = TextLayoutEngine::getInstance().getValue(paint, @@ -586,8 +600,12 @@ static void renderText(OpenGLRenderer* renderer, const jchar* text, int count, jfloat totalAdvance = value->getTotalAdvance(); const float* positions = value->getPos(); int bytesCount = glyphsCount * sizeof(jchar); - renderer->drawText((const char*) glyphs, bytesCount, glyphsCount, x, y, - positions, paint, totalAdvance); + const SkRect& r = value->getBounds(); + android::uirenderer::Rect bounds(r.fLeft, r.fTop, r.fRight, r.fBottom); + + renderer->drawText((const char*) glyphs, bytesCount, glyphsCount, + x + xOffsetForTextAlign(paint, totalAdvance), y, positions, + paint, totalAdvance, bounds); } static void renderTextOnPath(OpenGLRenderer* renderer, const jchar* text, int count, @@ -617,8 +635,12 @@ static void renderTextRun(OpenGLRenderer* renderer, const jchar* text, jfloat totalAdvance = value->getTotalAdvance(); const float* positions = value->getPos(); int bytesCount = glyphsCount * sizeof(jchar); - renderer->drawText((const char*) glyphs, bytesCount, glyphsCount, x, y, - positions, paint, totalAdvance); + const SkRect& r = value->getBounds(); + android::uirenderer::Rect bounds(r.fLeft, r.fTop, r.fRight, r.fBottom); + + renderer->drawText((const char*) glyphs, bytesCount, glyphsCount, + x + xOffsetForTextAlign(paint, totalAdvance), y, positions, + paint, totalAdvance, bounds); } static void android_view_GLES20Canvas_drawTextArray(JNIEnv* env, jobject clazz, diff --git a/core/jni/android_view_InputEventReceiver.cpp b/core/jni/android_view_InputEventReceiver.cpp index c350521..8e1e04a 100644 --- a/core/jni/android_view_InputEventReceiver.cpp +++ b/core/jni/android_view_InputEventReceiver.cpp @@ -27,6 +27,7 @@ #include <android_runtime/AndroidRuntime.h> #include <utils/Log.h> #include <utils/Looper.h> +#include <utils/Vector.h> #include <utils/threads.h> #include <androidfw/InputTransport.h> #include "android_os_MessageQueue.h" @@ -61,11 +62,20 @@ protected: virtual ~NativeInputEventReceiver(); private: + struct Finish { + uint32_t seq; + bool handled; + }; + jobject mReceiverWeakGlobal; InputConsumer mInputConsumer; sp<MessageQueue> mMessageQueue; PreallocatedInputEventFactory mInputEventFactory; bool mBatchedInputEventPending; + int mFdEvents; + Vector<Finish> mFinishQueue; + + void setFdEvents(int events); const char* getInputChannelName() { return mInputConsumer.getChannel()->getName().string(); @@ -80,7 +90,7 @@ NativeInputEventReceiver::NativeInputEventReceiver(JNIEnv* env, const sp<MessageQueue>& messageQueue) : mReceiverWeakGlobal(env->NewGlobalRef(receiverWeak)), mInputConsumer(inputChannel), mMessageQueue(messageQueue), - mBatchedInputEventPending(false) { + mBatchedInputEventPending(false), mFdEvents(0) { #if DEBUG_DISPATCH_CYCLE ALOGD("channel '%s' ~ Initializing input event receiver.", getInputChannelName()); #endif @@ -92,8 +102,7 @@ NativeInputEventReceiver::~NativeInputEventReceiver() { } status_t NativeInputEventReceiver::initialize() { - int receiveFd = mInputConsumer.getChannel()->getFd(); - mMessageQueue->getLooper()->addFd(receiveFd, 0, ALOOPER_EVENT_INPUT, this, NULL); + setFdEvents(ALOOPER_EVENT_INPUT); return OK; } @@ -102,7 +111,7 @@ void NativeInputEventReceiver::dispose() { ALOGD("channel '%s' ~ Disposing input event receiver.", getInputChannelName()); #endif - mMessageQueue->getLooper()->removeFd(mInputConsumer.getChannel()->getFd()); + setFdEvents(0); } status_t NativeInputEventReceiver::finishInputEvent(uint32_t seq, bool handled) { @@ -112,12 +121,38 @@ status_t NativeInputEventReceiver::finishInputEvent(uint32_t seq, bool handled) status_t status = mInputConsumer.sendFinishedSignal(seq, handled); if (status) { + if (status == WOULD_BLOCK) { +#if DEBUG_DISPATCH_CYCLE + ALOGD("channel '%s' ~ Could not send finished signal immediately. " + "Enqueued for later.", getInputChannelName()); +#endif + Finish finish; + finish.seq = seq; + finish.handled = handled; + mFinishQueue.add(finish); + if (mFinishQueue.size() == 1) { + setFdEvents(ALOOPER_EVENT_INPUT | ALOOPER_EVENT_OUTPUT); + } + return OK; + } ALOGW("Failed to send finished signal on channel '%s'. status=%d", getInputChannelName(), status); } return status; } +void NativeInputEventReceiver::setFdEvents(int events) { + if (mFdEvents != events) { + mFdEvents = events; + int fd = mInputConsumer.getChannel()->getFd(); + if (events) { + mMessageQueue->getLooper()->addFd(fd, 0, events, this, NULL); + } else { + mMessageQueue->getLooper()->removeFd(fd); + } + } +} + int NativeInputEventReceiver::handleEvent(int receiveFd, int events, void* data) { if (events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP)) { #if DEBUG_DISPATCH_CYCLE @@ -130,16 +165,52 @@ int NativeInputEventReceiver::handleEvent(int receiveFd, int events, void* data) return 0; // remove the callback } - if (!(events & ALOOPER_EVENT_INPUT)) { - ALOGW("channel '%s' ~ Received spurious callback for unhandled poll event. " - "events=0x%x", getInputChannelName(), events); + if (events & ALOOPER_EVENT_INPUT) { + JNIEnv* env = AndroidRuntime::getJNIEnv(); + status_t status = consumeEvents(env, false /*consumeBatches*/, -1); + mMessageQueue->raiseAndClearException(env, "handleReceiveCallback"); + return status == OK || status == NO_MEMORY ? 1 : 0; + } + + if (events & ALOOPER_EVENT_OUTPUT) { + for (size_t i = 0; i < mFinishQueue.size(); i++) { + const Finish& finish = mFinishQueue.itemAt(i); + status_t status = mInputConsumer.sendFinishedSignal(finish.seq, finish.handled); + if (status) { + mFinishQueue.removeItemsAt(0, i); + + if (status == WOULD_BLOCK) { +#if DEBUG_DISPATCH_CYCLE + ALOGD("channel '%s' ~ Sent %u queued finish events; %u left.", + getInputChannelName(), i, mFinishQueue.size()); +#endif + return 1; // keep the callback, try again later + } + + ALOGW("Failed to send finished signal on channel '%s'. status=%d", + getInputChannelName(), status); + if (status != DEAD_OBJECT) { + JNIEnv* env = AndroidRuntime::getJNIEnv(); + String8 message; + message.appendFormat("Failed to finish input event. status=%d", status); + jniThrowRuntimeException(env, message.string()); + mMessageQueue->raiseAndClearException(env, "finishInputEvent"); + } + return 0; // remove the callback + } + } +#if DEBUG_DISPATCH_CYCLE + ALOGD("channel '%s' ~ Sent %u queued finish events; none left.", + getInputChannelName(), mFinishQueue.size()); +#endif + mFinishQueue.clear(); + setFdEvents(ALOOPER_EVENT_INPUT); return 1; } - JNIEnv* env = AndroidRuntime::getJNIEnv(); - status_t status = consumeEvents(env, false /*consumeBatches*/, -1); - mMessageQueue->raiseAndClearException(env, "handleReceiveCallback"); - return status == OK || status == NO_MEMORY ? 1 : 0; + ALOGW("channel '%s' ~ Received spurious callback for unhandled poll event. " + "events=0x%x", getInputChannelName(), events); + return 1; } status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env, diff --git a/docs/html/tools/device.jd b/docs/html/tools/device.jd index c7827b2..a1fb817 100644 --- a/docs/html/tools/device.jd +++ b/docs/html/tools/device.jd @@ -177,6 +177,10 @@ above.</p> <td><code>18d1</code></td> </tr> <tr> + <td>Haier</td> + <td><code>201E</code></td> + </tr> + <tr> <td>Hisense</td> <td><code>109b</code></td> </tr> diff --git a/libs/hwui/DeferredDisplayList.cpp b/libs/hwui/DeferredDisplayList.cpp index 9323a3a..512d3b1 100644 --- a/libs/hwui/DeferredDisplayList.cpp +++ b/libs/hwui/DeferredDisplayList.cpp @@ -85,8 +85,8 @@ public: } virtual status_t replay(OpenGLRenderer& renderer, Rect& dirty, int index) { - DEFER_LOGD("%d replaying DrawingBatch %p, with %d ops (batch id %x, merge id %p)", - index, this, mOps.size(), mOps[0]->getBatchId(), mOps[0]->getMergeId()); + DEFER_LOGD("%d replaying DrawBatch %p, with %d ops (batch id %x, merge id %p)", + index, this, mOps.size(), getBatchId(), getMergeId()); status_t status = DrawGlInfo::kStatusDone; DisplayListLogBuffer& logBuffer = DisplayListLogBuffer::getInstance(); @@ -145,7 +145,10 @@ public: * dropped, so we make simplifying qualifications on the ops that can merge, per op type. */ bool canMergeWith(DrawOp* op) { - if (!op->state.mMatrix.isPureTranslate()) return false; + if (getBatchId() == DeferredDisplayList::kOpBatch_Bitmap) { + // Bitmap batches can handle translate and scaling + if (!op->state.mMatrix.isSimple()) return false; + } else if (!op->state.mMatrix.isPureTranslate()) return false; bool isTextBatch = getBatchId() == DeferredDisplayList::kOpBatch_Text || getBatchId() == DeferredDisplayList::kOpBatch_ColorText; @@ -193,10 +196,10 @@ public: } virtual status_t replay(OpenGLRenderer& renderer, Rect& dirty, int index) { - DEFER_LOGD("%d replaying DrawingBatch %p, with %d ops (batch id %x, merge id %p)", + DEFER_LOGD("%d replaying MergingDrawBatch %p, with %d ops (batch id %x, merge id %p)", index, this, mOps.size(), getBatchId(), getMergeId()); if (mOps.size() == 1) { - return DrawBatch::replay(renderer, dirty, false); + return DrawBatch::replay(renderer, dirty, 0); } DrawOp* op = mOps[0]; diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h index 990372e..6839b18 100644 --- a/libs/hwui/DisplayListOp.h +++ b/libs/hwui/DisplayListOp.h @@ -220,6 +220,9 @@ public: DrawBoundedOp(float left, float top, float right, float bottom, SkPaint* paint) : DrawOp(paint), mLocalBounds(left, top, right, bottom) {} + DrawBoundedOp(const Rect& localBounds, SkPaint* paint) + : DrawOp(paint), mLocalBounds(localBounds) {} + // Calculates bounds as smallest rect encompassing all points // NOTE: requires at least 1 vertex, and doesn't account for stroke size (should be handled in // subclass' constructor) @@ -757,10 +760,16 @@ public: TextureVertex vertices[6 * ops.size()]; TextureVertex* vertex = &vertices[0]; + bool transformed = false; + // TODO: manually handle rect clip for bitmaps by adjusting texCoords per op, // and allowing them to be merged in getBatchId() for (unsigned int i = 0; i < ops.size(); i++) { const Rect& opBounds = ops[i]->state.mBounds; + // When we reach multiDraw(), the matrix can be either + // pureTranslate or simple (translate and/or scale). + // If the matrix is not pureTranslate, then we have a scale + if (!ops[i]->state.mMatrix.isPureTranslate()) transformed = true; Rect texCoords(0, 0, 1, 1); ((DrawBitmapOp*) ops[i])->mUvMapper.map(texCoords); @@ -774,7 +783,8 @@ public: SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, bottom); } - return renderer.drawBitmaps(mBitmap, ops.size(), &vertices[0], bounds, mPaint); + return renderer.drawBitmaps(mBitmap, ops.size(), &vertices[0], + transformed, bounds, mPaint); } virtual void output(int level, uint32_t logFlags) { @@ -783,13 +793,18 @@ public: virtual const char* name() { return "DrawBitmap"; } + bool bitmapMergeAllowed() { + return state.mMatrix.isSimple() && !state.mClipped && + OpenGLRenderer::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode; + } + virtual bool onDefer(OpenGLRenderer& renderer, int* batchId, mergeid_t* mergeId) { *batchId = DeferredDisplayList::kOpBatch_Bitmap; *mergeId = mAtlasEntry ? (mergeid_t) &mAtlasEntry->atlas : (mergeid_t) mBitmap; // don't merge A8 bitmaps - the paint's color isn't compared by mergeId, or in // MergingDrawBatch::canMergeWith - return mergeAllowed() && (mBitmap->getConfig() != SkBitmap::kA8_Config); + return bitmapMergeAllowed() && (mBitmap->getConfig() != SkBitmap::kA8_Config); } const SkBitmap* bitmap() { return mBitmap; } @@ -1272,23 +1287,10 @@ private: class DrawTextOp : public DrawBoundedOp { public: DrawTextOp(const char* text, int bytesCount, int count, float x, float y, - const float* positions, SkPaint* paint, float length) - : DrawBoundedOp(paint), mText(text), mBytesCount(bytesCount), mCount(count), - mX(x), mY(y), mPositions(positions), mLength(length) { - // duplicates bounds calculation from OpenGLRenderer::drawText, but doesn't alter mX - SkPaint::FontMetrics metrics; - paint->getFontMetrics(&metrics, 0.0f); - switch (paint->getTextAlign()) { - case SkPaint::kCenter_Align: - x -= length / 2.0f; - break; - case SkPaint::kRight_Align: - x -= length; - break; - default: - break; - } - mLocalBounds.set(x, mY + metrics.fTop, x + length, mY + metrics.fBottom); + const float* positions, SkPaint* paint, float totalAdvance, const Rect& bounds) + : DrawBoundedOp(bounds, paint), mText(text), mBytesCount(bytesCount), mCount(count), + mX(x), mY(y), mPositions(positions), mTotalAdvance(totalAdvance) { + mLocalBounds.translate(x,y); memset(&mPrecacheTransform.data[0], 0xff, 16 * sizeof(float)); } @@ -1314,7 +1316,7 @@ public: virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { return renderer.drawText(mText, mBytesCount, mCount, mX, mY, - mPositions, getPaint(renderer), mLength); + mPositions, getPaint(renderer), mTotalAdvance, mLocalBounds); } virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty, @@ -1327,7 +1329,8 @@ public: DrawTextOp& op = *((DrawTextOp*)ops[i]); status |= renderer.drawText(op.mText, op.mBytesCount, op.mCount, op.mX, op.mY, - op.mPositions, op.getPaint(renderer), op.mLength, drawOpMode); + op.mPositions, op.getPaint(renderer), op.mTotalAdvance, op.mLocalBounds, + drawOpMode); } return status; } @@ -1345,7 +1348,7 @@ private: float mX; float mY; const float* mPositions; - float mLength; + float mTotalAdvance; mat4 mPrecacheTransform; }; diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp index bfd4086..6d85a16 100644 --- a/libs/hwui/DisplayListRenderer.cpp +++ b/libs/hwui/DisplayListRenderer.cpp @@ -420,17 +420,16 @@ status_t DisplayListRenderer::drawPosText(const char* text, int bytesCount, int status_t DisplayListRenderer::drawText(const char* text, int bytesCount, int count, float x, float y, const float* positions, SkPaint* paint, - float length, DrawOpMode drawOpMode) { + float totalAdvance, const Rect& bounds, DrawOpMode drawOpMode) { if (!text || count <= 0) return DrawGlInfo::kStatusDone; - if (length < 0.0f) length = paint->measureText(text, bytesCount); - text = refText(text, bytesCount); positions = refBuffer<float>(positions, count * 2); paint = refPaint(paint); - DrawOp* op = new (alloc()) DrawTextOp(text, bytesCount, count, x, y, positions, paint, length); + DrawOp* op = new (alloc()) DrawTextOp(text, bytesCount, count, + x, y, positions, paint, totalAdvance, bounds); addDrawOp(op); return DrawGlInfo::kStatusDone; } diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h index db08921..85d6107 100644 --- a/libs/hwui/DisplayListRenderer.h +++ b/libs/hwui/DisplayListRenderer.h @@ -121,7 +121,8 @@ public: virtual status_t drawPosText(const char* text, int bytesCount, int count, const float* positions, SkPaint* paint); virtual status_t drawText(const char* text, int bytesCount, int count, float x, float y, - const float* positions, SkPaint* paint, float length, DrawOpMode drawOpMode); + const float* positions, SkPaint* paint, float totalAdvance, const Rect& bounds, + DrawOpMode drawOpMode); virtual status_t drawRects(const float* rects, int count, SkPaint* paint); diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index 038df07..2465b48 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -1359,11 +1359,15 @@ bool OpenGLRenderer::storeDisplayState(DeferredDisplayState& state, int stateDef // state has bounds initialized in local coordinates if (!state.mBounds.isEmpty()) { currentMatrix.mapRect(state.mBounds); + state.mClipped = !currentClip.contains(state.mBounds); if (!state.mBounds.intersect(currentClip)) { // quick rejected return true; } } else { + // If we don't have bounds, let's assume we're clipped + // to prevent merging + state.mClipped = true; state.mBounds.set(currentClip); } } @@ -2010,7 +2014,7 @@ void OpenGLRenderer::drawAlphaBitmap(Texture* texture, float left, float top, Sk } status_t OpenGLRenderer::drawBitmaps(SkBitmap* bitmap, int bitmapCount, TextureVertex* vertices, - const Rect& bounds, SkPaint* paint) { + bool transformed, const Rect& bounds, SkPaint* paint) { // merged draw operations don't need scissor, but clip should still be valid mCaches.setScissorEnabled(mScissorOptimizationDisabled); @@ -2026,7 +2030,7 @@ status_t OpenGLRenderer::drawBitmaps(SkBitmap* bitmap, int bitmapCount, TextureV getAlphaAndMode(paint, &alpha, &mode); texture->setWrap(GL_CLAMP_TO_EDGE, true); - texture->setFilter(GL_NEAREST, true); // merged ops are always pure-translation for now + texture->setFilter(transformed ? FILTER(paint) : GL_NEAREST, true); const float x = (int) floorf(bounds.left + 0.5f); const float y = (int) floorf(bounds.top + 0.5f); @@ -2846,8 +2850,8 @@ mat4 OpenGLRenderer::findBestFontTransform(const mat4& transform) const { return fontTransform; } -status_t OpenGLRenderer::drawText(const char* text, int bytesCount, int count, - float x, float y, const float* positions, SkPaint* paint, float length, +status_t OpenGLRenderer::drawText(const char* text, int bytesCount, int count, float x, float y, + const float* positions, SkPaint* paint, float totalAdvance, const Rect& bounds, DrawOpMode drawOpMode) { if (drawOpMode == kDrawOpMode_Immediate && @@ -2855,24 +2859,8 @@ status_t OpenGLRenderer::drawText(const char* text, int bytesCount, int count, return DrawGlInfo::kStatusDone; } - if (length < 0.0f) length = paint->measureText(text, bytesCount); - switch (paint->getTextAlign()) { - case SkPaint::kCenter_Align: - x -= length / 2.0f; - break; - case SkPaint::kRight_Align: - x -= length; - break; - default: - break; - } - - SkPaint::FontMetrics metrics; - paint->getFontMetrics(&metrics, 0.0f); if (drawOpMode == kDrawOpMode_Immediate) { - if (quickReject(x, y + metrics.fTop, x + length, y + metrics.fBottom)) { - return DrawGlInfo::kStatusDone; - } + if (quickReject(bounds)) return DrawGlInfo::kStatusDone; } else { // merged draw operations don't need scissor, but clip should still be valid mCaches.setScissorEnabled(mScissorOptimizationDisabled); @@ -2923,7 +2911,7 @@ status_t OpenGLRenderer::drawText(const char* text, int bytesCount, int count, // TODO: Implement better clipping for scaled/rotated text const Rect* clip = !pureTranslate ? NULL : mSnapshot->clipRect; - Rect bounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f); + Rect layerBounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f); bool status; TextSetupFunctor functor(*this, x, y, pureTranslate, alpha, mode, paint); @@ -2934,20 +2922,20 @@ status_t OpenGLRenderer::drawText(const char* text, int bytesCount, int count, SkPaint paintCopy(*paint); paintCopy.setTextAlign(SkPaint::kLeft_Align); status = fontRenderer.renderPosText(&paintCopy, clip, text, 0, bytesCount, count, x, y, - positions, hasActiveLayer ? &bounds : NULL, &functor, forceFinish); + positions, hasActiveLayer ? &layerBounds : NULL, &functor, forceFinish); } else { status = fontRenderer.renderPosText(paint, clip, text, 0, bytesCount, count, x, y, - positions, hasActiveLayer ? &bounds : NULL, &functor, forceFinish); + positions, hasActiveLayer ? &layerBounds : NULL, &functor, forceFinish); } if ((status || drawOpMode != kDrawOpMode_Immediate) && hasActiveLayer) { if (!pureTranslate) { - transform.mapRect(bounds); + transform.mapRect(layerBounds); } - dirtyLayerUnchecked(bounds, getRegion()); + dirtyLayerUnchecked(layerBounds, getRegion()); } - drawTextDecorations(text, bytesCount, length, oldX, oldY, paint); + drawTextDecorations(text, bytesCount, totalAdvance, oldX, oldY, paint); return DrawGlInfo::kStatusDrew; } @@ -3231,17 +3219,12 @@ void OpenGLRenderer::drawPathTexture(const PathTexture* texture, #define kStdUnderline_Offset (1.0f / 9.0f) #define kStdUnderline_Thickness (1.0f / 18.0f) -void OpenGLRenderer::drawTextDecorations(const char* text, int bytesCount, float length, +void OpenGLRenderer::drawTextDecorations(const char* text, int bytesCount, float underlineWidth, float x, float y, SkPaint* paint) { // Handle underline and strike-through uint32_t flags = paint->getFlags(); if (flags & (SkPaint::kUnderlineText_Flag | SkPaint::kStrikeThruText_Flag)) { SkPaint paintCopy(*paint); - float underlineWidth = length; - // If length is > 0.0f, we already measured the text for the text alignment - if (length <= 0.0f) { - underlineWidth = paintCopy.measureText(text, bytesCount); - } if (CC_LIKELY(underlineWidth > 0.0f)) { const float textSize = paintCopy.getTextSize(); diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h index 597e458..d9ba93a 100644 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -87,6 +87,7 @@ struct DeferredDisplayState { // the below are set and used by the OpenGLRenderer at record and deferred playback bool mClipValid; Rect mClip; + bool mClipped; mat4 mMatrix; DrawModifiers mDrawModifiers; float mAlpha; @@ -241,6 +242,9 @@ public: ANDROID_API const Rect& getClipBounds(); ANDROID_API bool quickReject(float left, float top, float right, float bottom); + bool quickReject(const Rect& bounds) { + return quickReject(bounds.left, bounds.top, bounds.right, bounds.bottom); + } bool quickRejectNoScissor(float left, float top, float right, float bottom); virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op); virtual bool clipPath(SkPath* path, SkRegion::Op op); @@ -252,7 +256,7 @@ public: virtual status_t drawLayer(Layer* layer, float x, float y); virtual status_t drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint); status_t drawBitmaps(SkBitmap* bitmap, int bitmapCount, TextureVertex* vertices, - const Rect& bounds, SkPaint* paint); + bool transformed, const Rect& bounds, SkPaint* paint); virtual status_t drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint); virtual status_t drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop, float srcRight, float srcBottom, float dstLeft, float dstTop, @@ -280,7 +284,7 @@ public: virtual status_t drawPosText(const char* text, int bytesCount, int count, const float* positions, SkPaint* paint); virtual status_t drawText(const char* text, int bytesCount, int count, float x, float y, - const float* positions, SkPaint* paint, float length = -1.0f, + const float* positions, SkPaint* paint, float totalAdvance, const Rect& bounds, DrawOpMode drawOpMode = kDrawOpMode_Immediate); virtual status_t drawRects(const float* rects, int count, SkPaint* paint); @@ -824,12 +828,12 @@ private: * * @param text The text to decor * @param bytesCount The number of bytes in the text - * @param length The length in pixels of the text, can be <= 0.0f to force a measurement + * @param totalAdvance The total advance in pixels, defines underline/strikethrough length * @param x The x coordinate where the text will be drawn * @param y The y coordinate where the text will be drawn * @param paint The paint to draw the text with */ - void drawTextDecorations(const char* text, int bytesCount, float length, + void drawTextDecorations(const char* text, int bytesCount, float totalAdvance, float x, float y, SkPaint* paint); /** diff --git a/libs/hwui/Rect.h b/libs/hwui/Rect.h index f50ac3c..689fe6c0 100644 --- a/libs/hwui/Rect.h +++ b/libs/hwui/Rect.h @@ -125,11 +125,11 @@ public: return intersect(r.left, r.top, r.right, r.bottom); } - inline bool contains(float l, float t, float r, float b) { + inline bool contains(float l, float t, float r, float b) const { return l >= left && t >= top && r <= right && b <= bottom; } - inline bool contains(const Rect& r) { + inline bool contains(const Rect& r) const { return contains(r.left, r.top, r.right, r.bottom); } diff --git a/media/jni/android_media_MediaDrm.cpp b/media/jni/android_media_MediaDrm.cpp index ec88949..7799ca4 100644 --- a/media/jni/android_media_MediaDrm.cpp +++ b/media/jni/android_media_MediaDrm.cpp @@ -87,12 +87,18 @@ struct EntryFields { }; struct EventTypes { - int kEventProvisionRequired; - int kEventKeyRequired; - int kEventKeyExpired; - int kEventVendorDefined; + jint kEventProvisionRequired; + jint kEventKeyRequired; + jint kEventKeyExpired; + jint kEventVendorDefined; } gEventTypes; +struct KeyTypes { + jint kKeyTypeStreaming; + jint kKeyTypeOffline; + jint kKeyTypeRelease; +} gKeyTypes; + struct fields_t { jfieldID context; jmethodID post_event; @@ -128,7 +134,8 @@ JNIDrmListener::JNIDrmListener(JNIEnv* env, jobject thiz, jobject weak_thiz) jclass clazz = env->GetObjectClass(thiz); if (clazz == NULL) { ALOGE("Can't find android/media/MediaDrm"); - jniThrowException(env, "java/lang/Exception", NULL); + jniThrowException(env, "java/lang/Exception", + "Can't find android/media/MediaDrm"); return; } mClass = (jclass)env->NewGlobalRef(clazz); @@ -408,13 +415,15 @@ static KeyedVector<String8, String8> HashMapToKeyedVector(JNIEnv *env, jobject & if (entry) { jobject obj = env->CallObjectMethod(entry, gFields.entry.getKey); if (!env->IsInstanceOf(obj, clazz)) { - jniThrowException(env, "java/lang/IllegalArgumentException", NULL); + jniThrowException(env, "java/lang/IllegalArgumentException", + "HashMap key is not a String"); } jstring jkey = static_cast<jstring>(obj); obj = env->CallObjectMethod(entry, gFields.entry.getValue); if (!env->IsInstanceOf(obj, clazz)) { - jniThrowException(env, "java/lang/IllegalArgumentException", NULL); + jniThrowException(env, "java/lang/IllegalArgumentException", + "HashMap value is not a String"); } jstring jvalue = static_cast<jstring>(obj); @@ -486,12 +495,12 @@ static sp<JDrm> setDrm( static bool CheckSession(JNIEnv *env, const sp<IDrm> &drm, jbyteArray const &jsessionId) { if (drm == NULL) { - jniThrowException(env, "java/lang/IllegalStateException", NULL); + jniThrowException(env, "java/lang/IllegalStateException", "MediaDrm obj is null"); return false; } if (jsessionId == NULL) { - jniThrowException(env, "java/lang/IllegalArgumentException", NULL); + jniThrowException(env, "java/lang/IllegalArgumentException", "sessionId is null"); return false; } return true; @@ -521,6 +530,13 @@ static void android_media_MediaDrm_native_init(JNIEnv *env) { GET_STATIC_FIELD_ID(field, clazz, "EVENT_VENDOR_DEFINED", "I"); gEventTypes.kEventVendorDefined = env->GetStaticIntField(clazz, field); + GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_STREAMING", "I"); + gKeyTypes.kKeyTypeStreaming = env->GetStaticIntField(clazz, field); + GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_OFFLINE", "I"); + gKeyTypes.kKeyTypeOffline = env->GetStaticIntField(clazz, field); + GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_RELEASE", "I"); + gKeyTypes.kKeyTypeRelease = env->GetStaticIntField(clazz, field); + FIND_CLASS(clazz, "android/media/MediaDrm$KeyRequest"); GET_FIELD_ID(gFields.keyRequest.data, clazz, "mData", "[B"); GET_FIELD_ID(gFields.keyRequest.defaultUrl, clazz, "mDefaultUrl", "Ljava/lang/String;"); @@ -557,14 +573,15 @@ static void android_media_MediaDrm_native_setup( jobject weak_this, jbyteArray uuidObj) { if (uuidObj == NULL) { - jniThrowException(env, "java/lang/IllegalArgumentException", NULL); + jniThrowException(env, "java/lang/IllegalArgumentException", "uuid is null"); return; } Vector<uint8_t> uuid = JByteArrayToVector(env, uuidObj); if (uuid.size() != 16) { - jniThrowException(env, "java/lang/IllegalArgumentException", NULL); + jniThrowException(env, "java/lang/IllegalArgumentException", + "invalid UUID size, expected 16 bytes"); return; } @@ -604,7 +621,7 @@ static jboolean android_media_MediaDrm_isCryptoSchemeSupportedNative( jniThrowException( env, "java/lang/IllegalArgumentException", - NULL); + "invalid UUID size, expected 16 bytes"); return false; } @@ -616,7 +633,8 @@ static jbyteArray android_media_MediaDrm_openSession( sp<IDrm> drm = GetDrm(env, thiz); if (drm == NULL) { - jniThrowException(env, "java/lang/IllegalStateException", NULL); + jniThrowException(env, "java/lang/IllegalStateException", + "MediaDrm obj is null"); return NULL; } @@ -666,7 +684,18 @@ static jobject android_media_MediaDrm_getKeyRequest( mimeType = JStringToString8(env, jmimeType); } - DrmPlugin::KeyType keyType = (DrmPlugin::KeyType)jkeyType; + DrmPlugin::KeyType keyType; + if (jkeyType == gKeyTypes.kKeyTypeStreaming) { + keyType = DrmPlugin::kKeyType_Streaming; + } else if (jkeyType == gKeyTypes.kKeyTypeOffline) { + keyType = DrmPlugin::kKeyType_Offline; + } else if (jkeyType == gKeyTypes.kKeyTypeRelease) { + keyType = DrmPlugin::kKeyType_Release; + } else { + jniThrowException(env, "java/lang/IllegalArgumentException", + "invalid keyType"); + return NULL; + } KeyedVector<String8, String8> optParams; if (joptParams != NULL) { @@ -712,7 +741,8 @@ static jbyteArray android_media_MediaDrm_provideKeyResponse( Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId)); if (jresponse == NULL) { - jniThrowException(env, "java/lang/IllegalArgumentException", NULL); + jniThrowException(env, "java/lang/IllegalArgumentException", + "key response is null"); return NULL; } Vector<uint8_t> response(JByteArrayToVector(env, jresponse)); @@ -729,7 +759,8 @@ static void android_media_MediaDrm_removeKeys( sp<IDrm> drm = GetDrm(env, thiz); if (jkeysetId == NULL) { - jniThrowException(env, "java/lang/IllegalArgumentException", NULL); + jniThrowException(env, "java/lang/IllegalArgumentException", + "keySetId is null"); return; } @@ -788,7 +819,8 @@ static jobject android_media_MediaDrm_getProvisionRequest( sp<IDrm> drm = GetDrm(env, thiz); if (drm == NULL) { - jniThrowException(env, "java/lang/IllegalStateException", NULL); + jniThrowException(env, "java/lang/IllegalStateException", + "MediaDrm obj is null"); return NULL; } @@ -824,12 +856,14 @@ static void android_media_MediaDrm_provideProvisionResponse( sp<IDrm> drm = GetDrm(env, thiz); if (drm == NULL) { - jniThrowException(env, "java/lang/IllegalStateException", NULL); + jniThrowException(env, "java/lang/IllegalStateException", + "MediaDrm obj is null"); return; } if (jresponse == NULL) { - jniThrowException(env, "java/lang/IllegalArgumentException", NULL); + jniThrowException(env, "java/lang/IllegalArgumentException", + "provision response is null"); return; } @@ -845,7 +879,8 @@ static jobject android_media_MediaDrm_getSecureStops( sp<IDrm> drm = GetDrm(env, thiz); if (drm == NULL) { - jniThrowException(env, "java/lang/IllegalStateException", NULL); + jniThrowException(env, "java/lang/IllegalStateException", + "MediaDrm obj is null"); return NULL; } @@ -865,7 +900,8 @@ static void android_media_MediaDrm_releaseSecureStops( sp<IDrm> drm = GetDrm(env, thiz); if (drm == NULL) { - jniThrowException(env, "java/lang/IllegalStateException", NULL); + jniThrowException(env, "java/lang/IllegalStateException", + "MediaDrm obj is null"); return; } @@ -881,12 +917,14 @@ static jstring android_media_MediaDrm_getPropertyString( sp<IDrm> drm = GetDrm(env, thiz); if (drm == NULL) { - jniThrowException(env, "java/lang/IllegalStateException", NULL); + jniThrowException(env, "java/lang/IllegalStateException", + "MediaDrm obj is null"); return NULL; } if (jname == NULL) { - jniThrowException(env, "java/lang/IllegalArgumentException", NULL); + jniThrowException(env, "java/lang/IllegalArgumentException", + "property name String is null"); return NULL; } @@ -907,12 +945,14 @@ static jbyteArray android_media_MediaDrm_getPropertyByteArray( sp<IDrm> drm = GetDrm(env, thiz); if (drm == NULL) { - jniThrowException(env, "java/lang/IllegalStateException", NULL); + jniThrowException(env, "java/lang/IllegalStateException", + "MediaDrm obj is null"); return NULL; } if (jname == NULL) { - jniThrowException(env, "java/lang/IllegalArgumentException", NULL); + jniThrowException(env, "java/lang/IllegalArgumentException", + "property name String is null"); return NULL; } @@ -933,12 +973,20 @@ static void android_media_MediaDrm_setPropertyString( sp<IDrm> drm = GetDrm(env, thiz); if (drm == NULL) { - jniThrowException(env, "java/lang/IllegalStateException", NULL); + jniThrowException(env, "java/lang/IllegalStateException", + "MediaDrm obj is null"); return; } - if (jname == NULL || jvalue == NULL) { - jniThrowException(env, "java/lang/IllegalArgumentException", NULL); + if (jname == NULL) { + jniThrowException(env, "java/lang/IllegalArgumentException", + "property name String is null"); + return; + } + + if (jvalue == NULL) { + jniThrowException(env, "java/lang/IllegalArgumentException", + "property value String is null"); return; } @@ -955,12 +1003,20 @@ static void android_media_MediaDrm_setPropertyByteArray( sp<IDrm> drm = GetDrm(env, thiz); if (drm == NULL) { - jniThrowException(env, "java/lang/IllegalStateException", NULL); + jniThrowException(env, "java/lang/IllegalStateException", + "MediaDrm obj is null"); return; } - if (jname == NULL || jvalue == NULL) { - jniThrowException(env, "java/lang/IllegalArgumentException", NULL); + if (jname == NULL) { + jniThrowException(env, "java/lang/IllegalArgumentException", + "property name String is null"); + return; + } + + if (jvalue == NULL) { + jniThrowException(env, "java/lang/IllegalArgumentException", + "property value byte array is null"); return; } @@ -983,7 +1039,8 @@ static void android_media_MediaDrm_setCipherAlgorithmNative( } if (jalgorithm == NULL) { - jniThrowException(env, "java/lang/IllegalArgumentException", NULL); + jniThrowException(env, "java/lang/IllegalArgumentException", + "algorithm String is null"); return; } @@ -1006,7 +1063,8 @@ static void android_media_MediaDrm_setMacAlgorithmNative( } if (jalgorithm == NULL) { - jniThrowException(env, "java/lang/IllegalArgumentException", NULL); + jniThrowException(env, "java/lang/IllegalArgumentException", + "algorithm String is null"); return; } @@ -1030,7 +1088,8 @@ static jbyteArray android_media_MediaDrm_encryptNative( } if (jkeyId == NULL || jinput == NULL || jiv == NULL) { - jniThrowException(env, "java/lang/IllegalArgumentException", NULL); + jniThrowException(env, "java/lang/IllegalArgumentException", + "required argument is null"); return NULL; } @@ -1058,7 +1117,8 @@ static jbyteArray android_media_MediaDrm_decryptNative( } if (jkeyId == NULL || jinput == NULL || jiv == NULL) { - jniThrowException(env, "java/lang/IllegalArgumentException", NULL); + jniThrowException(env, "java/lang/IllegalArgumentException", + "required argument is null"); return NULL; } @@ -1085,7 +1145,8 @@ static jbyteArray android_media_MediaDrm_signNative( } if (jkeyId == NULL || jmessage == NULL) { - jniThrowException(env, "java/lang/IllegalArgumentException", NULL); + jniThrowException(env, "java/lang/IllegalArgumentException", + "required argument is null"); return NULL; } @@ -1112,7 +1173,8 @@ static jboolean android_media_MediaDrm_verifyNative( } if (jkeyId == NULL || jmessage == NULL || jsignature == NULL) { - jniThrowException(env, "java/lang/IllegalArgumentException", NULL); + jniThrowException(env, "java/lang/IllegalArgumentException", + "required argument is null"); return false; } diff --git a/services/java/com/android/server/accounts/AccountManagerService.java b/services/java/com/android/server/accounts/AccountManagerService.java index 4f5008d..c5242f0 100644 --- a/services/java/com/android/server/accounts/AccountManagerService.java +++ b/services/java/com/android/server/accounts/AccountManagerService.java @@ -2805,12 +2805,19 @@ public class AccountManagerService if (sharedAccounts == null || sharedAccounts.length == 0) return unfiltered; String requiredAccountType = ""; try { - for (String packageName : packages) { - PackageInfo pi = mPackageManager.getPackageInfo(packageName, 0); + // If there's an explicit callingPackage specified, check if that package + // opted in to see restricted accounts. + if (callingPackage != null) { + PackageInfo pi = mPackageManager.getPackageInfo(callingPackage, 0); if (pi != null && pi.restrictedAccountType != null) { requiredAccountType = pi.restrictedAccountType; - // If it matches the package name of the original caller, use this choice. - if (callingPackage != null && packageName.equals(callingPackage)) { + } + } else { + // Otherwise check if the callingUid has a package that has opted in + for (String packageName : packages) { + PackageInfo pi = mPackageManager.getPackageInfo(packageName, 0); + if (pi != null && pi.restrictedAccountType != null) { + requiredAccountType = pi.restrictedAccountType; break; } } diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index d1cc6ba..dcb2984 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -6062,7 +6062,8 @@ public final class ActivityManagerService extends ActivityManagerNative } rti.origActivity = tr.origActivity; rti.description = tr.lastDescription; - + rti.stackId = tr.stack.mStackId; + if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) { // Check whether this activity is currently available. try { |
