[Scummvm-git-logs] scummvm master -> 111dc18ef303fb299af97b5973ed1fe366b93072

sev- sev at scummvm.org
Tue Aug 30 15:14:19 CEST 2016


This automated email contains information about 2 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
61e911baf8 ANDROID: Update the asset archive code to use AAssets
111dc18ef3 Merge pull request #433 from klusark/assets


Commit: 61e911baf8d5f4d818abbe1926be93d5c14d758d
    https://github.com/scummvm/scummvm/commit/61e911baf8d5f4d818abbe1926be93d5c14d758d
Author: Joel Teichroeb (joel at teichroeb.net)
Date: 2015-01-05T19:19:34-08:00

Commit Message:
ANDROID: Update the asset archive code to use AAssets

The AAssets API was added in android 2.3, so it also requires using
the android-9 toolchain.

Using this gives a rather large speedboost to starting the ScummVM
application.

Changed paths:
    backends/platform/android/asset-archive.cpp
    backends/platform/android/asset-archive.h
    configure



diff --git a/backends/platform/android/asset-archive.cpp b/backends/platform/android/asset-archive.cpp
index 6680081..0ee6efc 100644
--- a/backends/platform/android/asset-archive.cpp
+++ b/backends/platform/android/asset-archive.cpp
@@ -22,8 +22,6 @@
 
 #if defined(__ANDROID__)
 
-#include <jni.h>
-
 #include <sys/types.h>
 #include <unistd.h>
 
@@ -37,443 +35,112 @@
 #include "backends/platform/android/jni.h"
 #include "backends/platform/android/asset-archive.h"
 
-// Must match android.content.res.AssetManager.ACCESS_*
-const jint ACCESS_UNKNOWN = 0;
-const jint ACCESS_RANDOM = 1;
+#include <android/asset_manager.h>
+#include <android/asset_manager_jni.h>
 
