Skip to content

Commit

Permalink
Access resource data asset as a file descriptor
Browse files Browse the repository at this point in the history
  • Loading branch information
hevrard committed Mar 13, 2019
1 parent 31c9f51 commit e9385e6
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 34 deletions.
21 changes: 11 additions & 10 deletions gapir/cc/android/asset_replay_service.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,22 +33,23 @@ std::unique_ptr<ReplayService::Payload> AssetReplayService::getPayload(
AAsset* asset_payload = AAssetManager_open(
mAssetManager, kAssetPathPayloadBin, AASSET_MODE_STREAMING);

off64_t outStart;
off64_t outLength;
int fd = AAsset_openFileDescriptor64(asset_payload, &outStart, &outLength);
if (fd < 0) {
GAPID_FATAL("AssetReplayService::getPayload cannot open payload asset as a "
off64_t offset;
off64_t length;
int payload_fd = AAsset_openFileDescriptor64(asset_payload, &offset, &length);
if (payload_fd < 0) {
GAPID_FATAL("AssetReplayService::getPayload() cannot open payload asset as a "
"file descriptor (because the asset was stored compressed?)");
}
AAsset_close(asset_payload);

off_t ret = lseek(fd, outStart, SEEK_SET);
if (ret == (off_t)-1) {
GAPID_FATAL("AssetReplayService::getPayload lseek failed");
off64_t ret = lseek64(payload_fd, offset, SEEK_SET);
if (ret == (off64_t)-1) {
GAPID_FATAL("AssetReplayService::getPayload() lseek64 failed");
}

std::unique_ptr<replay_service::Payload> payload(new replay_service::Payload);
payload->ParseFromFileDescriptor(fd);
close(fd);
payload->ParseFromFileDescriptor(payload_fd);
close(payload_fd);
return std::unique_ptr<Payload>(new Payload(std::move(payload)));
}

Expand Down
55 changes: 32 additions & 23 deletions gapir/cc/android/asset_resource_cache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "core/cc/log.h"

#include <android/asset_manager.h>
#include <unistd.h>

namespace gapir {

Expand Down Expand Up @@ -54,25 +55,42 @@ std::unique_ptr<ResourceCache> AssetResourceCache::create(

AssetResourceCache::AssetResourceCache(AAssetManager *assetManager) {
mAssetManager = assetManager;
AAsset *asset_index = AAssetManager_open(
AAsset *asset_resource_index = AAssetManager_open(
mAssetManager, kAssetPathResourcesIndex, AASSET_MODE_STREAMING);

// Load the archive index in memory.
for (;;) {
uint32_t idSize;
if (!asset_read(asset_index, &idSize, sizeof(idSize))) break;
if (!asset_read(asset_resource_index, &idSize, sizeof(idSize))) break;
std::string id(idSize, 0);
uint64_t offset;
uint32_t size;
if (!asset_read(asset_index, &id.front(), idSize) ||
!asset_read(asset_index, &offset, sizeof(offset)) ||
!asset_read(asset_index, &size, sizeof(size))) {
if (!asset_read(asset_resource_index, &id.front(), idSize) ||
!asset_read(asset_resource_index, &offset, sizeof(offset)) ||
!asset_read(asset_resource_index, &size, sizeof(size))) {
break;
}
mRecords.emplace(id, AssetRecord{offset, size});
}

AAsset_close(asset_index);
AAsset_close(asset_resource_index);

// Open the resource data file descriptor
AAsset* asset_resource_data = AAssetManager_open(
mAssetManager, kAssetPathResourcesData, AASSET_MODE_STREAMING);
off64_t length;
mResourceDataFd = AAsset_openFileDescriptor64(asset_resource_data, &mResourceDataStart, &length);
if (mResourceDataFd < 0) {
GAPID_FATAL("AssetResourceCache::AssetResourceCache() cannot open resource "
"data asset as a file descriptor (due to compressed asset?)");
}
AAsset_close(asset_resource_data);
}

AssetResourceCache::~AssetResourceCache() {
if (mResourceDataFd >= 0) {
close(mResourceDataFd);
}
}

bool AssetResourceCache::putCache(const Resource &resource, const void *data) {
Expand All @@ -94,26 +112,17 @@ bool AssetResourceCache::loadCache(const Resource &resource, void *data) {

AssetRecord record = it->second;

// NOTE: if this implementation is too slow, two ways to speed it up:
// 1. Open resources.data only once in the creator in AASSET_MODE_RANDOM,
// save the resulting asset pointer as a field and just seek and read here
// 2. Store resources uncompressed (aapt flags -0), and obtain a file
// descriptor
// to them using AAssetOpenFileDescriptor64()

AAsset *asset_resources = AAssetManager_open(
mAssetManager, kAssetPathResourcesData, AASSET_MODE_STREAMING);
off_t seek = AAsset_seek64(asset_resources, record.offset, SEEK_SET);
if (seek == (off_t)-1) {
GAPID_FATAL("AssetResourceCache::loadCache() AAsset_seek64 failed");
off64_t offset = mResourceDataStart + record.offset;
off64_t ret = lseek64(mResourceDataFd, offset, SEEK_SET);
if (ret == (off64_t)-1) {
GAPID_FATAL("AssetResourceCache::loadCache() lseek64() failed");
}
int read = AAsset_read(asset_resources, data, record.size);
if (read != record.size) {
GAPID_FATAL("AssetResourceCache::loadCache() AAsset_read failed");
ssize_t size = read(mResourceDataFd, data, record.size);
if (size != record.size) {
GAPID_FATAL("AssetResourceCache::loadCache() read() failed: "
"expecting %u, got %zu", record.size, size);
}

AAsset_close(asset_resources);

return true;
}

Expand Down
5 changes: 4 additions & 1 deletion gapir/cc/android/asset_resource_cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class AssetResourceCache : public ResourceCache {
// Creates new asset cache.
static std::unique_ptr<ResourceCache> create(AAssetManager* assetManager);

virtual ~AssetResourceCache() {}
~AssetResourceCache();

// ResourceCache interface implementation
virtual bool putCache(const Resource& res, const void* resData) override;
Expand All @@ -55,6 +55,9 @@ class AssetResourceCache : public ResourceCache {
};
std::unordered_map<std::string, AssetRecord> mRecords;
AAssetManager* mAssetManager;
// File descriptor data to access resources
int mResourceDataFd;
off64_t mResourceDataStart;
};

} // namespace gapir
Expand Down

0 comments on commit e9385e6

Please sign in to comment.