diff options
author | Mathias Agopian <mathias@google.com> | 2009-07-01 18:33:18 -0700 |
---|---|---|
committer | Mathias Agopian <mathias@google.com> | 2009-07-01 18:33:18 -0700 |
commit | dfe983bd7979ccb1602f29b8f9804c98411d9cd6 (patch) | |
tree | 8a5547078b72cb262e54f0640dd4ed746b5805ef /core/jni | |
parent | 3a6b160a3b52cd96fb383d5ee93c22e5e938e0e2 (diff) | |
parent | 7f32b426cd6a865ac5e6e3e9fa833e9327fb415a (diff) | |
download | frameworks_base-dfe983bd7979ccb1602f29b8f9804c98411d9cd6.zip frameworks_base-dfe983bd7979ccb1602f29b8f9804c98411d9cd6.tar.gz frameworks_base-dfe983bd7979ccb1602f29b8f9804c98411d9cd6.tar.bz2 |
Merge commit 'goog/master' into merge_master
Diffstat (limited to 'core/jni')
-rw-r--r-- | core/jni/Android.mk | 4 | ||||
-rw-r--r-- | core/jni/AndroidRuntime.cpp | 2 | ||||
-rw-r--r-- | core/jni/Time.cpp | 199 | ||||
-rw-r--r-- | core/jni/TimeUtils.h | 89 | ||||
-rw-r--r-- | core/jni/android_backup_BackupHelperDispatcher.cpp | 259 | ||||
-rw-r--r-- | core/jni/android_bluetooth_common.cpp | 380 | ||||
-rw-r--r-- | core/jni/android_hardware_Camera.cpp | 57 | ||||
-rw-r--r-- | core/jni/android_text_format_Time.cpp | 2 | ||||
-rw-r--r-- | core/jni/android_util_AssetManager.cpp | 5 | ||||
-rw-r--r-- | core/jni/android_util_Process.cpp | 6 |
10 files changed, 745 insertions, 258 deletions
diff --git a/core/jni/Android.mk b/core/jni/Android.mk index b5d3b26..e99971a 100644 --- a/core/jni/Android.mk +++ b/core/jni/Android.mk @@ -25,6 +25,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 \ @@ -123,7 +124,8 @@ LOCAL_SRC_FILES:= \ com_android_internal_graphics_NativeUtils.cpp \ android_backup_BackupDataInput.cpp \ android_backup_BackupDataOutput.cpp \ - android_backup_FileBackupHelperBase.cpp + android_backup_FileBackupHelperBase.cpp \ + android_backup_BackupHelperDispatcher.cpp LOCAL_C_INCLUDES += \ $(JNI_H_INCLUDE) \ diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index f8a4df0..c322b17 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -156,6 +156,7 @@ extern int register_android_location_GpsLocationProvider(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; @@ -1241,6 +1242,7 @@ static const RegJNIRec gRegJNI[] = { 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_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_bluetooth_common.cpp b/core/jni/android_bluetooth_common.cpp index 8361212..343fa53 100644 --- a/core/jni/android_bluetooth_common.cpp +++ b/core/jni/android_bluetooth_common.cpp @@ -67,6 +67,11 @@ static Properties adapter_properties[] = { {"Devices", DBUS_TYPE_ARRAY}, }; +typedef union { + char *str_val; + int int_val; + char **array_val; +} property_value; jfieldID get_field(JNIEnv *env, jclass clazz, const char *member, const char *mtype) { @@ -466,258 +471,217 @@ void append_variant(DBusMessageIter *iter, int type, void *val) dbus_message_iter_close_container(iter, &value_iter); } - -//TODO(): Remove code duplication between parse_properties and -//parse_property_change -jobjectArray parse_properties(JNIEnv *env, DBusMessageIter *iter, Properties *properties, - const int max_num_properties) { - DBusMessageIter dict_entry, dict, prop_val, device_val, array_val_iter; - jobjectArray strArray = NULL; - char * property; - char values[max_num_properties][256]; - char **uuid_array = NULL; - char **device_path = NULL; - char **array_elements = NULL; - char *string_val; - uint32_t int_val, bool_val; - int i, j, k, type, array_type, num_array_elements = 0; - int ret, num_properties = 0, num_uuids = 0, num_devices = 0; - - - jclass stringClass = env->FindClass("java/lang/String"); - DBusError err; - dbus_error_init(&err); - - for (i = 0; i < max_num_properties; i++) - memset(values[i], '\0', 128 * sizeof(char)); - - if(dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY) - goto failure; - dbus_message_iter_recurse(iter, &dict); - do { - if (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_DICT_ENTRY) - goto failure; - dbus_message_iter_recurse(&dict, &dict_entry); - if (dbus_message_iter_get_arg_type(&dict_entry) != DBUS_TYPE_STRING) - goto failure; - dbus_message_iter_get_basic(&dict_entry, &property); - if (!dbus_message_iter_next(&dict_entry)) - goto failure; - if (dbus_message_iter_get_arg_type(&dict_entry) != DBUS_TYPE_VARIANT) - goto failure; - - for (i = 0; i < max_num_properties; i++) { - if (!strncmp(properties[i].name, property, strlen(property))) { - num_properties ++; - break; - } - } - if (i == max_num_properties) - goto failure; - - type = properties[i].type; - dbus_message_iter_recurse(&dict_entry, &prop_val); - if(dbus_message_iter_get_arg_type(&prop_val) != type) { - LOGE("Property type mismatch in parse_properties: %d, expected:%d", - dbus_message_iter_get_arg_type(&prop_val), type); - goto failure; - } - - switch(type) { - case DBUS_TYPE_STRING: - case DBUS_TYPE_OBJECT_PATH: - dbus_message_iter_get_basic(&prop_val, &string_val); - strcpy(values[i], string_val); - break; - case DBUS_TYPE_UINT32: - case DBUS_TYPE_INT16: - dbus_message_iter_get_basic(&prop_val, &int_val); - sprintf(values[i], "%d", int_val); - break; - case DBUS_TYPE_BOOLEAN: - dbus_message_iter_get_basic(&prop_val, &bool_val); - sprintf(values[i], "%s", bool_val ? "true" : "false"); - break; - case DBUS_TYPE_ARRAY: - dbus_message_iter_recurse(&prop_val, &array_val_iter); - array_type = dbus_message_iter_get_arg_type(&array_val_iter); - num_array_elements = 0; - if (array_type == DBUS_TYPE_OBJECT_PATH || - array_type == DBUS_TYPE_STRING){ - do { - num_array_elements++; - } while(dbus_message_iter_next(&array_val_iter)); - dbus_message_iter_recurse(&prop_val, &array_val_iter); - // Allocate an array - array_elements = (char **)malloc(sizeof(char *) * - num_array_elements); - if (!array_elements) - goto failure; - - j = 0; - do { - dbus_message_iter_get_basic(&array_val_iter, &array_elements[j]); - j++; - } while(dbus_message_iter_next(&array_val_iter)); - if (!strncmp(property, "UUIDs", strlen("UUIDs"))) { - num_uuids = num_array_elements; - uuid_array = array_elements; - } else { - num_devices = num_array_elements; - device_path = array_elements; - } - } - break; - default: - goto failure; - } - } while(dbus_message_iter_next(&dict)); - - // Convert it to a array of strings. - strArray = env->NewObjectArray((num_properties + num_array_elements) * 2, - stringClass, NULL); - - j = 0; - for (i = 0; i < max_num_properties; i++) { - if (properties[i].type == DBUS_TYPE_ARRAY) { - if (!strncmp(properties[i].name, "UUIDs", strlen("UUIDs"))) { - num_array_elements = num_uuids; - array_elements = uuid_array; - } else { - num_array_elements = num_devices; - array_elements = device_path; - } - - for (k = 0; k < num_array_elements; k++) { - set_object_array_element(env, strArray, properties[i].name, j++); - set_object_array_element(env, strArray, array_elements[k], j++); - } - } else if (values[i][0] != '\0') { - set_object_array_element(env, strArray, properties[i].name, j++); - set_object_array_element(env, strArray, values[i], j++); - } - } - - if (uuid_array) - free(uuid_array); - if (device_path) - free(device_path); - return strArray; - -failure: - if (dbus_error_is_set(&err)) - LOG_AND_FREE_DBUS_ERROR(&err); - if (uuid_array) - free(uuid_array); - if (device_path) - free(device_path); - return NULL; -} - -jobjectArray create_prop_array(JNIEnv *env, Properties *properties, - int prop_index, void *value, int len ) { - jclass stringClass= env->FindClass("java/lang/String"); - char **prop_val = NULL; - char buf[32] = {'\0'}; - int i, j; - - jobjectArray strArray = env->NewObjectArray(1 + len, stringClass, NULL); - j = 0; - set_object_array_element(env, strArray, properties[prop_index].name, j++); - - if (properties[prop_index].type == DBUS_TYPE_UINT32) { - sprintf(buf, "%d", *(int *) value); - set_object_array_element(env, strArray, buf, j++); - } else if (properties[prop_index].type == DBUS_TYPE_BOOLEAN) { - sprintf(buf, "%s", *(int *) value ? "true" : "false"); - set_object_array_element(env, strArray, buf, j++); - } else if (properties[prop_index].type == DBUS_TYPE_ARRAY) { - prop_val = (char **) value; - for (i = 0; i < len; i++) - set_object_array_element(env, strArray, prop_val[i], j++); - } else { - set_object_array_element(env, strArray, (const char *) value, j++); - } - if (prop_val) - free (prop_val); - return strArray; -} - -jobjectArray parse_property_change(JNIEnv *env, DBusMessage *msg, - Properties *properties, int max_num_properties) { - DBusMessageIter iter, prop_val, array_val_iter; - DBusError err; - void *value; - char *property; +int get_property(DBusMessageIter iter, Properties *properties, + int max_num_properties, int *prop_index, property_value *value, int *len) { + DBusMessageIter prop_val, array_val_iter; + char *property = NULL; uint32_t array_type; - int i, j, type, len, prop_index; + char *str_val; + int i, j, type, int_val; - dbus_error_init(&err); - if (!dbus_message_iter_init(msg, &iter)) - goto failure; if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) - goto failure; + return -1; dbus_message_iter_get_basic(&iter, &property); if (!dbus_message_iter_next(&iter)) - goto failure; + return -1; if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) - goto failure; + return -1; for (i = 0; i < max_num_properties; i++) { - if (!strncmp(property, properties[i].name, strlen(properties[i].name))) + if (!strncmp(property, properties[i].name, strlen(property))) break; } - prop_index = i; + *prop_index = i; if (i == max_num_properties) - goto failure; + return -1; dbus_message_iter_recurse(&iter, &prop_val); - type = properties[prop_index].type; + type = properties[*prop_index].type; if (dbus_message_iter_get_arg_type(&prop_val) != type) { - LOGE("Property type mismatch in parse_properties: %d, expected:%d", - dbus_message_iter_get_arg_type(&prop_val), type); - goto failure; + LOGE("Property type mismatch in get_property: %d, expected:%d, index:%d", + dbus_message_iter_get_arg_type(&prop_val), type, *prop_index); + return -1; } switch(type) { case DBUS_TYPE_STRING: case DBUS_TYPE_OBJECT_PATH: - dbus_message_iter_get_basic(&prop_val, &value); - len = 1; + dbus_message_iter_get_basic(&prop_val, &value->str_val); + *len = 1; break; case DBUS_TYPE_UINT32: case DBUS_TYPE_INT16: case DBUS_TYPE_BOOLEAN: - uint32_t int_val; dbus_message_iter_get_basic(&prop_val, &int_val); - value = &int_val; - len = 1; + value->int_val = int_val; + *len = 1; break; case DBUS_TYPE_ARRAY: dbus_message_iter_recurse(&prop_val, &array_val_iter); array_type = dbus_message_iter_get_arg_type(&array_val_iter); - len = 0; + *len = 0; + value->array_val = NULL; if (array_type == DBUS_TYPE_OBJECT_PATH || array_type == DBUS_TYPE_STRING){ + j = 0; do { - len ++; + j ++; } while(dbus_message_iter_next(&array_val_iter)); dbus_message_iter_recurse(&prop_val, &array_val_iter); // Allocate an array of char * - char **tmp = (char **)malloc(sizeof(char *) * len); + *len = j; + char **tmp = (char **)malloc(sizeof(char *) * *len); if (!tmp) - goto failure; + return -1; j = 0; do { dbus_message_iter_get_basic(&array_val_iter, &tmp[j]); j ++; } while(dbus_message_iter_next(&array_val_iter)); - value = (char **) tmp; + value->array_val = tmp; } break; default: + return -1; + } + return 0; +} + +void create_prop_array(JNIEnv *env, jobjectArray strArray, Properties *property, + property_value *value, int len, int *array_index ) { + char **prop_val = NULL; + char buf[32] = {'\0'}, buf1[32] = {'\0'}; + int i; + + char *name = property->name; + int prop_type = property->type; + + set_object_array_element(env, strArray, name, *array_index); + *array_index += 1; + + if (prop_type == DBUS_TYPE_UINT32 || prop_type == DBUS_TYPE_INT16) { + sprintf(buf, "%d", value->int_val); + set_object_array_element(env, strArray, buf, *array_index); + *array_index += 1; + } else if (prop_type == DBUS_TYPE_BOOLEAN) { + sprintf(buf, "%s", value->int_val ? "true" : "false"); + + set_object_array_element(env, strArray, buf, *array_index); + *array_index += 1; + } else if (prop_type == DBUS_TYPE_ARRAY) { + // Write the length first + sprintf(buf1, "%d", len); + set_object_array_element(env, strArray, buf1, *array_index); + *array_index += 1; + + prop_val = value->array_val; + for (i = 0; i < len; i++) { + set_object_array_element(env, strArray, prop_val[i], *array_index); + *array_index += 1; + } + } else { + set_object_array_element(env, strArray, (const char *) value->str_val, *array_index); + *array_index += 1; + } +} + +jobjectArray parse_properties(JNIEnv *env, DBusMessageIter *iter, Properties *properties, + const int max_num_properties) { + DBusMessageIter dict_entry, dict; + jobjectArray strArray = NULL; + property_value value; + int i, size = 0,array_index = 0; + int len = 0, prop_type = DBUS_TYPE_INVALID, prop_index = -1, type; + struct { + property_value value; + int len; + bool used; + } values[max_num_properties]; + int t, j; + + jclass stringClass = env->FindClass("java/lang/String"); + DBusError err; + dbus_error_init(&err); + + for (i = 0; i < max_num_properties; i++) { + values[i].used = false; + } + + if(dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY) + goto failure; + dbus_message_iter_recurse(iter, &dict); + do { + len = 0; + if (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_DICT_ENTRY) + goto failure; + dbus_message_iter_recurse(&dict, &dict_entry); + + if (!get_property(dict_entry, properties, max_num_properties, &prop_index, + &value, &len)) { + size += 2; + if (properties[prop_index].type == DBUS_TYPE_ARRAY) + size += len; + values[prop_index].value = value; + values[prop_index].len = len; + values[prop_index].used = true; + } else { + goto failure; + } + } while(dbus_message_iter_next(&dict)); + + strArray = env->NewObjectArray(size, stringClass, NULL); + + for (i = 0; i < max_num_properties; i++) { + if (values[i].used) { + create_prop_array(env, strArray, &properties[i], &values[i].value, values[i].len, + &array_index); + + if (properties[i].type == DBUS_TYPE_ARRAY && values[i].used + && values[i].value.array_val != NULL) + free(values[i].value.array_val); + } + + } + return strArray; + +failure: + if (dbus_error_is_set(&err)) + LOG_AND_FREE_DBUS_ERROR(&err); + for (i = 0; i < max_num_properties; i++) + if (properties[i].type == DBUS_TYPE_ARRAY && values[i].used == true + && values[i].value.array_val != NULL) + free(values[i].value.array_val); + return NULL; +} + +jobjectArray parse_property_change(JNIEnv *env, DBusMessage *msg, + Properties *properties, int max_num_properties) { + DBusMessageIter iter; + DBusError err; + jobjectArray strArray = NULL; + jclass stringClass= env->FindClass("java/lang/String"); + int len = 0, prop_index = -1; + int array_index = 0, size = 0; + property_value value; + + dbus_error_init(&err); + if (!dbus_message_iter_init(msg, &iter)) goto failure; + + if (!get_property(iter, properties, max_num_properties, + &prop_index, &value, &len)) { + size += 2; + if (properties[prop_index].type == DBUS_TYPE_ARRAY) + size += len; + strArray = env->NewObjectArray(size, stringClass, NULL); + + create_prop_array(env, strArray, &properties[prop_index], + &value, len, &array_index); + + if (properties[prop_index].type == DBUS_TYPE_ARRAY && value.array_val != NULL) + free(value.array_val); + + return strArray; } - return create_prop_array(env, properties, prop_index, value, len); failure: LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg); return NULL; diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp index c7cc9b3..0420918 100644 --- a/core/jni/android_hardware_Camera.cpp +++ b/core/jni/android_hardware_Camera.cpp @@ -125,37 +125,8 @@ void JNICameraContext::notify(int32_t msgType, int32_t ext1, int32_t ext2) return; } JNIEnv *env = AndroidRuntime::getJNIEnv(); - - // parse message - switch (msgType) { - case CAMERA_MSG_ERROR: - LOGV("errorCallback"); - int error; - switch (ext1) { - case DEAD_OBJECT: - error = kCameraErrorMediaServer; - break; - default: - error = kCameraErrorUnknown; - break; - } - env->CallStaticVoidMethod(mCameraJClass, fields.post_event, - mCameraJObjectWeak, kErrorCallback, error, 0, NULL); - break; - case CAMERA_MSG_FOCUS: - LOGV("autoFocusCallback"); - env->CallStaticVoidMethod(mCameraJClass, fields.post_event, - mCameraJObjectWeak, kAutoFocusCallback, ext1, 0, NULL); - break; - case CAMERA_MSG_SHUTTER: - LOGV("shutterCallback"); - env->CallStaticVoidMethod(mCameraJClass, fields.post_event, - mCameraJObjectWeak, kShutterCallback, 0, 0, NULL); - break; - default: - LOGV("notifyCallback(%d, %d, %d)", msgType, ext1, ext2); - break; - } + env->CallStaticVoidMethod(mCameraJClass, fields.post_event, + mCameraJObjectWeak, msgType, ext1, ext2); } void JNICameraContext::copyAndPost(JNIEnv* env, const sp<IMemory>& dataPtr, int msgType) @@ -200,30 +171,27 @@ 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 (mCameraJObjectWeak == NULL) { + LOGW("callback on dead camera object"); + return; + } // return data based on callback type switch(msgType) { - case CAMERA_MSG_PREVIEW_FRAME: - LOGV("previewCallback"); - copyAndPost(env, dataPtr, kPreviewCallback); - break; case CAMERA_MSG_VIDEO_FRAME: - LOGV("recordingCallback"); + // 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, kRawCallback, 0, 0, NULL); - break; - case CAMERA_MSG_COMPRESSED_IMAGE: - LOGV("jpegCallback"); - copyAndPost(env, dataPtr, kJpegCallback); + mCameraJObjectWeak, msgType, 0, 0, NULL); break; default: LOGV("dataCallback(%d, %p)", msgType, dataPtr.get()); + copyAndPost(env, dataPtr, msgType); break; } - } // connect to camera service @@ -298,7 +266,10 @@ 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"); } diff --git a/core/jni/android_text_format_Time.cpp b/core/jni/android_text_format_Time.cpp index 7c208e9..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> 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 1c9ee7d..770c755 100644 --- a/core/jni/android_util_Process.cpp +++ b/core/jni/android_util_Process.cpp @@ -269,9 +269,9 @@ void android_os_Process_setProcessGroup(JNIEnv* env, jobject clazz, int pid, jin 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); } @@ -496,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'; |