summaryrefslogtreecommitdiffstats
path: root/core/jni
diff options
context:
space:
mode:
Diffstat (limited to 'core/jni')
-rw-r--r--core/jni/Android.mk9
-rw-r--r--core/jni/AndroidRuntime.cpp10
-rw-r--r--core/jni/Time.cpp199
-rw-r--r--core/jni/TimeUtils.h89
-rw-r--r--core/jni/android/graphics/Bitmap.cpp54
-rw-r--r--core/jni/android/graphics/BitmapFactory.cpp7
-rw-r--r--core/jni/android/graphics/Paint.cpp2
-rw-r--r--core/jni/android_backup_BackupDataInput.cpp164
-rw-r--r--core/jni/android_backup_BackupDataOutput.cpp128
-rw-r--r--core/jni/android_backup_BackupHelperDispatcher.cpp259
-rw-r--r--core/jni/android_backup_FileBackupHelper.cpp84
-rw-r--r--core/jni/android_backup_FileBackupHelperBase.cpp136
-rw-r--r--core/jni/android_bluetooth_Database.cpp1
-rw-r--r--core/jni/android_emoji_EmojiFactory.cpp87
-rw-r--r--core/jni/android_hardware_Camera.cpp335
-rw-r--r--core/jni/android_hardware_SensorManager.cpp37
-rwxr-xr-x[-rw-r--r--]core/jni/android_location_GpsLocationProvider.cpp17
-rw-r--r--core/jni/android_media_AudioRecord.cpp34
-rw-r--r--core/jni/android_media_AudioTrack.cpp7
-rw-r--r--core/jni/android_net_wifi_Wifi.cpp7
-rw-r--r--core/jni/android_opengl_GLES10.cpp25
-rw-r--r--core/jni/android_os_MemoryFile.cpp82
-rw-r--r--core/jni/android_server_BluetoothA2dpService.cpp1
-rw-r--r--core/jni/android_server_BluetoothDeviceService.cpp1
-rw-r--r--core/jni/android_server_BluetoothEventLoop.cpp33
-rw-r--r--core/jni/android_text_format_Time.cpp13
-rw-r--r--core/jni/android_util_AssetManager.cpp5
-rw-r--r--core/jni/android_util_Process.cpp81
-rw-r--r--core/jni/com_google_android_gles_jni_GLImpl.cpp62
29 files changed, 1501 insertions, 468 deletions
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 4839b6f..888cb11 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -19,6 +19,7 @@ LOCAL_SRC_FILES:= \
ActivityManager.cpp \
AndroidRuntime.cpp \
CursorWindow.cpp \
+ Time.cpp \
com_google_android_gles_jni_EGLImpl.cpp \
com_google_android_gles_jni_GLImpl.cpp.arm \
android_opengl_GLES10.cpp \
@@ -117,7 +118,10 @@ LOCAL_SRC_FILES:= \
android_location_GpsLocationProvider.cpp \
com_android_internal_os_ZygoteInit.cpp \
com_android_internal_graphics_NativeUtils.cpp \
- android_backup_FileBackupHelper.cpp
+ android_backup_BackupDataInput.cpp \
+ android_backup_BackupDataOutput.cpp \
+ android_backup_FileBackupHelperBase.cpp \
+ android_backup_BackupHelperDispatcher.cpp
LOCAL_C_INCLUDES += \
$(JNI_H_INCLUDE) \
@@ -164,8 +168,7 @@ LOCAL_SHARED_LIBRARIES := \
libicui18n \
libicudata \
libmedia \
- libwpa_client \
- libemoji
+ libwpa_client
ifeq ($(BOARD_HAVE_BLUETOOTH),true)
LOCAL_C_INCLUDES += \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index aa6450d..c815301 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -155,7 +155,10 @@ extern int register_android_ddm_DdmHandleNativeHeap(JNIEnv *env);
extern int register_com_android_internal_os_ZygoteInit(JNIEnv* env);
extern int register_android_util_Base64(JNIEnv* env);
extern int register_android_location_GpsLocationProvider(JNIEnv* env);
-extern int register_android_backup_FileBackupHelper(JNIEnv *env);
+extern int register_android_backup_BackupDataInput(JNIEnv *env);
+extern int register_android_backup_BackupDataOutput(JNIEnv *env);
+extern int register_android_backup_FileBackupHelperBase(JNIEnv *env);
+extern int register_android_backup_BackupHelperDispatcher(JNIEnv *env);
static AndroidRuntime* gCurRuntime = NULL;
@@ -1126,7 +1129,10 @@ static const RegJNIRec gRegJNI[] = {
REG_JNI(register_android_ddm_DdmHandleNativeHeap),
REG_JNI(register_android_util_Base64),
REG_JNI(register_android_location_GpsLocationProvider),
- REG_JNI(register_android_backup_FileBackupHelper),
+ REG_JNI(register_android_backup_BackupDataInput),
+ REG_JNI(register_android_backup_BackupDataOutput),
+ REG_JNI(register_android_backup_FileBackupHelperBase),
+ REG_JNI(register_android_backup_BackupHelperDispatcher),
};
/*
diff --git a/core/jni/Time.cpp b/core/jni/Time.cpp
new file mode 100644
index 0000000..f3037f3
--- /dev/null
+++ b/core/jni/Time.cpp
@@ -0,0 +1,199 @@
+#include "TimeUtils.h"
+#include <stdio.h>
+#include <cutils/tztime.h>
+
+namespace android {
+
+static void
+dump(const Time& t)
+{
+ #ifdef HAVE_TM_GMTOFF
+ long tm_gmtoff = t.t.tm_gmtoff;
+ #else
+ long tm_gmtoff = 0;
+ #endif
+ printf("%04d-%02d-%02d %02d:%02d:%02d (%d,%ld,%d,%d)\n",
+ t.t.tm_year+1900, t.t.tm_mon+1, t.t.tm_mday,
+ t.t.tm_hour, t.t.tm_min, t.t.tm_sec,
+ t.t.tm_isdst, tm_gmtoff, t.t.tm_wday, t.t.tm_yday);
+}
+
+Time::Time()
+{
+ t.tm_sec = 0;
+ t.tm_min = 0;
+ t.tm_hour = 0;
+ t.tm_mday = 0;
+ t.tm_mon = 0;
+ t.tm_year = 0;
+ t.tm_wday = 0;
+ t.tm_yday = 0;
+ t.tm_isdst = -1; // we don't know, so let the C library determine
+ #ifdef HAVE_TM_GMTOFF
+ t.tm_gmtoff = 0;
+ #endif
+}
+
+
+#define COMPARE_FIELD(field) do { \
+ int diff = a.t.field - b.t.field; \
+ if (diff != 0) return diff; \
+ } while(0)
+
+int
+Time::compare(Time& a, Time& b)
+{
+ if (0 == strcmp(a.timezone, b.timezone)) {
+ // if the timezones are the same, we can easily compare the two
+ // times. Otherwise, convert to milliseconds and compare that.
+ // This requires that object be normalized.
+ COMPARE_FIELD(tm_year);
+ COMPARE_FIELD(tm_mon);
+ COMPARE_FIELD(tm_mday);
+ COMPARE_FIELD(tm_hour);
+ COMPARE_FIELD(tm_min);
+ COMPARE_FIELD(tm_sec);
+ return 0;
+ } else {
+ int64_t am = a.toMillis(false /* use isDst */);
+ int64_t bm = b.toMillis(false /* use isDst */);
+ int64_t diff = am-bm;
+ return (diff < 0) ? -1 : ((diff > 0) ? 1 : 0);
+ }
+}
+
+static const int DAYS_PER_MONTH[] = {
+ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+ };
+
+static inline int days_this_month(int year, int month)
+{
+ int n = DAYS_PER_MONTH[month];
+ if (n != 28) {
+ return n;
+ } else {
+ int y = year;
+ return ((y%4)==0&&((y%100)!=0||(y%400)==0)) ? 29 : 28;
+ }
+}
+
+void
+Time::switchTimezone(const char* timezone)
+{
+ time_t seconds = mktime_tz(&(this->t), this->timezone);
+ localtime_tz(&seconds, &(this->t), timezone);
+}
+
+String8
+Time::format(const char *format, const struct strftime_locale *locale) const
+{
+ char buf[257];
+ int n = strftime_tz(buf, 257, format, &(this->t), locale);
+ if (n > 0) {
+ return String8(buf);
+ } else {
+ return String8();
+ }
+}
+
+static inline short
+tochar(int n)
+{
+ return (n >= 0 && n <= 9) ? ('0'+n) : ' ';
+}
+
+static inline short
+next_char(int *m, int k)
+{
+ int n = *m / k;
+ *m = *m % k;
+ return tochar(n);
+}
+
+void
+Time::format2445(short* buf, bool hasTime) const
+{
+ int n;
+
+ n = t.tm_year+1900;
+ buf[0] = next_char(&n, 1000);
+ buf[1] = next_char(&n, 100);
+ buf[2] = next_char(&n, 10);
+ buf[3] = tochar(n);
+
+ n = t.tm_mon+1;
+ buf[4] = next_char(&n, 10);
+ buf[5] = tochar(n);
+
+ n = t.tm_mday;
+ buf[6] = next_char(&n, 10);
+ buf[7] = tochar(n);
+
+ if (hasTime) {
+ buf[8] = 'T';
+
+ n = t.tm_hour;
+ buf[9] = next_char(&n, 10);
+ buf[10] = tochar(n);
+
+ n = t.tm_min;
+ buf[11] = next_char(&n, 10);
+ buf[12] = tochar(n);
+
+ n = t.tm_sec;
+ buf[13] = next_char(&n, 10);
+ buf[14] = tochar(n);
+ bool inUtc = strcmp("UTC", timezone) == 0;
+ if (inUtc) {
+ buf[15] = 'Z';
+ }
+ }
+}
+
+String8
+Time::toString() const
+{
+ String8 str;
+ char* s = str.lockBuffer(150);
+ #ifdef HAVE_TM_GMTOFF
+ long tm_gmtoff = t.tm_gmtoff;
+ #else
+ long tm_gmtoff = 0;
+ #endif
+ sprintf(s, "%04d%02d%02dT%02d%02d%02d%s(%d,%d,%ld,%d,%d)",
+ t.tm_year+1900, t.tm_mon+1, t.tm_mday, t.tm_hour, t.tm_min,
+ t.tm_sec, timezone, t.tm_wday, t.tm_yday, tm_gmtoff, t.tm_isdst,
+ (int)(((Time*)this)->toMillis(false /* use isDst */)/1000));
+ str.unlockBuffer();
+ return str;
+}
+
+void
+Time::setToNow()
+{
+ time_t seconds;
+ time(&seconds);
+ localtime_tz(&seconds, &(this->t), this->timezone);
+}
+
+int64_t
+Time::toMillis(bool ignoreDst)
+{
+ if (ignoreDst) {
+ this->t.tm_isdst = -1;
+ }
+ int64_t r = mktime_tz(&(this->t), this->timezone);
+ if (r == -1)
+ return -1;
+ return r * 1000;
+}
+
+void
+Time::set(int64_t millis)
+{
+ time_t seconds = millis / 1000;
+ localtime_tz(&seconds, &(this->t), this->timezone);
+}
+
+}; // namespace android
+
diff --git a/core/jni/TimeUtils.h b/core/jni/TimeUtils.h
new file mode 100644
index 0000000..b19e021
--- /dev/null
+++ b/core/jni/TimeUtils.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+#ifndef ANDROID_TIME_H
+#define ANDROID_TIME_H
+
+#include <time.h>
+#include <cutils/tztime.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <utils/String8.h>
+#include <utils/String16.h>
+
+namespace android {
+
+/*
+ * This class is the core implementation of the android.util.Time java
+ * class. It doesn't implement some of the methods that are implemented
+ * in Java. They could be done here, but it's not expected that this class
+ * will be used. If that assumption is incorrect, feel free to update this
+ * file. The reason to do it here is to not mix the implementation of this
+ * class and the jni glue code.
+ */
+class Time
+{
+public:
+ struct tm t;
+
+ // this object doesn't own this string
+ const char *timezone;
+
+ enum {
+ SEC = 1,
+ MIN = 2,
+ HOUR = 3,
+ MDAY = 4,
+ MON = 5,
+ YEAR = 6,
+ WDAY = 7,
+ YDAY = 8
+ };
+
+ static int compare(Time& a, Time& b);
+
+ Time();
+
+ void switchTimezone(const char *timezone);
+ String8 format(const char *format, const struct strftime_locale *locale) const;
+ void format2445(short* buf, bool hasTime) const;
+ String8 toString() const;
+ void setToNow();
+ int64_t toMillis(bool ignoreDst);
+ void set(int64_t millis);
+
+ inline void set(int sec, int min, int hour, int mday, int mon, int year,
+ int isdst)
+ {
+ this->t.tm_sec = sec;
+ this->t.tm_min = min;
+ this->t.tm_hour = hour;
+ this->t.tm_mday = mday;
+ this->t.tm_mon = mon;
+ this->t.tm_year = year;
+ this->t.tm_isdst = isdst;
+#ifdef HAVE_TM_GMTOFF
+ this->t.tm_gmtoff = 0;
+#endif
+ this->t.tm_wday = 0;
+ this->t.tm_yday = 0;
+ }
+};
+
+}; // namespace android
+
+#endif // ANDROID_TIME_H
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index 65f44d5..af8ecf5 100644
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -28,7 +28,7 @@ typedef void (*FromColorProc)(void* dst, const SkColor src[], int width,
static void FromColor_D32(void* dst, const SkColor src[], int width,
int, int) {
SkPMColor* d = (SkPMColor*)dst;
-
+
for (int i = 0; i < width; i++) {
*d++ = SkPreMultiplyColor(*src++);
}
@@ -37,7 +37,7 @@ static void FromColor_D32(void* dst, const SkColor src[], int width,
static void FromColor_D565(void* dst, const SkColor src[], int width,
int x, int y) {
uint16_t* d = (uint16_t*)dst;
-
+
DITHER_565_SCAN(y);
for (int stop = x + width; x < stop; x++) {
SkColor c = *src++;
@@ -49,7 +49,7 @@ static void FromColor_D565(void* dst, const SkColor src[], int width,
static void FromColor_D4444(void* dst, const SkColor src[], int width,
int x, int y) {
SkPMColor16* d = (SkPMColor16*)dst;
-
+
DITHER_4444_SCAN(y);
for (int stop = x + width; x < stop; x++) {
SkPMColor c = SkPreMultiplyColor(*src++);
@@ -80,14 +80,14 @@ bool GraphicsJNI::SetPixels(JNIEnv* env, jintArray srcColors,
SkAutoLockPixels alp(dstBitmap);
void* dst = dstBitmap.getPixels();
FromColorProc proc = ChooseFromColorProc(dstBitmap.config());
-
+
if (NULL == dst || NULL == proc) {
return false;
}
-
+
const jint* array = env->GetIntArrayElements(srcColors, NULL);
const SkColor* src = (const SkColor*)array + srcOffset;
-
+
// reset to to actual choice from caller
dst = dstBitmap.getAddr(x, y);
// now copy/convert each scanline
@@ -96,7 +96,7 @@ bool GraphicsJNI::SetPixels(JNIEnv* env, jintArray srcColors,
src += srcStride;
dst = (char*)dst + dstBitmap.rowBytes();
}
-
+
env->ReleaseIntArrayElements(srcColors, const_cast<jint*>(array),
JNI_ABORT);
return true;
@@ -212,7 +212,7 @@ static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,
doThrowIAE(env, "width and height must be > 0");
return NULL;
}
-
+
if (NULL != jColors) {
size_t n = env->GetArrayLength(jColors);
if (n < SkAbs32(stride) * (size_t)height) {
@@ -222,7 +222,7 @@ static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,
}
SkBitmap bitmap;
-
+
bitmap.setConfig(config, width, height);
if (!GraphicsJNI::setJavaPixelRef(env, &bitmap, NULL)) {
return NULL;
@@ -232,7 +232,7 @@ static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,
GraphicsJNI::SetPixels(env, jColors, offset, stride,
0, 0, width, height, bitmap);
}
-
+
return GraphicsJNI::createBitmap(env, new SkBitmap(bitmap), isMutable,
NULL);
}
@@ -245,7 +245,7 @@ static jobject Bitmap_copy(JNIEnv* env, jobject, const SkBitmap* src,
if (!src->copyTo(&result, dstConfig, &allocator)) {
return NULL;
}
-
+
return GraphicsJNI::createBitmap(env, new SkBitmap(result), isMutable,
NULL);
}
@@ -324,15 +324,15 @@ static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) {
SkDebugf("-------- unparcel parcel is NULL\n");
return NULL;
}
-
+
android::Parcel* p = android::parcelForJavaObject(env, parcel);
-
+
const bool isMutable = p->readInt32() != 0;
const SkBitmap::Config config = (SkBitmap::Config)p->readInt32();
const int width = p->readInt32();
const int height = p->readInt32();
const int rowBytes = p->readInt32();
-
+
if (SkBitmap::kARGB_8888_Config != config &&
SkBitmap::kRGB_565_Config != config &&
SkBitmap::kARGB_4444_Config != config &&
@@ -355,7 +355,7 @@ static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) {
ctable = new SkColorTable(src, count);
}
}
-
+
if (!GraphicsJNI::setJavaPixelRef(env, bitmap, ctable)) {
ctable->safeUnref();
delete bitmap;
@@ -368,7 +368,7 @@ static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) {
bitmap->lockPixels();
memcpy(bitmap->getPixels(), p->readInplace(size), size);
bitmap->unlockPixels();
-
+
return GraphicsJNI::createBitmap(env, bitmap, isMutable, NULL);
}
@@ -381,7 +381,7 @@ static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject,
}
android::Parcel* p = android::parcelForJavaObject(env, parcel);
-
+
p->writeInt32(isMutable);
p->writeInt32(bitmap->config());
p->writeInt32(bitmap->width());
@@ -413,7 +413,7 @@ static jobject Bitmap_extractAlpha(JNIEnv* env, jobject clazz,
jintArray offsetXY) {
SkIPoint offset;
SkBitmap* dst = new SkBitmap;
-
+
src->extractAlpha(dst, paint, &offset);
if (offsetXY != 0 && env->GetArrayLength(offsetXY) >= 2) {
int* array = env->GetIntArrayElements(offsetXY, NULL);
@@ -421,7 +421,7 @@ static jobject Bitmap_extractAlpha(JNIEnv* env, jobject clazz,
array[1] = offset.fY;
env->ReleaseIntArrayElements(offsetXY, array, 0);
}
-
+
return GraphicsJNI::createBitmap(env, dst, true, NULL);
}
@@ -439,7 +439,7 @@ static int Bitmap_getPixel(JNIEnv* env, jobject, const SkBitmap* bitmap,
if (NULL == src) {
return 0;
}
-
+
SkColor dst[1];
proc(dst, src, 1, bitmap->getColorTable());
return dst[0];
@@ -449,7 +449,7 @@ static void Bitmap_getPixels(JNIEnv* env, jobject, const SkBitmap* bitmap,
jintArray pixelArray, int offset, int stride,
int x, int y, int width, int height) {
SkAutoLockPixels alp(*bitmap);
-
+
ToColorProc proc = ChooseToColorProc(*bitmap);
if (NULL == proc) {
return;
@@ -498,7 +498,7 @@ static void Bitmap_copyPixelsToBuffer(JNIEnv* env, jobject,
const SkBitmap* bitmap, jobject jbuffer) {
SkAutoLockPixels alp(*bitmap);
const void* src = bitmap->getPixels();
-
+
if (NULL != src) {
android::AutoBufferPointer abp(env, jbuffer, JNI_TRUE);
@@ -511,7 +511,7 @@ static void Bitmap_copyPixelsFromBuffer(JNIEnv* env, jobject,
const SkBitmap* bitmap, jobject jbuffer) {
SkAutoLockPixels alp(*bitmap);
void* dst = bitmap->getPixels();
-
+
if (NULL != dst) {
android::AutoBufferPointer abp(env, jbuffer, JNI_FALSE);
// the java side has already checked that buffer is large enough
@@ -519,6 +519,11 @@ static void Bitmap_copyPixelsFromBuffer(JNIEnv* env, jobject,
}
}
+static void Bitmap_prepareToDraw(JNIEnv* env, jobject, SkBitmap* bitmap) {
+ bitmap->lockPixels();
+ bitmap->unlockPixels();
+}
+
///////////////////////////////////////////////////////////////////////////////
#include <android_runtime/AndroidRuntime.h>
@@ -552,7 +557,8 @@ static JNINativeMethod gBitmapMethods[] = {
{ "nativeCopyPixelsToBuffer", "(ILjava/nio/Buffer;)V",
(void*)Bitmap_copyPixelsToBuffer },
{ "nativeCopyPixelsFromBuffer", "(ILjava/nio/Buffer;)V",
- (void*)Bitmap_copyPixelsFromBuffer }
+ (void*)Bitmap_copyPixelsFromBuffer },
+ { "nativePrepareToDraw", "(I)V", (void*)Bitmap_prepareToDraw }
};
#define kClassPathName "android/graphics/Bitmap"
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index 1fd15d6..137707f 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -311,7 +311,7 @@ static SkPixelRef* installPixelRef(SkBitmap* bitmap, SkStream* stream,
int sampleSize) {
SkPixelRef* pr;
// only use ashmem for large images, since mmaps come at a price
- if (bitmap->getSize() >= 32 * 65536) {
+ if (bitmap->getSize() >= 32 * 1024) {
pr = new SkImageRef_ashmem(stream, bitmap->config(), sampleSize);
} else {
pr = new SkImageRef_GlobalPool(stream, bitmap->config(), sampleSize);
@@ -520,7 +520,10 @@ static jobject nativeDecodeFileDescriptor(JNIEnv* env, jobject clazz,
*/
AutoFDSeek as(descriptor);
- return doDecode(env, stream, padding, bitmapFactoryOptions, true);
+ /* Allow purgeable iff we own the FD, i.e., in the puregeable and
+ shareable case.
+ */
+ return doDecode(env, stream, padding, bitmapFactoryOptions, weOwnTheFD);
}
/* make a deep copy of the asset, and return it as a stream, or NULL if there
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index 76e6f02..d1fe83e 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -69,6 +69,8 @@ public:
static void reset(JNIEnv* env, jobject clazz, SkPaint* obj) {
obj->reset();
+ // utf16 is required for java
+ obj->setTextEncoding(SkPaint::kUTF16_TextEncoding);
}
static void assign(JNIEnv* env, jobject clazz, SkPaint* dst, const SkPaint* src) {
diff --git a/core/jni/android_backup_BackupDataInput.cpp b/core/jni/android_backup_BackupDataInput.cpp
new file mode 100644
index 0000000..cf8a8e8
--- /dev/null
+++ b/core/jni/android_backup_BackupDataInput.cpp
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * 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_TAG "FileBackupHelper_native"
+#include <utils/Log.h>
+
+#include "JNIHelp.h"
+#include <android_runtime/AndroidRuntime.h>
+
+#include <utils/BackupHelpers.h>
+
+namespace android
+{
+
+// java.io.FileDescriptor
+static jfieldID s_descriptorField = 0;
+
+// android.backup.BackupDataInput$EntityHeader
+static jfieldID s_keyField = 0;
+static jfieldID s_dataSizeField = 0;
+
+static int
+ctor_native(JNIEnv* env, jobject clazz, jobject fileDescriptor)
+{
+ int err;
+
+ int fd = env->GetIntField(fileDescriptor, s_descriptorField);
+ if (fd == -1) {
+ return NULL;
+ }
+
+ return (int)new BackupDataReader(fd);
+}
+
+static void
+dtor_native(JNIEnv* env, jobject clazz, int r)
+{
+ delete (BackupDataReader*)r;
+}
+
+static jint
+readNextHeader_native(JNIEnv* env, jobject clazz, int r, jobject entity)
+{
+ int err;
+ bool done;
+ BackupDataReader* reader = (BackupDataReader*)r;
+
+ int type = 0;
+
+ err = reader->ReadNextHeader(&done, &type);
+ if (done) {
+ return 1;
+ }
+
+ if (err != 0) {
+ return err < 0 ? err : -1;
+ }
+
+ switch (type) {
+ case BACKUP_HEADER_ENTITY_V1:
+ {
+ String8 key;
+ size_t dataSize;
+ err = reader->ReadEntityHeader(&key, &dataSize);
+ if (err != 0) {
+ return err < 0 ? err : -1;
+ }
+ // TODO: Set the fields in the entity object
+ jstring keyStr = env->NewStringUTF(key.string());
+ env->SetObjectField(entity, s_keyField, keyStr);
+ env->SetIntField(entity, s_dataSizeField, dataSize);
+ return 0;
+ }
+ default:
+ LOGD("Unknown header type: 0x%08x\n", type);
+ return -1;
+ }
+
+ // done
+ return 1;
+}
+
+static jint
+readEntityData_native(JNIEnv* env, jobject clazz, int r, jbyteArray data, int offset, int size)
+{
+ int err;
+ BackupDataReader* reader = (BackupDataReader*)r;
+
+ if (env->GetArrayLength(data) < (size+offset)) {
+ // size mismatch
+ return -1;
+ }
+
+ jbyte* dataBytes = env->GetByteArrayElements(data, NULL);
+ if (dataBytes == NULL) {
+ return -2;
+ }
+
+ err = reader->ReadEntityData(dataBytes+offset, size);
+
+ env->ReleaseByteArrayElements(data, dataBytes, 0);
+
+ return err;
+}
+
+static jint
+skipEntityData_native(JNIEnv* env, jobject clazz, int r)
+{
+ int err;
+ BackupDataReader* reader = (BackupDataReader*)r;
+
+ err = reader->SkipEntityData();
+
+ return err;
+}
+
+static const JNINativeMethod g_methods[] = {
+ { "ctor", "(Ljava/io/FileDescriptor;)I", (void*)ctor_native },
+ { "dtor", "(I)V", (void*)dtor_native },
+ { "readNextHeader_native", "(ILandroid/backup/BackupDataInput$EntityHeader;)I",
+ (void*)readNextHeader_native },
+ { "readEntityData_native", "(I[BII)I", (void*)readEntityData_native },
+ { "skipEntityData_native", "(I)I", (void*)skipEntityData_native },
+};
+
+int register_android_backup_BackupDataInput(JNIEnv* env)
+{
+ //LOGD("register_android_backup_BackupDataInput");
+
+ jclass clazz;
+
+ clazz = env->FindClass("java/io/FileDescriptor");
+ LOG_FATAL_IF(clazz == NULL, "Unable to find class java.io.FileDescriptor");
+ s_descriptorField = env->GetFieldID(clazz, "descriptor", "I");
+ LOG_FATAL_IF(s_descriptorField == NULL,
+ "Unable to find descriptor field in java.io.FileDescriptor");
+
+ clazz = env->FindClass("android/backup/BackupDataInput$EntityHeader");
+ LOG_FATAL_IF(clazz == NULL, "Unable to find class android.backup.BackupDataInput.EntityHeader");
+ s_keyField = env->GetFieldID(clazz, "key", "Ljava/lang/String;");
+ LOG_FATAL_IF(s_keyField == NULL,
+ "Unable to find key field in android.backup.BackupDataInput.EntityHeader");
+ s_dataSizeField = env->GetFieldID(clazz, "dataSize", "I");
+ LOG_FATAL_IF(s_dataSizeField == NULL,
+ "Unable to find dataSize field in android.backup.BackupDataInput.EntityHeader");
+
+ return AndroidRuntime::registerNativeMethods(env, "android/backup/BackupDataInput",
+ g_methods, NELEM(g_methods));
+}
+
+}
diff --git a/core/jni/android_backup_BackupDataOutput.cpp b/core/jni/android_backup_BackupDataOutput.cpp
new file mode 100644
index 0000000..d02590e
--- /dev/null
+++ b/core/jni/android_backup_BackupDataOutput.cpp
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * 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_TAG "FileBackupHelper_native"
+#include <utils/Log.h>
+
+#include "JNIHelp.h"
+#include <android_runtime/AndroidRuntime.h>
+
+#include <utils/BackupHelpers.h>
+
+namespace android
+{
+
+static jfieldID s_descriptorField = 0;
+
+static int
+ctor_native(JNIEnv* env, jobject clazz, jobject fileDescriptor)
+{
+ int err;
+
+ int fd = env->GetIntField(fileDescriptor, s_descriptorField);
+ if (fd == -1) {
+ return NULL;
+ }
+
+ return (int)new BackupDataWriter(fd);
+}
+
+static void
+dtor_native(JNIEnv* env, jobject clazz, int w)
+{
+ delete (BackupDataWriter*)w;
+}
+
+static jint
+writeEntityHeader_native(JNIEnv* env, jobject clazz, int w, jstring key, int dataSize)
+{
+ int err;
+ BackupDataWriter* writer = (BackupDataWriter*)w;
+
+ const char* keyUTF = env->GetStringUTFChars(key, NULL);
+ if (keyUTF == NULL) {
+ return -1;
+ }
+
+ err = writer->WriteEntityHeader(String8(keyUTF), dataSize);
+
+ env->ReleaseStringUTFChars(key, keyUTF);
+
+ return err;
+}
+
+static jint
+writeEntityData_native(JNIEnv* env, jobject clazz, int w, jbyteArray data, int size)
+{
+ int err;
+ BackupDataWriter* writer = (BackupDataWriter*)w;
+
+ if (env->GetArrayLength(data) > size) {
+ // size mismatch
+ return -1;
+ }
+
+ jbyte* dataBytes = env->GetByteArrayElements(data, NULL);
+ if (dataBytes == NULL) {
+ return -1;
+ }
+
+ err = writer->WriteEntityData(dataBytes, size);
+
+ env->ReleaseByteArrayElements(data, dataBytes, JNI_ABORT);
+
+ return err;
+}
+
+static void
+setKeyPrefix_native(JNIEnv* env, jobject clazz, int w, jstring keyPrefixObj)
+{
+ int err;
+ BackupDataWriter* writer = (BackupDataWriter*)w;
+
+ const char* keyPrefixUTF = env->GetStringUTFChars(keyPrefixObj, NULL);
+ String8 keyPrefix(keyPrefixUTF ? keyPrefixUTF : "");
+
+ writer->SetKeyPrefix(keyPrefix);
+
+ env->ReleaseStringUTFChars(keyPrefixObj, keyPrefixUTF);
+}
+
+static const JNINativeMethod g_methods[] = {
+ { "ctor", "(Ljava/io/FileDescriptor;)I", (void*)ctor_native },
+ { "dtor", "(I)V", (void*)dtor_native },
+ { "writeEntityHeader_native", "(ILjava/lang/String;I)I", (void*)writeEntityHeader_native },
+ { "writeEntityData_native", "(I[BI)I", (void*)writeEntityData_native },
+ { "setKeyPrefix_native", "(ILjava/lang/String;)V", (void*)setKeyPrefix_native },
+};
+
+int register_android_backup_BackupDataOutput(JNIEnv* env)
+{
+ //LOGD("register_android_backup_BackupDataOutput");
+
+ jclass clazz;
+
+ clazz = env->FindClass("java/io/FileDescriptor");
+ LOG_FATAL_IF(clazz == NULL, "Unable to find class java.io.FileDescriptor");
+ s_descriptorField = env->GetFieldID(clazz, "descriptor", "I");
+ LOG_FATAL_IF(s_descriptorField == NULL,
+ "Unable to find descriptor field in java.io.FileDescriptor");
+
+ return AndroidRuntime::registerNativeMethods(env, "android/backup/BackupDataOutput",
+ g_methods, NELEM(g_methods));
+}
+
+}
diff --git a/core/jni/android_backup_BackupHelperDispatcher.cpp b/core/jni/android_backup_BackupHelperDispatcher.cpp
new file mode 100644
index 0000000..2e3f0b9
--- /dev/null
+++ b/core/jni/android_backup_BackupHelperDispatcher.cpp
@@ -0,0 +1,259 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * 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_TAG "BackupHelperDispatcher_native"
+#include <utils/Log.h>
+
+#include "JNIHelp.h"
+#include <android_runtime/AndroidRuntime.h>
+
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <unistd.h>
+
+
+#define VERSION_1_HEADER 0x01706c48 // 'Hlp'1 little endian
+
+namespace android
+{
+
+struct chunk_header_v1 {
+ int headerSize;
+ int version;
+ int dataSize; // corresponds to Header.chunkSize
+ int nameLength; // not including the NULL terminator, which is not written to the file
+};
+
+// java.io.FileDescriptor
+static jfieldID s_descriptorField = 0;
+static jfieldID s_chunkSizeField = 0;
+static jfieldID s_keyPrefixField = 0;
+
+static int
+readHeader_native(JNIEnv* env, jobject clazz, jobject headerObj, jobject fdObj)
+{
+ chunk_header_v1 flattenedHeader;
+ int fd;
+ ssize_t amt;
+ String8 keyPrefix;
+ char* buf;
+
+ fd = env->GetIntField(fdObj, s_descriptorField);
+
+ amt = read(fd, &flattenedHeader.headerSize, sizeof(flattenedHeader.headerSize));
+ if (amt != sizeof(flattenedHeader.headerSize)) {
+ return -1;
+ }
+
+ int remainingHeader = flattenedHeader.headerSize - sizeof(flattenedHeader.headerSize);
+
+ if (flattenedHeader.headerSize < (int)sizeof(chunk_header_v1)) {
+ LOGW("Skipping unknown header: %d bytes", flattenedHeader.headerSize);
+ if (remainingHeader > 0) {
+ lseek(fd, remainingHeader, SEEK_CUR);
+ // >0 means skip this chunk
+ return 1;
+ }
+ }
+
+ amt = read(fd, &flattenedHeader.version,
+ sizeof(chunk_header_v1)-sizeof(flattenedHeader.headerSize));
+ if (amt <= 0) {
+ LOGW("Failed reading chunk header");
+ return -1;
+ }
+ remainingHeader -= sizeof(chunk_header_v1)-sizeof(flattenedHeader.headerSize);
+
+ if (flattenedHeader.version != VERSION_1_HEADER) {
+ LOGW("Skipping unknown header version: 0x%08x, %d bytes", flattenedHeader.version,
+ flattenedHeader.headerSize);
+ if (remainingHeader > 0) {
+ lseek(fd, remainingHeader, SEEK_CUR);
+ // >0 means skip this chunk
+ return 1;
+ }
+ }
+
+#if 0
+ LOGD("chunk header:");
+ LOGD(" headerSize=%d", flattenedHeader.headerSize);
+ LOGD(" version=0x%08x", flattenedHeader.version);
+ LOGD(" dataSize=%d", flattenedHeader.dataSize);
+ LOGD(" nameLength=%d", flattenedHeader.nameLength);
+#endif
+
+ if (flattenedHeader.dataSize < 0 || flattenedHeader.nameLength < 0 ||
+ remainingHeader < flattenedHeader.nameLength) {
+ LOGW("Malformed V1 header remainingHeader=%d dataSize=%d nameLength=%d", remainingHeader,
+ flattenedHeader.dataSize, flattenedHeader.nameLength);
+ return -1;
+ }
+
+ buf = keyPrefix.lockBuffer(flattenedHeader.nameLength);
+ if (buf == NULL) {
+ LOGW("unable to allocate %d bytes", flattenedHeader.nameLength);
+ return -1;
+ }
+
+ amt = read(fd, buf, flattenedHeader.nameLength);
+ buf[flattenedHeader.nameLength] = 0;
+
+ keyPrefix.unlockBuffer(flattenedHeader.nameLength);
+
+ remainingHeader -= flattenedHeader.nameLength;
+
+ if (remainingHeader > 0) {
+ lseek(fd, remainingHeader, SEEK_CUR);
+ }
+
+ env->SetIntField(headerObj, s_chunkSizeField, flattenedHeader.dataSize);
+ env->SetObjectField(headerObj, s_keyPrefixField, env->NewStringUTF(keyPrefix.string()));
+
+ return 0;
+}
+
+static int
+skipChunk_native(JNIEnv* env, jobject clazz, jobject fdObj, jint bytesToSkip)
+{
+ int fd;
+
+ fd = env->GetIntField(fdObj, s_descriptorField);
+
+ lseek(fd, bytesToSkip, SEEK_CUR);
+
+ return 0;
+}
+
+static int
+padding_len(int len)
+{
+ len = len % 4;
+ return len == 0 ? len : 4 - len;
+}
+
+static int
+allocateHeader_native(JNIEnv* env, jobject clazz, jobject headerObj, jobject fdObj)
+{
+ int pos;
+ jstring nameObj;
+ int nameLength;
+ int namePadding;
+ int headerSize;
+ int fd;
+
+ fd = env->GetIntField(fdObj, s_descriptorField);
+
+ nameObj = (jstring)env->GetObjectField(headerObj, s_keyPrefixField);
+
+ nameLength = env->GetStringUTFLength(nameObj);
+ namePadding = padding_len(nameLength);
+
+ headerSize = sizeof(chunk_header_v1) + nameLength + namePadding;
+
+ pos = lseek(fd, 0, SEEK_CUR);
+
+ lseek(fd, headerSize, SEEK_CUR);
+
+ return pos;
+}
+
+static int
+writeHeader_native(JNIEnv* env, jobject clazz, jobject headerObj, jobject fdObj, jint pos)
+{
+ int err;
+ chunk_header_v1 header;
+ int fd;
+ int namePadding;
+ int prevPos;
+ jstring nameObj;
+ const char* buf;
+
+ fd = env->GetIntField(fdObj, s_descriptorField);
+ prevPos = lseek(fd, 0, SEEK_CUR);
+
+ nameObj = (jstring)env->GetObjectField(headerObj, s_keyPrefixField);
+ header.nameLength = env->GetStringUTFLength(nameObj);
+ namePadding = padding_len(header.nameLength);
+
+ header.headerSize = sizeof(chunk_header_v1) + header.nameLength + namePadding;
+ header.version = VERSION_1_HEADER;
+ header.dataSize = prevPos - (pos + header.headerSize);
+
+ lseek(fd, pos, SEEK_SET);
+ err = write(fd, &header, sizeof(chunk_header_v1));
+ if (err != sizeof(chunk_header_v1)) {
+ return errno;
+ }
+
+ buf = env->GetStringUTFChars(nameObj, NULL);
+ err = write(fd, buf, header.nameLength);
+ env->ReleaseStringUTFChars(nameObj, buf);
+ if (err != header.nameLength) {
+ return errno;
+ }
+
+ if (namePadding != 0) {
+ int zero = 0;
+ err = write(fd, &zero, namePadding);
+ if (err != namePadding) {
+ return errno;
+ }
+ }
+
+ lseek(fd, prevPos, SEEK_SET);
+ return 0;
+}
+
+static const JNINativeMethod g_methods[] = {
+ { "readHeader_native",
+ "(Landroid/backup/BackupHelperDispatcher$Header;Ljava/io/FileDescriptor;)I",
+ (void*)readHeader_native },
+ { "skipChunk_native",
+ "(Ljava/io/FileDescriptor;I)I",
+ (void*)skipChunk_native },
+ { "allocateHeader_native",
+ "(Landroid/backup/BackupHelperDispatcher$Header;Ljava/io/FileDescriptor;)I",
+ (void*)allocateHeader_native },
+ { "writeHeader_native",
+ "(Landroid/backup/BackupHelperDispatcher$Header;Ljava/io/FileDescriptor;I)I",
+ (void*)writeHeader_native },
+};
+
+int register_android_backup_BackupHelperDispatcher(JNIEnv* env)
+{
+ jclass clazz;
+
+ clazz = env->FindClass("java/io/FileDescriptor");
+ LOG_FATAL_IF(clazz == NULL, "Unable to find class java.io.FileDescriptor");
+ s_descriptorField = env->GetFieldID(clazz, "descriptor", "I");
+ LOG_FATAL_IF(s_descriptorField == NULL,
+ "Unable to find descriptor field in java.io.FileDescriptor");
+
+ clazz = env->FindClass("android/backup/BackupHelperDispatcher$Header");
+ LOG_FATAL_IF(clazz == NULL,
+ "Unable to find class android.backup.BackupHelperDispatcher.Header");
+ s_chunkSizeField = env->GetFieldID(clazz, "chunkSize", "I");
+ LOG_FATAL_IF(s_chunkSizeField == NULL,
+ "Unable to find chunkSize field in android.backup.BackupHelperDispatcher.Header");
+ s_keyPrefixField = env->GetFieldID(clazz, "keyPrefix", "Ljava/lang/String;");
+ LOG_FATAL_IF(s_keyPrefixField == NULL,
+ "Unable to find keyPrefix field in android.backup.BackupHelperDispatcher.Header");
+
+ return AndroidRuntime::registerNativeMethods(env, "android/backup/BackupHelperDispatcher",
+ g_methods, NELEM(g_methods));
+}
+
+}
diff --git a/core/jni/android_backup_FileBackupHelper.cpp b/core/jni/android_backup_FileBackupHelper.cpp
deleted file mode 100644
index c6de3a5..0000000
--- a/core/jni/android_backup_FileBackupHelper.cpp
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * 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_TAG "FileBackupHelper_native"
-#include <utils/Log.h>
-
-#include "JNIHelp.h"
-#include <android_runtime/AndroidRuntime.h>
-
-#include <utils/backup_helpers.h>
-
-namespace android
-{
-
-static jfieldID s_descriptorField = 0;
-
-static int
-performBackup_native(JNIEnv* env, jobject clazz, jstring basePath, jobject oldState, jobject data,
- jobject newState, jobjectArray files)
-{
- int err;
-
- // all parameters have already been checked against null
- LOGD("oldState=%p newState=%p data=%p\n", oldState, newState, data);
- int oldStateFD = oldState != NULL ? env->GetIntField(oldState, s_descriptorField) : -1;
- int newStateFD = env->GetIntField(newState, s_descriptorField);
- int dataFD = env->GetIntField(data, s_descriptorField);
-
- char const* basePathUTF = env->GetStringUTFChars(basePath, NULL);
- LOGD("basePathUTF=\"%s\"\n", basePathUTF);
- const int fileCount = env->GetArrayLength(files);
- char const** filesUTF = (char const**)malloc(sizeof(char*)*fileCount);
- for (int i=0; i<fileCount; i++) {
- filesUTF[i] = env->GetStringUTFChars((jstring)env->GetObjectArrayElement(files, i), NULL);
- }
-
- err = back_up_files(oldStateFD, dataFD, newStateFD, basePathUTF, filesUTF, fileCount);
-
- for (int i=0; i<fileCount; i++) {
- env->ReleaseStringUTFChars((jstring)env->GetObjectArrayElement(files, i), filesUTF[i]);
- }
- free(filesUTF);
- env->ReleaseStringUTFChars(basePath, basePathUTF);
-
- return err;
-}
-
-static const JNINativeMethod g_methods[] = {
- { "performBackup_native",
- "(Ljava/lang/String;Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;"
- "Ljava/io/FileDescriptor;[Ljava/lang/String;)I",
- (void*)performBackup_native },
-};
-
-int register_android_backup_FileBackupHelper(JNIEnv* env)
-{
- LOGD("register_android_backup_FileBackupHelper");
-
- jclass clazz;
-
- clazz = env->FindClass("java/io/FileDescriptor");
- LOG_FATAL_IF(clazz == NULL, "Unable to find class java.io.FileDescriptor");
- s_descriptorField = env->GetFieldID(clazz, "descriptor", "I");
- LOG_FATAL_IF(s_descriptorField == NULL,
- "Unable to find descriptor field in java.io.FileDescriptor");
-
- return AndroidRuntime::registerNativeMethods(env, "android/backup/FileBackupHelper",
- g_methods, NELEM(g_methods));
-}
-
-}
diff --git a/core/jni/android_backup_FileBackupHelperBase.cpp b/core/jni/android_backup_FileBackupHelperBase.cpp
new file mode 100644
index 0000000..8225a36
--- /dev/null
+++ b/core/jni/android_backup_FileBackupHelperBase.cpp
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * 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_TAG "FileBackupHelper_native"
+#include <utils/Log.h>
+
+#include "JNIHelp.h"
+#include <android_runtime/AndroidRuntime.h>
+
+#include <utils/BackupHelpers.h>
+
+namespace android
+{
+
+// java.io.FileDescriptor
+static jfieldID s_descriptorField = 0;
+
+static int
+ctor(JNIEnv* env, jobject clazz)
+{
+ return (int)new RestoreHelperBase();
+}
+
+static void
+dtor(JNIEnv* env, jobject clazz, jint ptr)
+{
+ delete (RestoreHelperBase*)ptr;
+}
+
+static int
+performBackup_native(JNIEnv* env, jobject clazz, jobject oldState, int data,
+ jobject newState, jobjectArray files, jobjectArray keys)
+{
+ int err;
+
+ // all parameters have already been checked against null
+ int oldStateFD = oldState != NULL ? env->GetIntField(oldState, s_descriptorField) : -1;
+ int newStateFD = env->GetIntField(newState, s_descriptorField);
+ BackupDataWriter* dataStream = (BackupDataWriter*)data;
+
+ const int fileCount = env->GetArrayLength(files);
+ char const** filesUTF = (char const**)malloc(sizeof(char*)*fileCount);
+ for (int i=0; i<fileCount; i++) {
+ filesUTF[i] = env->GetStringUTFChars((jstring)env->GetObjectArrayElement(files, i), NULL);
+ }
+
+ const int keyCount = env->GetArrayLength(keys);
+ char const** keysUTF = (char const**)malloc(sizeof(char*)*keyCount);
+ for (int i=0; i<keyCount; i++) {
+ keysUTF[i] = env->GetStringUTFChars((jstring)env->GetObjectArrayElement(keys, i), NULL);
+ }
+
+ err = back_up_files(oldStateFD, dataStream, newStateFD, filesUTF, keysUTF, fileCount);
+
+ for (int i=0; i<fileCount; i++) {
+ env->ReleaseStringUTFChars((jstring)env->GetObjectArrayElement(files, i), filesUTF[i]);
+ }
+ free(filesUTF);
+
+ for (int i=0; i<keyCount; i++) {
+ env->ReleaseStringUTFChars((jstring)env->GetObjectArrayElement(keys, i), keysUTF[i]);
+ }
+ free(keysUTF);
+
+ return err;
+}
+
+
+static int
+writeFile_native(JNIEnv* env, jobject clazz, jint ptr, jstring filenameObj, int backupReaderPtr)
+{
+ int err;
+ RestoreHelperBase* restore = (RestoreHelperBase*)ptr;
+ BackupDataReader* reader = (BackupDataReader*)backupReaderPtr;
+ char const* filename;
+
+ filename = env->GetStringUTFChars(filenameObj, NULL);
+
+ err = restore->WriteFile(String8(filename), reader);
+
+ env->ReleaseStringUTFChars(filenameObj, filename);
+
+ return err;
+}
+
+static int
+writeSnapshot_native(JNIEnv* env, jobject clazz, jint ptr, jobject fileDescriptor)
+{
+ int err;
+
+ RestoreHelperBase* restore = (RestoreHelperBase*)ptr;
+ int fd = env->GetIntField(fileDescriptor, s_descriptorField);
+
+ err = restore->WriteSnapshot(fd);
+
+ return err;
+}
+
+static const JNINativeMethod g_methods[] = {
+ { "ctor", "()I", (void*)ctor },
+ { "dtor", "(I)V", (void*)dtor },
+ { "performBackup_native",
+ "(Ljava/io/FileDescriptor;ILjava/io/FileDescriptor;[Ljava/lang/String;[Ljava/lang/String;)I",
+ (void*)performBackup_native },
+ { "writeFile_native", "(ILjava/lang/String;I)I", (void*)writeFile_native },
+ { "writeSnapshot_native", "(ILjava/io/FileDescriptor;)I", (void*)writeSnapshot_native },
+};
+
+int register_android_backup_FileBackupHelperBase(JNIEnv* env)
+{
+ jclass clazz;
+
+ clazz = env->FindClass("java/io/FileDescriptor");
+ LOG_FATAL_IF(clazz == NULL, "Unable to find class java.io.FileDescriptor");
+ s_descriptorField = env->GetFieldID(clazz, "descriptor", "I");
+ LOG_FATAL_IF(s_descriptorField == NULL,
+ "Unable to find descriptor field in java.io.FileDescriptor");
+
+ return AndroidRuntime::registerNativeMethods(env, "android/backup/FileBackupHelperBase",
+ g_methods, NELEM(g_methods));
+}
+
+}
diff --git a/core/jni/android_bluetooth_Database.cpp b/core/jni/android_bluetooth_Database.cpp
index 136c9a3..73b8efd 100644
--- a/core/jni/android_bluetooth_Database.cpp
+++ b/core/jni/android_bluetooth_Database.cpp
@@ -53,6 +53,7 @@ static void initializeNativeDataNative(JNIEnv* env, jobject object) {
LOGE("Could not get onto the system bus!");
dbus_error_free(&err);
}
+ dbus_connection_set_exit_on_disconnect(conn, FALSE);
}
#endif
}
diff --git a/core/jni/android_emoji_EmojiFactory.cpp b/core/jni/android_emoji_EmojiFactory.cpp
index 59f63a8..7d6e24f 100644
--- a/core/jni/android_emoji_EmojiFactory.cpp
+++ b/core/jni/android_emoji_EmojiFactory.cpp
@@ -1,7 +1,7 @@
#include "SkTypes.h"
#include "SkImageDecoder.h"
-#define LOG_TAG "DoCoMoEmojiFactory_jni"
+#define LOG_TAG "EmojiFactory_jni"
#include <utils/Log.h>
#include <utils/String8.h>
@@ -13,15 +13,11 @@
namespace android {
-// Note: This class is originally developed so that libandroid_runtime does
-// not have to depend on libemoji which is optional library. However, we
-// cannot use this class, since current (2009-02-16) bionic libc does not allow
-// dlopen()-ing inside dlopen(), while not only this class but also libemoji
-// uses dlopen().
class EmojiFactoryCaller {
public:
- EmojiFactoryCaller();
+ EmojiFactoryCaller() {}
virtual ~EmojiFactoryCaller();
+ bool Init();
EmojiFactory *TryCallGetImplementation(const char* name);
EmojiFactory *TryCallGetAvailableImplementation();
private:
@@ -30,35 +26,45 @@ class EmojiFactoryCaller {
EmojiFactory *(*m_get_available_implementation)();
};
-EmojiFactoryCaller::EmojiFactoryCaller() {
+bool EmojiFactoryCaller::Init() {
+ const char* error_msg;
m_handle = dlopen("libemoji.so", RTLD_LAZY | RTLD_LOCAL);
- const char* error_str = dlerror();
- if (error_str) {
- LOGI("Failed to load libemoji.so: %s", error_str);
- return;
+
+ if (m_handle == NULL) {
+ error_msg = "Failed to load libemoji.so";
+ goto FAIL;
}
m_get_implementation =
reinterpret_cast<EmojiFactory *(*)(const char*)>(
dlsym(m_handle, "GetImplementation"));
- error_str = dlerror();
- if (error_str) {
- LOGE("Failed to get symbol of GetImplementation: %s", error_str);
- dlclose(m_handle);
- m_handle = NULL;
- return;
+ if (m_get_implementation == NULL) {
+ error_msg = "Failed to get symbol of GetImplementation";
+ goto FAIL;
}
m_get_available_implementation =
reinterpret_cast<EmojiFactory *(*)()>(
dlsym(m_handle,"GetAvailableImplementation"));
- error_str = dlerror();
- if (error_str) {
- LOGE("Failed to get symbol of GetAvailableImplementation: %s", error_str);
+ if (m_get_available_implementation == NULL) {
+ error_msg = "Failed to get symbol of GetAvailableImplementation";
+ goto FAIL;
+ }
+
+ return true;
+
+FAIL:
+ const char* error_str = dlerror();
+ if (error_str == NULL) {
+ error_str = "unknown reason";
+ }
+
+ LOGE("%s: %s", error_msg, error_str);
+ if (m_handle != NULL) {
dlclose(m_handle);
m_handle = NULL;
- return;
}
+ return false;
}
EmojiFactoryCaller::~EmojiFactoryCaller() {
@@ -82,10 +88,9 @@ EmojiFactory *EmojiFactoryCaller::TryCallGetAvailableImplementation() {
return m_get_available_implementation();
}
-// Note: bionic libc's dlopen() does not allow recursive dlopen(). So currently
-// we cannot use EmojiFactoryCaller here.
-// static EmojiFactoryCaller* gCaller;
-// static pthread_once_t g_once = PTHREAD_ONCE_INIT;
+static EmojiFactoryCaller* gCaller;
+static pthread_once_t g_once = PTHREAD_ONCE_INIT;
+static bool lib_emoji_factory_is_ready;
static jclass gString_class;
@@ -95,9 +100,10 @@ static jmethodID gBitmap_constructorMethodID;
static jclass gEmojiFactory_class;
static jmethodID gEmojiFactory_constructorMethodID;
-// static void InitializeCaller() {
-// gCaller = new EmojiFactoryCaller();
-// }
+static void InitializeCaller() {
+ gCaller = new EmojiFactoryCaller();
+ lib_emoji_factory_is_ready = gCaller->Init();
+}
static jobject create_java_EmojiFactory(
JNIEnv* env, EmojiFactory* factory, jstring name) {
@@ -116,19 +122,23 @@ static jobject create_java_EmojiFactory(
static jobject android_emoji_EmojiFactory_newInstance(
JNIEnv* env, jobject clazz, jstring name) {
- // pthread_once(&g_once, InitializeCaller);
-
if (NULL == name) {
return NULL;
}
+ pthread_once(&g_once, InitializeCaller);
+ if (!lib_emoji_factory_is_ready) {
+ return NULL;
+ }
const jchar* jchars = env->GetStringChars(name, NULL);
jsize len = env->GetStringLength(name);
String8 str(String16(jchars, len));
- // EmojiFactory *factory = gCaller->TryCallGetImplementation(str.string());
- EmojiFactory *factory = EmojiFactory::GetImplementation(str.string());
-
+ EmojiFactory *factory = gCaller->TryCallGetImplementation(str.string());
+ // EmojiFactory *factory = EmojiFactory::GetImplementation(str.string());
+ if (NULL == factory) {
+ return NULL;
+ }
env->ReleaseStringChars(name, jchars);
return create_java_EmojiFactory(env, factory, name);
@@ -136,10 +146,13 @@ static jobject android_emoji_EmojiFactory_newInstance(
static jobject android_emoji_EmojiFactory_newAvailableInstance(
JNIEnv* env, jobject clazz) {
- // pthread_once(&g_once, InitializeCaller);
+ pthread_once(&g_once, InitializeCaller);
+ if (!lib_emoji_factory_is_ready) {
+ return NULL;
+ }
- // EmojiFactory *factory = gCaller->TryCallGetAvailableImplementation();
- EmojiFactory *factory = EmojiFactory::GetAvailableImplementation();
+ EmojiFactory *factory = gCaller->TryCallGetAvailableImplementation();
+ // EmojiFactory *factory = EmojiFactory::GetAvailableImplementation();
if (NULL == factory) {
return NULL;
}
diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp
index c107993..77a8a72 100644
--- a/core/jni/android_hardware_Camera.cpp
+++ b/core/jni/android_hardware_Camera.cpp
@@ -38,12 +38,6 @@ enum CallbackMessageID {
kErrorCallback = 5
};
-enum CameraError {
- kCameraErrorUnknown = 1,
- kCameraErrorMediaServer = 100
-};
-
-
struct fields_t {
jfieldID context;
jfieldID surface;
@@ -53,19 +47,33 @@ struct fields_t {
static fields_t fields;
static Mutex sLock;
-struct camera_context_t {
+// provides persistent context for calls from native code to Java
+class JNICameraContext: public CameraListener
+{
+public:
+ JNICameraContext(JNIEnv* env, jobject weak_this, jclass clazz, const sp<Camera>& camera);
+ ~JNICameraContext() { release(); }
+ virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2);
+ virtual void postData(int32_t msgType, const sp<IMemory>& dataPtr);
+ sp<Camera> getCamera() { Mutex::Autolock _l(mLock); return mCamera; }
+ void release();
+
+private:
+ void copyAndPost(JNIEnv* env, const sp<IMemory>& dataPtr, int msgType);
+
jobject mCameraJObjectWeak; // weak reference to java object
jclass mCameraJClass; // strong reference to java class
sp<Camera> mCamera; // strong reference to native object
+ Mutex mLock;
};
-sp<Camera> get_native_camera(JNIEnv *env, jobject thiz, camera_context_t** pContext)
+sp<Camera> get_native_camera(JNIEnv *env, jobject thiz, JNICameraContext** pContext)
{
sp<Camera> camera;
Mutex::Autolock _l(sLock);
- camera_context_t* context = reinterpret_cast<camera_context_t*>(env->GetIntField(thiz, fields.context));
+ JNICameraContext* context = reinterpret_cast<JNICameraContext*>(env->GetIntField(thiz, fields.context));
if (context != NULL) {
- camera = context->mCamera;
+ camera = context->getCamera();
}
LOGV("get_native_camera: context=%p, camera=%p", context, camera.get());
if (camera == 0) {
@@ -76,30 +84,108 @@ sp<Camera> get_native_camera(JNIEnv *env, jobject thiz, camera_context_t** pCont
return camera;
}
-static void err_callback(status_t err, void *cookie)
+JNICameraContext::JNICameraContext(JNIEnv* env, jobject weak_this, jclass clazz, const sp<Camera>& camera)
{
- camera_context_t* context = reinterpret_cast<camera_context_t*>(cookie);
- if ((context == NULL) || (context->mCamera == 0)) return;
+ mCameraJObjectWeak = env->NewGlobalRef(weak_this);
+ mCameraJClass = (jclass)env->NewGlobalRef(clazz);
+ mCamera = camera;
+}
- LOGV("err_callback: context=%p, camera=%p", context, context->mCamera.get());
+void JNICameraContext::release()
+{
+ LOGV("release");
+ Mutex::Autolock _l(mLock);
+ JNIEnv *env = AndroidRuntime::getJNIEnv();
- int error;
- switch (err) {
- case DEAD_OBJECT:
- error = kCameraErrorMediaServer;
- break;
- default:
- error = kCameraErrorUnknown;
- break;
+ if (mCameraJObjectWeak != NULL) {
+ env->DeleteGlobalRef(mCameraJObjectWeak);
+ mCameraJObjectWeak = NULL;
+ }
+ if (mCameraJClass != NULL) {
+ env->DeleteGlobalRef(mCameraJClass);
+ mCameraJClass = NULL;
+ }
+ mCamera.clear();
+}
+
+void JNICameraContext::notify(int32_t msgType, int32_t ext1, int32_t ext2)
+{
+ LOGV("notify");
+
+ // VM pointer will be NULL if object is released
+ Mutex::Autolock _l(mLock);
+ if (mCameraJObjectWeak == NULL) {
+ LOGW("callback on dead camera object");
+ return;
+ }
+ JNIEnv *env = AndroidRuntime::getJNIEnv();
+ env->CallStaticVoidMethod(mCameraJClass, fields.post_event,
+ mCameraJObjectWeak, msgType, ext1, ext2);
+}
+
+void JNICameraContext::copyAndPost(JNIEnv* env, const sp<IMemory>& dataPtr, int msgType)
+{
+ jbyteArray obj = NULL;
+
+ // allocate Java byte array and copy data
+ if (dataPtr != NULL) {
+ ssize_t offset;
+ size_t size;
+ sp<IMemoryHeap> heap = dataPtr->getMemory(&offset, &size);
+ LOGV("postData: off=%d, size=%d", offset, size);
+ uint8_t *heapBase = (uint8_t*)heap->base();
+
+ if (heapBase != NULL) {
+ uint8_t *data = heapBase + offset;
+ obj = env->NewByteArray(size);
+ if (obj == NULL) {
+ LOGE("Couldn't allocate byte array for JPEG data");
+ env->ExceptionClear();
+ } else {
+ jbyte *bytes = env->GetByteArrayElements(obj, NULL);
+ memcpy(bytes, data, size);
+ env->ReleaseByteArrayElements(obj, bytes, 0);
+
+ }
+ } else {
+ LOGE("image heap is NULL");
+ }
+ }
+
+ // post image data to Java
+ env->CallStaticVoidMethod(mCameraJClass, fields.post_event,
+ mCameraJObjectWeak, msgType, 0, 0, obj);
+ if (obj) {
+ env->DeleteLocalRef(obj);
}
+}
+void JNICameraContext::postData(int32_t msgType, const sp<IMemory>& dataPtr)
+{
+ // VM pointer will be NULL if object is released
+ Mutex::Autolock _l(mLock);
JNIEnv *env = AndroidRuntime::getJNIEnv();
- if (env == NULL) {
- LOGE("err_callback on dead VM");
+ if (mCameraJObjectWeak == NULL) {
+ LOGW("callback on dead camera object");
return;
}
- env->CallStaticVoidMethod(context->mCameraJClass, fields.post_event,
- context->mCameraJObjectWeak, kErrorCallback, error, 0, NULL);
+
+ // return data based on callback type
+ switch(msgType) {
+ case CAMERA_MSG_VIDEO_FRAME:
+ // should never happen
+ break;
+ // don't return raw data to Java
+ case CAMERA_MSG_RAW_IMAGE:
+ LOGV("rawCallback");
+ env->CallStaticVoidMethod(mCameraJClass, fields.post_event,
+ mCameraJObjectWeak, msgType, 0, 0, NULL);
+ break;
+ default:
+ LOGV("dataCallback(%d, %p)", msgType, dataPtr.get());
+ copyAndPost(env, dataPtr, msgType);
+ break;
+ }
}
// connect to camera service
@@ -115,33 +201,24 @@ static void android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz, jobj
// make sure camera hardware is alive
if (camera->getStatus() != NO_ERROR) {
- jniThrowException(env, "java/io/IOException", "Camera initialization failed");
+ jniThrowException(env, "java/lang/RuntimeException", "Camera initialization failed");
return;
}
jclass clazz = env->GetObjectClass(thiz);
if (clazz == NULL) {
- LOGE("Can't find android/hardware/Camera");
- // XXX no idea what to throw here, can this even happen?
- jniThrowException(env, "java/lang/Exception", NULL);
+ jniThrowException(env, "java/lang/RuntimeException", "Can't find android/hardware/Camera");
return;
}
// We use a weak reference so the Camera object can be garbage collected.
// The reference is only used as a proxy for callbacks.
- camera_context_t* context = new camera_context_t;
- context->mCameraJObjectWeak = env->NewGlobalRef(weak_this);
- context->mCameraJClass = (jclass)env->NewGlobalRef(clazz);
- context->mCamera = camera;
+ sp<JNICameraContext> context = new JNICameraContext(env, weak_this, clazz, camera);
+ context->incStrong(thiz);
+ camera->setListener(context);
// save context in opaque field
- env->SetIntField(thiz, fields.context, (int)context);
-
- LOGV("native_setup: mCameraJObjectWeak=%x, camera_obj=%x, context=%p",
- (int)context->mCameraJObjectWeak, (int)thiz, context);
-
- // set error callback
- camera->setErrorCallback(err_callback, context);
+ env->SetIntField(thiz, fields.context, (int)context.get());
}
// disconnect from camera service
@@ -150,11 +227,11 @@ static void android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz, jobj
// finalizer is invoked later.
static void android_hardware_Camera_release(JNIEnv *env, jobject thiz)
{
- camera_context_t* context = NULL;
+ JNICameraContext* context = NULL;
sp<Camera> camera;
{
Mutex::Autolock _l(sLock);
- context = reinterpret_cast<camera_context_t*>(env->GetIntField(thiz, fields.context));
+ context = reinterpret_cast<JNICameraContext*>(env->GetIntField(thiz, fields.context));
// Make sure we do not attempt to callback on a deleted Java object.
env->SetIntField(thiz, fields.context, 0);
@@ -162,21 +239,18 @@ static void android_hardware_Camera_release(JNIEnv *env, jobject thiz)
// clean up if release has not been called before
if (context != NULL) {
- camera = context->mCamera;
- context->mCamera.clear();
+ camera = context->getCamera();
+ context->release();
LOGV("native_release: context=%p camera=%p", context, camera.get());
// clear callbacks
if (camera != NULL) {
- camera->setPreviewCallback(NULL, NULL, FRAME_CALLBACK_FLAG_NOOP);
- camera->setErrorCallback(NULL, NULL);
+ camera->setPreviewCallbackFlags(FRAME_CALLBACK_FLAG_NOOP);
camera->disconnect();
- env->DeleteGlobalRef(context->mCameraJObjectWeak);
- env->DeleteGlobalRef(context->mCameraJClass);
}
// remove context to prevent further Java access
- delete context;
+ context->decStrong(thiz);
}
}
@@ -186,54 +260,15 @@ static void android_hardware_Camera_setPreviewDisplay(JNIEnv *env, jobject thiz,
sp<Camera> camera = get_native_camera(env, thiz, NULL);
if (camera == 0) return;
- sp<Surface> surface = reinterpret_cast<Surface*>(env->GetIntField(jSurface, fields.surface));
+ sp<Surface> surface = NULL;
+ if (jSurface != NULL) {
+ surface = reinterpret_cast<Surface*>(env->GetIntField(jSurface, fields.surface));
+ }
if (camera->setPreviewDisplay(surface) != NO_ERROR) {
jniThrowException(env, "java/io/IOException", "setPreviewDisplay failed");
}
}
-static void preview_callback(const sp<IMemory>& mem, void *cookie)
-{
- LOGV("preview_callback");
- JNIEnv *env = AndroidRuntime::getJNIEnv();
- if (env == NULL) {
- LOGE("preview_callback on dead VM");
- return;
- }
- camera_context_t* context = reinterpret_cast<camera_context_t*>(cookie);
- if ((context == NULL) || (context->mCamera == 0)) {
- LOGW("context or camera is NULL in preview_callback");
- return;
- }
- LOGV("native_release: context=%p camera=%p", context, context->mCamera.get());
-
- int arg1 = 0, arg2 = 0;
- jobject obj = NULL;
-
- ssize_t offset;
- size_t size;
- sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
-
- uint8_t *data = ((uint8_t *)heap->base()) + offset;
-
- jbyteArray array = env->NewByteArray(size);
- if (array == NULL) {
- LOGE("Couldn't allocate byte array for YUV data");
- env->ExceptionClear();
- return;
- }
-
- jbyte *bytes = env->GetByteArrayElements(array, NULL);
- memcpy(bytes, data, size);
- env->ReleaseByteArrayElements(array, bytes, 0);
-
- obj = array;
-
- env->CallStaticVoidMethod(context->mCameraJClass, fields.post_event,
- context->mCameraJObjectWeak, kPreviewCallback, arg1, arg2, obj);
- env->DeleteLocalRef(array);
-}
-
static void android_hardware_Camera_startPreview(JNIEnv *env, jobject thiz)
{
LOGV("startPreview");
@@ -241,7 +276,7 @@ static void android_hardware_Camera_startPreview(JNIEnv *env, jobject thiz)
if (camera == 0) return;
if (camera->startPreview() != NO_ERROR) {
- jniThrowException(env, "java/io/IOException", "startPreview failed");
+ jniThrowException(env, "java/lang/RuntimeException", "startPreview failed");
return;
}
}
@@ -269,7 +304,7 @@ static void android_hardware_Camera_setHasPreviewCallback(JNIEnv *env, jobject t
// Important: Only install preview_callback if the Java code has called
// setPreviewCallback() with a non-null value, otherwise we'd pay to memcpy
// each preview frame for nothing.
- camera_context_t* context;
+ JNICameraContext* context;
sp<Camera> camera = get_native_camera(env, thiz, &context);
if (camera == 0) return;
@@ -279,130 +314,32 @@ static void android_hardware_Camera_setHasPreviewCallback(JNIEnv *env, jobject t
} else {
callback_flag = FRAME_CALLBACK_FLAG_NOOP;
}
- camera->setPreviewCallback(installed ? preview_callback : NULL, context, callback_flag);
-}
-
-static void autofocus_callback_impl(bool success, void *cookie)
-{
- LOGV("autoFocusCallback");
- camera_context_t* context = reinterpret_cast<camera_context_t*>(cookie);
-
- JNIEnv *env = AndroidRuntime::getJNIEnv();
- if (env == NULL) {
- LOGE("autofocus_callback on dead VM");
- return;
- }
- env->CallStaticVoidMethod(context->mCameraJClass, fields.post_event,
- context->mCameraJObjectWeak, kAutoFocusCallback, success, 0, NULL);
+ camera->setPreviewCallbackFlags(callback_flag);
}
static void android_hardware_Camera_autoFocus(JNIEnv *env, jobject thiz)
{
LOGV("autoFocus");
- camera_context_t* context;
+ JNICameraContext* context;
sp<Camera> c = get_native_camera(env, thiz, &context);
if (c == 0) return;
- c->setAutoFocusCallback(autofocus_callback_impl, context);
if (c->autoFocus() != NO_ERROR) {
- jniThrowException(env, "java/io/IOException", "autoFocus failed");
- }
-}
-
-static void jpeg_callback(const sp<IMemory>& mem, void *cookie)
-{
- LOGV("jpegCallback");
- camera_context_t* context = reinterpret_cast<camera_context_t*>(cookie);
-
- JNIEnv *env = AndroidRuntime::getJNIEnv();
- if (env == NULL) {
- LOGE("jpeg`_callback on dead VM");
- return;
- }
- int arg1 = 0, arg2 = 0;
- jobject obj = NULL;
-
- if (mem == NULL) {
- env->CallStaticVoidMethod(context->mCameraJClass, fields.post_event,
- context->mCameraJObjectWeak, kJpegCallback, arg1, arg2, NULL);
- return;
+ jniThrowException(env, "java/lang/RuntimeException", "autoFocus failed");
}
- ssize_t offset;
- size_t size;
- sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
- LOGV("jpeg_callback: mem off=%d, size=%d", offset, size);
-
- uint8_t *heap_base = (uint8_t *)heap->base();
- if (heap_base == NULL) {
- LOGE("YUV heap is NULL");
- return;
- }
-
- uint8_t *data = heap_base + offset;
-
- jbyteArray array = env->NewByteArray(size);
- if (array == NULL) {
- LOGE("Couldn't allocate byte array for JPEG data");
- env->ExceptionClear();
- return;
- }
-
- jbyte *bytes = env->GetByteArrayElements(array, NULL);
- memcpy(bytes, data, size);
- env->ReleaseByteArrayElements(array, bytes, 0);
-
- obj = array;
-
- env->CallStaticVoidMethod(context->mCameraJClass, fields.post_event,
- context->mCameraJObjectWeak, kJpegCallback, arg1, arg2, obj);
- env->DeleteLocalRef(array);
-}
-
-static void shutter_callback_impl(void *cookie)
-{
- LOGV("shutterCallback");
- camera_context_t* context = reinterpret_cast<camera_context_t*>(cookie);
-
- JNIEnv *env = AndroidRuntime::getJNIEnv();
- if (env == NULL) {
- LOGE("shutter_callback on dead VM");
- return;
- }
- env->CallStaticVoidMethod(context->mCameraJClass, fields.post_event,
- context->mCameraJObjectWeak, kShutterCallback, 0, 0, NULL);
-}
-
-static void raw_callback(const sp<IMemory>& mem __attribute__((unused)),
- void *cookie)
-{
- LOGV("rawCallback");
- camera_context_t* context = reinterpret_cast<camera_context_t*>(cookie);
-
- JNIEnv *env = AndroidRuntime::getJNIEnv();
- if (env == NULL) {
- LOGE("raw_callback on dead VM");
- return;
- }
- env->CallStaticVoidMethod(context->mCameraJClass, fields.post_event,
- context->mCameraJObjectWeak, kRawCallback, 0, 0, NULL);
}
static void android_hardware_Camera_takePicture(JNIEnv *env, jobject thiz)
{
LOGV("takePicture");
- camera_context_t* context;
+ JNICameraContext* context;
sp<Camera> camera = get_native_camera(env, thiz, &context);
if (camera == 0) return;
- camera->setShutterCallback(shutter_callback_impl, context);
- camera->setRawCallback(raw_callback, context);
- camera->setJpegCallback(jpeg_callback, context);
if (camera->takePicture() != NO_ERROR) {
- jniThrowException(env, "java/io/IOException", "takePicture failed");
+ jniThrowException(env, "java/lang/RuntimeException", "takePicture failed");
return;
}
-
- return;
}
static void android_hardware_Camera_setParameters(JNIEnv *env, jobject thiz, jstring params)
@@ -418,7 +355,7 @@ static void android_hardware_Camera_setParameters(JNIEnv *env, jobject thiz, jst
env->ReleaseStringCritical(params, str);
}
if (camera->setParameters(params8) != NO_ERROR) {
- jniThrowException(env, "java/lang/IllegalArgumentException", "setParameters failed");
+ jniThrowException(env, "java/lang/RuntimeException", "setParameters failed");
return;
}
}
diff --git a/core/jni/android_hardware_SensorManager.cpp b/core/jni/android_hardware_SensorManager.cpp
index 75aa458..3e27978 100644
--- a/core/jni/android_hardware_SensorManager.cpp
+++ b/core/jni/android_hardware_SensorManager.cpp
@@ -14,9 +14,13 @@
* limitations under the License.
*/
-#define LOG_TAG "Sensors"
+#define LOG_TAG "SensorManager"
+
+#define LOG_NDEBUG 0
+#include "utils/Log.h"
#include <hardware/sensors.h>
+#include <cutils/native_handle.h>
#include "jni.h"
#include "JNIHelp.h"
@@ -106,12 +110,33 @@ sensors_data_uninit(JNIEnv *env, jclass clazz)
}
static jint
-sensors_data_open(JNIEnv *env, jclass clazz, jobject fdo)
+sensors_data_open(JNIEnv *env, jclass clazz, jobjectArray fdArray, jintArray intArray)
{
jclass FileDescriptor = env->FindClass("java/io/FileDescriptor");
- jfieldID offset = env->GetFieldID(FileDescriptor, "descriptor", "I");
- int fd = env->GetIntField(fdo, offset);
- return sSensorDevice->data_open(sSensorDevice, fd); // doesn't take ownership of fd
+ jfieldID fieldOffset = env->GetFieldID(FileDescriptor, "descriptor", "I");
+ int numFds = (fdArray ? env->GetArrayLength(fdArray) : 0);
+ int numInts = (intArray ? env->GetArrayLength(intArray) : 0);
+ native_handle_t* handle = native_handle_create(numFds, numInts);
+ int offset = 0;
+
+ for (int i = 0; i < numFds; i++) {
+ jobject fdo = env->GetObjectArrayElement(fdArray, i);
+ if (fdo) {
+ handle->data[offset++] = env->GetIntField(fdo, fieldOffset);
+ } else {
+ handle->data[offset++] = -1;
+ }
+ }
+ if (numInts > 0) {
+ jint* ints = env->GetIntArrayElements(intArray, 0);
+ for (int i = 0; i < numInts; i++) {
+ handle->data[offset++] = ints[i];
+ }
+ env->ReleaseIntArrayElements(intArray, ints, 0);
+ }
+
+ // doesn't take ownership of the native handle
+ return sSensorDevice->data_open(sSensorDevice, handle);
}
static jint
@@ -157,7 +182,7 @@ static JNINativeMethod gMethods[] = {
(void*)sensors_module_get_next_sensor },
{"sensors_data_init", "()I", (void*)sensors_data_init },
{"sensors_data_uninit", "()I", (void*)sensors_data_uninit },
- {"sensors_data_open", "(Ljava/io/FileDescriptor;)I", (void*)sensors_data_open },
+ {"sensors_data_open", "([Ljava/io/FileDescriptor;[I)I", (void*)sensors_data_open },
{"sensors_data_close", "()I", (void*)sensors_data_close },
{"sensors_data_poll", "([F[I[J)I", (void*)sensors_data_poll },
};
diff --git a/core/jni/android_location_GpsLocationProvider.cpp b/core/jni/android_location_GpsLocationProvider.cpp
index 004b0e3..bf0bd65 100644..100755
--- a/core/jni/android_location_GpsLocationProvider.cpp
+++ b/core/jni/android_location_GpsLocationProvider.cpp
@@ -176,7 +176,7 @@ static jboolean android_location_GpsLocationProvider_start(JNIEnv* env, jobject
{
int result = sGpsInterface->set_position_mode(positionMode, (singleFix ? 0 : fixFrequency));
if (result) {
- return result;
+ return false;
}
return (sGpsInterface->start() == 0);
@@ -270,6 +270,12 @@ static void android_location_GpsLocationProvider_inject_time(JNIEnv* env, jobjec
sGpsInterface->inject_time(time, timeReference, uncertainty);
}
+static void android_location_GpsLocationProvider_inject_location(JNIEnv* env, jobject obj,
+ jdouble latitude, jdouble longitude, jfloat accuracy)
+{
+ sGpsInterface->inject_location(latitude, longitude, accuracy);
+}
+
static jboolean android_location_GpsLocationProvider_supports_xtra(JNIEnv* env, jobject obj)
{
if (!sGpsXtraInterface) {
@@ -330,13 +336,15 @@ static void android_location_GpsLocationProvider_agps_data_conn_failed(JNIEnv* e
}
static void android_location_GpsLocationProvider_set_agps_server(JNIEnv* env, jobject obj,
- jint type, jint addr, jint port)
+ jint type, jstring hostname, jint port)
{
if (!sAGpsInterface) {
sAGpsInterface = (const AGpsInterface*)sGpsInterface->get_extension(AGPS_INTERFACE);
}
if (sAGpsInterface) {
- sAGpsInterface->set_server(type, addr, port);
+ const char *c_hostname = env->GetStringUTFChars(hostname, NULL);
+ sAGpsInterface->set_server(type, c_hostname, port);
+ env->ReleaseStringUTFChars(hostname, c_hostname);
}
}
@@ -353,12 +361,13 @@ static JNINativeMethod sMethods[] = {
{"native_wait_for_event", "()V", (void*)android_location_GpsLocationProvider_wait_for_event},
{"native_read_sv_status", "([I[F[F[F[I)I", (void*)android_location_GpsLocationProvider_read_sv_status},
{"native_inject_time", "(JJI)V", (void*)android_location_GpsLocationProvider_inject_time},
+ {"native_inject_location", "(DDF)V", (void*)android_location_GpsLocationProvider_inject_location},
{"native_supports_xtra", "()Z", (void*)android_location_GpsLocationProvider_supports_xtra},
{"native_inject_xtra_data", "([BI)V", (void*)android_location_GpsLocationProvider_inject_xtra_data},
{"native_agps_data_conn_open", "(Ljava/lang/String;)V", (void*)android_location_GpsLocationProvider_agps_data_conn_open},
{"native_agps_data_conn_closed", "()V", (void*)android_location_GpsLocationProvider_agps_data_conn_closed},
{"native_agps_data_conn_failed", "()V", (void*)android_location_GpsLocationProvider_agps_data_conn_failed},
- {"native_set_agps_server", "(III)V", (void*)android_location_GpsLocationProvider_set_agps_server},
+ {"native_set_agps_server", "(ILjava/lang/String;I)V", (void*)android_location_GpsLocationProvider_set_agps_server},
};
int register_android_location_GpsLocationProvider(JNIEnv* env)
diff --git a/core/jni/android_media_AudioRecord.cpp b/core/jni/android_media_AudioRecord.cpp
index 288433a..e71e348 100644
--- a/core/jni/android_media_AudioRecord.cpp
+++ b/core/jni/android_media_AudioRecord.cpp
@@ -45,8 +45,6 @@ struct fields_t {
jmethodID postNativeEventInJava; //... event post callback method
int PCM16; //... format constants
int PCM8; //... format constants
- int SOURCE_DEFAULT; //... record source constants
- int SOURCE_MIC; //... record source constants
jfieldID nativeRecorderInJavaObj; // provides access to the C++ AudioRecord object
jfieldID nativeCallbackCookie; // provides access to the AudioRecord callback data
};
@@ -66,7 +64,7 @@ struct audiorecord_callback_cookie {
#define AUDIORECORD_ERROR_SETUP_ZEROFRAMECOUNT -16
#define AUDIORECORD_ERROR_SETUP_INVALIDCHANNELCOUNT -17
#define AUDIORECORD_ERROR_SETUP_INVALIDFORMAT -18
-#define AUDIORECORD_ERROR_SETUP_INVALIDSTREAMTYPE -19
+#define AUDIORECORD_ERROR_SETUP_INVALIDSOURCE -19
#define AUDIORECORD_ERROR_SETUP_NATIVEINITFAILED -20
jint android_media_translateRecorderErrorCode(int code) {
@@ -154,17 +152,16 @@ android_media_AudioRecord_setup(JNIEnv *env, jobject thiz, jobject weak_this,
int frameSize = nbChannels * bytesPerSample;
size_t frameCount = buffSizeInBytes / frameSize;
- // compare the source against the Java constants
- AudioRecord::stream_type arSource;
- if (source == javaAudioRecordFields.SOURCE_DEFAULT) {
- arSource = AudioRecord::DEFAULT_INPUT;
- } else if (source == javaAudioRecordFields.SOURCE_MIC) {
- arSource = AudioRecord::MIC_INPUT;
- } else {
+ // convert and check input source value
+ // input_source values defined in AudioRecord.h are equal to
+ // JAVA MediaRecord.AudioSource values minus 1.
+ AudioRecord::input_source arSource = (AudioRecord::input_source)(source - 1);
+ if (arSource < AudioRecord::DEFAULT_INPUT ||
+ arSource >= AudioRecord::NUM_INPUT_SOURCES) {
LOGE("Error creating AudioRecord: unknown source.");
- return AUDIORECORD_ERROR_SETUP_INVALIDSTREAMTYPE;
+ return AUDIORECORD_ERROR_SETUP_INVALIDSOURCE;
}
-
+
audiorecord_callback_cookie *lpCallbackData = NULL;
AudioRecord* lpRecorder = NULL;
@@ -511,8 +508,6 @@ static JNINativeMethod gMethods[] = {
#define JAVA_POSTEVENT_CALLBACK_NAME "postEventFromNative"
#define JAVA_CONST_PCM16_NAME "ENCODING_PCM_16BIT"
#define JAVA_CONST_PCM8_NAME "ENCODING_PCM_8BIT"
-#define JAVA_CONST_SOURCEDEFAULT_NAME "SOURCE_DEFAULT"
-#define JAVA_CONST_SOURCEMIC_NAME "SOURCE_MIC"
#define JAVA_NATIVERECORDERINJAVAOBJ_FIELD_NAME "mNativeRecorderInJavaObj"
#define JAVA_NATIVECALLBACKINFO_FIELD_NAME "mNativeCallbackCookie"
@@ -583,17 +578,6 @@ int register_android_media_AudioRecord(JNIEnv *env)
return -1;
}
- // Get the recording source constants from the AudioRecord class
- if ( !android_media_getIntConstantFromClass(env, javaAudioRecordFields.audioRecordClass,
- kClassPathName,
- JAVA_CONST_SOURCEDEFAULT_NAME, &(javaAudioRecordFields.SOURCE_DEFAULT))
- || !android_media_getIntConstantFromClass(env, javaAudioRecordFields.audioRecordClass,
- kClassPathName,
- JAVA_CONST_SOURCEMIC_NAME, &(javaAudioRecordFields.SOURCE_MIC)) ) {
- // error log performed in getIntConstantFromClass()
- return -1;
- }
-
return AndroidRuntime::registerNativeMethods(env,
kClassPathName, gMethods, NELEM(gMethods));
}
diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp
index 42ada54..e7d4694 100644
--- a/core/jni/android_media_AudioTrack.cpp
+++ b/core/jni/android_media_AudioTrack.cpp
@@ -539,16 +539,17 @@ static jint android_media_AudioTrack_get_native_frame_count(JNIEnv *env, jobjec
// ----------------------------------------------------------------------------
-static void android_media_AudioTrack_set_playback_rate(JNIEnv *env, jobject thiz,
+static jint android_media_AudioTrack_set_playback_rate(JNIEnv *env, jobject thiz,
jint sampleRateInHz) {
AudioTrack *lpTrack = (AudioTrack *)env->GetIntField(
thiz, javaAudioTrackFields.nativeTrackInJavaObj);
if (lpTrack) {
- lpTrack->setSampleRate(sampleRateInHz);
+ return android_media_translateErrorCode(lpTrack->setSampleRate(sampleRateInHz));
} else {
jniThrowException(env, "java/lang/IllegalStateException",
"Unable to retrieve AudioTrack pointer for setSampleRate()");
+ return AUDIOTRACK_ERROR;
}
}
@@ -788,7 +789,7 @@ static JNINativeMethod gMethods[] = {
{"native_get_native_frame_count",
"()I", (void *)android_media_AudioTrack_get_native_frame_count},
{"native_set_playback_rate",
- "(I)V", (void *)android_media_AudioTrack_set_playback_rate},
+ "(I)I", (void *)android_media_AudioTrack_set_playback_rate},
{"native_get_playback_rate",
"()I", (void *)android_media_AudioTrack_get_playback_rate},
{"native_set_marker_pos","(I)I", (void *)android_media_AudioTrack_set_marker_pos},
diff --git a/core/jni/android_net_wifi_Wifi.cpp b/core/jni/android_net_wifi_Wifi.cpp
index 25670df..9f93e2f 100644
--- a/core/jni/android_net_wifi_Wifi.cpp
+++ b/core/jni/android_net_wifi_Wifi.cpp
@@ -317,8 +317,13 @@ static jint android_net_wifi_getRssiCommand(JNIEnv* env, jobject clazz)
}
// reply comes back in the form "<SSID> rssi XX" where XX is the
// number we're interested in. if we're associating, it returns "OK".
+ // beware - <SSID> can contain spaces.
if (strcmp(reply, "OK") != 0) {
- sscanf(reply, "%*s %*s %d", &rssi);
+ char* lastSpace = strrchr(reply, ' ');
+ // lastSpace should be preceded by "rssi" and followed by the value
+ if (lastSpace && !strncmp(lastSpace - 4, "rssi", 4)) {
+ sscanf(lastSpace + 1, "%d", &rssi);
+ }
}
return (jint)rssi;
}
diff --git a/core/jni/android_opengl_GLES10.cpp b/core/jni/android_opengl_GLES10.cpp
index 482d8eb..2685d75 100644
--- a/core/jni/android_opengl_GLES10.cpp
+++ b/core/jni/android_opengl_GLES10.cpp
@@ -133,6 +133,19 @@ releasePointer(JNIEnv *_env, jarray array, void *data, jboolean commit)
commit ? 0 : JNI_ABORT);
}
+static void *
+getDirectBufferPointer(JNIEnv *_env, jobject buffer) {
+ char* buf = (char*) _env->GetDirectBufferAddress(buffer);
+ if (buf) {
+ jint position = _env->GetIntField(buffer, positionID);
+ jint elementSizeShift = _env->GetIntField(buffer, elementSizeShiftID);
+ buf += position << elementSizeShift;
+ } else {
+ _env->ThrowNew(IAEClass, "Must use a native order direct Buffer");
+ }
+ return (void*) buf;
+}
+
static int
getNumCompressedTextureFormats() {
int numCompressedTextureFormats = 0;
@@ -305,9 +318,8 @@ android_glColorPointerBounds__IIILjava_nio_Buffer_2I
GLvoid *pointer = (GLvoid *) 0;
if (pointer_buf) {
- pointer = (GLvoid *) _env->GetDirectBufferAddress(pointer_buf);
+ pointer = (GLvoid *) getDirectBufferPointer(_env, pointer_buf);
if ( ! pointer ) {
- _env->ThrowNew(IAEClass, "Must use a native order direct Buffer");
return;
}
}
@@ -2779,9 +2791,8 @@ android_glNormalPointerBounds__IILjava_nio_Buffer_2I
GLvoid *pointer = (GLvoid *) 0;
if (pointer_buf) {
- pointer = (GLvoid *) _env->GetDirectBufferAddress(pointer_buf);
+ pointer = (GLvoid *) getDirectBufferPointer(_env, pointer_buf);
if ( ! pointer ) {
- _env->ThrowNew(IAEClass, "Must use a native order direct Buffer");
return;
}
}
@@ -3034,9 +3045,8 @@ android_glTexCoordPointerBounds__IIILjava_nio_Buffer_2I
GLvoid *pointer = (GLvoid *) 0;
if (pointer_buf) {
- pointer = (GLvoid *) _env->GetDirectBufferAddress(pointer_buf);
+ pointer = (GLvoid *) getDirectBufferPointer(_env, pointer_buf);
if ( ! pointer ) {
- _env->ThrowNew(IAEClass, "Must use a native order direct Buffer");
return;
}
}
@@ -3392,9 +3402,8 @@ android_glVertexPointerBounds__IIILjava_nio_Buffer_2I
GLvoid *pointer = (GLvoid *) 0;
if (pointer_buf) {
- pointer = (GLvoid *) _env->GetDirectBufferAddress(pointer_buf);
+ pointer = (GLvoid *) getDirectBufferPointer(_env, pointer_buf);
if ( ! pointer ) {
- _env->ThrowNew(IAEClass, "Must use a native order direct Buffer");
return;
}
}
diff --git a/core/jni/android_os_MemoryFile.cpp b/core/jni/android_os_MemoryFile.cpp
index edf7dc4..8643393 100644
--- a/core/jni/android_os_MemoryFile.cpp
+++ b/core/jni/android_os_MemoryFile.cpp
@@ -26,7 +26,7 @@
namespace android {
-static jint android_os_MemoryFile_open(JNIEnv* env, jobject clazz, jstring name, jint length)
+static jobject android_os_MemoryFile_open(JNIEnv* env, jobject clazz, jstring name, jint length)
{
const char* namestr = (name ? env->GetStringUTFChars(name, NULL) : NULL);
@@ -37,37 +37,52 @@ static jint android_os_MemoryFile_open(JNIEnv* env, jobject clazz, jstring name,
if (name)
env->ReleaseStringUTFChars(name, namestr);
- if (result < 0)
+ if (result < 0) {
jniThrowException(env, "java/io/IOException", "ashmem_create_region failed");
- return result;
+ return NULL;
+ }
+
+ return jniCreateFileDescriptor(env, result);
}
-static jint android_os_MemoryFile_mmap(JNIEnv* env, jobject clazz, jint fd, jint length)
+static jint android_os_MemoryFile_mmap(JNIEnv* env, jobject clazz, jobject fileDescriptor,
+ jint length, jint prot)
{
- jint result = (jint)mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
+ int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
+ jint result = (jint)mmap(NULL, length, prot, MAP_SHARED, fd, 0);
if (!result)
jniThrowException(env, "java/io/IOException", "mmap failed");
return result;
}
-static void android_os_MemoryFile_close(JNIEnv* env, jobject clazz, jint fd)
+static void android_os_MemoryFile_munmap(JNIEnv* env, jobject clazz, jint addr, jint length)
+{
+ int result = munmap((void *)addr, length);
+ if (result < 0)
+ jniThrowException(env, "java/io/IOException", "munmap failed");
+}
+
+static void android_os_MemoryFile_close(JNIEnv* env, jobject clazz, jobject fileDescriptor)
{
- close(fd);
+ int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
+ if (fd >= 0) {
+ jniSetFileDescriptorOfFD(env, fileDescriptor, -1);
+ close(fd);
+ }
}
static jint android_os_MemoryFile_read(JNIEnv* env, jobject clazz,
- jint fd, jint address, jbyteArray buffer, jint srcOffset, jint destOffset,
+ jobject fileDescriptor, jint address, jbyteArray buffer, jint srcOffset, jint destOffset,
jint count, jboolean unpinned)
{
+ int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
if (unpinned && ashmem_pin_region(fd, 0, 0) == ASHMEM_WAS_PURGED) {
ashmem_unpin_region(fd, 0, 0);
jniThrowException(env, "java/io/IOException", "ashmem region was purged");
return -1;
}
- jbyte* bytes = env->GetByteArrayElements(buffer, 0);
- memcpy(bytes + destOffset, (const char *)address + srcOffset, count);
- env->ReleaseByteArrayElements(buffer, bytes, 0);
+ env->SetByteArrayRegion(buffer, destOffset, count, (const jbyte *)address + srcOffset);
if (unpinned) {
ashmem_unpin_region(fd, 0, 0);
@@ -76,18 +91,17 @@ static jint android_os_MemoryFile_read(JNIEnv* env, jobject clazz,
}
static jint android_os_MemoryFile_write(JNIEnv* env, jobject clazz,
- jint fd, jint address, jbyteArray buffer, jint srcOffset, jint destOffset,
+ jobject fileDescriptor, jint address, jbyteArray buffer, jint srcOffset, jint destOffset,
jint count, jboolean unpinned)
{
+ int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
if (unpinned && ashmem_pin_region(fd, 0, 0) == ASHMEM_WAS_PURGED) {
ashmem_unpin_region(fd, 0, 0);
jniThrowException(env, "java/io/IOException", "ashmem region was purged");
return -1;
}
- jbyte* bytes = env->GetByteArrayElements(buffer, 0);
- memcpy((char *)address + destOffset, bytes + srcOffset, count);
- env->ReleaseByteArrayElements(buffer, bytes, 0);
+ env->GetByteArrayRegion(buffer, srcOffset, count, (jbyte *)address + destOffset);
if (unpinned) {
ashmem_unpin_region(fd, 0, 0);
@@ -95,21 +109,45 @@ static jint android_os_MemoryFile_write(JNIEnv* env, jobject clazz,
return count;
}
-static void android_os_MemoryFile_pin(JNIEnv* env, jobject clazz, jint fd, jboolean pin)
+static void android_os_MemoryFile_pin(JNIEnv* env, jobject clazz, jobject fileDescriptor, jboolean pin)
{
+ int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
int result = (pin ? ashmem_pin_region(fd, 0, 0) : ashmem_unpin_region(fd, 0, 0));
if (result < 0) {
jniThrowException(env, "java/io/IOException", NULL);
}
}
+static jboolean android_os_MemoryFile_is_ashmem_region(JNIEnv* env, jobject clazz,
+ jobject fileDescriptor) {
+ int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
+ // Use ASHMEM_GET_SIZE to find out if the fd refers to an ashmem region.
+ // ASHMEM_GET_SIZE should succeed for all ashmem regions, and the kernel
+ // should return ENOTTY for all other valid file descriptors
+ int result = ashmem_get_size_region(fd);
+ if (result < 0) {
+ if (errno == ENOTTY) {
+ // ENOTTY means that the ioctl does not apply to this object,
+ // i.e., it is not an ashmem region.
+ return JNI_FALSE;
+ }
+ // Some other error, throw exception
+ jniThrowIOException(env, errno);
+ return JNI_FALSE;
+ }
+ return JNI_TRUE;
+}
+
static const JNINativeMethod methods[] = {
- {"native_open", "(Ljava/lang/String;I)I", (void*)android_os_MemoryFile_open},
- {"native_mmap", "(II)I", (void*)android_os_MemoryFile_mmap},
- {"native_close", "(I)V", (void*)android_os_MemoryFile_close},
- {"native_read", "(II[BIIIZ)I", (void*)android_os_MemoryFile_read},
- {"native_write", "(II[BIIIZ)V", (void*)android_os_MemoryFile_write},
- {"native_pin", "(IZ)V", (void*)android_os_MemoryFile_pin},
+ {"native_open", "(Ljava/lang/String;I)Ljava/io/FileDescriptor;", (void*)android_os_MemoryFile_open},
+ {"native_mmap", "(Ljava/io/FileDescriptor;II)I", (void*)android_os_MemoryFile_mmap},
+ {"native_munmap", "(II)V", (void*)android_os_MemoryFile_munmap},
+ {"native_close", "(Ljava/io/FileDescriptor;)V", (void*)android_os_MemoryFile_close},
+ {"native_read", "(Ljava/io/FileDescriptor;I[BIIIZ)I", (void*)android_os_MemoryFile_read},
+ {"native_write", "(Ljava/io/FileDescriptor;I[BIIIZ)V", (void*)android_os_MemoryFile_write},
+ {"native_pin", "(Ljava/io/FileDescriptor;Z)V", (void*)android_os_MemoryFile_pin},
+ {"native_is_ashmem_region", "(Ljava/io/FileDescriptor;)Z",
+ (void*)android_os_MemoryFile_is_ashmem_region}
};
static const char* const kClassPathName = "android/os/MemoryFile";
diff --git a/core/jni/android_server_BluetoothA2dpService.cpp b/core/jni/android_server_BluetoothA2dpService.cpp
index fe94642..91a8e8e 100644
--- a/core/jni/android_server_BluetoothA2dpService.cpp
+++ b/core/jni/android_server_BluetoothA2dpService.cpp
@@ -84,6 +84,7 @@ static bool initNative(JNIEnv* env, jobject object) {
dbus_error_free(&err);
return false;
}
+ dbus_connection_set_exit_on_disconnect(nat->conn, FALSE);
#endif /*HAVE_BLUETOOTH*/
return true;
}
diff --git a/core/jni/android_server_BluetoothDeviceService.cpp b/core/jni/android_server_BluetoothDeviceService.cpp
index b6e9798..58ae4f6 100644
--- a/core/jni/android_server_BluetoothDeviceService.cpp
+++ b/core/jni/android_server_BluetoothDeviceService.cpp
@@ -109,6 +109,7 @@ static bool initializeNativeDataNative(JNIEnv* env, jobject object) {
dbus_error_free(&err);
return false;
}
+ dbus_connection_set_exit_on_disconnect(nat->conn, FALSE);
nat->adapter = BLUEZ_ADAPTER_OBJECT_NAME;
#endif /*HAVE_BLUETOOTH*/
diff --git a/core/jni/android_server_BluetoothEventLoop.cpp b/core/jni/android_server_BluetoothEventLoop.cpp
index 7c5da5b..ad24136 100644
--- a/core/jni/android_server_BluetoothEventLoop.cpp
+++ b/core/jni/android_server_BluetoothEventLoop.cpp
@@ -132,6 +132,7 @@ static void initializeNativeDataNative(JNIEnv* env, jobject object) {
LOGE("%s: Could not get onto the system bus!", __FUNCTION__);
dbus_error_free(&err);
}
+ dbus_connection_set_exit_on_disconnect(nat->conn, FALSE);
}
#endif
}
@@ -161,6 +162,19 @@ static const DBusObjectPathVTable agent_vtable = {
NULL, agent_event_filter, NULL, NULL, NULL, NULL
};
+static unsigned int unix_events_to_dbus_flags(short events) {
+ return (events & DBUS_WATCH_READABLE ? POLLIN : 0) |
+ (events & DBUS_WATCH_WRITABLE ? POLLOUT : 0) |
+ (events & DBUS_WATCH_ERROR ? POLLERR : 0) |
+ (events & DBUS_WATCH_HANGUP ? POLLHUP : 0);
+}
+
+static short dbus_flags_to_unix_events(unsigned int flags) {
+ return (flags & POLLIN ? DBUS_WATCH_READABLE : 0) |
+ (flags & POLLOUT ? DBUS_WATCH_WRITABLE : 0) |
+ (flags & POLLERR ? DBUS_WATCH_ERROR : 0) |
+ (flags & POLLHUP ? DBUS_WATCH_HANGUP : 0);
+}
static jboolean setUpEventLoop(native_data_t *nat) {
LOGV(__FUNCTION__);
@@ -384,8 +398,7 @@ static void handleWatchAdd(native_data_t *nat) {
read(nat->controlFdR, &newFD, sizeof(int));
read(nat->controlFdR, &flags, sizeof(unsigned int));
read(nat->controlFdR, &watch, sizeof(DBusWatch *));
- int events = (flags & DBUS_WATCH_READABLE ? POLLIN : 0)
- | (flags & DBUS_WATCH_WRITABLE ? POLLOUT : 0);
+ short events = dbus_flags_to_unix_events(flags);
for (int y = 0; y<nat->pollMemberCount; y++) {
if ((nat->pollData[y].fd == newFD) &&
@@ -429,8 +442,7 @@ static void handleWatchRemove(native_data_t *nat) {
read(nat->controlFdR, &removeFD, sizeof(int));
read(nat->controlFdR, &flags, sizeof(unsigned int));
- int events = (flags & DBUS_WATCH_READABLE ? POLLIN : 0)
- | (flags & DBUS_WATCH_WRITABLE ? POLLOUT : 0);
+ short events = dbus_flags_to_unix_events(flags);
for (int y = 0; y < nat->pollMemberCount; y++) {
if ((nat->pollData[y].fd == removeFD) &&
@@ -494,13 +506,12 @@ static void *eventLoopMain(void *ptr) {
}
}
} else {
- int event = nat->pollData[i].revents;
- int flags = (event & POLLIN ? DBUS_WATCH_READABLE : 0) |
- (event & POLLOUT ? DBUS_WATCH_WRITABLE : 0);
- dbus_watch_handle(nat->watchData[i], event);
- nat->pollData[i].revents = 0;
- // can only do one - it may have caused a 'remove'
- break;
+ short events = nat->pollData[i].revents;
+ unsigned int flags = unix_events_to_dbus_flags(events);
+ dbus_watch_handle(nat->watchData[i], flags);
+ nat->pollData[i].revents = 0;
+ // can only do one - it may have caused a 'remove'
+ break;
}
}
while (dbus_connection_dispatch(nat->conn) ==
diff --git a/core/jni/android_text_format_Time.cpp b/core/jni/android_text_format_Time.cpp
index 923e1aa..98f4e03 100644
--- a/core/jni/android_text_format_Time.cpp
+++ b/core/jni/android_text_format_Time.cpp
@@ -23,7 +23,7 @@
#include "jni.h"
#include "utils/misc.h"
#include "android_runtime/AndroidRuntime.h"
-#include <utils/TimeUtils.h>
+#include "TimeUtils.h"
#include <nativehelper/JNIHelp.h>
#include <cutils/tztime.h>
@@ -44,6 +44,7 @@ static jfieldID g_timezoneField = 0;
static jfieldID g_shortMonthsField = 0;
static jfieldID g_longMonthsField = 0;
+static jfieldID g_longStandaloneMonthsField = 0;
static jfieldID g_shortWeekdaysField = 0;
static jfieldID g_longWeekdaysField = 0;
static jfieldID g_timeOnlyFormatField = 0;
@@ -193,6 +194,7 @@ static jstring android_text_format_Time_format(JNIEnv* env, jobject This,
static jobject js_locale_previous = NULL;
static struct strftime_locale locale;
static jstring js_mon[12], js_month[12], js_wday[7], js_weekday[7];
+ static jstring js_standalone_month[12];
static jstring js_X_fmt, js_x_fmt, js_c_fmt, js_am, js_pm, js_date_fmt;
Time t;
@@ -206,8 +208,10 @@ static jstring android_text_format_Time_format(JNIEnv* env, jobject This,
for (int i = 0; i < 12; i++) {
env->ReleaseStringUTFChars(js_mon[i], locale.mon[i]);
env->ReleaseStringUTFChars(js_month[i], locale.month[i]);
+ env->ReleaseStringUTFChars(js_standalone_month[i], locale.standalone_month[i]);
env->DeleteGlobalRef(js_mon[i]);
env->DeleteGlobalRef(js_month[i]);
+ env->DeleteGlobalRef(js_standalone_month[i]);
}
for (int i = 0; i < 7; i++) {
@@ -245,6 +249,12 @@ static jstring android_text_format_Time_format(JNIEnv* env, jobject This,
locale.month[i] = env->GetStringUTFChars(js_month[i], NULL);
}
+ ja = (jobjectArray) env->GetStaticObjectField(timeClass, g_longStandaloneMonthsField);
+ for (int i = 0; i < 12; i++) {
+ js_standalone_month[i] = (jstring) env->NewGlobalRef(env->GetObjectArrayElement(ja, i));
+ locale.standalone_month[i] = env->GetStringUTFChars(js_standalone_month[i], NULL);
+ }
+
ja = (jobjectArray) env->GetStaticObjectField(timeClass, g_shortWeekdaysField);
for (int i = 0; i < 7; i++) {
js_wday[i] = (jstring) env->NewGlobalRef(env->GetObjectArrayElement(ja, i));
@@ -639,6 +649,7 @@ int register_android_text_format_Time(JNIEnv* env)
g_shortMonthsField = env->GetStaticFieldID(timeClass, "sShortMonths", "[Ljava/lang/String;");
g_longMonthsField = env->GetStaticFieldID(timeClass, "sLongMonths", "[Ljava/lang/String;");
+ g_longStandaloneMonthsField = env->GetStaticFieldID(timeClass, "sLongStandaloneMonths", "[Ljava/lang/String;");
g_shortWeekdaysField = env->GetStaticFieldID(timeClass, "sShortWeekdays", "[Ljava/lang/String;");
g_longWeekdaysField = env->GetStaticFieldID(timeClass, "sLongWeekdays", "[Ljava/lang/String;");
g_timeOnlyFormatField = env->GetStaticFieldID(timeClass, "sTimeOnlyFormat", "Ljava/lang/String;");
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index d147bcc..2d90ba4 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -535,7 +535,7 @@ static void android_content_AssetManager_setConfiguration(JNIEnv* env, jobject c
jint keyboard, jint keyboardHidden,
jint navigation,
jint screenWidth, jint screenHeight,
- jint sdkVersion)
+ jint screenLayout, jint sdkVersion)
{
AssetManager* am = assetManagerForJavaObject(env, clazz);
if (am == NULL) {
@@ -557,6 +557,7 @@ static void android_content_AssetManager_setConfiguration(JNIEnv* env, jobject c
config.navigation = (uint8_t)navigation;
config.screenWidth = (uint16_t)screenWidth;
config.screenHeight = (uint16_t)screenHeight;
+ config.screenLayout = (uint8_t)screenLayout;
config.sdkVersion = (uint16_t)sdkVersion;
config.minorVersion = 0;
am->setConfiguration(config, locale8);
@@ -1567,7 +1568,7 @@ static JNINativeMethod gAssetManagerMethods[] = {
(void*) android_content_AssetManager_setLocale },
{ "getLocales", "()[Ljava/lang/String;",
(void*) android_content_AssetManager_getLocales },
- { "setConfiguration", "(IILjava/lang/String;IIIIIIIII)V",
+ { "setConfiguration", "(IILjava/lang/String;IIIIIIIIII)V",
(void*) android_content_AssetManager_setConfiguration },
{ "getResourceIdentifier","(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",
(void*) android_content_AssetManager_getResourceIdentifier },
diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp
index d760feb..aee0ed7 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -50,8 +50,6 @@ pid_t gettid() { return syscall(__NR_gettid);}
#undef __KERNEL__
#endif
-#define ENABLE_CGROUP_ERR_LOGGING 0
-
/*
* List of cgroup names which map to ANDROID_TGROUP_ values in Thread.h
* and Process.java
@@ -198,50 +196,82 @@ jint android_os_Process_getGidForName(JNIEnv* env, jobject clazz, jstring name)
static int add_pid_to_cgroup(int pid, int grp)
{
- FILE *fp;
+ int fd;
char path[255];
- int rc;
+ char text[64];
- sprintf(path, "/dev/cpuctl/%s/tasks", (cgroup_names[grp] ? cgroup_names[grp] : ""));
+ sprintf(path, "/dev/cpuctl/%s/tasks",
+ (cgroup_names[grp] ? cgroup_names[grp] : ""));
- if (!(fp = fopen(path, "w"))) {
-#if ENABLE_CGROUP_ERR_LOGGING
- LOGW("Unable to open %s (%s)\n", path, strerror(errno));
-#endif
- return -errno;
+ if ((fd = open(path, O_WRONLY)) < 0)
+ return -1;
+
+ sprintf(text, "%d", pid);
+ if (write(fd, text, strlen(text)) < 0) {
+ close(fd);
+ return -1;
}
- rc = fprintf(fp, "%d", pid);
- fclose(fp);
+ close(fd);
+ return 0;
+}
- if (rc < 0) {
-#if ENABLE_CGROUP_ERR_LOGGING
- LOGW("Unable to move pid %d to cgroup %s (%s)\n", pid,
- (cgroup_names[grp] ? cgroup_names[grp] : "<default>"),
- strerror(errno));
-#endif
+void android_os_Process_setThreadGroup(JNIEnv* env, jobject clazz, int pid, jint grp)
+{
+ if (grp > ANDROID_TGROUP_MAX || grp < 0) {
+ signalExceptionForGroupError(env, clazz, EINVAL);
+ return;
}
- return (rc < 0) ? errno : 0;
+ if (add_pid_to_cgroup(pid, grp)) {
+ // If the thread exited on us, don't generate an exception
+ if (errno != ESRCH && errno != ENOENT)
+ signalExceptionForGroupError(env, clazz, errno);
+ }
}
-void android_os_Process_setThreadGroup(JNIEnv* env, jobject clazz, int pid, jint grp)
+void android_os_Process_setProcessGroup(JNIEnv* env, jobject clazz, int pid, jint grp)
{
+ DIR *d;
+ FILE *fp;
+ char proc_path[255];
+ struct dirent *de;
+
if (grp > ANDROID_TGROUP_MAX || grp < 0) {
signalExceptionForGroupError(env, clazz, EINVAL);
return;
}
- if (add_pid_to_cgroup(pid, grp))
- signalExceptionForGroupError(env, clazz, errno);
+ sprintf(proc_path, "/proc/%d/task", pid);
+ if (!(d = opendir(proc_path))) {
+ // If the process exited on us, don't generate an exception
+ if (errno != ENOENT)
+ signalExceptionForGroupError(env, clazz, errno);
+ return;
+ }
+
+ while ((de = readdir(d))) {
+ if (de->d_name[0] == '.')
+ continue;
+
+ if (add_pid_to_cgroup(atoi(de->d_name), grp)) {
+ // If the thread exited on us, ignore it and keep going
+ if (errno != ESRCH && errno != ENOENT) {
+ signalExceptionForGroupError(env, clazz, errno);
+ closedir(d);
+ return;
+ }
+ }
+ }
+ closedir(d);
}
void android_os_Process_setThreadPriority(JNIEnv* env, jobject clazz,
jint pid, jint pri)
{
- if (pri == ANDROID_PRIORITY_BACKGROUND) {
+ if (pri >= ANDROID_PRIORITY_BACKGROUND) {
add_pid_to_cgroup(pid, ANDROID_TGROUP_BG_NONINTERACT);
- } else if (getpriority(PRIO_PROCESS, pid) == ANDROID_PRIORITY_BACKGROUND) {
+ } else if (getpriority(PRIO_PROCESS, pid) >= ANDROID_PRIORITY_BACKGROUND) {
add_pid_to_cgroup(pid, ANDROID_TGROUP_DEFAULT);
}
@@ -466,7 +496,7 @@ void android_os_Process_readProcLines(JNIEnv* env, jobject clazz, jstring fileSt
const String8& field = fields[i];
if (strncmp(p, field.string(), field.length()) == 0) {
p += field.length();
- while (*p == ' ') p++;
+ while (*p == ' ' || *p == '\t') p++;
char* num = p;
while (*p >= '0' && *p <= '9') p++;
skipToEol = *p != '\n';
@@ -820,6 +850,7 @@ static const JNINativeMethod methods[] = {
{"setThreadPriority", "(I)V", (void*)android_os_Process_setCallingThreadPriority},
{"getThreadPriority", "(I)I", (void*)android_os_Process_getThreadPriority},
{"setThreadGroup", "(II)V", (void*)android_os_Process_setThreadGroup},
+ {"setProcessGroup", "(II)V", (void*)android_os_Process_setProcessGroup},
{"setOomAdj", "(II)Z", (void*)android_os_Process_setOomAdj},
{"setArgV0", "(Ljava/lang/String;)V", (void*)android_os_Process_setArgV0},
{"setUid", "(I)I", (void*)android_os_Process_setUid},
diff --git a/core/jni/com_google_android_gles_jni_GLImpl.cpp b/core/jni/com_google_android_gles_jni_GLImpl.cpp
index 11822e0..89b1f96 100644
--- a/core/jni/com_google_android_gles_jni_GLImpl.cpp
+++ b/core/jni/com_google_android_gles_jni_GLImpl.cpp
@@ -45,9 +45,11 @@ static jclass OOMEClass;
static jclass UOEClass;
static jclass IAEClass;
static jclass AIOOBEClass;
+static jclass G11ImplClass;
static jmethodID getBasePointerID;
static jmethodID getBaseArrayID;
static jmethodID getBaseArrayOffsetID;
+static jmethodID allowIndirectBuffersID;
static jfieldID positionID;
static jfieldID limitID;
static jfieldID elementSizeShiftID;
@@ -63,13 +65,17 @@ nativeClassInitBuffer(JNIEnv *_env)
jclass bufferClassLocal = _env->FindClass("java/nio/Buffer");
bufferClass = (jclass) _env->NewGlobalRef(bufferClassLocal);
+ jclass g11impClassLocal = _env->FindClass("com/google/android/gles_jni/GLImpl");
+ G11ImplClass = (jclass) _env->NewGlobalRef(g11impClassLocal);
+
getBasePointerID = _env->GetStaticMethodID(nioAccessClass,
"getBasePointer", "(Ljava/nio/Buffer;)J");
getBaseArrayID = _env->GetStaticMethodID(nioAccessClass,
"getBaseArray", "(Ljava/nio/Buffer;)Ljava/lang/Object;");
getBaseArrayOffsetID = _env->GetStaticMethodID(nioAccessClass,
"getBaseArrayOffset", "(Ljava/nio/Buffer;)I");
-
+ allowIndirectBuffersID = _env->GetStaticMethodID(g11impClassLocal,
+ "allowIndirectBuffers", "(Ljava/lang/String;)Z");
positionID = _env->GetFieldID(bufferClass, "position", "I");
limitID = _env->GetFieldID(bufferClass, "limit", "I");
elementSizeShiftID =
@@ -119,6 +125,9 @@ getPointer(JNIEnv *_env, jobject buffer, jarray *array, jint *remaining)
*array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
getBaseArrayID, buffer);
+ if (*array == NULL) {
+ return (void*) NULL;
+ }
offset = _env->CallStaticIntMethod(nioAccessClass,
getBaseArrayOffsetID, buffer);
data = _env->GetPrimitiveArrayCritical(*array, (jboolean *) 0);
@@ -133,6 +142,45 @@ releasePointer(JNIEnv *_env, jarray array, void *data, jboolean commit)
commit ? 0 : JNI_ABORT);
}
+extern "C" {
+extern char* __progname;
+}
+
+static bool
+allowIndirectBuffers(JNIEnv *_env) {
+ static jint sIndirectBufferCompatability;
+ if (sIndirectBufferCompatability == 0) {
+ jobject appName = _env->NewStringUTF(::__progname);
+ sIndirectBufferCompatability = _env->CallStaticBooleanMethod(G11ImplClass, allowIndirectBuffersID, appName) ? 2 : 1;
+ }
+ return sIndirectBufferCompatability == 2;
+}
+
+static void *
+getDirectBufferPointer(JNIEnv *_env, jobject buffer) {
+ if (!buffer) {
+ return NULL;
+ }
+ void* buf = _env->GetDirectBufferAddress(buffer);
+ if (buf) {
+ jint position = _env->GetIntField(buffer, positionID);
+ jint elementSizeShift = _env->GetIntField(buffer, elementSizeShiftID);
+ buf = ((char*) buf) + (position << elementSizeShift);
+ } else {
+ if (allowIndirectBuffers(_env)) {
+ jarray array = 0;
+ jint remaining;
+ buf = getPointer(_env, buffer, &array, &remaining);
+ if (array) {
+ releasePointer(_env, array, buf, 0);
+ }
+ } else {
+ _env->ThrowNew(IAEClass, "Must use a native order direct Buffer");
+ }
+ }
+ return buf;
+}
+
static int
getNumCompressedTextureFormats() {
int numCompressedTextureFormats = 0;
@@ -305,9 +353,8 @@ android_glColorPointerBounds__IIILjava_nio_Buffer_2I
GLvoid *pointer = (GLvoid *) 0;
if (pointer_buf) {
- pointer = (GLvoid *) _env->GetDirectBufferAddress(pointer_buf);
+ pointer = (GLvoid *) getDirectBufferPointer(_env, pointer_buf);
if ( ! pointer ) {
- _env->ThrowNew(IAEClass, "Must use a native order direct Buffer");
return;
}
}
@@ -2779,9 +2826,8 @@ android_glNormalPointerBounds__IILjava_nio_Buffer_2I
GLvoid *pointer = (GLvoid *) 0;
if (pointer_buf) {
- pointer = (GLvoid *) _env->GetDirectBufferAddress(pointer_buf);
+ pointer = (GLvoid *) getDirectBufferPointer(_env, pointer_buf);
if ( ! pointer ) {
- _env->ThrowNew(IAEClass, "Must use a native order direct Buffer");
return;
}
}
@@ -3034,9 +3080,8 @@ android_glTexCoordPointerBounds__IIILjava_nio_Buffer_2I
GLvoid *pointer = (GLvoid *) 0;
if (pointer_buf) {
- pointer = (GLvoid *) _env->GetDirectBufferAddress(pointer_buf);
+ pointer = (GLvoid *) getDirectBufferPointer(_env, pointer_buf);
if ( ! pointer ) {
- _env->ThrowNew(IAEClass, "Must use a native order direct Buffer");
return;
}
}
@@ -3392,9 +3437,8 @@ android_glVertexPointerBounds__IIILjava_nio_Buffer_2I
GLvoid *pointer = (GLvoid *) 0;
if (pointer_buf) {
- pointer = (GLvoid *) _env->GetDirectBufferAddress(pointer_buf);
+ pointer = (GLvoid *) getDirectBufferPointer(_env, pointer_buf);
if ( ! pointer ) {
- _env->ThrowNew(IAEClass, "Must use a native order direct Buffer");
return;
}
}