summaryrefslogtreecommitdiffstats
path: root/core/jni
diff options
context:
space:
mode:
Diffstat (limited to 'core/jni')
-rw-r--r--core/jni/Android.mk3
-rw-r--r--core/jni/AndroidRuntime.cpp6
-rw-r--r--core/jni/android/graphics/Bitmap.cpp9
-rw-r--r--core/jni/android_app_NativeActivity.cpp16
-rw-r--r--core/jni/android_media_AudioSystem.cpp67
-rw-r--r--core/jni/android_net_wifi_WifiNative.cpp (renamed from core/jni/android_net_wifi_Wifi.cpp)137
-rw-r--r--core/jni/android_os_ParcelFileDescriptor.cpp151
-rw-r--r--core/jni/android_view_Surface.cpp15
8 files changed, 96 insertions, 308 deletions
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 0efa227..d5d746a 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -63,7 +63,6 @@ LOCAL_SRC_FILES:= \
android_os_FileUtils.cpp \
android_os_MemoryFile.cpp \
android_os_MessageQueue.cpp \
- android_os_ParcelFileDescriptor.cpp \
android_os_Parcel.cpp \
android_os_SELinux.cpp \
android_os_SystemClock.cpp \
@@ -73,7 +72,7 @@ LOCAL_SRC_FILES:= \
android_net_LocalSocketImpl.cpp \
android_net_NetUtils.cpp \
android_net_TrafficStats.cpp \
- android_net_wifi_Wifi.cpp \
+ android_net_wifi_WifiNative.cpp \
android_nio_utils.cpp \
android_text_format_Time.cpp \
android_util_AssetManager.cpp \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 91fdcc2..8472705 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -135,7 +135,6 @@ extern int register_android_text_format_Time(JNIEnv* env);
extern int register_android_os_Debug(JNIEnv* env);
extern int register_android_os_MessageQueue(JNIEnv* env);
extern int register_android_os_Parcel(JNIEnv* env);
-extern int register_android_os_ParcelFileDescriptor(JNIEnv *env);
extern int register_android_os_SELinux(JNIEnv* env);
extern int register_android_os_SystemProperties(JNIEnv *env);
extern int register_android_os_SystemClock(JNIEnv* env);
@@ -148,7 +147,7 @@ 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);
-extern int register_android_net_wifi_WifiManager(JNIEnv* env);
+extern int register_android_net_wifi_WifiNative(JNIEnv* env);
extern int register_android_text_AndroidCharacter(JNIEnv *env);
extern int register_android_text_AndroidBidi(JNIEnv *env);
extern int register_android_opengl_classes(JNIEnv *env);
@@ -1178,7 +1177,6 @@ static const RegJNIRec gRegJNI[] = {
REG_JNI(register_android_os_FileObserver),
REG_JNI(register_android_os_FileUtils),
REG_JNI(register_android_os_MessageQueue),
- REG_JNI(register_android_os_ParcelFileDescriptor),
REG_JNI(register_android_os_SELinux),
REG_JNI(register_android_os_Trace),
REG_JNI(register_android_os_UEventObserver),
@@ -1186,7 +1184,7 @@ static const RegJNIRec gRegJNI[] = {
REG_JNI(register_android_net_LocalSocketImpl),
REG_JNI(register_android_net_NetworkUtils),
REG_JNI(register_android_net_TrafficStats),
- REG_JNI(register_android_net_wifi_WifiManager),
+ REG_JNI(register_android_net_wifi_WifiNative),
REG_JNI(register_android_os_MemoryFile),
REG_JNI(register_com_android_internal_os_ZygoteInit),
REG_JNI(register_android_hardware_Camera),
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index b03d12a..0ea3bf7 100644
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -222,8 +222,12 @@ static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,
}
}
- SkBitmap bitmap;
+ // ARGB_4444 is a deprecated format, convert automatically to 8888
+ if (config == SkBitmap::kARGB_4444_Config) {
+ config = SkBitmap::kARGB_8888_Config;
+ }
+ SkBitmap bitmap;
bitmap.setConfig(config, width, height);
jbyteArray buff = GraphicsJNI::allocateJavaPixelRef(env, &bitmap, NULL);
@@ -232,8 +236,7 @@ static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,
}
if (jColors != NULL) {
- GraphicsJNI::SetPixels(env, jColors, offset, stride,
- 0, 0, width, height, bitmap);
+ GraphicsJNI::SetPixels(env, jColors, offset, stride, 0, 0, width, height, bitmap);
}
return GraphicsJNI::createBitmap(env, new SkBitmap(bitmap), buff, isMutable, NULL, NULL);
diff --git a/core/jni/android_app_NativeActivity.cpp b/core/jni/android_app_NativeActivity.cpp
index f768ce8..5418006 100644
--- a/core/jni/android_app_NativeActivity.cpp
+++ b/core/jni/android_app_NativeActivity.cpp
@@ -306,19 +306,23 @@ loadNativeCode_native(JNIEnv* env, jobject clazz, jstring path, jstring funcName
code->internalDataPath = code->internalDataPathObj.string();
env->ReleaseStringUTFChars(internalDataDir, dirStr);
- dirStr = env->GetStringUTFChars(externalDataDir, NULL);
- code->externalDataPathObj = dirStr;
+ if (externalDataDir != NULL) {
+ dirStr = env->GetStringUTFChars(externalDataDir, NULL);
+ code->externalDataPathObj = dirStr;
+ env->ReleaseStringUTFChars(externalDataDir, dirStr);
+ }
code->externalDataPath = code->externalDataPathObj.string();
- env->ReleaseStringUTFChars(externalDataDir, dirStr);
code->sdkVersion = sdkVersion;
code->assetManager = assetManagerForJavaObject(env, jAssetMgr);
- dirStr = env->GetStringUTFChars(obbDir, NULL);
- code->obbPathObj = dirStr;
+ if (obbDir != NULL) {
+ dirStr = env->GetStringUTFChars(obbDir, NULL);
+ code->obbPathObj = dirStr;
+ env->ReleaseStringUTFChars(obbDir, dirStr);
+ }
code->obbPath = code->obbPathObj.string();
- env->ReleaseStringUTFChars(obbDir, dirStr);
jbyte* rawSavedState = NULL;
jsize rawSavedSize = 0;
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index d6c5e4f..7d99464 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -41,11 +41,15 @@ enum AudioError {
static int check_AudioSystem_Command(status_t status)
{
- if (status == NO_ERROR) {
+ switch (status) {
+ case DEAD_OBJECT:
+ return kAudioStatusMediaServerDied;
+ case NO_ERROR:
return kAudioStatusOk;
- } else {
- return kAudioStatusError;
+ default:
+ break;
}
+ return kAudioStatusError;
}
static int
@@ -112,61 +116,19 @@ android_media_AudioSystem_getParameters(JNIEnv *env, jobject thiz, jstring keys)
return env->NewStringUTF(AudioSystem::getParameters(0, c_keys8).string());
}
-static JNIEnv* AudioSystem_getJNIEnv(bool* needsDetach) {
- *needsDetach = false;
- JNIEnv* env = AndroidRuntime::getJNIEnv();
- if (env == NULL) {
- JavaVMAttachArgs args = {JNI_VERSION_1_4, NULL, NULL};
- JavaVM* vm = AndroidRuntime::getJavaVM();
- int result = vm->AttachCurrentThread(&env, (void*) &args);
- if (result != JNI_OK) {
- ALOGE("thread attach failed: %#x", result);
- return NULL;
- }
- *needsDetach = true;
- }
- return env;
-}
-
-static void AudioSystem_detachJNI() {
- JavaVM* vm = AndroidRuntime::getJavaVM();
- int result = vm->DetachCurrentThread();
- if (result != JNI_OK) {
- ALOGE("thread detach failed: %#x", result);
- }
-}
-
static void
android_media_AudioSystem_error_callback(status_t err)
{
- bool needsDetach = false;
- JNIEnv *env = AudioSystem_getJNIEnv(&needsDetach);
-
+ JNIEnv *env = AndroidRuntime::getJNIEnv();
if (env == NULL) {
return;
}
jclass clazz = env->FindClass(kClassPathName);
- int error;
-
- switch (err) {
- case DEAD_OBJECT:
- error = kAudioStatusMediaServerDied;
- break;
- case NO_ERROR:
- error = kAudioStatusOk;
- break;
- default:
- error = kAudioStatusError;
- break;
- }
-
- env->CallStaticVoidMethod(clazz, env->GetStaticMethodID(clazz, "errorCallbackFromNative","(I)V"), error);
-
- if (needsDetach) {
- AudioSystem_detachJNI();
- }
+ env->CallStaticVoidMethod(clazz, env->GetStaticMethodID(clazz,
+ "errorCallbackFromNative","(I)V"),
+ check_AudioSystem_Command(err));
}
static int
@@ -313,6 +275,12 @@ android_media_AudioSystem_setLowRamDevice(JNIEnv *env, jobject clazz, jboolean i
return (jint) AudioSystem::setLowRamDevice((bool) isLowRamDevice);
}
+static int
+android_media_AudioSystem_checkAudioFlinger(JNIEnv *env, jobject clazz)
+{
+ return check_AudioSystem_Command(AudioSystem::checkAudioFlinger());
+}
+
// ----------------------------------------------------------------------------
static JNINativeMethod gMethods[] = {
@@ -340,6 +308,7 @@ static JNINativeMethod gMethods[] = {
{"getPrimaryOutputFrameCount", "()I", (void *)android_media_AudioSystem_getPrimaryOutputFrameCount},
{"getOutputLatency", "(I)I", (void *)android_media_AudioSystem_getOutputLatency},
{"setLowRamDevice", "(Z)I", (void *)android_media_AudioSystem_setLowRamDevice},
+ {"checkAudioFlinger", "()I", (void *)android_media_AudioSystem_checkAudioFlinger},
};
int register_android_media_AudioSystem(JNIEnv *env)
diff --git a/core/jni/android_net_wifi_Wifi.cpp b/core/jni/android_net_wifi_WifiNative.cpp
index aa6dbf3..6e11192 100644
--- a/core/jni/android_net_wifi_Wifi.cpp
+++ b/core/jni/android_net_wifi_WifiNative.cpp
@@ -25,111 +25,91 @@
#include "wifi.h"
-#define WIFI_PKG_NAME "android/net/wifi/WifiNative"
-#define BUF_SIZE 256
+#define REPLY_BUF_SIZE 4096 // wpa_supplicant's maximum size.
#define EVENT_BUF_SIZE 2048
namespace android {
static jint DBG = false;
-static int doCommand(char *cmd, char *replybuf, int replybuflen)
-{
- size_t reply_len = replybuflen - 1;
+static bool doCommand(JNIEnv* env, jstring javaCommand,
+ char* reply, size_t reply_len) {
+ ScopedUtfChars command(env, javaCommand);
+ if (command.c_str() == NULL) {
+ return false; // ScopedUtfChars already threw on error.
+ }
- if (::wifi_command(cmd, replybuf, &reply_len) != 0)
- return -1;
- else {
- // Strip off trailing newline
- if (reply_len > 0 && replybuf[reply_len-1] == '\n')
- replybuf[reply_len-1] = '\0';
- else
- replybuf[reply_len] = '\0';
- return 0;
+ if (DBG) {
+ ALOGD("doCommand: %s", command.c_str());
}
-}
-static jint doIntCommand(const char* fmt, ...)
-{
- char buf[BUF_SIZE];
- va_list args;
- va_start(args, fmt);
- int byteCount = vsnprintf(buf, sizeof(buf), fmt, args);
- va_end(args);
- if (byteCount < 0 || byteCount >= BUF_SIZE) {
- return -1;
+ --reply_len; // Ensure we have room to add NUL termination.
+ if (::wifi_command(command.c_str(), reply, &reply_len) != 0) {
+ return false;
+ }
+
+ // Strip off trailing newline.
+ if (reply_len > 0 && reply[reply_len-1] == '\n') {
+ reply[reply_len-1] = '\0';
+ } else {
+ reply[reply_len] = '\0';
}
- char reply[BUF_SIZE];
- if (doCommand(buf, reply, sizeof(reply)) != 0) {
+ return true;
+}
+
+static jint doIntCommand(JNIEnv* env, jstring javaCommand) {
+ char reply[REPLY_BUF_SIZE];
+ if (!doCommand(env, javaCommand, reply, sizeof(reply))) {
return -1;
}
return static_cast<jint>(atoi(reply));
}
-static jboolean doBooleanCommand(const char* expect, const char* fmt, ...)
-{
- char buf[BUF_SIZE];
- va_list args;
- va_start(args, fmt);
- int byteCount = vsnprintf(buf, sizeof(buf), fmt, args);
- va_end(args);
- if (byteCount < 0 || byteCount >= BUF_SIZE) {
- return JNI_FALSE;
- }
- char reply[BUF_SIZE];
- if (doCommand(buf, reply, sizeof(reply)) != 0) {
+static jboolean doBooleanCommand(JNIEnv* env, jstring javaCommand) {
+ char reply[REPLY_BUF_SIZE];
+ if (!doCommand(env, javaCommand, reply, sizeof(reply))) {
return JNI_FALSE;
}
- return (strcmp(reply, expect) == 0);
+ return (strcmp(reply, "OK") == 0);
}
-// Send a command to the supplicant, and return the reply as a String
-static jstring doStringCommand(JNIEnv* env, const char* fmt, ...) {
- char buf[BUF_SIZE];
- va_list args;
- va_start(args, fmt);
- int byteCount = vsnprintf(buf, sizeof(buf), fmt, args);
- va_end(args);
- if (byteCount < 0 || byteCount >= BUF_SIZE) {
- return NULL;
- }
- char reply[4096];
- if (doCommand(buf, reply, sizeof(reply)) != 0) {
+// Send a command to the supplicant, and return the reply as a String.
+static jstring doStringCommand(JNIEnv* env, jstring javaCommand) {
+ char reply[REPLY_BUF_SIZE];
+ if (!doCommand(env, javaCommand, reply, sizeof(reply))) {
return NULL;
}
- // TODO: why not just NewStringUTF?
- String16 str((char *)reply);
- return env->NewString((const jchar *)str.string(), str.size());
+ return env->NewStringUTF(reply);
}
static jboolean android_net_wifi_isDriverLoaded(JNIEnv* env, jobject)
{
- return (jboolean)(::is_wifi_driver_loaded() == 1);
+ return (::is_wifi_driver_loaded() == 1);
}
static jboolean android_net_wifi_loadDriver(JNIEnv* env, jobject)
{
- return (jboolean)(::wifi_load_driver() == 0);
+ return (::wifi_load_driver() == 0);
}
static jboolean android_net_wifi_unloadDriver(JNIEnv* env, jobject)
{
- return (jboolean)(::wifi_unload_driver() == 0);
+ return (::wifi_unload_driver() == 0);
}
static jboolean android_net_wifi_startSupplicant(JNIEnv* env, jobject, jboolean p2pSupported)
{
- return (jboolean)(::wifi_start_supplicant(p2pSupported) == 0);
+ return (::wifi_start_supplicant(p2pSupported) == 0);
}
static jboolean android_net_wifi_killSupplicant(JNIEnv* env, jobject, jboolean p2pSupported)
{
- return (jboolean)(::wifi_stop_supplicant(p2pSupported) == 0);
+ return (::wifi_stop_supplicant(p2pSupported) == 0);
}
static jboolean android_net_wifi_connectToSupplicant(JNIEnv* env, jobject)
{
- return (jboolean)(::wifi_connect_to_supplicant() == 0);
+ return (::wifi_connect_to_supplicant() == 0);
}
static void android_net_wifi_closeSupplicantConnection(JNIEnv* env, jobject)
@@ -148,36 +128,16 @@ static jstring android_net_wifi_waitForEvent(JNIEnv* env, jobject)
}
}
-static jboolean android_net_wifi_doBooleanCommand(JNIEnv* env, jobject, jstring jCommand)
-{
- ScopedUtfChars command(env, jCommand);
-
- if (command.c_str() == NULL) {
- return JNI_FALSE;
- }
- if (DBG) ALOGD("doBoolean: %s", command.c_str());
- return doBooleanCommand("OK", "%s", command.c_str());
+static jboolean android_net_wifi_doBooleanCommand(JNIEnv* env, jobject, jstring javaCommand) {
+ return doBooleanCommand(env, javaCommand);
}
-static jint android_net_wifi_doIntCommand(JNIEnv* env, jobject, jstring jCommand)
-{
- ScopedUtfChars command(env, jCommand);
-
- if (command.c_str() == NULL) {
- return -1;
- }
- if (DBG) ALOGD("doInt: %s", command.c_str());
- return doIntCommand("%s", command.c_str());
+static jint android_net_wifi_doIntCommand(JNIEnv* env, jobject, jstring javaCommand) {
+ return doIntCommand(env, javaCommand);
}
-static jstring android_net_wifi_doStringCommand(JNIEnv* env, jobject, jstring jCommand)
-{
- ScopedUtfChars command(env, jCommand);
- if (command.c_str() == NULL) {
- return NULL;
- }
- if (DBG) ALOGD("doString: %s", command.c_str());
- return doStringCommand(env, "%s", command.c_str());
+static jstring android_net_wifi_doStringCommand(JNIEnv* env, jobject, jstring javaCommand) {
+ return doStringCommand(env,javaCommand);
}
@@ -205,10 +165,9 @@ static JNINativeMethod gWifiMethods[] = {
(void*) android_net_wifi_doStringCommand },
};
-int register_android_net_wifi_WifiManager(JNIEnv* env)
-{
+int register_android_net_wifi_WifiNative(JNIEnv* env) {
return AndroidRuntime::registerNativeMethods(env,
- WIFI_PKG_NAME, gWifiMethods, NELEM(gWifiMethods));
+ "android/net/wifi/WifiNative", gWifiMethods, NELEM(gWifiMethods));
}
}; // namespace android
diff --git a/core/jni/android_os_ParcelFileDescriptor.cpp b/core/jni/android_os_ParcelFileDescriptor.cpp
deleted file mode 100644
index 99a2d04..0000000
--- a/core/jni/android_os_ParcelFileDescriptor.cpp
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright (C) 2008 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.
- */
-
-//#define LOG_NDEBUG 0
-
-#include "JNIHelp.h"
-
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <stdio.h>
-
-#include <utils/Log.h>
-
-#include <android_runtime/AndroidRuntime.h>
-
-namespace android
-{
-
-static struct parcel_file_descriptor_offsets_t
-{
- jfieldID mFileDescriptor;
-} gParcelFileDescriptorOffsets;
-
-static jobject android_os_ParcelFileDescriptor_getFileDescriptorFromFd(JNIEnv* env,
- jobject clazz, jint origfd)
-{
- int fd = dup(origfd);
- if (fd < 0) {
- jniThrowException(env, "java/io/IOException", strerror(errno));
- return NULL;
- }
- return jniCreateFileDescriptor(env, fd);
-}
-
-static jobject android_os_ParcelFileDescriptor_getFileDescriptorFromFdNoDup(JNIEnv* env,
- jobject clazz, jint fd)
-{
- return jniCreateFileDescriptor(env, fd);
-}
-
-static void android_os_ParcelFileDescriptor_createPipeNative(JNIEnv* env,
- jobject clazz, jobjectArray outFds)
-{
- int fds[2];
- if (pipe(fds) < 0) {
- int therr = errno;
- jniThrowException(env, "java/io/IOException", strerror(therr));
- return;
- }
-
- for (int i=0; i<2; i++) {
- jobject fdObj = jniCreateFileDescriptor(env, fds[i]);
- env->SetObjectArrayElement(outFds, i, fdObj);
- }
-}
-
-static jint getFd(JNIEnv* env, jobject clazz)
-{
- jobject descriptor = env->GetObjectField(clazz, gParcelFileDescriptorOffsets.mFileDescriptor);
- if (descriptor == NULL) return -1;
- return jniGetFDFromFileDescriptor(env, descriptor);
-}
-
-static jlong android_os_ParcelFileDescriptor_getStatSize(JNIEnv* env,
- jobject clazz)
-{
- jint fd = getFd(env, clazz);
- if (fd < 0) {
- jniThrowException(env, "java/lang/IllegalArgumentException", "bad file descriptor");
- return -1;
- }
-
- struct stat st;
- if (fstat(fd, &st) != 0) {
- return -1;
- }
-
- if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) {
- return st.st_size;
- }
-
- return -1;
-}
-
-static jlong android_os_ParcelFileDescriptor_seekTo(JNIEnv* env,
- jobject clazz, jlong pos)
-{
- jint fd = getFd(env, clazz);
- if (fd < 0) {
- jniThrowException(env, "java/lang/IllegalArgumentException", "bad file descriptor");
- return -1;
- }
-
- return lseek(fd, pos, SEEK_SET);
-}
-
-static jlong android_os_ParcelFileDescriptor_getFdNative(JNIEnv* env, jobject clazz)
-{
- jint fd = getFd(env, clazz);
- if (fd < 0) {
- jniThrowException(env, "java/lang/IllegalArgumentException", "bad file descriptor");
- return -1;
- }
-
- return fd;
-}
-
-static const JNINativeMethod gParcelFileDescriptorMethods[] = {
- {"getFileDescriptorFromFd", "(I)Ljava/io/FileDescriptor;",
- (void*)android_os_ParcelFileDescriptor_getFileDescriptorFromFd},
- {"getFileDescriptorFromFdNoDup", "(I)Ljava/io/FileDescriptor;",
- (void*)android_os_ParcelFileDescriptor_getFileDescriptorFromFdNoDup},
- {"createPipeNative", "([Ljava/io/FileDescriptor;)V",
- (void*)android_os_ParcelFileDescriptor_createPipeNative},
- {"getStatSize", "()J",
- (void*)android_os_ParcelFileDescriptor_getStatSize},
- {"seekTo", "(J)J",
- (void*)android_os_ParcelFileDescriptor_seekTo},
- {"getFdNative", "()I",
- (void*)android_os_ParcelFileDescriptor_getFdNative}
-};
-
-const char* const kParcelFileDescriptorPathName = "android/os/ParcelFileDescriptor";
-
-int register_android_os_ParcelFileDescriptor(JNIEnv* env)
-{
- jclass clazz = env->FindClass(kParcelFileDescriptorPathName);
- LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.ParcelFileDescriptor");
- gParcelFileDescriptorOffsets.mFileDescriptor = env->GetFieldID(clazz, "mFileDescriptor", "Ljava/io/FileDescriptor;");
- LOG_FATAL_IF(gParcelFileDescriptorOffsets.mFileDescriptor == NULL,
- "Unable to find mFileDescriptor field in android.os.ParcelFileDescriptor");
-
- return AndroidRuntime::registerNativeMethods(
- env, kParcelFileDescriptorPathName,
- gParcelFileDescriptorMethods, NELEM(gParcelFileDescriptorMethods));
-}
-
-}
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 304514b..3f54fd7 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -196,13 +196,13 @@ static inline void swapCanvasPtr(JNIEnv* env, jobject canvasObj, SkCanvas* newCa
SkSafeUnref(previousCanvas);
}
-static void nativeLockCanvas(JNIEnv* env, jclass clazz,
+static jint nativeLockCanvas(JNIEnv* env, jclass clazz,
jint nativeObject, jobject canvasObj, jobject dirtyRectObj) {
sp<Surface> surface(reinterpret_cast<Surface *>(nativeObject));
if (!isSurfaceValid(surface)) {
doThrowIAE(env);
- return;
+ return 0;
}
Rect dirtyRect;
@@ -223,7 +223,7 @@ static void nativeLockCanvas(JNIEnv* env, jclass clazz,
OutOfResourcesException :
"java/lang/IllegalArgumentException";
jniThrowException(env, exception, NULL);
- return;
+ return 0;
}
// Associate a SkCanvas object to this surface
@@ -255,6 +255,13 @@ static void nativeLockCanvas(JNIEnv* env, jclass clazz,
env->SetIntField(dirtyRectObj, gRectClassInfo.right, dirtyRect.right);
env->SetIntField(dirtyRectObj, gRectClassInfo.bottom, dirtyRect.bottom);
}
+
+ // Create another reference to the surface and return it. This reference
+ // should be passed to nativeUnlockCanvasAndPost in place of mNativeObject,
+ // because the latter could be replaced while the surface is locked.
+ sp<Surface> lockedSurface(surface);
+ lockedSurface->incStrong(&sRefBaseOwner);
+ return (int) lockedSurface.get();
}
static void nativeUnlockCanvasAndPost(JNIEnv* env, jclass clazz,
@@ -351,7 +358,7 @@ static JNINativeMethod gSurfaceMethods[] = {
(void*)nativeIsValid },
{"nativeIsConsumerRunningBehind", "(I)Z",
(void*)nativeIsConsumerRunningBehind },
- {"nativeLockCanvas", "(ILandroid/graphics/Canvas;Landroid/graphics/Rect;)V",
+ {"nativeLockCanvas", "(ILandroid/graphics/Canvas;Landroid/graphics/Rect;)I",
(void*)nativeLockCanvas },
{"nativeUnlockCanvasAndPost", "(ILandroid/graphics/Canvas;)V",
(void*)nativeUnlockCanvasAndPost },