Merge "Fix T-junctions in layers' generated meshes" into jb-mr2-dev
diff --git a/api/current.txt b/api/current.txt
index aa73b06..a89c30a 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -16032,7 +16032,7 @@
method public static void resetThreadGcInvocationCount();
method public static deprecated int setAllocationLimit(int);
method public static deprecated int setGlobalAllocationLimit(int);
- method public static void startAllocCounting();
+ method public static deprecated void startAllocCounting();
method public static void startMethodTracing();
method public static void startMethodTracing(java.lang.String);
method public static void startMethodTracing(java.lang.String, int);
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index ff3e843..612f1af 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -16,6 +16,7 @@
package android.content;
+import static android.content.pm.PackageManager.GET_PROVIDERS;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import android.app.AppOpsManager;
@@ -1169,6 +1170,15 @@
}
/**
+ * Like {@link #attachInfo(Context, android.content.pm.ProviderInfo)}, but for use
+ * when directly instantiating the provider for testing.
+ * @hide
+ */
+ public void attachInfoForTesting(Context context, ProviderInfo info) {
+ attachInfo(context, info, true);
+ }
+
+ /**
* After being instantiated, this is called to tell the content provider
* about itself.
*
@@ -1176,12 +1186,18 @@
* @param info Registered information about this content provider
*/
public void attachInfo(Context context, ProviderInfo info) {
+ attachInfo(context, info, false);
+ }
+
+ private void attachInfo(Context context, ProviderInfo info, boolean testing) {
/*
* We may be using AsyncTask from binder threads. Make it init here
* so its static handler is on the main thread.
*/
AsyncTask.init();
+ mNoPerms = testing;
+
/*
* Only allow it to be set once, so after the content service gives
* this to us clients can't change it.
@@ -1194,16 +1210,6 @@
setWritePermission(info.writePermission);
setPathPermissions(info.pathPermissions);
mExported = info.exported;
- mNoPerms = false;
- } else {
- // We enter here because the content provider is being instantiated
- // as a mock. We don't have any information about the provider (such
- // as its required permissions), and also want to avoid doing app op
- // checks since these aren't real calls coming in and we may not be
- // able to get the app ops service at all (if the test is using something
- // like the IsolatedProvider). So set this to true, to prevent us
- // from enabling app ops on this object.
- mNoPerms = true;
}
ContentProvider.this.onCreate();
}
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index e50c948..2e77237 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -45,7 +45,7 @@
/**
- * Provides various debugging functions for Android applications, including
+ * Provides various debugging methods for Android applications, including
* tracing and allocation counts.
* <p><strong>Logging Trace Files</strong></p>
* <p>Debug can create log files that give details about an application, such as
@@ -130,7 +130,7 @@
public int otherSharedDirty;
/** @hide */
- public static final int NUM_OTHER_STATS = 9;
+ public static final int NUM_OTHER_STATS = 10;
private int[] otherStats = new int[NUM_OTHER_STATS*3];
@@ -177,15 +177,16 @@
/* @hide */
public static String getOtherLabel(int which) {
switch (which) {
- case 0: return "Cursor";
- case 1: return "Ashmem";
- case 2: return "Other dev";
- case 3: return ".so mmap";
- case 4: return ".jar mmap";
- case 5: return ".apk mmap";
- case 6: return ".ttf mmap";
- case 7: return ".dex mmap";
- case 8: return "Other mmap";
+ case 0: return "Stack";
+ case 1: return "Cursor";
+ case 2: return "Ashmem";
+ case 3: return "Other dev";
+ case 4: return ".so mmap";
+ case 5: return ".jar mmap";
+ case 6: return ".apk mmap";
+ case 7: return ".ttf mmap";
+ case 8: return ".dex mmap";
+ case 9: return "Other mmap";
default: return "????";
}
}
@@ -554,16 +555,19 @@
/**
* Start counting the number and aggregate size of memory allocations.
*
- * <p>The {@link #startAllocCounting() start} function resets the counts and enables counting.
- * The {@link #stopAllocCounting() stop} function disables the counting so that the analysis
- * code doesn't cause additional allocations. The various <code>get</code> functions return
- * the specified value. And the various <code>reset</code> functions reset the specified
+ * <p>The {@link #startAllocCounting() start} method resets the counts and enables counting.
+ * The {@link #stopAllocCounting() stop} method disables the counting so that the analysis
+ * code doesn't cause additional allocations. The various <code>get</code> methods return
+ * the specified value. And the various <code>reset</code> methods reset the specified
* count.</p>
*
- * <p>Counts are kept for the system as a whole and for each thread.
+ * <p>Counts are kept for the system as a whole (global) and for each thread.
* The per-thread counts for threads other than the current thread
* are not cleared by the "reset" or "start" calls.</p>
+ *
+ * @deprecated Accurate counting is a burden on the runtime and may be removed.
*/
+ @Deprecated
public static void startAllocCounting() {
VMDebug.startAllocCounting();
}
@@ -577,32 +581,122 @@
VMDebug.stopAllocCounting();
}
+ /**
+ * Returns the global count of objects allocated by the runtime between a
+ * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
+ */
public static int getGlobalAllocCount() {
return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_OBJECTS);
}
+
+ /**
+ * Clears the global count of objects allocated.
+ * @see #getGlobalAllocCount()
+ */
+ public static void resetGlobalAllocCount() {
+ VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_OBJECTS);
+ }
+
+ /**
+ * Returns the global size, in bytes, of objects allocated by the runtime between a
+ * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
+ */
public static int getGlobalAllocSize() {
return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_BYTES);
}
+
+ /**
+ * Clears the global size of objects allocated.
+ * @see #getGlobalAllocCountSize()
+ */
+ public static void resetGlobalAllocSize() {
+ VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_BYTES);
+ }
+
+ /**
+ * Returns the global count of objects freed by the runtime between a
+ * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
+ */
public static int getGlobalFreedCount() {
return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_FREED_OBJECTS);
}
+
+ /**
+ * Clears the global count of objects freed.
+ * @see #getGlobalFreedCount()
+ */
+ public static void resetGlobalFreedCount() {
+ VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_FREED_OBJECTS);
+ }
+
+ /**
+ * Returns the global size, in bytes, of objects freed by the runtime between a
+ * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
+ */
public static int getGlobalFreedSize() {
return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_FREED_BYTES);
}
+
+ /**
+ * Clears the global size of objects freed.
+ * @see #getGlobalFreedSize()
+ */
+ public static void resetGlobalFreedSize() {
+ VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_FREED_BYTES);
+ }
+
+ /**
+ * Returns the number of non-concurrent GC invocations between a
+ * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
+ */
+ public static int getGlobalGcInvocationCount() {
+ return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_GC_INVOCATIONS);
+ }
+
+ /**
+ * Clears the count of non-concurrent GC invocations.
+ * @see #getGlobalGcInvocationCount()
+ */
+ public static void resetGlobalGcInvocationCount() {
+ VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_GC_INVOCATIONS);
+ }
+
+ /**
+ * Returns the number of classes successfully initialized (ie those that executed without
+ * throwing an exception) between a {@link #startAllocCounting() start} and
+ * {@link #stopAllocCounting() stop}.
+ */
public static int getGlobalClassInitCount() {
- /* number of classes that have been successfully initialized */
return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_CLASS_INIT_COUNT);
}
+
+ /**
+ * Clears the count of classes initialized.
+ * @see #getGlobalClassInitCount()
+ */
+ public static void resetGlobalClassInitCount() {
+ VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_CLASS_INIT_COUNT);
+ }
+
+ /**
+ * Returns the time spent successfully initializing classes between a
+ * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
+ */
public static int getGlobalClassInitTime() {
/* cumulative elapsed time for class initialization, in usec */
return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_CLASS_INIT_TIME);
}
/**
- * Returns the global count of external allocation requests. The
- * external allocation tracking feature was removed in Honeycomb.
+ * Clears the count of time spent initializing classes.
+ * @see #getGlobalClassInitTime()
+ */
+ public static void resetGlobalClassInitTime() {
+ VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_CLASS_INIT_TIME);
+ }
+
+ /**
* This method exists for compatibility and always returns 0.
- *
* @deprecated This method is now obsolete.
*/
@Deprecated
@@ -611,10 +705,21 @@
}
/**
- * Returns the global count of bytes externally allocated. The
- * external allocation tracking feature was removed in Honeycomb.
+ * This method exists for compatibility and has no effect.
+ * @deprecated This method is now obsolete.
+ */
+ @Deprecated
+ public static void resetGlobalExternalAllocSize() {}
+
+ /**
+ * This method exists for compatibility and has no effect.
+ * @deprecated This method is now obsolete.
+ */
+ @Deprecated
+ public static void resetGlobalExternalAllocCount() {}
+
+ /**
* This method exists for compatibility and always returns 0.
- *
* @deprecated This method is now obsolete.
*/
@Deprecated
@@ -623,11 +728,7 @@
}
/**
- * Returns the global count of freed external allocation requests.
- * The external allocation tracking feature was removed in
- * Honeycomb. This method exists for compatibility and always
- * returns 0.
- *
+ * This method exists for compatibility and always returns 0.
* @deprecated This method is now obsolete.
*/
@Deprecated
@@ -636,11 +737,14 @@
}
/**
- * Returns the global count of freed bytes from external
- * allocation requests. The external allocation tracking feature
- * was removed in Honeycomb. This method exists for compatibility
- * and always returns 0.
- *
+ * This method exists for compatibility and has no effect.
+ * @deprecated This method is now obsolete.
+ */
+ @Deprecated
+ public static void resetGlobalExternalFreedCount() {}
+
+ /**
+ * This method exists for compatibility and has no effect.
* @deprecated This method is now obsolete.
*/
@Deprecated
@@ -648,22 +752,48 @@
return 0;
}
- public static int getGlobalGcInvocationCount() {
- return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_GC_INVOCATIONS);
- }
+ /**
+ * This method exists for compatibility and has no effect.
+ * @deprecated This method is now obsolete.
+ */
+ @Deprecated
+ public static void resetGlobalExternalFreedSize() {}
+
+ /**
+ * Returns the thread-local count of objects allocated by the runtime between a
+ * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
+ */
public static int getThreadAllocCount() {
return VMDebug.getAllocCount(VMDebug.KIND_THREAD_ALLOCATED_OBJECTS);
}
+
+ /**
+ * Clears the thread-local count of objects allocated.
+ * @see #getThreadAllocCount()
+ */
+ public static void resetThreadAllocCount() {
+ VMDebug.resetAllocCount(VMDebug.KIND_THREAD_ALLOCATED_OBJECTS);
+ }
+
+ /**
+ * Returns the thread-local size of objects allocated by the runtime between a
+ * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
+ * @return The allocated size in bytes.
+ */
public static int getThreadAllocSize() {
return VMDebug.getAllocCount(VMDebug.KIND_THREAD_ALLOCATED_BYTES);
}
/**
- * Returns the count of external allocation requests made by the
- * current thread. The external allocation tracking feature was
- * removed in Honeycomb. This method exists for compatibility and
- * always returns 0.
- *
+ * Clears the thread-local count of objects allocated.
+ * @see #getThreadAllocSize()
+ */
+ public static void resetThreadAllocSize() {
+ VMDebug.resetAllocCount(VMDebug.KIND_THREAD_ALLOCATED_BYTES);
+ }
+
+ /**
+ * This method exists for compatibility and has no effect.
* @deprecated This method is now obsolete.
*/
@Deprecated
@@ -672,10 +802,14 @@
}
/**
- * Returns the global count of bytes externally allocated. The
- * external allocation tracking feature was removed in Honeycomb.
- * This method exists for compatibility and always returns 0.
- *
+ * This method exists for compatibility and has no effect.
+ * @deprecated This method is now obsolete.
+ */
+ @Deprecated
+ public static void resetThreadExternalAllocCount() {}
+
+ /**
+ * This method exists for compatibility and has no effect.
* @deprecated This method is now obsolete.
*/
@Deprecated
@@ -683,105 +817,33 @@
return 0;
}
- public static int getThreadGcInvocationCount() {
- return VMDebug.getAllocCount(VMDebug.KIND_THREAD_GC_INVOCATIONS);
- }
-
- public static void resetGlobalAllocCount() {
- VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_OBJECTS);
- }
- public static void resetGlobalAllocSize() {
- VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_BYTES);
- }
- public static void resetGlobalFreedCount() {
- VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_FREED_OBJECTS);
- }
- public static void resetGlobalFreedSize() {
- VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_FREED_BYTES);
- }
- public static void resetGlobalClassInitCount() {
- VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_CLASS_INIT_COUNT);
- }
- public static void resetGlobalClassInitTime() {
- VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_CLASS_INIT_TIME);
- }
-
/**
- * Resets the global count of external allocation requests. The
- * external allocation tracking feature was removed in Honeycomb.
* This method exists for compatibility and has no effect.
- *
- * @deprecated This method is now obsolete.
- */
- @Deprecated
- public static void resetGlobalExternalAllocCount() {}
-
- /**
- * Resets the global count of bytes externally allocated. The
- * external allocation tracking feature was removed in Honeycomb.
- * This method exists for compatibility and has no effect.
- *
- * @deprecated This method is now obsolete.
- */
- @Deprecated
- public static void resetGlobalExternalAllocSize() {}
-
- /**
- * Resets the global count of freed external allocations. The
- * external allocation tracking feature was removed in Honeycomb.
- * This method exists for compatibility and has no effect.
- *
- * @deprecated This method is now obsolete.
- */
- @Deprecated
- public static void resetGlobalExternalFreedCount() {}
-
- /**
- * Resets the global count counter of freed bytes from external
- * allocations. The external allocation tracking feature was
- * removed in Honeycomb. This method exists for compatibility and
- * has no effect.
- *
- * @deprecated This method is now obsolete.
- */
- @Deprecated
- public static void resetGlobalExternalFreedSize() {}
-
- public static void resetGlobalGcInvocationCount() {
- VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_GC_INVOCATIONS);
- }
- public static void resetThreadAllocCount() {
- VMDebug.resetAllocCount(VMDebug.KIND_THREAD_ALLOCATED_OBJECTS);
- }
- public static void resetThreadAllocSize() {
- VMDebug.resetAllocCount(VMDebug.KIND_THREAD_ALLOCATED_BYTES);
- }
-
- /**
- * Resets the count of external allocation requests made by the
- * current thread. The external allocation tracking feature was
- * removed in Honeycomb. This method exists for compatibility and
- * has no effect.
- *
- * @deprecated This method is now obsolete.
- */
- @Deprecated
- public static void resetThreadExternalAllocCount() {}
-
- /**
- * Resets the count of bytes externally allocated by the current
- * thread. The external allocation tracking feature was removed
- * in Honeycomb. This method exists for compatibility and has no
- * effect.
- *
* @deprecated This method is now obsolete.
*/
@Deprecated
public static void resetThreadExternalAllocSize() {}
+ /**
+ * Returns the number of thread-local non-concurrent GC invocations between a
+ * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
+ */
+ public static int getThreadGcInvocationCount() {
+ return VMDebug.getAllocCount(VMDebug.KIND_THREAD_GC_INVOCATIONS);
+ }
+
+ /**
+ * Clears the thread-local count of non-concurrent GC invocations.
+ * @see #getThreadGcInvocationCount()
+ */
public static void resetThreadGcInvocationCount() {
VMDebug.resetAllocCount(VMDebug.KIND_THREAD_GC_INVOCATIONS);
}
+
+ /**
+ * Clears all the global and thread-local memory allocation counters.
+ * @see #startAllocCounting()
+ */
public static void resetAllCounts() {
VMDebug.resetAllocCount(VMDebug.KIND_ALL_COUNTS);
}
@@ -1380,7 +1442,7 @@
}
/**
- * @return a String describing the immediate caller of the calling function.
+ * @return a String describing the immediate caller of the calling method.
* {@hide}
*/
public static String getCaller() {
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 1321515..dcb664e 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -334,8 +334,9 @@
* See {@link WebView#capturePicture} for details of the picture.
*
* @param view the WebView that owns the picture
- * @param picture the new picture. Applications targetting Jelly
- * Bean MR2 or above will always receive a null Picture.
+ * @param picture the new picture. Applications targeting
+ * {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2} or above
+ * will always receive a null Picture.
* @deprecated Deprecated due to internal changes.
*/
@Deprecated
diff --git a/core/java/android/webkit/WebViewClassic.java b/core/java/android/webkit/WebViewClassic.java
index 19784a4..6fefcca 100644
--- a/core/java/android/webkit/WebViewClassic.java
+++ b/core/java/android/webkit/WebViewClassic.java
@@ -7909,10 +7909,8 @@
if (mPictureListener != null) {
// trigger picture listener for hardware layers. Software layers are
// triggered in setNewPicture
- // TODO: Update CUR_DEVELOPMENT when appropriate JBMR2 constant is
- // available.
Picture picture = mContext.getApplicationInfo().targetSdkVersion <
- Build.VERSION_CODES.CUR_DEVELOPMENT ? capturePicture() : null;
+ Build.VERSION_CODES.JELLY_BEAN_MR2 ? capturePicture() : null;
mPictureListener.onNewPicture(getWebView(), picture);
}
}
@@ -7998,10 +7996,8 @@
|| mWebView.getLayerType() == View.LAYER_TYPE_SOFTWARE) {
// trigger picture listener for software layers. Hardware layers are
// triggered in pageSwapCallback
- // TODO: Update CUR_DEVELOPMENT when appropriate JBMR2 constant is
- // available.
Picture picture = mContext.getApplicationInfo().targetSdkVersion <
- Build.VERSION_CODES.CUR_DEVELOPMENT ? capturePicture() : null;
+ Build.VERSION_CODES.JELLY_BEAN_MR2 ? capturePicture() : null;
mPictureListener.onNewPicture(getWebView(), picture);
}
}
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index 6e21a11..2883c10 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -43,6 +43,7 @@
HEAP_UNKNOWN,
HEAP_DALVIK,
HEAP_NATIVE,
+ HEAP_STACK,
HEAP_CURSOR,
HEAP_ASHMEM,
HEAP_UNKNOWN_DEV,
@@ -109,7 +110,7 @@
static jlong android_os_Debug_getNativeHeapFreeSize(JNIEnv *env, jobject clazz)
{
-#ifdef HAVE_MALLOC_H
+#ifdef HAVE_MALLOC_H
struct mallinfo info = mallinfo();
return (jlong) info.fordblks;
#else
@@ -164,6 +165,8 @@
whichHeap = HEAP_NATIVE;
} else if (strstr(name, "/dev/ashmem/dalvik-") == name) {
whichHeap = HEAP_DALVIK;
+ } else if (strstr(name, "[stack") == name) {
+ whichHeap = HEAP_STACK;
} else if (strstr(name, "/dev/ashmem/CursorWindow") == name) {
whichHeap = HEAP_CURSOR;
} else if (strstr(name, "/dev/ashmem/") == name) {
@@ -191,7 +194,7 @@
//ALOGI("native=%d dalvik=%d sqlite=%d: %s\n", isNativeHeap, isDalvikHeap,
// isSqliteHeap, line);
-
+
while (true) {
if (fgets(line, 1024, fp) == 0) {
done = true;
@@ -233,7 +236,7 @@
{
char tmp[128];
FILE *fp;
-
+
sprintf(tmp, "/proc/%d/smaps", pid);
fp = fopen(tmp, "r");
if (fp == 0) return;
@@ -247,7 +250,7 @@
{
stats_t stats[_NUM_HEAP];
memset(&stats, 0, sizeof(stats));
-
+
load_maps(pid, stats);
for (int i=_NUM_CORE_HEAP; i<_NUM_HEAP; i++) {
@@ -261,9 +264,9 @@
env->SetIntField(object, stat_fields[i].privateDirty_field, stats[i].privateDirty);
env->SetIntField(object, stat_fields[i].sharedDirty_field, stats[i].sharedDirty);
}
-
+
jintArray otherIntArray = (jintArray)env->GetObjectField(object, otherStats_field);
-
+
jint* otherArray = (jint*)env->GetPrimitiveArrayCritical(otherIntArray, 0);
if (otherArray == NULL) {
return;
@@ -328,7 +331,7 @@
char compare[128];
int len = snprintf(compare, 128, "proc %d", getpid());
-
+
// loop until we have the block that represents this process
do {
if (fgets(line, 1024, fp) == 0) {
@@ -336,15 +339,15 @@
}
} while (strncmp(compare, line, len));
- // now that we have this process, read until we find the stat that we are looking for
+ // now that we have this process, read until we find the stat that we are looking for
len = snprintf(compare, 128, " %s: ", stat);
-
+
do {
if (fgets(line, 1024, fp) == 0) {
return -1;
}
} while (strncmp(compare, line, len));
-
+
// we have the line, now increment the line ptr to the value
char* ptr = line + len;
return atoi(ptr);
@@ -510,7 +513,7 @@
jobject fileDescriptor)
{
if (fileDescriptor == NULL) {
- jniThrowNullPointerException(env, NULL);
+ jniThrowNullPointerException(env, "fd == null");
return;
}
int origFd = jniGetFDFromFileDescriptor(env, fileDescriptor);
@@ -547,7 +550,7 @@
jint pid, jstring fileName)
{
if (fileName == NULL) {
- jniThrowNullPointerException(env, NULL);
+ jniThrowNullPointerException(env, "file == null");
return;
}
const jchar* str = env->GetStringCritical(fileName, 0);
@@ -611,6 +614,19 @@
{
jclass clazz = env->FindClass("android/os/Debug$MemoryInfo");
+ // Sanity check the number of other statistics expected in Java matches here.
+ jfieldID numOtherStats_field = env->GetStaticFieldID(clazz, "NUM_OTHER_STATS", "I");
+ jint numOtherStats = env->GetStaticIntField(clazz, numOtherStats_field);
+ int expectedNumOtherStats = _NUM_HEAP - _NUM_CORE_HEAP;
+ if (numOtherStats != expectedNumOtherStats) {
+ jniThrowExceptionFmt(env, "java/lang/RuntimeException",
+ "android.os.Debug.Meminfo.NUM_OTHER_STATS=%d expected %d",
+ numOtherStats, expectedNumOtherStats);
+ return JNI_ERR;
+ }
+
+ otherStats_field = env->GetFieldID(clazz, "otherStats", "[I");
+
for (int i=0; i<_NUM_CORE_HEAP; i++) {
stat_fields[i].pss_field =
env->GetFieldID(clazz, stat_field_names[i].pss_name, "I");
@@ -620,8 +636,6 @@
env->GetFieldID(clazz, stat_field_names[i].sharedDirty_name, "I");
}
- otherStats_field = env->GetFieldID(clazz, "otherStats", "[I");
-
return jniRegisterNativeMethods(env, "android/os/Debug", gMethods, NELEM(gMethods));
}
diff --git a/docs/html/distribute/googleplay/about/distribution.jd b/docs/html/distribute/googleplay/about/distribution.jd
index 1ddc4ca..7d90426 100644
--- a/docs/html/distribute/googleplay/about/distribution.jd
+++ b/docs/html/distribute/googleplay/about/distribution.jd
@@ -75,24 +75,29 @@
Google Play Developer Console, you can list the supported devices and
even exclude specific devices if needed.</p>
-<h2 id="stats">Statistics for analyzing installs</h2>
+<h2 id="stats">Statistics for analyzing installs and ratings</h2>
<p>Once you’ve published your app, Google Play makes it easy to see how it’s
doing. The Google Play Developer Console gives you access to a variety
-of anonymized metrics that show your app’s installation performance measured by
-unique users and unique devices, across a variety of different dimensions such
-as country, Android version, device, country, carrier, and app version.</p>
+of anonymized statistics and custom charts that show you the app's installation
+performance and ratings.</p>
-<div style="border:1px solid #DDD;margin:1.5em;margin-left:8%;width:608px">
-<img src="{@docRoot}images/gp-dc-stats-mini.png"
-style="width:600px;padding:4px;margin-bottom:0;">
+<p>You can view data and charts for active, daily, and total installs
+per unique devices or users, as well as upgrades and uninstalls.
+You can also view the app's daily average user rating and its cumulative
+user rating. To help you analyze the data, you can view install
+and ratings statistics across a variety of different dimensions such as Android
+version, device, country, app version, and carrier.</p>
+
+<div class="figure-left">
+ <img src="{@docRoot}images/gp-dc-stats-mini.png" class="frame">
</div>
-<p>You can also view your installation data on timeline charts, for all metrics and
-dimensions. At a glance, these charts highlight your app’s installation peaks
-and longer-term trends, which you can correlate to promotions, app improvements,
-or other factors. You can even focus in on data inside a dimension by
-highlighting specific data points (such as individual platform versions or
-languages) on the timeline.</p>
+<p>You can see your app statistics on timeline charts, for
+all metrics and dimensions. At a glance, the charts highlight your app’s
+installation and ratings peaks and longer-term trends, which you can correlate
+to promotions, app improvements, or other factors. You can even focus in on
+data inside a dimension by highlighting specific data points (such as
+individual platform versions or languages) on the timeline.</p>
<p>So that you can “take your data with you”, you can download all of your
installation data as a CSV file for viewing in the business program of your
@@ -123,7 +128,7 @@
upload the expansion files, Google Play hosts them for free and handles the
download of the files as part of the normal APK installation.</p>
-<h2 id="licensing">Protecting your App</h2>
+<h2 id="licensing">Protecting your app</h2>
<p>Google Play provides two key features to help you protect your application
against piracy — Google Play Licensing and app encryption.</p>
diff --git a/docs/html/distribute/googleplay/publish/console.jd b/docs/html/distribute/googleplay/publish/console.jd
index 069b2d2..0bf5e78 100644
--- a/docs/html/distribute/googleplay/publish/console.jd
+++ b/docs/html/distribute/googleplay/publish/console.jd
@@ -4,7 +4,7 @@
<p>Once you've <a
href="{@docRoot}distribute/googleplay/publish/register.html">registered</a> and
-received verification by email, you can sign in to your Google Play Android
+received verification by email, you can sign in to your Google Play
Developer Console, which will be the home for your app publishing operations and
tools on Google Play. This sections below introduce a few of the key areas
you'll find in the Developer Console.</p>
diff --git a/docs/html/distribute/googleplay/publish/preparing.jd b/docs/html/distribute/googleplay/publish/preparing.jd
index 0925f3c..416f02e 100644
--- a/docs/html/distribute/googleplay/publish/preparing.jd
+++ b/docs/html/distribute/googleplay/publish/preparing.jd
@@ -203,11 +203,19 @@
changes in your app binary, so you will need to make those changes before
creating your release-ready APK.</p>
+<p>To minimize the size of your app binary, make sure that you run the
+<a href="{@docRoot}tools/help/proguard.html">Proguard</a> tool on your code when
+building your release-ready APK.</p>
+
<table>
<tr>
<td><p>Related resources:</p>
<ul style="margin-top:-.5em;">
-<li><strong><a href="{@docRoot}google/play/expansion-files.html">APK Expansion Files</a></strong> — Developer documentation describing APK Expansion Files and how to support them in your app.</li>
+<li><strong><a href="{@docRoot}google/play/expansion-files.html">APK Expansion Files</a></strong>
+— Developer documentation describing APK Expansion Files and how to support them in your app.</li>
+<li><strong><a href="{@docRoot}tools/help/proguard.html">ProGuard</a></strong> — Developer
+documentation describing how to use ProGuard to shrink, optimize, and obfuscate your code prior
+to release.</li>
</ul>
</td>
</tr>
diff --git a/docs/html/google/play/filters.jd b/docs/html/google/play/filters.jd
index a68f4910..b2d780e 100644
--- a/docs/html/google/play/filters.jd
+++ b/docs/html/google/play/filters.jd
@@ -394,9 +394,10 @@
determine the country based on IP.</p></li> <li><p>Carrier is determined based on
the device's SIM (for GSM devices), not the current roaming carrier.</p></li></ul>
</td> </tr> <tr>
- <td valign="top">Native Platform</td> <td valign="top"><p>An application that includes native
- libraries that target a specific platform (ARM EABI v7 or x86, for example) are
- visible only on devices that support that platform. For details about the NDK and using
+ <td valign="top" style="white-space:nowrap;">CPU Architecture (ABI)</td>
+ <td valign="top"><p>An application that includes native
+ libraries that target a specific CPU architecture (ARM EABI v7 or x86, for example) are
+ visible only on devices that support that architecture. For details about the NDK and using
native libraries, see <a href="{@docRoot}tools/sdk/ndk/index.html#overview">What is the
Android NDK?</a></p> </tr> <tr>
<td valign="top">Copy-Protected Applications</td> <td valign="top"><p class="caution">Google
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 7d99fec..8da20f2 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -1197,14 +1197,14 @@
return 0f;
}
if (!mHasCompatScaling) {
- return native_measureText(text, index, count);
+ return (float) Math.ceil(native_measureText(text, index, count));
}
final float oldSize = getTextSize();
setTextSize(oldSize*mCompatScaling);
float w = native_measureText(text, index, count);
setTextSize(oldSize);
- return w*mInvCompatScaling;
+ return (float) Math.ceil(w*mInvCompatScaling);
}
private native float native_measureText(char[] text, int index, int count);
@@ -1229,14 +1229,14 @@
return 0f;
}
if (!mHasCompatScaling) {
- return native_measureText(text, start, end);
+ return (float) Math.ceil(native_measureText(text, start, end));
}
final float oldSize = getTextSize();
setTextSize(oldSize*mCompatScaling);
float w = native_measureText(text, start, end);
setTextSize(oldSize);
- return w*mInvCompatScaling;
+ return (float) Math.ceil(w*mInvCompatScaling);
}
private native float native_measureText(String text, int start, int end);
@@ -1256,12 +1256,14 @@
return 0f;
}
- if (!mHasCompatScaling) return native_measureText(text);
+ if (!mHasCompatScaling) {
+ return (float) Math.ceil(native_measureText(text));
+ }
final float oldSize = getTextSize();
setTextSize(oldSize*mCompatScaling);
float w = native_measureText(text);
setTextSize(oldSize);
- return w*mInvCompatScaling;
+ return (float) Math.ceil(w*mInvCompatScaling);
}
private native float native_measureText(String text);
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index 97812d4..9db8fe8 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -176,8 +176,8 @@
*/
DeferredDisplayState state;
protected:
- SkPaint* getPaint(OpenGLRenderer& renderer) {
- return renderer.filterPaint(mPaint);
+ SkPaint* getPaint(OpenGLRenderer& renderer, bool alwaysCopy = false) {
+ return renderer.filterPaint(mPaint, alwaysCopy);
}
SkPaint* mPaint; // should be accessed via getPaint() when applying
@@ -643,16 +643,13 @@
virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
bool caching, int multipliedAlpha) {
- SkPaint* paint = getPaint(renderer);
- int oldAlpha = -1;
- if (caching && multipliedAlpha < 255) {
- oldAlpha = paint->getAlpha();
+ bool makeCopy = caching && multipliedAlpha < 255;
+ SkPaint* paint = getPaint(renderer, makeCopy);
+ if (makeCopy) {
+ // The paint is safe to modify since we're working on a copy
paint->setAlpha(multipliedAlpha);
}
status_t ret = renderer.drawBitmap(mBitmap, mLocalBounds.left, mLocalBounds.top, paint);
- if (oldAlpha >= 0) {
- paint->setAlpha(oldAlpha);
- }
return ret;
}
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index eec5f5f..d683c27 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -2562,10 +2562,14 @@
glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
}
+bool OpenGLRenderer::canSkipText(const SkPaint* paint) const {
+ float alpha = (mDrawModifiers.mHasShadow ? 1.0f : paint->getAlpha()) * mSnapshot->alpha;
+ return alpha == 0.0f && getXfermode(paint->getXfermode()) == SkXfermode::kSrcOver_Mode;
+}
+
status_t OpenGLRenderer::drawPosText(const char* text, int bytesCount, int count,
const float* positions, SkPaint* paint) {
- if (text == NULL || count == 0 || mSnapshot->isIgnored() ||
- (paint->getAlpha() * mSnapshot->alpha == 0 && paint->getXfermode() == NULL)) {
+ if (text == NULL || count == 0 || mSnapshot->isIgnored() || canSkipText(paint)) {
return DrawGlInfo::kStatusDone;
}
@@ -2637,8 +2641,7 @@
status_t OpenGLRenderer::drawText(const char* text, int bytesCount, int count,
float x, float y, const float* positions, SkPaint* paint, float length) {
- if (text == NULL || count == 0 || mSnapshot->isIgnored() ||
- (paint->getAlpha() * mSnapshot->alpha == 0 && paint->getXfermode() == NULL)) {
+ if (text == NULL || count == 0 || mSnapshot->isIgnored() || canSkipText(paint)) {
return DrawGlInfo::kStatusDone;
}
@@ -2742,8 +2745,7 @@
status_t OpenGLRenderer::drawTextOnPath(const char* text, int bytesCount, int count, SkPath* path,
float hOffset, float vOffset, SkPaint* paint) {
- if (text == NULL || count == 0 || mSnapshot->isIgnored() ||
- (paint->getAlpha() == 0 && paint->getXfermode() == NULL)) {
+ if (text == NULL || count == 0 || mSnapshot->isIgnored() || canSkipText(paint)) {
return DrawGlInfo::kStatusDone;
}
@@ -2949,8 +2951,14 @@
mDrawModifiers.mPaintFilterSetBits = setBits & SkPaint::kAllFlags;
}
-SkPaint* OpenGLRenderer::filterPaint(SkPaint* paint) {
- if (CC_LIKELY(!mDrawModifiers.mHasDrawFilter || !paint)) return paint;
+SkPaint* OpenGLRenderer::filterPaint(SkPaint* paint, bool alwaysCopy) {
+ if (CC_LIKELY(!mDrawModifiers.mHasDrawFilter || !paint)) {
+ if (CC_UNLIKELY(alwaysCopy)) {
+ mFilteredPaint = *paint;
+ return &mFilteredPaint;
+ }
+ return paint;
+ }
uint32_t flags = paint->getFlags();
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 80f2081..3f47264 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -259,7 +259,7 @@
virtual void resetPaintFilter();
virtual void setupPaintFilter(int clearBits, int setBits);
- SkPaint* filterPaint(SkPaint* paint);
+ SkPaint* filterPaint(SkPaint* paint, bool alwaysCopy = false);
bool disallowDeferral() {
// returns true if the OpenGLRenderer's state can be completely represented by
@@ -779,6 +779,11 @@
void resetDrawTextureTexCoords(float u1, float v1, float u2, float v2);
/**
+ * Returns true if the specified paint will draw invisible text.
+ */
+ bool canSkipText(const SkPaint* paint) const;
+
+ /**
* Binds the specified texture. The texture unit must have been selected
* prior to calling this method.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
index 8d949a5..f3eecf2 100644
--- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
@@ -365,6 +365,7 @@
if (DEBUG) {
Log.d(TAG, "Redrawing wallpaper");
}
+
if (mIsHwAccelerated) {
if (!drawWallpaperWithOpenGL(sh, availw, availh, xPixels, yPixels)) {
drawWallpaperWithCanvas(sh, availw, availh, xPixels, yPixels);
@@ -626,13 +627,26 @@
}
mEglContext = createContext(mEgl, mEglDisplay, mEglConfig);
+
+ int[] maxSize = new int[1];
+ Rect frame = surfaceHolder.getSurfaceFrame();
+ glGetIntegerv(GL_MAX_TEXTURE_SIZE, maxSize, 0);
+ if(frame.width() > maxSize[0] || frame.height() > maxSize[0]) {
+ mEgl.eglDestroyContext(mEglDisplay, mEglContext);
+ mEgl.eglTerminate(mEglDisplay);
+ Log.e(GL_LOG_TAG, "requested texture size " +
+ frame.width() + "x" + frame.height() + " exceeds the support maximum of " +
+ maxSize[0] + "x" + maxSize[0]);
+ return false;
+ }
mEglSurface = mEgl.eglCreateWindowSurface(mEglDisplay, mEglConfig, surfaceHolder, null);
if (mEglSurface == null || mEglSurface == EGL_NO_SURFACE) {
int error = mEgl.eglGetError();
- if (error == EGL_BAD_NATIVE_WINDOW) {
- Log.e(GL_LOG_TAG, "createWindowSurface returned EGL_BAD_NATIVE_WINDOW.");
+ if (error == EGL_BAD_NATIVE_WINDOW || error == EGL_BAD_ALLOC) {
+ Log.e(GL_LOG_TAG, "createWindowSurface returned " +
+ GLUtils.getEGLErrorString(error) + ".");
return false;
}
throw new RuntimeException("createWindowSurface failed " +
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 0e545c6..bb05325 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -1500,6 +1500,9 @@
return null;
}
+ WindowManager wm = null;
+ View view = null;
+
try {
Context context = mContext;
if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "addStartingWindow " + packageName
@@ -1559,8 +1562,8 @@
params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
params.setTitle("Starting " + packageName);
- WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
- View view = win.getDecorView();
+ wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
+ view = win.getDecorView();
if (win.isFloating()) {
// Whoops, there is no way to display an animation/preview
@@ -1590,6 +1593,11 @@
// failure loading resources because we are loading from an app
// on external storage that has been unmounted.
Log.w(TAG, appToken + " failed creating starting window", e);
+ } finally {
+ if (view != null && view.getParent() == null) {
+ Log.w(TAG, "view not successfully added to wm, removing view");
+ wm.removeViewImmediate(view);
+ }
}
return null;
diff --git a/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
index fd5e79a..520bf71 100644
--- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -1741,25 +1741,23 @@
@Override
public void onServiceConnected(ComponentName componentName, IBinder service) {
- final int connectionId;
synchronized (mLock) {
- connectionId = mId;
mService = service;
mServiceInterface = IAccessibilityServiceClient.Stub.asInterface(service);
UserState userState = getUserStateLocked(mUserId);
addServiceLocked(this, userState);
- if (!userState.mBindingServices.contains(mComponentName)) {
- binderDied();
- } else {
+ if (userState.mBindingServices.contains(mComponentName)) {
userState.mBindingServices.remove(mComponentName);
onUserStateChangedLocked(userState);
+ try {
+ mServiceInterface.setConnection(this, mId);
+ } catch (RemoteException re) {
+ Slog.w(LOG_TAG, "Error while setting connection for service: " + service, re);
+ }
+ } else {
+ binderDied();
}
}
- try {
- mServiceInterface.setConnection(this, connectionId);
- } catch (RemoteException re) {
- Slog.w(LOG_TAG, "Error while setting connection for service: " + service, re);
- }
}
@Override
diff --git a/test-runner/src/android/test/ProviderTestCase.java b/test-runner/src/android/test/ProviderTestCase.java
index 74cebee..1b323cf 100644
--- a/test-runner/src/android/test/ProviderTestCase.java
+++ b/test-runner/src/android/test/ProviderTestCase.java
@@ -68,7 +68,7 @@
mProviderContext = new IsolatedContext(mResolver, targetContextWrapper);
mProvider = mProviderClass.newInstance();
- mProvider.attachInfo(mProviderContext, null);
+ mProvider.attachInfoForTesting(mProviderContext, null);
assertNotNull(mProvider);
mResolver.addProvider(mProviderAuthority, getProvider());
}
@@ -108,7 +108,7 @@
DatabaseUtils.createDbFromSqlStatements(context, databaseName, databaseVersion, sql);
T provider = providerClass.newInstance();
- provider.attachInfo(context, null);
+ provider.attachInfoForTesting(context, null);
resolver.addProvider(authority, provider);
return resolver;
diff --git a/test-runner/src/android/test/ProviderTestCase2.java b/test-runner/src/android/test/ProviderTestCase2.java
index f7c4e03..dcd089da 100644
--- a/test-runner/src/android/test/ProviderTestCase2.java
+++ b/test-runner/src/android/test/ProviderTestCase2.java
@@ -140,7 +140,7 @@
mProviderContext = new IsolatedContext(mResolver, targetContextWrapper);
mProvider = mProviderClass.newInstance();
- mProvider.attachInfo(mProviderContext, null);
+ mProvider.attachInfoForTesting(mProviderContext, null);
assertNotNull(mProvider);
mResolver.addProvider(mProviderAuthority, getProvider());
}
@@ -219,7 +219,7 @@
DatabaseUtils.createDbFromSqlStatements(context, databaseName, databaseVersion, sql);
T provider = providerClass.newInstance();
- provider.attachInfo(context, null);
+ provider.attachInfoForTesting(context, null);
resolver.addProvider(authority, provider);
return resolver;
diff --git a/test-runner/src/android/test/RenamingDelegatingContext.java b/test-runner/src/android/test/RenamingDelegatingContext.java
index eee3ad7..3d763c7 100644
--- a/test-runner/src/android/test/RenamingDelegatingContext.java
+++ b/test-runner/src/android/test/RenamingDelegatingContext.java
@@ -63,7 +63,7 @@
if (allowAccessToExistingFilesAndDbs) {
mContext.makeExistingFilesAndDbsAccessible();
}
- mProvider.attachInfo(mContext, null);
+ mProvider.attachInfoForTesting(mContext, null);
return mProvider;
}
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pDevice.java b/wifi/java/android/net/wifi/p2p/WifiP2pDevice.java
index ad52585..7196c1b 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pDevice.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pDevice.java
@@ -335,7 +335,7 @@
deviceCapability = source.deviceCapability;
groupCapability = source.groupCapability;
status = source.status;
- wfdInfo = source.wfdInfo;
+ wfdInfo = new WifiP2pWfdInfo(source.wfdInfo);
}
}
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.java b/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.java
index 4f40ebc..0900351 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.java
@@ -44,7 +44,7 @@
public WifiP2pDeviceList(WifiP2pDeviceList source) {
if (source != null) {
for (WifiP2pDevice d : source.getDeviceList()) {
- mDevices.put(d.deviceAddress, d);
+ mDevices.put(d.deviceAddress, new WifiP2pDevice(d));
}
}
}
@@ -53,7 +53,7 @@
public WifiP2pDeviceList(ArrayList<WifiP2pDevice> devices) {
for (WifiP2pDevice device : devices) {
if (device.deviceAddress != null) {
- mDevices.put(device.deviceAddress, device);
+ mDevices.put(device.deviceAddress, new WifiP2pDevice(device));
}
}
}
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pService.java b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
index 1589fec..4a489d5 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pService.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
@@ -1839,7 +1839,7 @@
private void sendPeersChangedBroadcast() {
final Intent intent = new Intent(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
- intent.putExtra(WifiP2pManager.EXTRA_P2P_DEVICE_LIST, mPeers);
+ intent.putExtra(WifiP2pManager.EXTRA_P2P_DEVICE_LIST, new WifiP2pDeviceList(mPeers));
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
}