| /* |
| * Copyright (C) 2010 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #define LOG_TAG "NAsset" |
| #include <utils/Log.h> |
| |
| #include <android/asset_manager_jni.h> |
| #include <android_runtime/android_util_AssetManager.h> |
| #include <androidfw/Asset.h> |
| #include <androidfw/AssetDir.h> |
| #include <androidfw/AssetManager.h> |
| #include <androidfw/AssetManager2.h> |
| #include <utils/threads.h> |
| |
| #include "jni.h" |
| #include <nativehelper/JNIHelp.h> |
| |
| using namespace android; |
| |
| // -------------------- Backing implementation of the public API -------------------- |
| |
| // AAssetManager is actually a secret typedef for an empty base class of AssetManager, |
| // but AAssetDir and AAsset are actual wrappers for isolation. |
| |
| // ----- |
| struct AAssetDir { |
| std::unique_ptr<AssetDir> mAssetDir; |
| size_t mCurFileIndex; |
| String8 mCachedFileName; |
| |
| explicit AAssetDir(std::unique_ptr<AssetDir> dir) : |
| mAssetDir(std::move(dir)), mCurFileIndex(0) { } |
| }; |
| |
| |
| // ----- |
| struct AAsset { |
| std::unique_ptr<Asset> mAsset; |
| |
| explicit AAsset(std::unique_ptr<Asset> asset) : mAsset(std::move(asset)) { } |
| }; |
| |
| // -------------------- Public native C API -------------------- |
| |
| /** |
| * Supporting information |
| */ |
| |
| static struct assetmanager_offsets_t |
| { |
| jfieldID mObject; |
| } gAssetManagerOffsets; |
| |
| static volatile bool gJNIConfigured = false; |
| static Mutex gMutex; |
| |
| /** |
| * Asset Manager functionality |
| */ |
| AAssetManager* AAssetManager_fromJava(JNIEnv* env, jobject assetManager) |
| { |
| { |
| Mutex::Autolock _l(gMutex); |
| |
| if (gJNIConfigured == false) { |
| jclass amClass = env->FindClass("android/content/res/AssetManager"); |
| gAssetManagerOffsets.mObject = env->GetFieldID(amClass, "mObject", "J"); |
| gJNIConfigured = true; |
| } |
| } |
| |
| return (AAssetManager*) env->GetLongField(assetManager, gAssetManagerOffsets.mObject); |
| } |
| |
| AAsset* AAssetManager_open(AAssetManager* amgr, const char* filename, int mode) |
| { |
| Asset::AccessMode amMode; |
| switch (mode) { |
| case AASSET_MODE_UNKNOWN: |
| amMode = Asset::ACCESS_UNKNOWN; |
| break; |
| case AASSET_MODE_RANDOM: |
| amMode = Asset::ACCESS_RANDOM; |
| break; |
| case AASSET_MODE_STREAMING: |
| amMode = Asset::ACCESS_STREAMING; |
| break; |
| case AASSET_MODE_BUFFER: |
| amMode = Asset::ACCESS_BUFFER; |
| break; |
| default: |
| return NULL; |
| } |
| |
| ScopedLock<AssetManager2> locked_mgr(*AssetManagerForNdkAssetManager(amgr)); |
| std::unique_ptr<Asset> asset = locked_mgr->Open(filename, amMode); |
| if (asset == nullptr) { |
| return nullptr; |
| } |
| return new AAsset(std::move(asset)); |
| } |
| |
| AAssetDir* AAssetManager_openDir(AAssetManager* amgr, const char* dirName) |
| { |
| ScopedLock<AssetManager2> locked_mgr(*AssetManagerForNdkAssetManager(amgr)); |
| return new AAssetDir(locked_mgr->OpenDir(dirName)); |
| } |
| |
| /** |
| * AssetDir functionality |
| */ |
| |
| const char* AAssetDir_getNextFileName(AAssetDir* assetDir) |
| { |
| const char* returnName = NULL; |
| size_t index = assetDir->mCurFileIndex; |
| const size_t max = assetDir->mAssetDir->getFileCount(); |
| |
| // Find the next regular file; explicitly don't report directories even if the |
| // underlying implementation changes to report them. At that point we can add |
| // a more general iterator to this native interface set if appropriate. |
| while ((index < max) && (assetDir->mAssetDir->getFileType(index) != kFileTypeRegular)) { |
| index++; |
| } |
| |
| // still in bounds? then the one at 'index' is the next to be reported; generate |
| // the string to return and advance the iterator for next time. |
| if (index < max) { |
| assetDir->mCachedFileName = assetDir->mAssetDir->getFileName(index); |
| returnName = assetDir->mCachedFileName.string(); |
| index++; |
| } |
| |
| assetDir->mCurFileIndex = index; |
| return returnName; |
| } |
| |
| void AAssetDir_rewind(AAssetDir* assetDir) |
| { |
| assetDir->mCurFileIndex = 0; |
| } |
| |
| const char* AAssetDir_getFileName(AAssetDir* assetDir, int index) |
| { |
| assetDir->mCachedFileName = assetDir->mAssetDir->getFileName(index); |
| return assetDir->mCachedFileName.string(); |
| } |
| |
| void AAssetDir_close(AAssetDir* assetDir) |
| { |
| delete assetDir; |
| } |
| |
| /** |
| * Asset functionality |
| */ |
| |
| int AAsset_read(AAsset* asset, void* buf, size_t count) |
| { |
| return asset->mAsset->read(buf, (size_t)count); |
| } |
| |
| off_t AAsset_seek(AAsset* asset, off_t offset, int whence) |
| { |
| return asset->mAsset->seek(offset, whence); |
| } |
| |
| off64_t AAsset_seek64(AAsset* asset, off64_t offset, int whence) |
| { |
| return asset->mAsset->seek(offset, whence); |
| } |
| |
| void AAsset_close(AAsset* asset) |
| { |
| asset->mAsset->close(); |
| delete asset; |
| } |
| |
| const void* AAsset_getBuffer(AAsset* asset) |
| { |
| return asset->mAsset->getBuffer(false); |
| } |
| |
| off_t AAsset_getLength(AAsset* asset) |
| { |
| return asset->mAsset->getLength(); |
| } |
| |
| off64_t AAsset_getLength64(AAsset* asset) |
| { |
| return asset->mAsset->getLength(); |
| } |
| |
| off_t AAsset_getRemainingLength(AAsset* asset) |
| { |
| return asset->mAsset->getRemainingLength(); |
| } |
| |
| off64_t AAsset_getRemainingLength64(AAsset* asset) |
| { |
| return asset->mAsset->getRemainingLength(); |
| } |
| |
| int AAsset_openFileDescriptor(AAsset* asset, off_t* outStart, off_t* outLength) |
| { |
| off64_t outStart64, outLength64; |
| |
| int ret = asset->mAsset->openFileDescriptor(&outStart64, &outLength64); |
| |
| *outStart = off_t(outStart64); |
| *outLength = off_t(outLength64); |
| return ret; |
| } |
| |
| int AAsset_openFileDescriptor64(AAsset* asset, off64_t* outStart, off64_t* outLength) |
| { |
| return asset->mAsset->openFileDescriptor(outStart, outLength); |
| } |
| |
| int AAsset_isAllocated(AAsset* asset) |
| { |
| return asset->mAsset->isAllocated() ? 1 : 0; |
| } |