1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#define LOG_TAG "NAsset" 18#include <utils/Log.h> 19 20#include <android/asset_manager_jni.h> 21#include <androidfw/Asset.h> 22#include <androidfw/AssetDir.h> 23#include <androidfw/AssetManager.h> 24#include <utils/threads.h> 25 26#include "jni.h" 27#include "JNIHelp.h" 28 29using namespace android; 30 31// -------------------- Backing implementation of the public API -------------------- 32 33// AAssetManager is actually a secret typedef for an empty base class of AssetManager, 34// but AAssetDir and AAsset are actual wrappers for isolation. 35 36// ----- 37struct AAssetDir { 38 AssetDir* mAssetDir; 39 size_t mCurFileIndex; 40 String8 mCachedFileName; 41 42 AAssetDir(AssetDir* dir) : mAssetDir(dir), mCurFileIndex(0) { } 43 ~AAssetDir() { delete mAssetDir; } 44}; 45 46 47// ----- 48struct AAsset { 49 Asset* mAsset; 50 51 AAsset(Asset* asset) : mAsset(asset) { } 52 ~AAsset() { delete mAsset; } 53}; 54 55// -------------------- Public native C API -------------------- 56 57/** 58 * Supporting information 59 */ 60 61static struct assetmanager_offsets_t 62{ 63 jfieldID mObject; 64} gAssetManagerOffsets; 65 66static volatile bool gJNIConfigured = false; 67static Mutex gMutex; 68 69/** 70 * Asset Manager functionality 71 */ 72AAssetManager* AAssetManager_fromJava(JNIEnv* env, jobject assetManager) 73{ 74 { 75 Mutex::Autolock _l(gMutex); 76 77 if (gJNIConfigured == false) { 78 jclass amClass = env->FindClass("android/content/res/AssetManager"); 79 gAssetManagerOffsets.mObject = env->GetFieldID(amClass, "mObject", "I"); 80 gJNIConfigured = true; 81 } 82 } 83 84 return (AAssetManager*) env->GetIntField(assetManager, gAssetManagerOffsets.mObject); 85} 86 87AAsset* AAssetManager_open(AAssetManager* amgr, const char* filename, int mode) 88{ 89 Asset::AccessMode amMode; 90 switch (mode) { 91 case AASSET_MODE_UNKNOWN: 92 amMode = Asset::ACCESS_UNKNOWN; 93 break; 94 case AASSET_MODE_RANDOM: 95 amMode = Asset::ACCESS_RANDOM; 96 break; 97 case AASSET_MODE_STREAMING: 98 amMode = Asset::ACCESS_STREAMING; 99 break; 100 case AASSET_MODE_BUFFER: 101 amMode = Asset::ACCESS_BUFFER; 102 break; 103 default: 104 return NULL; 105 } 106 107 AssetManager* mgr = static_cast<AssetManager*>(amgr); 108 Asset* asset = mgr->open(filename, amMode); 109 if (asset == NULL) { 110 return NULL; 111 } 112 113 return new AAsset(asset); 114} 115 116AAssetDir* AAssetManager_openDir(AAssetManager* amgr, const char* dirName) 117{ 118 AssetManager* mgr = static_cast<AssetManager*>(amgr); 119 return new AAssetDir(mgr->openDir(dirName)); 120} 121 122/** 123 * AssetDir functionality 124 */ 125 126const char* AAssetDir_getNextFileName(AAssetDir* assetDir) 127{ 128 const char* returnName = NULL; 129 size_t index = assetDir->mCurFileIndex; 130 const size_t max = assetDir->mAssetDir->getFileCount(); 131 132 // Find the next regular file; explicitly don't report directories even if the 133 // underlying implementation changes to report them. At that point we can add 134 // a more general iterator to this native interface set if appropriate. 135 while ((index < max) && (assetDir->mAssetDir->getFileType(index) != kFileTypeRegular)) { 136 index++; 137 } 138 139 // still in bounds? then the one at 'index' is the next to be reported; generate 140 // the string to return and advance the iterator for next time. 141 if (index < max) { 142 assetDir->mCachedFileName = assetDir->mAssetDir->getFileName(index); 143 returnName = assetDir->mCachedFileName.string(); 144 index++; 145 } 146 147 assetDir->mCurFileIndex = index; 148 return returnName; 149} 150 151void AAssetDir_rewind(AAssetDir* assetDir) 152{ 153 assetDir->mCurFileIndex = 0; 154} 155 156const char* AAssetDir_getFileName(AAssetDir* assetDir, int index) 157{ 158 assetDir->mCachedFileName = assetDir->mAssetDir->getFileName(index); 159 return assetDir->mCachedFileName.string(); 160} 161 162void AAssetDir_close(AAssetDir* assetDir) 163{ 164 delete assetDir; 165} 166 167/** 168 * Asset functionality 169 */ 170 171int AAsset_read(AAsset* asset, void* buf, size_t count) 172{ 173 return asset->mAsset->read(buf, (size_t)count); 174} 175 176off_t AAsset_seek(AAsset* asset, off_t offset, int whence) 177{ 178 return asset->mAsset->seek(offset, whence); 179} 180 181off64_t AAsset_seek64(AAsset* asset, off64_t offset, int whence) 182{ 183 return asset->mAsset->seek(offset, whence); 184} 185 186void AAsset_close(AAsset* asset) 187{ 188 asset->mAsset->close(); 189 delete asset; 190} 191 192const void* AAsset_getBuffer(AAsset* asset) 193{ 194 return asset->mAsset->getBuffer(false); 195} 196 197off_t AAsset_getLength(AAsset* asset) 198{ 199 return asset->mAsset->getLength(); 200} 201 202off64_t AAsset_getLength64(AAsset* asset) 203{ 204 return asset->mAsset->getLength(); 205} 206 207off_t AAsset_getRemainingLength(AAsset* asset) 208{ 209 return asset->mAsset->getRemainingLength(); 210} 211 212off64_t AAsset_getRemainingLength64(AAsset* asset) 213{ 214 return asset->mAsset->getRemainingLength(); 215} 216 217int AAsset_openFileDescriptor(AAsset* asset, off_t* outStart, off_t* outLength) 218{ 219 off64_t outStart64, outLength64; 220 221 int ret = asset->mAsset->openFileDescriptor(&outStart64, &outLength64); 222 223 *outStart = off_t(outStart64); 224 *outLength = off_t(outLength64); 225 return ret; 226} 227 228int AAsset_openFileDescriptor64(AAsset* asset, off64_t* outStart, off64_t* outLength) 229{ 230 return asset->mAsset->openFileDescriptor(outStart, outLength); 231} 232 233int AAsset_isAllocated(AAsset* asset) 234{ 235 return asset->mAsset->isAllocated() ? 1 : 0; 236} 237