Merge "Introduce SystemUI-managed alternative system bars."
diff --git a/api/current.txt b/api/current.txt
index a896ecb..481521e 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -18385,6 +18385,40 @@
}
+package android.print.pdf {
+
+ public final class PdfDocument {
+ method public void close();
+ method protected final void finalize() throws java.lang.Throwable;
+ method public void finishPage(android.print.pdf.PdfDocument.Page);
+ method public java.util.List<android.print.pdf.PdfDocument.PageInfo> getPages();
+ method public static android.print.pdf.PdfDocument open();
+ method public android.print.pdf.PdfDocument.Page startPage(android.print.pdf.PdfDocument.PageInfo);
+ method public void writeTo(java.io.OutputStream);
+ }
+
+ public static final class PdfDocument.Page {
+ method public android.graphics.Canvas getCanvas();
+ method public android.print.pdf.PdfDocument.PageInfo getInfo();
+ }
+
+ public static final class PdfDocument.PageInfo {
+ method public android.graphics.Rect getContentSize();
+ method public int getDesity();
+ method public android.graphics.Matrix getInitialTransform();
+ method public int getPageNumber();
+ method public android.graphics.Rect getPageSize();
+ }
+
+ public static final class PdfDocument.PageInfo.Builder {
+ ctor public PdfDocument.PageInfo.Builder(android.graphics.Rect, int, int);
+ method public android.print.pdf.PdfDocument.PageInfo create();
+ method public android.print.pdf.PdfDocument.PageInfo.Builder setContentSize(android.graphics.Rect);
+ method public android.print.pdf.PdfDocument.PageInfo.Builder setInitialTransform(android.graphics.Matrix);
+ }
+
+}
+
package android.provider {
public final class AlarmClock {
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index b3f0d96..f090e07 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -72,7 +72,13 @@
*/
@Deprecated
public static final String SYNC_EXTRAS_ACCOUNT = "account";
+
+ /**
+ * If this extra is set to true, the sync request will be scheduled
+ * at the front of the sync request queue and without any delay
+ */
public static final String SYNC_EXTRAS_EXPEDITED = "expedited";
+
/**
* @deprecated instead use
* {@link #SYNC_EXTRAS_MANUAL}
@@ -104,8 +110,25 @@
*/
public static final String SYNC_EXTRAS_MANUAL = "force";
+ /**
+ * Indicates that this sync is intended to only upload local changes to the server.
+ * For example, this will be set to true if the sync is initiated by a call to
+ * {@link ContentResolver#notifyChange(android.net.Uri, android.database.ContentObserver, boolean)}
+ */
public static final String SYNC_EXTRAS_UPLOAD = "upload";
+
+ /**
+ * Indicates that the sync adapter should proceed with the delete operations,
+ * even if it determines that there are too many.
+ * See {@link SyncResult#tooManyDeletions}
+ */
public static final String SYNC_EXTRAS_OVERRIDE_TOO_MANY_DELETIONS = "deletions_override";
+
+ /**
+ * Indicates that the sync adapter should not proceed with the delete operations,
+ * if it determines that there are too many.
+ * See {@link SyncResult#tooManyDeletions}
+ */
public static final String SYNC_EXTRAS_DISCARD_LOCAL_DELETIONS = "discard_deletions";
/**
diff --git a/core/java/android/print/pdf/PdfDocument.java b/core/java/android/print/pdf/PdfDocument.java
new file mode 100644
index 0000000..7fb170e
--- /dev/null
+++ b/core/java/android/print/pdf/PdfDocument.java
@@ -0,0 +1,443 @@
+/*
+ * Copyright (C) 2013 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
+ *
+ * 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
+ * limitations under the License.
+ */
+
+package android.print.pdf;
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Matrix;
+import android.graphics.Rect;
+
+import dalvik.system.CloseGuard;
+
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * <p>
+ * This class enables generating a PDF document from native Android content. You
+ * open a new document and then for every page you want to add you start a page,
+ * write content to the page, and finish the page. After you are done with all
+ * pages, you write the document to an output stream and close the document.
+ * After a document is closed you should not use it anymore.
+ * </p>
+ * <p>
+ * A typical use of the APIs looks like this:
+ * </p>
+ * <pre>
+ * // open a new document
+ * PdfDocument document = PdfDocument.open();
+ *
+ * // crate a page description
+ * PageInfo pageInfo = new PageInfo.Builder(new Rect(0, 0, 100, 100), 1, 300).create();
+ *
+ * // start a page
+ * Page page = document.startPage(pageInfo);
+ *
+ * // draw something on the page
+ * View content = getContentView();
+ * content.draw(page.getCanvas());
+ *
+ * // finish the page
+ * document.finishPage(page);
+ * . . .
+ * add more pages
+ * . . .
+ * // write the document content
+ * document.writeTo(getOutputStream());
+ *
+ * //close the document
+ * document.close();
+ * </pre>
+ */
+public final class PdfDocument {
+
+ private final byte[] mChunk = new byte[4096];
+
+ private final CloseGuard mCloseGuard = CloseGuard.get();
+
+ private final List<PageInfo> mPages = new ArrayList<PageInfo>();
+
+ private int mNativeDocument;
+
+ private Page mCurrentPage;
+
+ /**
+ * Opens a new document.
+ * <p>
+ * <strong>Note:</strong> You must close the document after you are
+ * done by calling {@link #close()}
+ * </p>
+ *
+ * @return The document.
+ *
+ * @see #close()
+ */
+ public static PdfDocument open() {
+ return new PdfDocument();
+ }
+
+ /**
+ * Creates a new instance.
+ */
+ private PdfDocument() {
+ mNativeDocument = nativeCreateDocument();
+ mCloseGuard.open("close");
+ }
+
+ /**
+ * Starts a page using the provided {@link PageInfo}. After the page
+ * is created you can draw arbitrary content on the page's canvas which
+ * you can get by calling {@link Page#getCanvas()}. After you are done
+ * drawing the content you should finish the page by calling
+ * {@link #finishPage(Page). After the page is finished you should
+ * no longer access the page or its canvas.
+ * <p>
+ * <strong>Note:</strong> Do not call this method after {@link #close()}.
+ * </p>
+ *
+ * @param pageInfo The page info.
+ * @return A blank page.
+ *
+ * @see #finishPage(Page)
+ */
+ public Page startPage(PageInfo pageInfo) {
+ throwIfClosed();
+ if (pageInfo == null) {
+ throw new IllegalArgumentException("page cannot be null!");
+ }
+ if (mCurrentPage != null) {
+ throw new IllegalStateException("Previous page not finished!");
+ }
+ Canvas canvas = new PdfCanvas(nativeCreatePage(pageInfo.mPageSize,
+ pageInfo.mContentSize, pageInfo.mInitialTransform.native_instance),
+ pageInfo.mDensity);
+ mCurrentPage = new Page(canvas, pageInfo);
+ return mCurrentPage;
+ }
+
+ /**
+ * Finishes a started page. You should always finish the last started page.
+ * <p>
+ * <strong>Note:</strong> Do not call this method after {@link #close()}.
+ * </p>
+ *
+ * @param page The page.
+ *
+ * @see #startPage(PageInfo)
+ */
+ public void finishPage(Page page) {
+ throwIfClosed();
+ if (page == null) {
+ throw new IllegalArgumentException("page cannot be null");
+ }
+ if (page != mCurrentPage) {
+ throw new IllegalStateException("invalid page");
+ }
+ mPages.add(page.getInfo());
+ mCurrentPage = null;
+ nativeAppendPage(mNativeDocument, page.mCanvas.mNativeCanvas);
+ page.finish();
+ }
+
+ /**
+ * Writes the document to an output stream.
+ * <p>
+ * <strong>Note:</strong> Do not call this method after {@link #close()}.
+ * </p>
+ *
+ * @param out The output stream.
+ */
+ public void writeTo(OutputStream out) {
+ throwIfClosed();
+ if (out == null) {
+ throw new IllegalArgumentException("out cannot be null!");
+ }
+ nativeWriteTo(mNativeDocument, out, mChunk);
+ }
+
+ /**
+ * Gets the pages of the document.
+ *
+ * @return The pages.
+ */
+ public List<PageInfo> getPages() {
+ return Collections.unmodifiableList(mPages);
+ }
+
+ /**
+ * Closes this document. This method should be called after you
+ * are done working with the document. After this call the document
+ * is considered closed and none of its methods should be called.
+ */
+ public void close() {
+ dispose();
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ try {
+ mCloseGuard.warnIfOpen();
+ dispose();
+ } finally {
+ super.finalize();
+ }
+ }
+
+ private void dispose() {
+ if (mNativeDocument != 0) {
+ nativeFinalize(mNativeDocument);
+ mCloseGuard.close();
+ mNativeDocument = 0;
+ }
+ }
+
+ /**
+ * Throws an exception if the document is already closed.
+ */
+ private void throwIfClosed() {
+ if (mNativeDocument == 0) {
+ throw new IllegalStateException("document is closed!");
+ }
+ }
+
+ private native int nativeCreateDocument();
+
+ private native void nativeFinalize(int document);
+
+ private native void nativeAppendPage(int document, int page);
+
+ private native void nativeWriteTo(int document, OutputStream out, byte[] chunk);
+
+ private static native int nativeCreatePage(Rect pageSize,
+ Rect contentSize, int nativeMatrix);
+
+
+ private final class PdfCanvas extends Canvas {
+
+ public PdfCanvas(int nativeCanvas, int density) {
+ super(nativeCanvas);
+ super.setDensity(density);
+ }
+
+ @Override
+ public void setBitmap(Bitmap bitmap) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void setDensity(int density) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void setScreenDensity(int density) {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ /**
+ * This class represents meta-data that describes a PDF {@link Page}.
+ */
+ public static final class PageInfo {
+ private Rect mPageSize;
+ private Rect mContentSize;
+ private Matrix mInitialTransform;
+ private int mPageNumber;
+ private int mDensity;
+
+ /**
+ * Creates a new instance.
+ */
+ private PageInfo() {
+ /* do nothing */
+ }
+
+ /**
+ * Gets the page size in pixels.
+ *
+ * @return The page size.
+ */
+ public Rect getPageSize() {
+ return mPageSize;
+ }
+
+ /**
+ * Get the content size in pixels.
+ *
+ * @return The content size.
+ */
+ public Rect getContentSize() {
+ return mContentSize;
+ }
+
+ /**
+ * Gets the initial transform which is applied to the page. This may be
+ * useful to move the origin to account for a margin, apply scale, or
+ * apply a rotation.
+ *
+ * @return The initial transform.
+ */
+ public Matrix getInitialTransform() {
+ return mInitialTransform;
+ }
+
+ /**
+ * Gets the page number.
+ *
+ * @return The page number.
+ */
+ public int getPageNumber() {
+ return mPageNumber;
+ }
+
+ /**
+ * Gets the density of the page in DPI.
+ *
+ * @return The density.
+ */
+ public int getDesity() {
+ return mDensity;
+ }
+
+ /**
+ * Builder for creating a {@link PageInfo}.
+ */
+ public static final class Builder {
+ private final PageInfo mPageInfo = new PageInfo();
+
+ /**
+ * Creates a new builder with the mandatory page info attributes.
+ *
+ * @param pageSize The page size in pixels.
+ * @param pageNumber The page number.
+ * @param density The page density in DPI.
+ */
+ public Builder(Rect pageSize, int pageNumber, int density) {
+ if (pageSize.width() == 0 || pageSize.height() == 0) {
+ throw new IllegalArgumentException("page width and height" +
+ " must be greater than zero!");
+ }
+ if (pageNumber < 0) {
+ throw new IllegalArgumentException("pageNumber cannot be less than zero!");
+ }
+ if (density <= 0) {
+ throw new IllegalArgumentException("density must be greater than zero!");
+ }
+ mPageInfo.mPageSize = pageSize;
+ mPageInfo.mPageNumber = pageNumber;
+ mPageInfo.mDensity = density;
+ }
+
+ /**
+ * Sets the content size in pixels.
+ *
+ * @param contentSize The content size.
+ */
+ public Builder setContentSize(Rect contentSize) {
+ Rect pageSize = mPageInfo.mPageSize;
+ if (contentSize != null && (pageSize.left > contentSize.left
+ || pageSize.top > contentSize.top
+ || pageSize.right < contentSize.right
+ || pageSize.bottom < contentSize.bottom)) {
+ throw new IllegalArgumentException("contentSize does not fit the pageSize!");
+ }
+ mPageInfo.mContentSize = contentSize;
+ return this;
+ }
+
+ /**
+ * Sets the initial transform which is applied to the page. This may be
+ * useful to move the origin to account for a margin, apply scale, or
+ * apply a rotation.
+ *
+ * @param transform The initial transform.
+ */
+ public Builder setInitialTransform(Matrix transform) {
+ mPageInfo.mInitialTransform = transform;
+ return this;
+ }
+
+ /**
+ * Creates a new {@link PageInfo}.
+ *
+ * @return The new instance.
+ */
+ public PageInfo create() {
+ if (mPageInfo.mContentSize == null) {
+ mPageInfo.mContentSize = mPageInfo.mPageSize;
+ }
+ if (mPageInfo.mInitialTransform == null) {
+ mPageInfo.mInitialTransform = new Matrix();
+ }
+ return mPageInfo;
+ }
+ }
+ }
+
+ /**
+ * This class represents a PDF document page. It has associated
+ * a canvas on which you can draw content and is acquired by a
+ * call to {@link #getCanvas()}. It also has associated a
+ * {@link PageInfo} instance that describes its attributes.
+ */
+ public static final class Page {
+ private final PageInfo mPageInfo;
+ private Canvas mCanvas;
+
+ /**
+ * Creates a new instance.
+ *
+ * @param canvas The canvas of the page.
+ * @param pageInfo The info with meta-data.
+ */
+ private Page(Canvas canvas, PageInfo pageInfo) {
+ mCanvas = canvas;
+ mPageInfo = pageInfo;
+ }
+
+ /**
+ * Gets the {@link Canvas} of the page.
+ *
+ * @return The canvas if the page is not finished, null otherwise.
+ *
+ * @see PdfDocument#finishPage(Page)
+ */
+ public Canvas getCanvas() {
+ return mCanvas;
+ }
+
+ /**
+ * Gets the {@link PageInfo} with meta-data for the page.
+ *
+ * @return The page info.
+ *
+ * @see PdfDocument#finishPage(Page)
+ */
+ public PageInfo getInfo() {
+ return mPageInfo;
+ }
+
+ private void finish() {
+ if (mCanvas != null) {
+ mCanvas.release();
+ mCanvas = null;
+ }
+ }
+ }
+}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index e62abbe..9bc66be 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -923,9 +923,14 @@
}
void disposeResizeBuffer() {
- if (mResizeBuffer != null) {
- mResizeBuffer.destroy();
- mResizeBuffer = null;
+ if (mResizeBuffer != null && mAttachInfo.mHardwareRenderer != null) {
+ mAttachInfo.mHardwareRenderer.safelyRun(new Runnable() {
+ @Override
+ public void run() {
+ mResizeBuffer.destroy();
+ mResizeBuffer = null;
+ }
+ });
}
}
@@ -1466,8 +1471,7 @@
if (mResizeBuffer != null) {
mResizeBuffer.end(hwRendererCanvas);
if (!completed) {
- mResizeBuffer.destroy();
- mResizeBuffer = null;
+ disposeResizeBuffer();
}
}
}
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 5e1090f..faaf588 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -140,6 +140,7 @@
android_util_FileObserver.cpp \
android/opengl/poly_clip.cpp.arm \
android/opengl/util.cpp.arm \
+ android/print/android_print_pdf_PdfDocument.cpp \
android_server_NetworkManagementSocketTagger.cpp \
android_server_Watchdog.cpp \
android_ddm_DdmHandleNativeHeap.cpp \
@@ -164,6 +165,7 @@
$(call include-path-for, libhardware_legacy)/hardware_legacy \
$(TOP)/frameworks/av/include \
external/skia/src/core \
+ external/skia/src/pdf \
external/skia/src/images \
external/skia/include/utils \
external/sqlite/dist \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 0158bf5..144cc84 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -144,6 +144,7 @@
extern int register_android_os_FileUtils(JNIEnv *env);
extern int register_android_os_UEventObserver(JNIEnv* env);
extern int register_android_os_MemoryFile(JNIEnv* env);
+extern int register_android_print_pdf_PdfDocument(JNIEnv* env);
extern int register_android_net_LocalSocketImpl(JNIEnv* env);
extern int register_android_net_NetworkUtils(JNIEnv* env);
extern int register_android_net_TrafficStats(JNIEnv* env);
@@ -1182,6 +1183,7 @@
REG_JNI(register_android_os_SELinux),
REG_JNI(register_android_os_Trace),
REG_JNI(register_android_os_UEventObserver),
+ REG_JNI(register_android_print_pdf_PdfDocument),
REG_JNI(register_android_net_LocalSocketImpl),
REG_JNI(register_android_net_NetworkUtils),
REG_JNI(register_android_net_TrafficStats),
diff --git a/core/jni/android/print/android_print_pdf_PdfDocument.cpp b/core/jni/android/print/android_print_pdf_PdfDocument.cpp
new file mode 100644
index 0000000..745fe8a
--- /dev/null
+++ b/core/jni/android/print/android_print_pdf_PdfDocument.cpp
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2013 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
+ *
+ * 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
+ * limitations under the License.
+ */
+
+#include "jni.h"
+#include "GraphicsJNI.h"
+#include <android_runtime/AndroidRuntime.h>
+
+#include "SkCanvas.h"
+#include "SkPDFDevice.h"
+#include "SkPDFDocument.h"
+#include "SkRect.h"
+#include "SkSize.h"
+#include "CreateJavaOutputStreamAdaptor.h"
+
+namespace android {
+
+static jint nativeCreateDocument(JNIEnv* env, jobject clazz) {
+ return reinterpret_cast<jint>(new SkPDFDocument());
+}
+
+static void nativeFinalize(JNIEnv* env, jobject thiz, jint documentPtr) {
+ delete reinterpret_cast<SkPDFDocument*>(documentPtr);
+}
+
+static jint nativeCreatePage(JNIEnv* env, jobject thiz,
+ jobject pageSize, jobject contentSize, jint initialTransformation) {
+ SkIRect skPageSizeRect;
+ GraphicsJNI::jrect_to_irect(env, pageSize, &skPageSizeRect);
+ SkISize skPageSize = SkISize::Make(skPageSizeRect.width(),
+ skPageSizeRect.height());
+
+ SkIRect skContentRect;
+ GraphicsJNI::jrect_to_irect(env, contentSize, &skContentRect);
+ SkISize skContentSize = SkISize::Make(skContentRect.width(),
+ skContentRect.height());
+
+ SkMatrix* transformation = reinterpret_cast<SkMatrix*>(initialTransformation);
+ SkPDFDevice* skPdfDevice = new SkPDFDevice(skPageSize, skContentSize, *transformation);
+
+ return reinterpret_cast<jint>(new SkCanvas(skPdfDevice));
+}
+
+static void nativeAppendPage(JNIEnv* env, jobject thiz, jint documentPtr, jint pagePtr) {
+ SkCanvas* page = reinterpret_cast<SkCanvas*>(pagePtr);
+ SkPDFDocument* document = reinterpret_cast<SkPDFDocument*>(documentPtr);
+ SkPDFDevice* device = static_cast<SkPDFDevice*>(page->getDevice());
+ document->appendPage(device);
+}
+
+static void nativeWriteTo(JNIEnv* env, jobject clazz, jint documentPtr,
+ jobject out, jbyteArray chunk) {
+ SkWStream* skWStream = CreateJavaOutputStreamAdaptor(env, out, chunk);
+ SkPDFDocument* document = reinterpret_cast<SkPDFDocument*>(documentPtr);
+ document->emitPDF(skWStream);
+ delete skWStream;
+}
+
+static JNINativeMethod gPdfDocument_Methods[] = {
+ {"nativeCreateDocument", "()I", (void*) nativeCreateDocument},
+ {"nativeFinalize", "(I)V", (void*) nativeFinalize},
+ {"nativeCreatePage", "(Landroid/graphics/Rect;Landroid/graphics/Rect;I)I",
+ (void*) nativeCreatePage},
+ {"nativeAppendPage", "(II)V", (void*) nativeAppendPage},
+ {"nativeWriteTo", "(ILjava/io/OutputStream;[B)V", (void*) nativeWriteTo}
+};
+
+int register_android_print_pdf_PdfDocument(JNIEnv* env) {
+ int result = android::AndroidRuntime::registerNativeMethods(
+ env, "android/print/pdf/PdfDocument", gPdfDocument_Methods,
+ NELEM(gPdfDocument_Methods));
+ return result;
+}
+
+};
diff --git a/docs/html/distribute/googleplay/edu/about.jd b/docs/html/distribute/googleplay/edu/about.jd
index 7306c5b..cc131c64 100644
--- a/docs/html/distribute/googleplay/edu/about.jd
+++ b/docs/html/distribute/googleplay/edu/about.jd
@@ -24,6 +24,7 @@
that will help schools. We want to help you create innovative educational apps,
without having to knock on school doors to reach teachers and students.</p>
+<p><a class="landing-page-link" style="text-align:right;" href="#video">Watch a Video</a></p>
<div class="landing-docs">
<div class="col-6 normal-links">
@@ -79,3 +80,25 @@
</div>
+<div id="video" style="background: #F0F0F0;
+ border-top: 1px solid #DDD;
+ padding: 0px 0 24px 0;
+ overflow: auto;
+ clear:both;
+ margin-bottom:40px;
+ margin-top:30px;">
+ <div style="padding:0 0 0 29px;">
+ <h4>Introducing Google Play for Education</h4>
+
+ <div style="width:700px;">
+ <p style="margin-top:26px;
+ margin-bottom:12px;">
+ Hear how Google Play for Education works and how developers can leverage the unique business opportunities in creating educational apps for the K-12 market. There's a demo at 4m10s.</p>
+ </div>
+ <iframe style="float:left;
+ margin-right:24px;
+ margin-top:14px;" width="700" height="394" src=
+ "http://www.youtube.com/embed/haEmsMo0f3w?HD=1;rel=0;origin=developer.android.com;" frameborder="0" allowfullscreen>
+ </iframe>
+ </div>
+</div>
diff --git a/docs/html/distribute/googleplay/promote/badges.jd b/docs/html/distribute/googleplay/promote/badges.jd
index 738e76b..9a32921 100644
--- a/docs/html/distribute/googleplay/promote/badges.jd
+++ b/docs/html/distribute/googleplay/promote/badges.jd
@@ -201,10 +201,8 @@
onchange="changeBadgeLang()">
<option title="Afrikaans"
value="af">Afrikaans</option>
-<!--
<option title="Arabic"
value="ar">العربية</option>
--->
<option title="Belarusian"
value="be">Беларуская</option>
<option title="Bulgarian"
diff --git a/docs/html/images/brand/ar_generic_rgb_wo_45.png b/docs/html/images/brand/ar_generic_rgb_wo_45.png
index bdb0ff6..c403608 100644
--- a/docs/html/images/brand/ar_generic_rgb_wo_45.png
+++ b/docs/html/images/brand/ar_generic_rgb_wo_45.png
Binary files differ
diff --git a/docs/html/images/brand/ar_generic_rgb_wo_60.png b/docs/html/images/brand/ar_generic_rgb_wo_60.png
index ba9fc69..95e31eb 100644
--- a/docs/html/images/brand/ar_generic_rgb_wo_60.png
+++ b/docs/html/images/brand/ar_generic_rgb_wo_60.png
Binary files differ
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index a1c87cb..bd871c4 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -37,12 +37,14 @@
* Canvas and Drawables</a> developer guide.</p></div>
*/
public class Canvas {
+
// assigned in constructors or setBitmap, freed in finalizer
- int mNativeCanvas;
-
+ /** @hide */
+ public int mNativeCanvas;
+
// may be null
private Bitmap mBitmap;
-
+
// optional field set by the caller
private DrawFilter mDrawFilter;
@@ -59,7 +61,6 @@
protected int mScreenDensity = Bitmap.DENSITY_NONE;
// Used by native code
- @SuppressWarnings({"UnusedDeclaration"})
private int mSurfaceFormat;
/**
@@ -79,10 +80,9 @@
private static final int MAXMIMUM_BITMAP_SIZE = 32766;
// This field is used to finalize the native Canvas properly
- @SuppressWarnings({"UnusedDeclaration"})
private final CanvasFinalizer mFinalizer;
- private static class CanvasFinalizer {
+ private static final class CanvasFinalizer {
private int mNativeCanvas;
public CanvasFinalizer(int nativeCanvas) {
@@ -92,13 +92,18 @@
@Override
protected void finalize() throws Throwable {
try {
- if (mNativeCanvas != 0) {
- finalizer(mNativeCanvas);
- }
+ dispose();
} finally {
super.finalize();
}
}
+
+ public void dispose() {
+ if (mNativeCanvas != 0) {
+ finalizer(mNativeCanvas);
+ mNativeCanvas = 0;
+ }
+ }
}
/**
@@ -132,13 +137,14 @@
mBitmap = bitmap;
mDensity = bitmap.mDensity;
}
-
- Canvas(int nativeCanvas) {
+
+ /** @hide */
+ public Canvas(int nativeCanvas) {
if (nativeCanvas == 0) {
throw new IllegalStateException();
}
mNativeCanvas = nativeCanvas;
- mFinalizer = new CanvasFinalizer(nativeCanvas);
+ mFinalizer = new CanvasFinalizer(mNativeCanvas);
mDensity = Bitmap.getDefaultDensity();
}
@@ -155,7 +161,18 @@
}
finalizer(oldCanvas);
}
-
+
+ /**
+ * Gets the native canvas pointer.
+ *
+ * @return The native pointer.
+ *
+ * @hide
+ */
+ public int getNativeCanvas() {
+ return mNativeCanvas;
+ }
+
/**
* Returns null.
*
@@ -1660,6 +1677,15 @@
}
/**
+ * Releases the resources associated with this canvas.
+ *
+ * @hide
+ */
+ public void release() {
+ mFinalizer.dispose();
+ }
+
+ /**
* Free up as much memory as possible from private caches (e.g. fonts, images)
*
* @hide
diff --git a/libs/hwui/DeferredDisplayList.cpp b/libs/hwui/DeferredDisplayList.cpp
index 887e822..7ce15c5 100644
--- a/libs/hwui/DeferredDisplayList.cpp
+++ b/libs/hwui/DeferredDisplayList.cpp
@@ -152,8 +152,9 @@
class MergingDrawBatch : public DrawBatch {
public:
- MergingDrawBatch(DeferInfo& deferInfo, Rect viewport) :
- DrawBatch(deferInfo), mClipRect(viewport), mClipSideFlags(kClipSide_None) {}
+ MergingDrawBatch(DeferInfo& deferInfo, int width, int height) :
+ DrawBatch(deferInfo), mClipRect(width, height),
+ mClipSideFlags(kClipSide_None) {}
/*
* Helper for determining if a new op can merge with a MergingDrawBatch based on their bounds
@@ -489,6 +490,7 @@
// complex clip has a complex set of expectations on the renderer state - for now, avoid taking
// the merge path in those cases
deferInfo.mergeable &= !recordingComplexClip();
+ deferInfo.opaqueOverBounds &= !recordingComplexClip() && mSaveStack.isEmpty();
if (CC_LIKELY(mAvoidOverdraw) && mBatches.size() &&
op->state.mClipSideFlags != kClipSide_ConservativeFull &&
@@ -570,7 +572,8 @@
if (!targetBatch) {
if (deferInfo.mergeable) {
- targetBatch = new MergingDrawBatch(deferInfo, mBounds);
+ targetBatch = new MergingDrawBatch(deferInfo,
+ renderer.getViewportWidth(), renderer.getViewportHeight());
mMergingBatches[deferInfo.batchId].put(deferInfo.mergeId, targetBatch);
} else {
targetBatch = new DrawBatch(deferInfo);
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index f678bfd..6099f5d 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -77,7 +77,7 @@
virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
bool useQuickReject) = 0;
- virtual void output(int level, uint32_t logFlags = 0) = 0;
+ virtual void output(int level, uint32_t logFlags = 0) const = 0;
// NOTE: it would be nice to declare constants and overriding the implementation in each op to
// point at the constants, but that seems to require a .cpp file
@@ -278,7 +278,7 @@
renderer.save(mFlags);
}
- virtual void output(int level, uint32_t logFlags) {
+ virtual void output(int level, uint32_t logFlags) const {
OP_LOG("Save flags %x", mFlags);
}
@@ -312,7 +312,7 @@
renderer.restoreToCount(saveCount + mCount);
}
- virtual void output(int level, uint32_t logFlags) {
+ virtual void output(int level, uint32_t logFlags) const {
OP_LOG("Restore to count %d", mCount);
}
@@ -351,7 +351,7 @@
renderer.saveLayer(mArea.left, mArea.top, mArea.right, mArea.bottom, mAlpha, mMode, mFlags);
}
- virtual void output(int level, uint32_t logFlags) {
+ virtual void output(int level, uint32_t logFlags) const {
OP_LOG("SaveLayer%s of area " RECT_STRING,
(isSaveLayerAlpha() ? "Alpha" : ""),RECT_ARGS(mArea));
}
@@ -372,7 +372,7 @@
return this;
}
- bool isSaveLayerAlpha() { return mAlpha < 255 && mMode == SkXfermode::kSrcOver_Mode; }
+ bool isSaveLayerAlpha() const { return mAlpha < 255 && mMode == SkXfermode::kSrcOver_Mode; }
Rect mArea;
int mAlpha;
SkXfermode::Mode mMode;
@@ -388,7 +388,7 @@
renderer.translate(mDx, mDy);
}
- virtual void output(int level, uint32_t logFlags) {
+ virtual void output(int level, uint32_t logFlags) const {
OP_LOG("Translate by %f %f", mDx, mDy);
}
@@ -408,7 +408,7 @@
renderer.rotate(mDegrees);
}
- virtual void output(int level, uint32_t logFlags) {
+ virtual void output(int level, uint32_t logFlags) const {
OP_LOG("Rotate by %f degrees", mDegrees);
}
@@ -427,7 +427,7 @@
renderer.scale(mSx, mSy);
}
- virtual void output(int level, uint32_t logFlags) {
+ virtual void output(int level, uint32_t logFlags) const {
OP_LOG("Scale by %f %f", mSx, mSy);
}
@@ -447,7 +447,7 @@
renderer.skew(mSx, mSy);
}
- virtual void output(int level, uint32_t logFlags) {
+ virtual void output(int level, uint32_t logFlags) const {
OP_LOG("Skew by %f %f", mSx, mSy);
}
@@ -467,7 +467,7 @@
renderer.setMatrix(mMatrix);
}
- virtual void output(int level, uint32_t logFlags) {
+ virtual void output(int level, uint32_t logFlags) const {
OP_LOG("SetMatrix " MATRIX_STRING, MATRIX_ARGS(mMatrix));
}
@@ -486,7 +486,7 @@
renderer.concatMatrix(mMatrix);
}
- virtual void output(int level, uint32_t logFlags) {
+ virtual void output(int level, uint32_t logFlags) const {
OP_LOG("ConcatMatrix " MATRIX_STRING, MATRIX_ARGS(mMatrix));
}
@@ -530,7 +530,7 @@
renderer.clipRect(mArea.left, mArea.top, mArea.right, mArea.bottom, mOp);
}
- virtual void output(int level, uint32_t logFlags) {
+ virtual void output(int level, uint32_t logFlags) const {
OP_LOG("ClipRect " RECT_STRING, RECT_ARGS(mArea));
}
@@ -559,7 +559,7 @@
renderer.clipPath(mPath, mOp);
}
- virtual void output(int level, uint32_t logFlags) {
+ virtual void output(int level, uint32_t logFlags) const {
SkRect bounds = mPath->getBounds();
OP_LOG("ClipPath bounds " RECT_STRING,
bounds.left(), bounds.top(), bounds.right(), bounds.bottom());
@@ -580,7 +580,7 @@
renderer.clipRegion(mRegion, mOp);
}
- virtual void output(int level, uint32_t logFlags) {
+ virtual void output(int level, uint32_t logFlags) const {
SkIRect bounds = mRegion->getBounds();
OP_LOG("ClipRegion bounds %d %d %d %d",
bounds.left(), bounds.top(), bounds.right(), bounds.bottom());
@@ -599,7 +599,7 @@
renderer.resetShader();
}
- virtual void output(int level, uint32_t logFlags) {
+ virtual void output(int level, uint32_t logFlags) const {
OP_LOGS("ResetShader");
}
@@ -614,7 +614,7 @@
renderer.setupShader(mShader);
}
- virtual void output(int level, uint32_t logFlags) {
+ virtual void output(int level, uint32_t logFlags) const {
OP_LOG("SetupShader, shader %p", mShader);
}
@@ -630,7 +630,7 @@
renderer.resetColorFilter();
}
- virtual void output(int level, uint32_t logFlags) {
+ virtual void output(int level, uint32_t logFlags) const {
OP_LOGS("ResetColorFilter");
}
@@ -646,7 +646,7 @@
renderer.setupColorFilter(mColorFilter);
}
- virtual void output(int level, uint32_t logFlags) {
+ virtual void output(int level, uint32_t logFlags) const {
OP_LOG("SetupColorFilter, filter %p", mColorFilter);
}
@@ -662,7 +662,7 @@
renderer.resetShadow();
}
- virtual void output(int level, uint32_t logFlags) {
+ virtual void output(int level, uint32_t logFlags) const {
OP_LOGS("ResetShadow");
}
@@ -678,7 +678,7 @@
renderer.setupShadow(mRadius, mDx, mDy, mColor);
}
- virtual void output(int level, uint32_t logFlags) {
+ virtual void output(int level, uint32_t logFlags) const {
OP_LOG("SetupShadow, radius %f, %f, %f, color %#x", mRadius, mDx, mDy, mColor);
}
@@ -697,7 +697,7 @@
renderer.resetPaintFilter();
}
- virtual void output(int level, uint32_t logFlags) {
+ virtual void output(int level, uint32_t logFlags) const {
OP_LOGS("ResetPaintFilter");
}
@@ -713,7 +713,7 @@
renderer.setupPaintFilter(mClearBits, mSetBits);
}
- virtual void output(int level, uint32_t logFlags) {
+ virtual void output(int level, uint32_t logFlags) const {
OP_LOG("SetupPaintFilter, clear %#x, set %#x", mClearBits, mSetBits);
}
@@ -751,12 +751,18 @@
TextureVertex::set(ptr++, posRect.xDim - offsetRect.left, posRect.yDim - offsetRect.top, \
texCoordsRect.xDim, texCoordsRect.yDim)
+ /**
+ * This multi-draw operation builds a mesh on the stack by generating a quad
+ * for each bitmap in the batch. This method is also responsible for dirtying
+ * the current layer, if any.
+ */
virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty,
const Vector<DrawOp*>& ops, const Rect& bounds) {
renderer.restoreDisplayState(state, true); // restore all but the clip
TextureVertex vertices[6 * ops.size()];
TextureVertex* vertex = &vertices[0];
+ const bool hasLayer = renderer.hasLayer();
bool transformed = false;
// TODO: manually handle rect clip for bitmaps by adjusting texCoords per op,
@@ -778,13 +784,18 @@
SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, bottom);
SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, top);
SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, bottom);
+
+ if (hasLayer) {
+ const Rect& dirty = ops[i]->state.mBounds;
+ renderer.dirtyLayer(dirty.left, dirty.top, dirty.right, dirty.bottom);
+ }
}
return renderer.drawBitmaps(mBitmap, ops.size(), &vertices[0],
transformed, bounds, mPaint);
}
- virtual void output(int level, uint32_t logFlags) {
+ virtual void output(int level, uint32_t logFlags) const {
OP_LOG("Draw bitmap %p at %f %f", mBitmap, mLocalBounds.left, mLocalBounds.top);
}
@@ -822,7 +833,7 @@
return renderer.drawBitmap(mBitmap, mMatrix, getPaint(renderer));
}
- virtual void output(int level, uint32_t logFlags) {
+ virtual void output(int level, uint32_t logFlags) const {
OP_LOG("Draw bitmap %p matrix " MATRIX_STRING, mBitmap, MATRIX_ARGS(mMatrix));
}
@@ -850,7 +861,7 @@
getPaint(renderer));
}
- virtual void output(int level, uint32_t logFlags) {
+ virtual void output(int level, uint32_t logFlags) const {
OP_LOG("Draw bitmap %p src="RECT_STRING", dst="RECT_STRING,
mBitmap, RECT_ARGS(mSrc), RECT_ARGS(mLocalBounds));
}
@@ -876,7 +887,7 @@
mLocalBounds.top, getPaint(renderer));
}
- virtual void output(int level, uint32_t logFlags) {
+ virtual void output(int level, uint32_t logFlags) const {
OP_LOG("Draw bitmap %p", mBitmap);
}
@@ -900,7 +911,7 @@
mVertices, mColors, getPaint(renderer));
}
- virtual void output(int level, uint32_t logFlags) {
+ virtual void output(int level, uint32_t logFlags) const {
OP_LOG("Draw bitmap %p mesh %d x %d", mBitmap, mMeshWidth, mMeshHeight);
}
@@ -921,28 +932,107 @@
class DrawPatchOp : public DrawBoundedOp {
public:
DrawPatchOp(SkBitmap* bitmap, Res_png_9patch* patch,
- float left, float top, float right, float bottom, int alpha, SkXfermode::Mode mode)
- : DrawBoundedOp(left, top, right, bottom, 0),
- mBitmap(bitmap), mPatch(patch), mAlpha(alpha), mMode(mode),
- mGenerationId(0), mMesh(NULL) {
+ float left, float top, float right, float bottom, SkPaint* paint)
+ : DrawBoundedOp(left, top, right, bottom, paint),
+ mBitmap(bitmap), mPatch(patch), mGenerationId(0), mMesh(NULL) {
mEntry = Caches::getInstance().assetAtlas.getEntry(bitmap);
};
- virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
+ const Patch* getMesh(OpenGLRenderer& renderer) {
if (!mMesh || renderer.getCaches().patchCache.getGenerationId() != mGenerationId) {
PatchCache& cache = renderer.getCaches().patchCache;
mMesh = cache.get(mEntry, mBitmap->width(), mBitmap->height(),
- mLocalBounds.right - mLocalBounds.left, mLocalBounds.bottom - mLocalBounds.top,
- mPatch);
+ mLocalBounds.getWidth(), mLocalBounds.getHeight(), mPatch);
mGenerationId = cache.getGenerationId();
}
- // We're not calling the public variant of drawPatch() here
- // This method won't perform the quickReject() since we've already done it at this point
- return renderer.drawPatch(mBitmap, mMesh, mEntry, mLocalBounds.left, mLocalBounds.top,
- mLocalBounds.right, mLocalBounds.bottom, mAlpha, mMode);
+ return mMesh;
}
- virtual void output(int level, uint32_t logFlags) {
+ /**
+ * This multi-draw operation builds an indexed mesh on the stack by copying
+ * and transforming the vertices of each 9-patch in the batch. This method
+ * is also responsible for dirtying the current layer, if any.
+ */
+ virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty,
+ const Vector<DrawOp*>& ops, const Rect& bounds) {
+ renderer.restoreDisplayState(state, true);
+
+ // Batches will usually contain a small number of items so it's
+ // worth performing a first iteration to count the exact number
+ // of vertices we need in the new mesh
+ uint32_t totalVertices = 0;
+ for (unsigned int i = 0; i < ops.size(); i++) {
+ totalVertices += ((DrawPatchOp*) ops[i])->getMesh(renderer)->verticesCount;
+ }
+
+ const bool hasLayer = renderer.hasLayer();
+
+ uint32_t indexCount = 0;
+
+ TextureVertex vertices[totalVertices];
+ TextureVertex* vertex = &vertices[0];
+
+ // Create a mesh that contains the transformed vertices for all the
+ // 9-patch objects that are part of the batch. Note that onDefer()
+ // enforces ops drawn by this function to have a pure translate or
+ // identity matrix
+ for (unsigned int i = 0; i < ops.size(); i++) {
+ DrawPatchOp* patchOp = (DrawPatchOp*) ops[i];
+ const Patch* opMesh = patchOp->getMesh(renderer);
+ uint32_t vertexCount = opMesh->verticesCount;
+ if (vertexCount == 0) continue;
+
+ // We use the bounds to know where to translate our vertices
+ // Using patchOp->state.mBounds wouldn't work because these
+ // bounds are clipped
+ const float tx = (int) floorf(patchOp->state.mMatrix.getTranslateX() +
+ patchOp->mLocalBounds.left + 0.5f);
+ const float ty = (int) floorf(patchOp->state.mMatrix.getTranslateY() +
+ patchOp->mLocalBounds.top + 0.5f);
+
+ // Copy & transform all the vertices for the current operation
+ TextureVertex* opVertices = opMesh->vertices;
+ for (uint32_t j = 0; j < vertexCount; j++, opVertices++) {
+ TextureVertex::set(vertex++,
+ opVertices->position[0] + tx, opVertices->position[1] + ty,
+ opVertices->texture[0], opVertices->texture[1]);
+ }
+
+ // Dirty the current layer if possible. When the 9-patch does not
+ // contain empty quads we can take a shortcut and simply set the
+ // dirty rect to the object's bounds.
+ if (hasLayer) {
+ if (!opMesh->hasEmptyQuads) {
+ renderer.dirtyLayer(tx, ty,
+ tx + patchOp->mLocalBounds.getWidth(),
+ ty + patchOp->mLocalBounds.getHeight());
+ } else {
+ const size_t count = opMesh->quads.size();
+ for (size_t i = 0; i < count; i++) {
+ const Rect& quadBounds = opMesh->quads[i];
+ const float x = tx + quadBounds.left;
+ const float y = ty + quadBounds.top;
+ renderer.dirtyLayer(x, y,
+ x + quadBounds.getWidth(), y + quadBounds.getHeight());
+ }
+ }
+ }
+
+ indexCount += opMesh->indexCount;
+ }
+
+ return renderer.drawPatches(mBitmap, mEntry, &vertices[0], indexCount, getPaint(renderer));
+ }
+
+ virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
+ // We're not calling the public variant of drawPatch() here
+ // This method won't perform the quickReject() since we've already done it at this point
+ return renderer.drawPatch(mBitmap, getMesh(renderer), mEntry,
+ mLocalBounds.left, mLocalBounds.top, mLocalBounds.right, mLocalBounds.bottom,
+ getPaint(renderer));
+ }
+
+ virtual void output(int level, uint32_t logFlags) const {
OP_LOG("Draw patch "RECT_STRING, RECT_ARGS(mLocalBounds));
}
@@ -951,7 +1041,8 @@
virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo) {
deferInfo.batchId = DeferredDisplayList::kOpBatch_Patch;
deferInfo.mergeId = mEntry ? (mergeid_t) &mEntry->atlas : (mergeid_t) mBitmap;
- deferInfo.mergeable = true;
+ deferInfo.mergeable = state.mMatrix.isPureTranslate() &&
+ OpenGLRenderer::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode;
deferInfo.opaqueOverBounds = isOpaqueOverBounds() && mBitmap->isOpaque();
}
@@ -959,11 +1050,9 @@
SkBitmap* mBitmap;
Res_png_9patch* mPatch;
- int mAlpha;
- SkXfermode::Mode mMode;
-
uint32_t mGenerationId;
const Patch* mMesh;
+
AssetAtlas::Entry* mEntry;
};
@@ -976,7 +1065,7 @@
return renderer.drawColor(mColor, mMode);
}
- virtual void output(int level, uint32_t logFlags) {
+ virtual void output(int level, uint32_t logFlags) const {
OP_LOG("Draw color %#x, mode %d", mColor, mMode);
}
@@ -1021,7 +1110,7 @@
mLocalBounds.right, mLocalBounds.bottom, getPaint(renderer));
}
- virtual void output(int level, uint32_t logFlags) {
+ virtual void output(int level, uint32_t logFlags) const {
OP_LOG("Draw Rect "RECT_STRING, RECT_ARGS(mLocalBounds));
}
@@ -1044,7 +1133,7 @@
return renderer.drawRects(mRects, mCount, getPaint(renderer));
}
- virtual void output(int level, uint32_t logFlags) {
+ virtual void output(int level, uint32_t logFlags) const {
OP_LOG("Draw Rects count %d", mCount);
}
@@ -1070,7 +1159,7 @@
mLocalBounds.right, mLocalBounds.bottom, mRx, mRy, getPaint(renderer));
}
- virtual void output(int level, uint32_t logFlags) {
+ virtual void output(int level, uint32_t logFlags) const {
OP_LOG("Draw RoundRect "RECT_STRING", rx %f, ry %f", RECT_ARGS(mLocalBounds), mRx, mRy);
}
@@ -1091,7 +1180,7 @@
return renderer.drawCircle(mX, mY, mRadius, getPaint(renderer));
}
- virtual void output(int level, uint32_t logFlags) {
+ virtual void output(int level, uint32_t logFlags) const {
OP_LOG("Draw Circle x %f, y %f, r %f", mX, mY, mRadius);
}
@@ -1113,7 +1202,7 @@
mLocalBounds.right, mLocalBounds.bottom, getPaint(renderer));
}
- virtual void output(int level, uint32_t logFlags) {
+ virtual void output(int level, uint32_t logFlags) const {
OP_LOG("Draw Oval "RECT_STRING, RECT_ARGS(mLocalBounds));
}
@@ -1133,7 +1222,7 @@
mStartAngle, mSweepAngle, mUseCenter, getPaint(renderer));
}
- virtual void output(int level, uint32_t logFlags) {
+ virtual void output(int level, uint32_t logFlags) const {
OP_LOG("Draw Arc "RECT_STRING", start %f, sweep %f, useCenter %d",
RECT_ARGS(mLocalBounds), mStartAngle, mSweepAngle, mUseCenter);
}
@@ -1169,7 +1258,7 @@
deferInfo.batchId = DeferredDisplayList::kOpBatch_AlphaMaskTexture;
}
- virtual void output(int level, uint32_t logFlags) {
+ virtual void output(int level, uint32_t logFlags) const {
OP_LOG("Draw Path %p in "RECT_STRING, mPath, RECT_ARGS(mLocalBounds));
}
@@ -1191,7 +1280,7 @@
return renderer.drawLines(mPoints, mCount, getPaint(renderer));
}
- virtual void output(int level, uint32_t logFlags) {
+ virtual void output(int level, uint32_t logFlags) const {
OP_LOG("Draw Lines count %d", mCount);
}
@@ -1217,7 +1306,7 @@
return renderer.drawPoints(mPoints, mCount, getPaint(renderer));
}
- virtual void output(int level, uint32_t logFlags) {
+ virtual void output(int level, uint32_t logFlags) const {
OP_LOG("Draw Points count %d", mCount);
}
@@ -1229,7 +1318,7 @@
DrawSomeTextOp(const char* text, int bytesCount, int count, SkPaint* paint)
: DrawOp(paint), mText(text), mBytesCount(bytesCount), mCount(count) {};
- virtual void output(int level, uint32_t logFlags) {
+ virtual void output(int level, uint32_t logFlags) const {
OP_LOG("Draw some text, %d bytes", mBytesCount);
}
@@ -1339,7 +1428,7 @@
return status;
}
- virtual void output(int level, uint32_t logFlags) {
+ virtual void output(int level, uint32_t logFlags) const {
OP_LOG("Draw Text of count %d, bytes %d", mCount, mBytesCount);
}
@@ -1372,7 +1461,7 @@
return ret;
}
- virtual void output(int level, uint32_t logFlags) {
+ virtual void output(int level, uint32_t logFlags) const {
OP_LOG("Draw Functor %p", mFunctor);
}
@@ -1406,7 +1495,7 @@
return DrawGlInfo::kStatusDone;
}
- virtual void output(int level, uint32_t logFlags) {
+ virtual void output(int level, uint32_t logFlags) const {
OP_LOG("Draw Display List %p, flags %#x", mDisplayList, mFlags);
if (mDisplayList && (logFlags & kOpLogFlag_Recurse)) {
mDisplayList->output(level + 1);
@@ -1429,7 +1518,7 @@
return renderer.drawLayer(mLayer, mX, mY);
}
- virtual void output(int level, uint32_t logFlags) {
+ virtual void output(int level, uint32_t logFlags) const {
OP_LOG("Draw Layer %p at %f %f", mLayer, mX, mY);
}
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index 6d85a16..5d23e1d 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -317,13 +317,10 @@
status_t DisplayListRenderer::drawPatch(SkBitmap* bitmap, Res_png_9patch* patch,
float left, float top, float right, float bottom, SkPaint* paint) {
- int alpha;
- SkXfermode::Mode mode;
- OpenGLRenderer::getAlphaAndModeDirect(paint, &alpha, &mode);
-
bitmap = refBitmap(bitmap);
+ paint = refPaint(paint);
- addDrawOp(new (alloc()) DrawPatchOp(bitmap, patch, left, top, right, bottom, alpha, mode));
+ addDrawOp(new (alloc()) DrawPatchOp(bitmap, patch, left, top, right, bottom, paint));
return DrawGlInfo::kStatusDone;
}
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 1dcf21a..6f1dc6f 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -827,6 +827,7 @@
if (!mSnapshot->isIgnored()) {
mSnapshot->resetTransform(-bounds.left, -bounds.top, 0.0f);
mSnapshot->resetClip(clip.left, clip.top, clip.right, clip.bottom);
+ mSnapshot->viewport.set(0.0f, 0.0f, bounds.getWidth(), bounds.getHeight());
}
}
@@ -1191,7 +1192,7 @@
// after we setup drawing in case we need to mess with the
// stencil buffer in setupDraw()
TextureVertex* mesh = mCaches.getRegionMesh();
- GLsizei numQuads = 0;
+ uint32_t numQuads = 0;
setupDrawWithTexture();
setupDrawColor(alpha, alpha, alpha, alpha);
@@ -2049,6 +2050,11 @@
GL_TRIANGLE_STRIP, gMeshCount, ignoreTransform);
}
+/**
+ * Important note: this method is intended to draw batches of bitmaps and
+ * will not set the scissor enable or dirty the current layer, if any.
+ * The caller is responsible for properly dirtying the current layer.
+ */
status_t OpenGLRenderer::drawBitmaps(SkBitmap* bitmap, int bitmapCount, TextureVertex* vertices,
bool transformed, const Rect& bounds, SkPaint* paint) {
mCaches.activeTexture(0);
@@ -2071,12 +2077,12 @@
drawAlpha8TextureMesh(x, y, x + bounds.getWidth(), y + bounds.getHeight(),
texture->id, paint != NULL, color, alpha, mode,
&vertices[0].position[0], &vertices[0].texture[0],
- GL_TRIANGLES, bitmapCount * 6, true, true);
+ GL_TRIANGLES, bitmapCount * 6, true, true, false);
} else {
drawTextureMesh(x, y, x + bounds.getWidth(), y + bounds.getHeight(),
texture->id, alpha / 255.0f, mode, texture->blend,
&vertices[0].position[0], &vertices[0].texture[0],
- GL_TRIANGLES, bitmapCount * 6, false, true, 0, true);
+ GL_TRIANGLES, bitmapCount * 6, false, true, 0, true, false);
}
return DrawGlInfo::kStatusDrew;
@@ -2367,10 +2373,6 @@
status_t OpenGLRenderer::drawPatch(SkBitmap* bitmap, Res_png_9patch* patch,
float left, float top, float right, float bottom, SkPaint* paint) {
- int alpha;
- SkXfermode::Mode mode;
- getAlphaAndMode(paint, &alpha, &mode);
-
if (quickReject(left, top, right, bottom)) {
return DrawGlInfo::kStatusDone;
}
@@ -2379,13 +2381,11 @@
const Patch* mesh = mCaches.patchCache.get(entry, bitmap->width(), bitmap->height(),
right - left, bottom - top, patch);
- return drawPatch(bitmap, mesh, entry, left, top, right, bottom, alpha, mode);
+ return drawPatch(bitmap, mesh, entry, left, top, right, bottom, paint);
}
-status_t OpenGLRenderer::drawPatch(SkBitmap* bitmap, const Patch* mesh,
- AssetAtlas::Entry* entry, float left, float top, float right, float bottom,
- int alpha, SkXfermode::Mode mode) {
-
+status_t OpenGLRenderer::drawPatch(SkBitmap* bitmap, const Patch* mesh, AssetAtlas::Entry* entry,
+ float left, float top, float right, float bottom, SkPaint* paint) {
if (quickReject(left, top, right, bottom)) {
return DrawGlInfo::kStatusDone;
}
@@ -2399,6 +2399,10 @@
texture->setWrap(GL_CLAMP_TO_EDGE, true);
texture->setFilter(GL_LINEAR, true);
+ int alpha;
+ SkXfermode::Mode mode;
+ getAlphaAndMode(paint, &alpha, &mode);
+
const bool pureTranslate = currentTransform().isPureTranslate();
// Mark the current layer dirty where we are going to draw the patch
if (hasLayer() && mesh->hasEmptyQuads) {
@@ -2418,8 +2422,6 @@
}
}
- alpha *= mSnapshot->alpha;
-
if (CC_LIKELY(pureTranslate)) {
const float x = (int) floorf(left + currentTransform().getTranslateX() + 0.5f);
const float y = (int) floorf(top + currentTransform().getTranslateY() + 0.5f);
@@ -2441,6 +2443,32 @@
return DrawGlInfo::kStatusDrew;
}
+/**
+ * Important note: this method is intended to draw batches of 9-patch objects and
+ * will not set the scissor enable or dirty the current layer, if any.
+ * The caller is responsible for properly dirtying the current layer.
+ */
+status_t OpenGLRenderer::drawPatches(SkBitmap* bitmap, AssetAtlas::Entry* entry,
+ TextureVertex* vertices, uint32_t indexCount, SkPaint* paint) {
+ mCaches.activeTexture(0);
+ Texture* texture = entry ? entry->texture : mCaches.textureCache.get(bitmap);
+ if (!texture) return DrawGlInfo::kStatusDone;
+ const AutoTexture autoCleanup(texture);
+
+ texture->setWrap(GL_CLAMP_TO_EDGE, true);
+ texture->setFilter(GL_LINEAR, true);
+
+ int alpha;
+ SkXfermode::Mode mode;
+ getAlphaAndMode(paint, &alpha, &mode);
+
+ drawIndexedTextureMesh(0.0f, 0.0f, 1.0f, 1.0f, texture->id, alpha / 255.0f,
+ mode, texture->blend, &vertices[0].position[0], &vertices[0].texture[0],
+ GL_TRIANGLES, indexCount, false, true, 0, true, false);
+
+ return DrawGlInfo::kStatusDrew;
+}
+
status_t OpenGLRenderer::drawVertexBuffer(const VertexBuffer& vertexBuffer, SkPaint* paint,
bool useOffset) {
if (!vertexBuffer.getVertexCount()) {
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 0760f9c..aa0f9fc 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -297,10 +297,12 @@
virtual status_t drawBitmapData(SkBitmap* bitmap, float left, float top, SkPaint* paint);
virtual status_t drawBitmapMesh(SkBitmap* bitmap, int meshWidth, int meshHeight,
float* vertices, int* colors, SkPaint* paint);
+ status_t drawPatches(SkBitmap* bitmap, AssetAtlas::Entry* entry,
+ TextureVertex* vertices, uint32_t indexCount, SkPaint* paint);
virtual status_t drawPatch(SkBitmap* bitmap, Res_png_9patch* patch,
float left, float top, float right, float bottom, SkPaint* paint);
status_t drawPatch(SkBitmap* bitmap, const Patch* mesh, AssetAtlas::Entry* entry,
- float left, float top, float right, float bottom, int alpha, SkXfermode::Mode mode);
+ float left, float top, float right, float bottom, SkPaint* paint);
virtual status_t drawColor(int color, SkXfermode::Mode mode);
virtual status_t drawRect(float left, float top, float right, float bottom, SkPaint* paint);
virtual status_t drawRoundRect(float left, float top, float right, float bottom,
@@ -358,6 +360,9 @@
return mSnapshot->clipRegion->isEmpty();
}
+ int getViewportWidth() { return getSnapshot()->viewport.getWidth(); }
+ int getViewportHeight() { return getSnapshot()->viewport.getHeight(); }
+
/**
* Scales the alpha on the current snapshot. This alpha value will be modulated
* with other alpha values when drawing primitives.
@@ -1115,6 +1120,8 @@
friend class DisplayListRenderer;
friend class Layer;
friend class TextSetupFunctor;
+ friend class DrawBitmapOp;
+ friend class DrawPatchOp;
}; // class OpenGLRenderer
diff --git a/libs/hwui/Patch.cpp b/libs/hwui/Patch.cpp
index 6b0734a..9e3e701 100644
--- a/libs/hwui/Patch.cpp
+++ b/libs/hwui/Patch.cpp
@@ -32,7 +32,7 @@
// Constructors/destructor
///////////////////////////////////////////////////////////////////////////////
-Patch::Patch(): verticesCount(0), indexCount(0), hasEmptyQuads(false) {
+Patch::Patch(): vertices(NULL), verticesCount(0), indexCount(0), hasEmptyQuads(false) {
}
Patch::~Patch() {
@@ -47,14 +47,14 @@
}
TextureVertex* Patch::createMesh(const float bitmapWidth, const float bitmapHeight,
- float left, float top, float right, float bottom, const Res_png_9patch* patch) {
+ float width, float height, const Res_png_9patch* patch) {
UvMapper mapper;
- return createMesh(bitmapWidth, bitmapHeight, left, top, right, bottom, mapper, patch);
+ return createMesh(bitmapWidth, bitmapHeight, width, height, mapper, patch);
}
TextureVertex* Patch::createMesh(const float bitmapWidth, const float bitmapHeight,
- float left, float top, float right, float bottom,
- const UvMapper& mapper, const Res_png_9patch* patch) {
+ float width, float height, const UvMapper& mapper, const Res_png_9patch* patch) {
+ if (vertices) return vertices;
const uint32_t* colors = &patch->colors[0];
const int8_t numColors = patch->numColors;
@@ -79,7 +79,7 @@
uint32_t maxVertices = ((xCount + 1) * (yCount + 1) - emptyQuads) * 4;
if (maxVertices == 0) return NULL;
- TextureVertex* vertices = new TextureVertex[maxVertices];
+ vertices = new TextureVertex[maxVertices];
TextureVertex* vertex = vertices;
const int32_t* xDivs = patch->xDivs;
@@ -101,9 +101,9 @@
}
const float xStretchTex = stretchSize;
const float fixed = bitmapWidth - stretchSize;
- const float xStretch = fmaxf(right - left - fixed, 0.0f);
+ const float xStretch = fmaxf(width - fixed, 0.0f);
stretchX = xStretch / xStretchTex;
- rescaleX = fixed == 0.0f ? 0.0f : fminf(fmaxf(right - left, 0.0f) / fixed, 1.0f);
+ rescaleX = fixed == 0.0f ? 0.0f : fminf(fmaxf(width, 0.0f) / fixed, 1.0f);
}
if (yStretchCount > 0) {
@@ -113,9 +113,9 @@
}
const float yStretchTex = stretchSize;
const float fixed = bitmapHeight - stretchSize;
- const float yStretch = fmaxf(bottom - top - fixed, 0.0f);
+ const float yStretch = fmaxf(height - fixed, 0.0f);
stretchY = yStretch / yStretchTex;
- rescaleY = fixed == 0.0f ? 0.0f : fminf(fmaxf(bottom - top, 0.0f) / fixed, 1.0f);
+ rescaleY = fixed == 0.0f ? 0.0f : fminf(fmaxf(height, 0.0f) / fixed, 1.0f);
}
uint32_t quadCount = 0;
@@ -144,7 +144,7 @@
if (stepY > 0.0f) {
generateRow(xDivs, xCount, vertex, y1, y2, v1, v2, stretchX, rescaleX,
- right - left, bitmapWidth, quadCount);
+ width, bitmapWidth, quadCount);
}
y1 = y2;
@@ -154,9 +154,9 @@
}
if (previousStepY != bitmapHeight) {
- y2 = bottom - top;
+ y2 = height;
generateRow(xDivs, xCount, vertex, y1, y2, v1, 1.0f, stretchX, rescaleX,
- right - left, bitmapWidth, quadCount);
+ width, bitmapWidth, quadCount);
}
return vertices;
diff --git a/libs/hwui/Patch.h b/libs/hwui/Patch.h
index 448cf60..246ba66 100644
--- a/libs/hwui/Patch.h
+++ b/libs/hwui/Patch.h
@@ -45,6 +45,7 @@
*/
uint32_t getSize() const;
+ TextureVertex* vertices;
uint32_t verticesCount;
uint32_t indexCount;
bool hasEmptyQuads;
@@ -54,11 +55,9 @@
GLintptr textureOffset;
TextureVertex* createMesh(const float bitmapWidth, const float bitmapHeight,
- float left, float top, float right, float bottom,
- const Res_png_9patch* patch);
+ float width, float height, const Res_png_9patch* patch);
TextureVertex* createMesh(const float bitmapWidth, const float bitmapHeight,
- float left, float top, float right, float bottom,
- const UvMapper& mapper, const Res_png_9patch* patch);
+ float width, float height, const UvMapper& mapper, const Res_png_9patch* patch);
private:
void generateRow(const int32_t* xDivs, uint32_t xCount, TextureVertex*& vertex,
diff --git a/libs/hwui/PatchCache.cpp b/libs/hwui/PatchCache.cpp
index c23e991..dc69d7f 100644
--- a/libs/hwui/PatchCache.cpp
+++ b/libs/hwui/PatchCache.cpp
@@ -118,10 +118,10 @@
if (entry) {
vertices = newMesh->createMesh(bitmapWidth, bitmapHeight,
- 0.0f, 0.0f, pixelWidth, pixelHeight, entry->uvMapper, patch);
+ pixelWidth, pixelHeight, entry->uvMapper, patch);
} else {
vertices = newMesh->createMesh(bitmapWidth, bitmapHeight,
- 0.0f, 0.0f, pixelWidth, pixelHeight, patch);
+ pixelWidth, pixelHeight, patch);
}
if (vertices) {
@@ -141,8 +141,6 @@
mSize += size;
glBufferSubData(GL_ARRAY_BUFFER, newMesh->offset, size, vertices);
-
- delete[] vertices;
}
mCache.put(description, newMesh);
diff --git a/libs/hwui/PixelBuffer.cpp b/libs/hwui/PixelBuffer.cpp
index 74b628a..36e89c6 100644
--- a/libs/hwui/PixelBuffer.cpp
+++ b/libs/hwui/PixelBuffer.cpp
@@ -132,7 +132,10 @@
if (mAccessMode != kAccessMode_None) {
if (mMappedPointer) {
mCaches.bindPixelBuffer(mBuffer);
- glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
+ GLboolean status = glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
+ if (status == GL_FALSE) {
+ ALOGE("Corrupted GPU pixel buffer");
+ }
}
mAccessMode = kAccessMode_None;
mMappedPointer = NULL;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
index a19b52a..0e40140 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -90,7 +90,6 @@
boolean mShowPhoneRSSIForData = false;
boolean mShowAtLeastThreeGees = false;
boolean mAlwaysShowCdmaRssi = false;
- boolean mShow4GforLTE = false;
String mContentDescriptionPhoneSignal;
String mContentDescriptionWifi;
@@ -200,7 +199,6 @@
mShowPhoneRSSIForData = res.getBoolean(R.bool.config_showPhoneRSSIForData);
mShowAtLeastThreeGees = res.getBoolean(R.bool.config_showMin3G);
- mShow4GforLTE = res.getBoolean(R.bool.config_show4GForLTE);
mAlwaysShowCdmaRssi = res.getBoolean(
com.android.internal.R.bool.config_alwaysUseCdmaRssi);
@@ -680,7 +678,8 @@
R.string.accessibility_data_connection_3g);
break;
case TelephonyManager.NETWORK_TYPE_LTE:
- if (mShow4GforLTE) {
+ boolean show4GforLTE = mContext.getResources().getBoolean(R.bool.config_show4GForLTE);
+ if (show4GforLTE) {
mDataIconList = TelephonyIcons.DATA_4G[mInetCondition];
mDataTypeIconId = R.drawable.stat_sys_data_connected_4g;
mQSDataTypeIconId = R.drawable.ic_qs_signal_4g;
diff --git a/telephony/java/android/telephony/CellSignalStrengthLte.java b/telephony/java/android/telephony/CellSignalStrengthLte.java
index 55680c8..b456bb3 100644
--- a/telephony/java/android/telephony/CellSignalStrengthLte.java
+++ b/telephony/java/android/telephony/CellSignalStrengthLte.java
@@ -94,7 +94,7 @@
* @hide
*/
public void initialize(SignalStrength ss, int timingAdvance) {
- mSignalStrength = ss.getLteSignalStrenght();
+ mSignalStrength = ss.getLteSignalStrength();
mRsrp = ss.getLteRsrp();
mRsrq = ss.getLteRsrq();
mRssnr = ss.getLteRssnr();
diff --git a/telephony/java/android/telephony/SignalStrength.java b/telephony/java/android/telephony/SignalStrength.java
index 674955c..7b9cf4e 100644
--- a/telephony/java/android/telephony/SignalStrength.java
+++ b/telephony/java/android/telephony/SignalStrength.java
@@ -438,7 +438,7 @@
}
/** @hide */
- public int getLteSignalStrenght() {
+ public int getLteSignalStrength() {
return mLteSignalStrength;
}