1 /* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 */
22
23 #if defined(__ANDROID__)
24
25 #include <sys/types.h>
26 #include <unistd.h>
27
28 #include "common/str.h"
29 #include "common/stream.h"
30 #include "common/util.h"
31 #include "common/archive.h"
32 #include "common/debug.h"
33 #include "common/textconsole.h"
34
35 #include "backends/platform/android/jni.h"
36 #include "backends/platform/android/asset-archive.h"
37
38 #include <android/asset_manager.h>
39 #include <android/asset_manager_jni.h>
40
41 class AssetInputStream : public Common::SeekableReadStream {
42 public:
43 AssetInputStream(AAssetManager *as, const Common::String &path);
44 virtual ~AssetInputStream();
45
eos() const46 virtual bool eos() const { return _eos; }
47
clearErr()48 virtual void clearErr() {_eos = false; }
49
50 virtual uint32 read(void *dataPtr, uint32 dataSize);
51
pos() const52 virtual int32 pos() const { return _pos; }
53
size() const54 virtual int32 size() const { return _len; }
55
56 virtual bool seek(int32 offset, int whence = SEEK_SET);
57
58 private:
59 void close();
60 AAsset *_asset;
61
62 uint32 _pos;
63 uint32 _len;
64 bool _eos;
65 };
66
AssetInputStream(AAssetManager * as,const Common::String & path)67 AssetInputStream::AssetInputStream(AAssetManager *as, const Common::String &path) :
68 _eos(false), _pos(0) {
69 _asset = AAssetManager_open(as, path.c_str(), AASSET_MODE_RANDOM);
70 _len = AAsset_getLength(_asset);
71 }
72
~AssetInputStream()73 AssetInputStream::~AssetInputStream() {
74 }
75
close()76 void AssetInputStream::close() {
77 AAsset_close(_asset);
78 }
79
read(void * dataPtr,uint32 dataSize)80 uint32 AssetInputStream::read(void *dataPtr, uint32 dataSize) {
81 uint32 readlen = AAsset_read(_asset, dataPtr, dataSize);
82 _pos += readlen;
83 if (readlen != dataSize) {
84 _eos = true;
85 }
86 return readlen;
87 }
88
seek(int32 offset,int whence)89 bool AssetInputStream::seek(int32 offset, int whence) {
90 int res = AAsset_seek(_asset, offset, whence);
91 if (res == -1) {
92 return false;
93 }
94 if (whence == SEEK_CUR) {
95 _pos += offset;
96 } else if (whence == SEEK_SET) {
97 _pos = offset;
98 } else if (whence == SEEK_END) {
99 _pos = _len + offset;
100 }
101 assert(_pos < _len);
102 _eos = false;
103 return true;
104 }
105
106
AndroidAssetArchive(jobject am)107 AndroidAssetArchive::AndroidAssetArchive(jobject am) {
108 JNIEnv *env = JNI::getEnv();
109
110 _am = AAssetManager_fromJava(env, am);
111 _cachedMembers = NULL;
112 }
113
~AndroidAssetArchive()114 AndroidAssetArchive::~AndroidAssetArchive() {
115 delete _cachedMembers;
116 _cachedMembers = NULL;
117 }
118
hasFile(const Common::String & name) const119 bool AndroidAssetArchive::hasFile(const Common::String &name) const {
120 AAsset *asset = AAssetManager_open(_am, name.c_str(), AASSET_MODE_RANDOM);
121 bool exists = false;
122 if (asset != NULL) {
123 exists = true;
124 AAsset_close(asset);
125 }
126 return exists;
127 }
128
listMembers(Common::ArchiveMemberList & member_list) const129 int AndroidAssetArchive::listMembers(Common::ArchiveMemberList &member_list) const {
130 if (_cachedMembers) {
131 member_list.insert(member_list.end(), _cachedMembers->begin(), _cachedMembers->end());
132 return _cachedMembers->size();
133 }
134
135 Common::List<Common::String> dirs;
136 dirs.push_back("");
137 dirs.push_back("shaders");
138 int count = 0;
139 while (!dirs.empty()) {
140 Common::String currentDir = dirs.front();
141 dirs.pop_front();
142 AAssetDir *dir = AAssetManager_openDir(_am, currentDir.c_str());
143 const char *file = AAssetDir_getNextFileName(dir);
144
145 while (file) {
146 Common::String f(file);
147 f = currentDir + f;
148 member_list.push_back(getMember(f));
149 ++count;
150 file = AAssetDir_getNextFileName(dir);
151 }
152 AAssetDir_close(dir);
153 }
154
155 _cachedMembers = new Common::ArchiveMemberList(member_list);
156
157 return count;
158 }
159
getMember(const Common::String & name) const160 const Common::ArchiveMemberPtr AndroidAssetArchive::getMember(const Common::String &name) const {
161 return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(name, this));
162 }
163
createReadStreamForMember(const Common::String & path) const164 Common::SeekableReadStream *AndroidAssetArchive::createReadStreamForMember(const Common::String &path) const {
165 if (!hasFile(path)) {
166 return nullptr;
167 }
168 return new AssetInputStream(_am, path);
169 }
170
171 #endif
172