2121#include < string.h>
2222
2323#include < utils/BlobCache.h>
24+ #include < utils/Errors.h>
2425#include < utils/Log.h>
2526
2627namespace android {
2728
29+ // BlobCache::Header::mMagicNumber value
30+ static const uint32_t blobCacheMagic = ' _Bb$' ;
31+
32+ // BlobCache::Header::mBlobCacheVersion value
33+ static const uint32_t blobCacheVersion = 1 ;
34+
35+ // BlobCache::Header::mDeviceVersion value
36+ static const uint32_t blobCacheDeviceVersion = 1 ;
37+
2838BlobCache::BlobCache (size_t maxKeySize, size_t maxValueSize, size_t maxTotalSize):
2939 mMaxKeySize (maxKeySize),
3040 mMaxValueSize (maxValueSize),
@@ -67,12 +77,10 @@ void BlobCache::set(const void* key, size_t keySize, const void* value,
6777 return ;
6878 }
6979
70- Mutex::Autolock lock (mMutex );
7180 sp<Blob> dummyKey (new Blob (key, keySize, false ));
7281 CacheEntry dummyEntry (dummyKey, NULL );
7382
7483 while (true ) {
75-
7684 ssize_t index = mCacheEntries .indexOf (dummyEntry);
7785 if (index < 0 ) {
7886 // Create a new cache entry.
@@ -129,7 +137,6 @@ size_t BlobCache::get(const void* key, size_t keySize, void* value,
129137 keySize, mMaxKeySize );
130138 return 0 ;
131139 }
132- Mutex::Autolock lock (mMutex );
133140 sp<Blob> dummyKey (new Blob (key, keySize, false ));
134141 CacheEntry dummyEntry (dummyKey, NULL );
135142 ssize_t index = mCacheEntries .indexOf (dummyEntry);
@@ -152,6 +159,133 @@ size_t BlobCache::get(const void* key, size_t keySize, void* value,
152159 return valueBlobSize;
153160}
154161
162+ static inline size_t align4 (size_t size) {
163+ return (size + 3 ) & ~3 ;
164+ }
165+
166+ size_t BlobCache::getFlattenedSize () const {
167+ size_t size = sizeof (Header);
168+ for (size_t i = 0 ; i < mCacheEntries .size (); i++) {
169+ const CacheEntry& e (mCacheEntries [i]);
170+ sp<Blob> keyBlob = e.getKey ();
171+ sp<Blob> valueBlob = e.getValue ();
172+ size = align4 (size);
173+ size += sizeof (EntryHeader) + keyBlob->getSize () +
174+ valueBlob->getSize ();
175+ }
176+ return size;
177+ }
178+
179+ size_t BlobCache::getFdCount () const {
180+ return 0 ;
181+ }
182+
183+ status_t BlobCache::flatten (void * buffer, size_t size, int fds[], size_t count)
184+ const {
185+ if (count != 0 ) {
186+ LOGE (" flatten: nonzero fd count: %d" , count);
187+ return BAD_VALUE;
188+ }
189+
190+ // Write the cache header
191+ if (size < sizeof (Header)) {
192+ LOGE (" flatten: not enough room for cache header" );
193+ return BAD_VALUE;
194+ }
195+ Header* header = reinterpret_cast <Header*>(buffer);
196+ header->mMagicNumber = blobCacheMagic;
197+ header->mBlobCacheVersion = blobCacheVersion;
198+ header->mDeviceVersion = blobCacheDeviceVersion;
199+ header->mNumEntries = mCacheEntries .size ();
200+
201+ // Write cache entries
202+ uint8_t * byteBuffer = reinterpret_cast <uint8_t *>(buffer);
203+ off_t byteOffset = align4 (sizeof (Header));
204+ for (size_t i = 0 ; i < mCacheEntries .size (); i++) {
205+ const CacheEntry& e (mCacheEntries [i]);
206+ sp<Blob> keyBlob = e.getKey ();
207+ sp<Blob> valueBlob = e.getValue ();
208+ size_t keySize = keyBlob->getSize ();
209+ size_t valueSize = valueBlob->getSize ();
210+
211+ size_t entrySize = sizeof (EntryHeader) + keySize + valueSize;
212+ if (byteOffset + entrySize > size) {
213+ LOGE (" flatten: not enough room for cache entries" );
214+ return BAD_VALUE;
215+ }
216+
217+ EntryHeader* eheader = reinterpret_cast <EntryHeader*>(
218+ &byteBuffer[byteOffset]);
219+ eheader->mKeySize = keySize;
220+ eheader->mValueSize = valueSize;
221+
222+ memcpy (eheader->mData , keyBlob->getData (), keySize);
223+ memcpy (eheader->mData + keySize, valueBlob->getData (), valueSize);
224+
225+ byteOffset += align4 (entrySize);
226+ }
227+
228+ return OK;
229+ }
230+
231+ status_t BlobCache::unflatten (void const * buffer, size_t size, int fds[],
232+ size_t count) {
233+ // All errors should result in the BlobCache being in an empty state.
234+ mCacheEntries .clear ();
235+
236+ if (count != 0 ) {
237+ LOGE (" unflatten: nonzero fd count: %d" , count);
238+ return BAD_VALUE;
239+ }
240+
241+ // Read the cache header
242+ if (size < sizeof (Header)) {
243+ LOGE (" unflatten: not enough room for cache header" );
244+ return BAD_VALUE;
245+ }
246+ const Header* header = reinterpret_cast <const Header*>(buffer);
247+ if (header->mMagicNumber != blobCacheMagic) {
248+ LOGE (" unflatten: bad magic number: %d" , header->mMagicNumber );
249+ return BAD_VALUE;
250+ }
251+ if (header->mBlobCacheVersion != blobCacheVersion ||
252+ header->mDeviceVersion != blobCacheDeviceVersion) {
253+ // We treat version mismatches as an empty cache.
254+ return OK;
255+ }
256+
257+ // Read cache entries
258+ const uint8_t * byteBuffer = reinterpret_cast <const uint8_t *>(buffer);
259+ off_t byteOffset = align4 (sizeof (Header));
260+ size_t numEntries = header->mNumEntries ;
261+ for (size_t i = 0 ; i < numEntries; i++) {
262+ if (byteOffset + sizeof (EntryHeader) > size) {
263+ mCacheEntries .clear ();
264+ LOGE (" unflatten: not enough room for cache entry headers" );
265+ return BAD_VALUE;
266+ }
267+
268+ const EntryHeader* eheader = reinterpret_cast <const EntryHeader*>(
269+ &byteBuffer[byteOffset]);
270+ size_t keySize = eheader->mKeySize ;
271+ size_t valueSize = eheader->mValueSize ;
272+ size_t entrySize = sizeof (EntryHeader) + keySize + valueSize;
273+
274+ if (byteOffset + entrySize > size) {
275+ mCacheEntries .clear ();
276+ LOGE (" unflatten: not enough room for cache entry headers" );
277+ return BAD_VALUE;
278+ }
279+
280+ const uint8_t * data = eheader->mData ;
281+ set (data, keySize, data + keySize, valueSize);
282+
283+ byteOffset += align4 (entrySize);
284+ }
285+
286+ return OK;
287+ }
288+
155289long int BlobCache::blob_random () {
156290#ifdef _WIN32
157291 return rand ();
@@ -179,7 +313,7 @@ BlobCache::Blob::Blob(const void* data, size_t size, bool copyData):
179313 mData (copyData ? malloc(size) : data),
180314 mSize (size),
181315 mOwnsData (copyData) {
182- if (copyData) {
316+ if (data != NULL && copyData) {
183317 memcpy (const_cast <void *>(mData ), data, size);
184318 }
185319}
0 commit comments