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 <android_runtime/android_util_AssetManager.h> 22 #include <androidfw/Asset.h> 23 #include <androidfw/AssetDir.h> 24 #include <androidfw/AssetManager.h> 25 #include <androidfw/AssetManager2.h> 26 #include <utils/threads.h> 27 28 #include "jni.h" 29 #include <nativehelper/JNIHelp.h> 30 31 using namespace android; 32 33 // -------------------- Backing implementation of the public API -------------------- 34 35 // AAssetManager is actually a secret typedef for an empty base class of AssetManager, 36 // but AAssetDir and AAsset are actual wrappers for isolation. 37 38 // ----- 39 struct AAssetDir { 40 std::unique_ptr<AssetDir> mAssetDir; 41 size_t mCurFileIndex; 42 String8 mCachedFileName; 43 44 explicit AAssetDir(std::unique_ptr<AssetDir> dir) : 45 mAssetDir(std::move(dir)), mCurFileIndex(0) { } 46 }; 47 48 49 // ----- 50 struct AAsset { 51 std::unique_ptr<Asset> mAsset; 52 53 explicit AAsset(std::unique_ptr<Asset> asset) : mAsset(std::move(asset)) { } 54 }; 55 56 // -------------------- Public native C API -------------------- 57 58 /** 59 * Asset Manager functionality 60 */ 61 AAssetManager* AAssetManager_fromJava(JNIEnv* env, jobject assetManager) 62 { 63 return (AAssetManager*) env->GetLongField(assetManager, gAssetManagerOffsets.mObject); 64 } 65 66 AAsset* AAssetManager_open(AAssetManager* amgr, const char* filename, int mode) 67 { 68 Asset::AccessMode amMode; 69 switch (mode) { 70 case AASSET_MODE_UNKNOWN: 71 amMode = Asset::ACCESS_UNKNOWN; 72 break; 73 case AASSET_MODE_RANDOM: 74 amMode = Asset::ACCESS_RANDOM; 75 break; 76 case AASSET_MODE_STREAMING: 77 amMode = Asset::ACCESS_STREAMING; 78 break; 79 case AASSET_MODE_BUFFER: 80 amMode = Asset::ACCESS_BUFFER; 81 break; 82 default: 83 return NULL; 84 } 85 86 ScopedLock<AssetManager2> locked_mgr(*AssetManagerForNdkAssetManager(amgr)); 87 std::unique_ptr<Asset> asset = locked_mgr->Open(filename, amMode); 88 if (asset == nullptr) { 89 return nullptr; 90 } 91 return new AAsset(std::move(asset)); 92 } 93 94 AAssetDir* AAssetManager_openDir(AAssetManager* amgr, const char* dirName) 95 { 96 ScopedLock<AssetManager2> locked_mgr(*AssetManagerForNdkAssetManager(amgr)); 97 return new AAssetDir(locked_mgr->OpenDir(dirName)); 98 } 99 100 /** 101 * AssetDir functionality 102 */ 103 104 const char* AAssetDir_getNextFileName(AAssetDir* assetDir) 105 { 106 const char* returnName = NULL; 107 size_t index = assetDir->mCurFileIndex; 108 const size_t max = assetDir->mAssetDir->getFileCount(); 109 110 // Find the next regular file; explicitly don't report directories even if the 111 // underlying implementation changes to report them. At that point we can add 112 // a more general iterator to this native interface set if appropriate. 113 while ((index < max) && (assetDir->mAssetDir->getFileType(index) != kFileTypeRegular)) { 114 index++; 115 } 116 117 // still in bounds? then the one at 'index' is the next to be reported; generate 118 // the string to return and advance the iterator for next time. 119 if (index < max) { 120 assetDir->mCachedFileName = assetDir->mAssetDir->getFileName(index); 121 returnName = assetDir->mCachedFileName.string(); 122 index++; 123 } 124 125 assetDir->mCurFileIndex = index; 126 return returnName; 127 } 128 129 void AAssetDir_rewind(AAssetDir* assetDir) 130 { 131 assetDir->mCurFileIndex = 0; 132 } 133 134 const char* AAssetDir_getFileName(AAssetDir* assetDir, int index) 135 { 136 assetDir->mCachedFileName = assetDir->mAssetDir->getFileName(index); 137 return assetDir->mCachedFileName.string(); 138 } 139 140 void AAssetDir_close(AAssetDir* assetDir) 141 { 142 delete assetDir; 143 } 144 145 /** 146 * Asset functionality 147 */ 148 149 int AAsset_read(AAsset* asset, void* buf, size_t count) 150 { 151 return asset->mAsset->read(buf, (size_t)count); 152 } 153 154 off_t AAsset_seek(AAsset* asset, off_t offset, int whence) 155 { 156 return asset->mAsset->seek(offset, whence); 157 } 158 159 off64_t AAsset_seek64(AAsset* asset, off64_t offset, int whence) 160 { 161 return asset->mAsset->seek(offset, whence); 162 } 163 164 void AAsset_close(AAsset* asset) 165 { 166 asset->mAsset->close(); 167 delete asset; 168 } 169 170 const void* AAsset_getBuffer(AAsset* asset) 171 { 172 return asset->mAsset->getBuffer(false); 173 } 174 175 off_t AAsset_getLength(AAsset* asset) 176 { 177 return asset->mAsset->getLength(); 178 } 179 180 off64_t AAsset_getLength64(AAsset* asset) 181 { 182 return asset->mAsset->getLength(); 183 } 184 185 off_t AAsset_getRemainingLength(AAsset* asset) 186 { 187 return asset->mAsset->getRemainingLength(); 188 } 189 190 off64_t AAsset_getRemainingLength64(AAsset* asset) 191 { 192 return asset->mAsset->getRemainingLength(); 193 } 194 195 int AAsset_openFileDescriptor(AAsset* asset, off_t* outStart, off_t* outLength) 196 { 197 off64_t outStart64, outLength64; 198 199 int ret = asset->mAsset->openFileDescriptor(&outStart64, &outLength64); 200 201 *outStart = off_t(outStart64); 202 *outLength = off_t(outLength64); 203 return ret; 204 } 205 206 int AAsset_openFileDescriptor64(AAsset* asset, off64_t* outStart, off64_t* outLength) 207 { 208 return asset->mAsset->openFileDescriptor(outStart, outLength); 209 } 210 211 int AAsset_isAllocated(AAsset* asset) 212 { 213 return asset->mAsset->isAllocated() ? 1 : 0; 214 } 215