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 <nativehelper/JNIHelp.h> 28 29 using 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 // ----- 37 struct AAssetDir { 38 AssetDir* mAssetDir; 39 size_t mCurFileIndex; 40 String8 mCachedFileName; 41 42 explicit AAssetDir(AssetDir* dir) : mAssetDir(dir), mCurFileIndex(0) { } 43 ~AAssetDir() { delete mAssetDir; } 44 }; 45 46 47 // ----- 48 struct AAsset { 49 Asset* mAsset; 50 51 explicit AAsset(Asset* asset) : mAsset(asset) { } 52 ~AAsset() { delete mAsset; } 53 }; 54 55 // -------------------- Public native C API -------------------- 56 57 /** 58 * Supporting information 59 */ 60 61 static struct assetmanager_offsets_t 62 { 63 jfieldID mObject; 64 } gAssetManagerOffsets; 65 66 static volatile bool gJNIConfigured = false; 67 static Mutex gMutex; 68 69 /** 70 * Asset Manager functionality 71 */ 72 AAssetManager* 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", "J"); 80 gJNIConfigured = true; 81 } 82 } 83 84 return (AAssetManager*) env->GetLongField(assetManager, gAssetManagerOffsets.mObject); 85 } 86 87 AAsset* 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 116 AAssetDir* 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 126 const 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 151 void AAssetDir_rewind(AAssetDir* assetDir) 152 { 153 assetDir->mCurFileIndex = 0; 154 } 155 156 const char* AAssetDir_getFileName(AAssetDir* assetDir, int index) 157 { 158 assetDir->mCachedFileName = assetDir->mAssetDir->getFileName(index); 159 return assetDir->mCachedFileName.string(); 160 } 161 162 void AAssetDir_close(AAssetDir* assetDir) 163 { 164 delete assetDir; 165 } 166 167 /** 168 * Asset functionality 169 */ 170 171 int AAsset_read(AAsset* asset, void* buf, size_t count) 172 { 173 return asset->mAsset->read(buf, (size_t)count); 174 } 175 176 off_t AAsset_seek(AAsset* asset, off_t offset, int whence) 177 { 178 return asset->mAsset->seek(offset, whence); 179 } 180 181 off64_t AAsset_seek64(AAsset* asset, off64_t offset, int whence) 182 { 183 return asset->mAsset->seek(offset, whence); 184 } 185 186 void AAsset_close(AAsset* asset) 187 { 188 asset->mAsset->close(); 189 delete asset; 190 } 191 192 const void* AAsset_getBuffer(AAsset* asset) 193 { 194 return asset->mAsset->getBuffer(false); 195 } 196 197 off_t AAsset_getLength(AAsset* asset) 198 { 199 return asset->mAsset->getLength(); 200 } 201 202 off64_t AAsset_getLength64(AAsset* asset) 203 { 204 return asset->mAsset->getLength(); 205 } 206 207 off_t AAsset_getRemainingLength(AAsset* asset) 208 { 209 return asset->mAsset->getRemainingLength(); 210 } 211 212 off64_t AAsset_getRemainingLength64(AAsset* asset) 213 { 214 return asset->mAsset->getRemainingLength(); 215 } 216 217 int 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 228 int AAsset_openFileDescriptor64(AAsset* asset, off64_t* outStart, off64_t* outLength) 229 { 230 return asset->mAsset->openFileDescriptor(outStart, outLength); 231 } 232 233 int AAsset_isAllocated(AAsset* asset) 234 { 235 return asset->mAsset->isAllocated() ? 1 : 0; 236 } 237