This source file includes following definitions.
- AAssetManager_fromJava
- AAssetManager_open
- AAsset_close
- android_asset_create_stream
- android_asset_read_internal
- AAsset_getLength
- AAsset_getBuffer
- AAsset_read
- AAsset_seek
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 #include <android/log.h>
21
22
23
24
25
26
27
28
29 struct android_asset_manager
30 {
31
32 JNIEnv *env;
33
34
35 jclass class;
36 jmethodID open_fd;
37
38
39 jclass fd_class;
40 jmethodID get_length;
41 jmethodID create_input_stream;
42 jmethodID close;
43
44
45 jclass input_stream_class;
46 jmethodID read;
47 jmethodID stream_close;
48
49
50 jobject asset_manager;
51 };
52
53 typedef struct android_asset_manager AAssetManager;
54
55 struct android_asset
56 {
57
58 AAssetManager *manager;
59
60
61 jlong length;
62
63
64 jobject fd, stream;
65
66
67 int mode;
68 };
69
70 typedef struct android_asset AAsset;
71
72 static AAssetManager *
73 AAssetManager_fromJava (JNIEnv *env, jobject java_manager)
74 {
75 AAssetManager *manager;
76 jclass temp;
77
78 manager = malloc (sizeof *manager);
79
80 if (!manager)
81 return NULL;
82
83 manager->env = env;
84 manager->asset_manager
85 = (*env)->NewGlobalRef (env, java_manager);
86
87 if (!manager->asset_manager)
88 {
89 free (manager);
90 return NULL;
91 }
92
93 manager->class
94 = (*env)->FindClass (env, "android/content/res/AssetManager");
95 assert (manager->class);
96
97 manager->open_fd
98 = (*env)->GetMethodID (env, manager->class, "openFd",
99 "(Ljava/lang/String;)"
100 "Landroid/content/res/AssetFileDescriptor;");
101 assert (manager->open);
102
103 manager->fd_class
104 = (*env)->FindClass (env, "android/content/res/AssetFileDescriptor");
105 assert (manager->fd_class);
106
107 manager->get_length
108 = (*env)->GetMethodID (env, manager->fd_class, "getLength",
109 "()J");
110 assert (manager->get_length);
111
112 manager->create_input_stream
113 = (*env)->GetMethodID (env, manager->fd_class,
114 "createInputStream",
115 "()Ljava/io/FileInputStream;");
116 assert (manager->create_input_stream);
117
118 manager->close
119 = (*env)->GetMethodID (env, manager->fd_class,
120 "close", "()V");
121 assert (manager->close);
122
123 manager->input_stream_class
124 = (*env)->FindClass (env, "java/io/InputStream");
125 assert (manager->input_stream_class);
126
127 manager->read
128 = (*env)->GetMethodID (env, manager->input_stream_class,
129 "read", "([B)I");
130 assert (manager->read);
131
132 manager->stream_close
133 = (*env)->GetMethodID (env, manager->input_stream_class,
134 "close", "()V");
135 assert (manager->stream_close);
136
137
138 temp = manager->class;
139 manager->class
140 = (*env)->NewGlobalRef (env, temp);
141 assert (manager->class);
142 (*env)->DeleteLocalRef (env, temp);
143 temp = manager->fd_class;
144 manager->fd_class
145 = (*env)->NewGlobalRef (env, temp);
146 assert (manager->fd_class);
147 (*env)->DeleteLocalRef (env, temp);
148 temp = manager->input_stream_class;
149 manager->input_stream_class
150 = (*env)->NewGlobalRef (env, temp);
151 assert (manager->input_stream_class);
152 (*env)->DeleteLocalRef (env, temp);
153
154
155 return manager;
156 }
157
158 enum
159 {
160 AASSET_MODE_STREAMING = 0,
161 AASSET_MODE_BUFFER = 1,
162 };
163
164 static AAsset *
165 AAssetManager_open (AAssetManager *manager, const char *c_name,
166 int mode)
167 {
168 jobject desc;
169 jstring name;
170 AAsset *asset;
171
172
173 asset = NULL;
174
175 (*(manager->env))->PushLocalFrame (manager->env, 3);
176
177 if ((*(manager->env))->ExceptionCheck (manager->env))
178 goto fail;
179
180
181
182 name = (*(manager->env))->NewStringUTF (manager->env, c_name);
183
184 if (!name)
185 goto fail;
186
187
188 desc = (*(manager->env))->CallObjectMethod (manager->env,
189 manager->asset_manager,
190 manager->open_fd,
191 name);
192
193 if (!desc)
194 goto fail;
195
196
197 asset = calloc (1, sizeof *asset);
198
199 if (!asset)
200 {
201 (*(manager->env))->CallVoidMethod (manager->env,
202 desc,
203 manager->close);
204 goto fail;
205 }
206
207
208 desc = (*(manager->env))->NewGlobalRef (manager->env, desc);
209
210 if (!desc)
211 goto fail;
212
213 (*(manager->env))->PopLocalFrame (manager->env, NULL);
214
215 asset->manager = manager;
216 asset->length = -1;
217 asset->fd = desc;
218 asset->mode = mode;
219
220 return asset;
221
222 fail:
223 (*(manager->env))->ExceptionClear (manager->env);
224 (*(manager->env))->PopLocalFrame (manager->env, NULL);
225 free (asset);
226
227 return NULL;
228 }
229
230 static AAsset *
231 AAsset_close (AAsset *asset)
232 {
233 JNIEnv *env;
234
235 env = asset->manager->env;
236
237 (*env)->CallVoidMethod (asset->manager->env,
238 asset->fd,
239 asset->manager->close);
240 (*env)->DeleteGlobalRef (asset->manager->env,
241 asset->fd);
242
243 if (asset->stream)
244 {
245 (*env)->CallVoidMethod (asset->manager->env,
246 asset->stream,
247 asset->manager->stream_close);
248 (*env)->DeleteGlobalRef (asset->manager->env,
249 asset->stream);
250 }
251
252 free (asset);
253 }
254
255
256
257
258
259
260
261 static int
262 android_asset_create_stream (AAsset *asset)
263 {
264 jobject stream;
265 JNIEnv *env;
266
267 env = asset->manager->env;
268 stream
269 = (*env)->CallObjectMethod (env, asset->fd,
270 asset->manager->create_input_stream);
271
272 if (!stream)
273 {
274 (*env)->ExceptionClear (env);
275 return 1;
276 }
277
278 asset->stream
279 = (*env)->NewGlobalRef (env, stream);
280
281 if (!asset->stream)
282 {
283 (*env)->ExceptionClear (env);
284 (*env)->DeleteLocalRef (env, stream);
285 return 1;
286 }
287
288 (*env)->DeleteLocalRef (env, stream);
289 return 0;
290 }
291
292
293
294
295
296
297
298
299
300
301 static int
302 android_asset_read_internal (AAsset *asset, int nbytes, char *buffer)
303 {
304 jbyteArray stash;
305 JNIEnv *env;
306 jint bytes_read, total;
307
308
309
310 env = asset->manager->env;
311 stash = (*env)->NewByteArray (env, MIN (nbytes, 4096));
312
313 if (!stash)
314 {
315 (*env)->ExceptionClear (env);
316 errno = ENOMEM;
317 return -1;
318 }
319
320
321
322 if (!asset->stream
323 && android_asset_create_stream (asset))
324 {
325 (*env)->DeleteLocalRef (env, stash);
326 errno = ENOMEM;
327 return -1;
328 }
329
330
331
332 total = 0;
333
334 while (nbytes)
335 {
336 bytes_read = (*env)->CallIntMethod (env, asset->stream,
337 asset->manager->read,
338 stash);
339
340
341
342 if ((*env)->ExceptionCheck (env))
343 goto out;
344
345
346
347 if (bytes_read == -1)
348 goto out;
349
350
351 bytes_read = MIN (bytes_read, nbytes);
352 (*env)->GetByteArrayRegion (env, stash, 0, bytes_read, buffer);
353
354 buffer += bytes_read;
355 total += bytes_read;
356 nbytes -= bytes_read;
357 }
358
359
360 assert (nbytes >= 0);
361
362 out:
363 (*env)->ExceptionClear (env);
364 (*env)->DeleteLocalRef (env, stash);
365 return total;
366 }
367
368 static long
369 AAsset_getLength (AAsset *asset)
370 {
371 JNIEnv *env;
372
373 if (asset->length != -1)
374 return asset->length;
375
376 env = asset->manager->env;
377 asset->length
378 = (*env)->CallLongMethod (env, asset->fd,
379 asset->manager->get_length);
380 return asset->length;
381 }
382
383 static char *
384 AAsset_getBuffer (AAsset *asset)
385 {
386 long length;
387 char *buffer;
388
389 length = AAsset_getLength (asset);
390
391 if (!length)
392 return NULL;
393
394 buffer = malloc (length);
395
396 if (!buffer)
397 return NULL;
398
399 if (android_asset_read_internal (asset, length, buffer)
400 != length)
401 {
402 xfree (buffer);
403 return NULL;
404 }
405
406 return buffer;
407 }
408
409 static size_t
410 AAsset_read (AAsset *asset, void *buffer, size_t size)
411 {
412 return android_asset_read_internal (asset, MIN (size, INT_MAX),
413 buffer);
414 }
415
416 static off_t
417 AAsset_seek (AAsset *asset, off_t offset, int whence)
418 {
419
420 errno = ESPIPE;
421 return -1;
422 }