-// This might be useful to someone else.  Assumes markSupported() == true.
-class JavaInputStream : public Common::SeekableReadStream {
+class AssetInputStream : public Common::SeekableReadStream {
 public:
-	JavaInputStream(JNIEnv *env, jobject is);
-	virtual ~JavaInputStream();
-
-	virtual bool eos() const {
-		return _eos;
-	}
+	AssetInputStream(AAssetManager *as, const Common::String &path);
+	virtual ~AssetInputStream();
 
-	virtual bool err() const {
-		return _err;
-	}
+	virtual bool eos() const { return _eos; }
 
-	virtual void clearErr() {
-		_eos = _err = false;
-	}
+	virtual void clearErr() {_eos = false; }
 
 	virtual uint32 read(void *dataPtr, uint32 dataSize);
 
-	virtual int32 pos() const {
-		return _pos;
-	}
+	virtual int32 pos() const { return _pos; }
 
-	virtual int32 size() const {
-		return _len;
-	}
+	virtual int32 size() const { return _len; }
 
 	virtual bool seek(int32 offset, int whence = SEEK_SET);
 
 private:
-	void close(JNIEnv *env);
-
-	jmethodID MID_mark;
-	jmethodID MID_available;
-	jmethodID MID_close;
-	jmethodID MID_read;
-	jmethodID MID_reset;
-	jmethodID MID_skip;
+	void close();
+	AAsset *_asset;
 
-	jobject _input_stream;
-	jsize _buflen;
-	jbyteArray _buf;
 	uint32 _pos;
-	jint _len;
+	uint32 _len;
 	bool _eos;
-	bool _err;
 };
 
-JavaInputStream::JavaInputStream(JNIEnv *env, jobject is) :
-	_eos(false),
-	_err(false),
-	_pos(0)
-{
-	_input_stream = env->NewGlobalRef(is);
-	_buflen = 8192;
-	jobject buf = env->NewByteArray(_buflen);
-	_buf = (jbyteArray)env->NewGlobalRef(buf);
-	env->DeleteLocalRef(buf);
-
-	jclass cls = env->GetObjectClass(_input_stream);
-	MID_mark = env->GetMethodID(cls, "mark", "(I)V");
-	assert(MID_mark);
-	MID_available = env->GetMethodID(cls, "available", "()I");
-	assert(MID_available);
-	MID_close = env->GetMethodID(cls, "close", "()V");
-	assert(MID_close);
-	MID_read = env->GetMethodID(cls, "read", "([BII)I");
-	assert(MID_read);
-	MID_reset = env->GetMethodID(cls, "reset", "()V");
-	assert(MID_reset);
-	MID_skip = env->GetMethodID(cls, "skip", "(J)J");
-	assert(MID_skip);
-	env->DeleteLocalRef(cls);
-
-	// Mark start of stream, so we can reset back to it.
-	// readlimit is set to something bigger than anything we might
-	// want to seek within.
-	env->CallVoidMethod(_input_stream, MID_mark, 10 * 1024 * 1024);
-	_len = env->CallIntMethod(_input_stream, MID_available);
+AssetInputStream::AssetInputStream(AAssetManager *as, const Common::String &path) :
+	_eos(false), _pos(0) {
+	_asset = AAssetManager_open(as, path.c_str(), AASSET_MODE_RANDOM);
+	_len = AAsset_getLength(_asset);
 }
 
-JavaInputStream::~JavaInputStream() {
-	JNIEnv *env = JNI::getEnv();
-	close(env);
-
-	env->DeleteGlobalRef(_buf);
-	env->DeleteGlobalRef(_input_stream);
+AssetInputStream::~AssetInputStream() {
 }
 
-void JavaInputStream::close(JNIEnv *env) {
-	env->CallVoidMethod(_input_stream, MID_close);
-
-	if (env->ExceptionCheck())
-		env->ExceptionClear();
+void AssetInputStream::close() {
+	AAsset_close(_asset);
 }
 
-uint32 JavaInputStream::read(void *dataPtr, uint32 dataSize) {
-	JNIEnv *env = JNI::getEnv();
-
-	if (_buflen < jint(dataSize)) {
-		_buflen = dataSize;
-
-		env->DeleteGlobalRef(_buf);
-		jobject buf = env->NewByteArray(_buflen);
-		_buf = static_cast<jbyteArray>(env->NewGlobalRef(buf));
-		env->DeleteLocalRef(buf);
-	}
-
-	jint ret = env->CallIntMethod(_input_stream, MID_read, _buf, 0, dataSize);
-
-	if (env->ExceptionCheck()) {
-		warning("Exception during JavaInputStream::read(%p, %d)",
-				dataPtr, dataSize);
-
-		env->ExceptionDescribe();
-		env->ExceptionClear();
-
-		_err = true;
-		ret = -1;
-	} else if (ret == -1) {
+uint32 AssetInputStream::read(void *dataPtr, uint32 dataSize) {
+	uint32 readlen = AAsset_read(_asset, dataPtr, dataSize);
+	_pos += readlen;
+	if (readlen != dataSize) {
 		_eos = true;
-		ret = 0;
-	} else {
-		env->GetByteArrayRegion(_buf, 0, ret, static_cast<jbyte *>(dataPtr));
-		_pos += ret;
 	}
-
-	return ret;
+	return readlen;
 }
 
-bool JavaInputStream::seek(int32 offset, int whence) {
-	JNIEnv *env = JNI::getEnv();
-	uint32 newpos;
-
-	switch (whence) {
-	case SEEK_SET:
-		newpos = offset;
-		break;
-	case SEEK_CUR:
-		newpos = _pos + offset;
-		break;
-	case SEEK_END:
-		newpos = _len + offset;
-		break;
-	default:
-		debug("Unknown 'whence' arg %d", whence);
+bool AssetInputStream::seek(int32 offset, int whence) {
+	int res = AAsset_seek(_asset, offset, whence);
+	if (res == -1) {
 		return false;
 	}
-
-	jlong skip_bytes;
-	if (newpos > _pos) {
-		skip_bytes = newpos - _pos;
-	} else {
-		// Can't skip backwards, so jump back to start and skip from there.
-		env->CallVoidMethod(_input_stream, MID_reset);
-
-		if (env->ExceptionCheck()) {
-			warning("Failed to rewind to start of asset stream");
-
-			env->ExceptionDescribe();
-			env->ExceptionClear();
-
-			return false;
-		}
-
-		_pos = 0;
-		skip_bytes = newpos;
-	}
-
-	while (skip_bytes > 0) {
-		jlong ret = env->CallLongMethod(_input_stream, MID_skip, skip_bytes);
-
-		if (env->ExceptionCheck()) {
-			warning("Failed to skip %ld bytes into asset stream",
-					static_cast<long>(skip_bytes));
-
-			env->ExceptionDescribe();
-			env->ExceptionClear();
-
-			return false;
-		} else if (ret == 0) {
-			warning("InputStream->skip(%ld) didn't skip any bytes. Aborting seek.",
-					static_cast<long>(skip_bytes));
-
-			// No point looping forever...
-			return false;
-		}
-
-		_pos += ret;
-		skip_bytes -= ret;
-	}
-
-	_eos = false;
-	return true;
-}
-
-// Must match android.content.res.AssetFileDescriptor.UNKNOWN_LENGTH
-const jlong UNKNOWN_LENGTH = -1;
-
-// Reading directly from a fd is so much more efficient, that it is
-// worth optimising for.
-class AssetFdReadStream : public Common::SeekableReadStream {
-public:
-	AssetFdReadStream(JNIEnv *env, jobject assetfd);
-	virtual ~AssetFdReadStream();
-
-	virtual bool eos() const {
-		return _eos;
-	}
-
-	virtual bool err() const {
-		return _err;
-	}
-
-	virtual void clearErr() {
-		_eos = _err = false;
-	}
-
-	virtual uint32 read(void *dataPtr, uint32 dataSize);
-
-	virtual int32 pos() const {
-		return _pos;
-	}
-
-	virtual int32 size() const {
-		return _declared_len;
-	}
-
-	virtual bool seek(int32 offset, int whence = SEEK_SET);
-
-private:
-	void close(JNIEnv *env);
-
-	int _fd;
-	jmethodID MID_close;
-	jobject _assetfd;
-	jlong _start_off;
-	jlong _declared_len;
-	uint32 _pos;
-	bool _eos;
-	bool _err;
-};
-
-AssetFdReadStream::AssetFdReadStream(JNIEnv *env, jobject assetfd) :
-	_eos(false),
-	_err(false),
-	_pos(0)
-{
-	_assetfd = env->NewGlobalRef(assetfd);
-
-	jclass cls = env->GetObjectClass(_assetfd);
-	MID_close = env->GetMethodID(cls, "close", "()V");
-	assert(MID_close);
-
-	jmethodID MID_getStartOffset =
-		env->GetMethodID(cls, "getStartOffset", "()J");
-	assert(MID_getStartOffset);
-	_start_off = env->CallLongMethod(_assetfd, MID_getStartOffset);
-
-	jmethodID MID_getDeclaredLength =
-		env->GetMethodID(cls, "getDeclaredLength", "()J");
-	assert(MID_getDeclaredLength);
-	_declared_len = env->CallLongMethod(_assetfd, MID_getDeclaredLength);
-
-	jmethodID MID_getFileDescriptor =
-		env->GetMethodID(cls, "getFileDescriptor",
-							"()Ljava/io/FileDescriptor;");
-	assert(MID_getFileDescriptor);
-	jobject javafd = env->CallObjectMethod(_assetfd, MID_getFileDescriptor);
-	assert(javafd);
-
-	jclass fd_cls = env->GetObjectClass(javafd);
-	jfieldID FID_descriptor = env->GetFieldID(fd_cls, "descriptor", "I");
-	assert(FID_descriptor);
-	env->DeleteLocalRef(fd_cls);
-
-	_fd = env->GetIntField(javafd, FID_descriptor);
-	env->DeleteLocalRef(javafd);
-
-	env->DeleteLocalRef(cls);
-}
-
-AssetFdReadStream::~AssetFdReadStream() {
-	JNIEnv *env = JNI::getEnv();
-	env->CallVoidMethod(_assetfd, MID_close);
-
-	if (env->ExceptionCheck())
-		env->ExceptionClear();
-
-	env->DeleteGlobalRef(_assetfd);
-}
-
-uint32 AssetFdReadStream::read(void *dataPtr, uint32 dataSize) {
-	if (_declared_len != UNKNOWN_LENGTH) {
-		jlong cap = _declared_len - _pos;
-		if (dataSize > cap)
-			dataSize = cap;
-	}
-
-	int ret = ::read(_fd, dataPtr, dataSize);
-
-	if (ret == 0)
-		_eos = true;
-	else if (ret == -1)
-		_err = true;
-	else
-		_pos += ret;
-
-	return ret;
-}
-
-bool AssetFdReadStream::seek(int32 offset, int whence) {
-	if (whence == SEEK_SET) {
-		if (_declared_len != UNKNOWN_LENGTH && offset > _declared_len)
-			offset = _declared_len;
-
-		offset += _start_off;
-	} else if (whence == SEEK_END && _declared_len != UNKNOWN_LENGTH) {
-		whence = SEEK_SET;
-		offset = _start_off + _declared_len + offset;
+	if (whence == SEEK_CUR) {
+		_pos += offset;
+	} else if (whence == SEEK_SET) {
+		_pos = offset;
+	} else if (whence == SEEK_END) {
+		_pos = _len + offset;
 	}
-
-	int ret = lseek(_fd, offset, whence);
-
-	if (ret == -1)
-		return false;
-
-	_pos = ret - _start_off;
+	assert(_pos <= _len);
 	_eos = false;
-
 	return true;
 }
 
-AndroidAssetArchive::AndroidAssetArchive(jobject am) {
+AndroidAssetArchive::AndroidAssetArchive(jobject am) : _hasCached(false) {
 	JNIEnv *env = JNI::getEnv();
-	_am = env->NewGlobalRef(am);
 
-	jclass cls = env->GetObjectClass(_am);
-	MID_open = env->GetMethodID(cls, "open",
-								"(Ljava/lang/String;I)Ljava/io/InputStream;");
-	assert(MID_open);
-
-	MID_openFd = env->GetMethodID(cls, "openFd", "(Ljava/lang/String;)"
-								"Landroid/content/res/AssetFileDescriptor;");
-	assert(MID_openFd);
-
-	MID_list = env->GetMethodID(cls, "list",
-								"(Ljava/lang/String;)[Ljava/lang/String;");
-	assert(MID_list);
-	env->DeleteLocalRef(cls);
+	_am = AAssetManager_fromJava(env, am);
 }
 
 AndroidAssetArchive::~AndroidAssetArchive() {
-	JNIEnv *env = JNI::getEnv();
-	env->DeleteGlobalRef(_am);
 }
 
 bool AndroidAssetArchive::hasFile(const Common::String &name) const {
-	JNIEnv *env = JNI::getEnv();
-	jstring path = env->NewStringUTF(name.c_str());
-	jobject result = env->CallObjectMethod(_am, MID_open, path, ACCESS_UNKNOWN);
-	if (env->ExceptionCheck()) {
-		// Assume FileNotFoundException
-		//warning("Error while calling AssetManager->open(%s)", name.c_str());
-		//env->ExceptionDescribe();
-		env->ExceptionClear();
-		env->DeleteLocalRef(path);
-
-		return false;
+	AAsset *asset = AAssetManager_open(_am, name.c_str(), AASSET_MODE_RANDOM);
+	bool exists = false;
+	if (asset != NULL) {
+		exists = true;
+		AAsset_close(asset);
 	}
-
-	env->DeleteLocalRef(result);
-	env->DeleteLocalRef(path);
-
-	return true;
+	return exists;
 }
 
 int AndroidAssetArchive::listMembers(Common::ArchiveMemberList &member_list) const {
-	JNIEnv *env = JNI::getEnv();
-	Common::List<Common::String> dirlist;
-	dirlist.push_back("");
+	if (_hasCached) {
+		member_list.insert(member_list.end(), _cachedMembers.begin(), _cachedMembers.end());
+		return _cachedMembers.size();
+	}
 
 	int count = 0;
-	while (!dirlist.empty()) {
-		const Common::String dir = dirlist.back();
-		dirlist.pop_back();
-
-		jstring jpath = env->NewStringUTF(dir.c_str());
-		jobjectArray jpathlist =
-			(jobjectArray)env->CallObjectMethod(_am, MID_list, jpath);
-
-		if (env->ExceptionCheck()) {
-			warning("Error while calling AssetManager->list(%s). Ignoring.",
-					dir.c_str());
-			env->ExceptionDescribe();
-			env->ExceptionClear();
-
-			// May as well keep going ...
-			continue;
-		}
-
-		env->DeleteLocalRef(jpath);
+	AAssetDir *dir = AAssetManager_openDir(_am, "");
+	const char *file = AAssetDir_getNextFileName(dir);
 
-		for (jsize i = 0; i < env->GetArrayLength(jpathlist); ++i) {
-			jstring elem = (jstring)env->GetObjectArrayElement(jpathlist, i);
-			const char *p = env->GetStringUTFChars(elem, 0);
-
-			if (strlen(p)) {
-				Common::String thispath = dir;
-
-				if (!thispath.empty())
-					thispath += "/";
-
-				thispath += p;
-
-				// Assume files have a . in them, and directories don't
-				if (strchr(p, '.')) {
-					member_list.push_back(getMember(thispath));
-					++count;
-				} else {
-					// AssetManager is ridiculously slow and we don't care
-					// about subdirectories at the moment, so ignore them.
-					// dirlist.push_back(thispath);
-				}
-			}
-
-			env->ReleaseStringUTFChars(elem, p);
-			env->DeleteLocalRef(elem);
-		}
-
-		env->DeleteLocalRef(jpathlist);
+	while (file) {
+		member_list.push_back(getMember(file));
+		++count;
+		file = AAssetDir_getNextFileName(dir);
 	}
+	AAssetDir_close(dir);
+
+	_cachedMembers = Common::ArchiveMemberList(member_list);
+	_hasCached = true;
 
 	return count;
 }
@@ -483,39 +150,10 @@ const Common::ArchiveMemberPtr AndroidAssetArchive::getMember(const Common::Stri
 }
 
 Common::SeekableReadStream *AndroidAssetArchive::createReadStreamForMember(const Common::String &path) const {
-	JNIEnv *env = JNI::getEnv();
-	jstring jpath = env->NewStringUTF(path.c_str());
-
-	// Try openFd() first ...
-	jobject afd = env->CallObjectMethod(_am, MID_openFd, jpath);
-
-	if (env->ExceptionCheck())
-		env->ExceptionClear();
-	else if (afd != 0) {
-		// success :)
-		Common::SeekableReadStream *stream = new AssetFdReadStream(env, afd);
-		env->DeleteLocalRef(jpath);
-		env->DeleteLocalRef(afd);
-		return stream;
+	if (!hasFile(path)) {
+		return nullptr;
 	}
-
-	// ... and fallback to normal open() if that doesn't work
-	jobject is = env->CallObjectMethod(_am, MID_open, jpath, ACCESS_RANDOM);
-
-	if (env->ExceptionCheck()) {
-		// Assume FileNotFoundException
-		//warning("Error opening %s", path.c_str());
-		//env->ExceptionDescribe();
-		env->ExceptionClear();
-		env->DeleteLocalRef(jpath);
-
-		return 0;
-	}
-
-	Common::SeekableReadStream *stream = new JavaInputStream(env, is);
-	env->DeleteLocalRef(jpath);
-	env->DeleteLocalRef(is);
-	return stream;
+	return new AssetInputStream(_am, path);
 }
 
 #endif
diff --git a/backends/platform/android/asset-archive.h b/backends/platform/android/asset-archive.h
index 6a0033d..8ae55b2 100644
--- a/backends/platform/android/asset-archive.h
+++ b/backends/platform/android/asset-archive.h
@@ -32,6 +32,8 @@
 #include "common/util.h"
 #include "common/archive.h"
 
+#include <android/asset_manager.h>
+
 class AndroidAssetArchive : public Common::Archive {
 public:
 	AndroidAssetArchive(jobject am);
@@ -43,11 +45,9 @@ public:
 	virtual Common::SeekableReadStream *createReadStreamForMember(const Common::String &name) const;
 
 private:
-	jmethodID MID_open;
-	jmethodID MID_openFd;
-	jmethodID MID_list;
-
-	jobject _am;
+	AAssetManager *_am;
+	mutable Common::ArchiveMemberList _cachedMembers;
+	mutable bool _hasCached;
 };
 
 #endif
diff --git a/configure b/configure
index 7c4c87e..6cc98f6 100755
--- a/configure
+++ b/configure
@@ -2084,7 +2084,7 @@ case $_host_os in
 				CXXFLAGS="$CXXFLAGS -mtune=xscale"
 				CXXFLAGS="$CXXFLAGS -msoft-float"
 				ABI="armeabi"
-				ANDROID_PLATFORM=4
+				ANDROID_PLATFORM=9
 				ANDROID_PLATFORM_ARCH="arm"
 				;;
 			android-v7a | android-arm-v7a)
@@ -2093,7 +2093,7 @@ case $_host_os in
 				CXXFLAGS="$CXXFLAGS -mfpu=vfp"
 				LDFLAGS="$LDFLAGS -Wl,--fix-cortex-a8"
 				ABI="armeabi-v7a"
-				ANDROID_PLATFORM=4
+				ANDROID_PLATFORM=9
 				ANDROID_PLATFORM_ARCH="arm"
 				;;
 			android-mips)
@@ -4325,7 +4325,7 @@ case $_backend in
 		# -lgcc is carefully placed here - we want to catch
 		# all toolchain symbols in *our* libraries rather
 		# than pick up anything unhygenic from the Android libs.
-		LIBS="-Wl,-Bstatic $static_libs -Wl,-Bdynamic -lgcc $system_libs -llog -lGLESv1_CM"
+		LIBS="-Wl,-Bstatic $static_libs -Wl,-Bdynamic -lgcc $system_libs -llog -landroid -lGLESv1_CM"
 		;;
 	n64)
 		# Move some libs down here, otherwise some symbols requires by libvorbis aren't found


Commit: 111dc18ef303fb299af97b5973ed1fe366b93072
    https://github.com/scummvm/scummvm/commit/111dc18ef303fb299af97b5973ed1fe366b93072
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2016-08-30T15:14:12+02:00

Commit Message:
Merge pull request #433 from klusark/assets

ANDROID: Update the asset archive code to use AAssets

Changed paths:
    backends/platform/android/asset-archive.cpp
    backends/platform/android/asset-archive.h
    configure



diff --cc configure
index baf8264,6cc98f6..ece7eaa
--- a/configure
+++ b/configure
@@@ -2267,20 -2080,20 +2267,20 @@@ case $_host_os i
  	android)
  		case $_host in
  			android | android-arm)
 -				CXXFLAGS="$CXXFLAGS -march=armv5te"
 -				CXXFLAGS="$CXXFLAGS -mtune=xscale"
 -				CXXFLAGS="$CXXFLAGS -msoft-float"
 +				append_var CXXFLAGS "-march=armv5te"
 +				append_var CXXFLAGS "-mtune=xscale"
 +				append_var CXXFLAGS "-msoft-float"
  				ABI="armeabi"
- 				ANDROID_PLATFORM=4
+ 				ANDROID_PLATFORM=9
  				ANDROID_PLATFORM_ARCH="arm"
  				;;
  			android-v7a | android-arm-v7a)
 -				CXXFLAGS="$CXXFLAGS -march=armv7-a"
 -				CXXFLAGS="$CXXFLAGS -mfloat-abi=softfp"
 -				CXXFLAGS="$CXXFLAGS -mfpu=vfp"
 -				LDFLAGS="$LDFLAGS -Wl,--fix-cortex-a8"
 +				append_var CXXFLAGS "-march=armv7-a"
 +				append_var CXXFLAGS "-mfloat-abi=softfp"
 +				append_var CXXFLAGS "-mfpu=vfp"
 +				append_var LDFLAGS "-Wl,--fix-cortex-a8"
  				ABI="armeabi-v7a"
- 				ANDROID_PLATFORM=4
+ 				ANDROID_PLATFORM=9
  				ANDROID_PLATFORM_ARCH="arm"
  				;;
  			android-mips)





More information about the Scummvm-git-logs mailing list