Merge "liblp: Improve reliability of UpdatePartitionTable."
diff --git a/libcutils/Android.bp b/libcutils/Android.bp
index cdbb65f..58e59d6 100644
--- a/libcutils/Android.bp
+++ b/libcutils/Android.bp
@@ -65,7 +65,6 @@
"iosched_policy.cpp",
"load_file.cpp",
"native_handle.cpp",
- "open_memstream.c",
"record_stream.cpp",
"sched_policy.cpp",
"sockets.cpp",
diff --git a/libcutils/hashmap.cpp b/libcutils/hashmap.cpp
index 10e3b25..2a4a52e 100644
--- a/libcutils/hashmap.cpp
+++ b/libcutils/hashmap.cpp
@@ -36,7 +36,7 @@
size_t bucketCount;
int (*hash)(void* key);
bool (*equals)(void* keyA, void* keyB);
- mutex_t lock;
+ mutex_t lock;
size_t size;
};
@@ -44,18 +44,18 @@
int (*hash)(void* key), bool (*equals)(void* keyA, void* keyB)) {
assert(hash != NULL);
assert(equals != NULL);
-
+
Hashmap* map = static_cast<Hashmap*>(malloc(sizeof(Hashmap)));
if (map == NULL) {
return NULL;
}
-
+
// 0.75 load factor.
size_t minimumBucketCount = initialCapacity * 4 / 3;
map->bucketCount = 1;
while (map->bucketCount <= minimumBucketCount) {
// Bucket count must be power of 2.
- map->bucketCount <<= 1;
+ map->bucketCount <<= 1;
}
map->buckets = static_cast<Entry**>(calloc(map->bucketCount, sizeof(Entry*)));
@@ -63,14 +63,14 @@
free(map);
return NULL;
}
-
+
map->size = 0;
map->hash = hash;
map->equals = equals;
-
+
mutex_init(&map->lock);
-
+
return map;
}
@@ -89,12 +89,8 @@
h ^= (((unsigned int) h) >> 14);
h += (h << 4);
h ^= (((unsigned int) h) >> 10);
-
- return h;
-}
-size_t hashmapSize(Hashmap* map) {
- return map->size;
+ return h;
}
static inline size_t calculateIndex(size_t bucketCount, int hash) {
@@ -111,7 +107,7 @@
// Abort expansion.
return;
}
-
+
// Move over existing entries.
size_t i;
for (i = 0; i < map->bucketCount; i++) {
@@ -240,54 +236,6 @@
return NULL;
}
-bool hashmapContainsKey(Hashmap* map, void* key) {
- int hash = hashKey(map, key);
- size_t index = calculateIndex(map->bucketCount, hash);
-
- Entry* entry = map->buckets[index];
- while (entry != NULL) {
- if (equalKeys(entry->key, entry->hash, key, hash, map->equals)) {
- return true;
- }
- entry = entry->next;
- }
-
- return false;
-}
-
-void* hashmapMemoize(Hashmap* map, void* key,
- void* (*initialValue)(void* key, void* context), void* context) {
- int hash = hashKey(map, key);
- size_t index = calculateIndex(map->bucketCount, hash);
-
- Entry** p = &(map->buckets[index]);
- while (true) {
- Entry* current = *p;
-
- // Add a new entry.
- if (current == NULL) {
- *p = createEntry(key, hash, NULL);
- if (*p == NULL) {
- errno = ENOMEM;
- return NULL;
- }
- void* value = initialValue(key, context);
- (*p)->value = value;
- map->size++;
- expandIfNecessary(map);
- return value;
- }
-
- // Return existing value.
- if (equalKeys(current->key, current->hash, key, hash, map->equals)) {
- return current->value;
- }
-
- // Move to next entry.
- p = ¤t->next;
- }
-}
-
void* hashmapRemove(Hashmap* map, void* key) {
int hash = hashKey(map, key);
size_t index = calculateIndex(map->bucketCount, hash);
@@ -310,9 +258,8 @@
return NULL;
}
-void hashmapForEach(Hashmap* map,
- bool (*callback)(void* key, void* value, void* context),
- void* context) {
+void hashmapForEach(Hashmap* map, bool (*callback)(void* key, void* value, void* context),
+ void* context) {
size_t i;
for (i = 0; i < map->bucketCount; i++) {
Entry* entry = map->buckets[i];
@@ -325,34 +272,3 @@
}
}
}
-
-size_t hashmapCurrentCapacity(Hashmap* map) {
- size_t bucketCount = map->bucketCount;
- return bucketCount * 3 / 4;
-}
-
-size_t hashmapCountCollisions(Hashmap* map) {
- size_t collisions = 0;
- size_t i;
- for (i = 0; i < map->bucketCount; i++) {
- Entry* entry = map->buckets[i];
- while (entry != NULL) {
- if (entry->next != NULL) {
- collisions++;
- }
- entry = entry->next;
- }
- }
- return collisions;
-}
-
-int hashmapIntHash(void* key) {
- // Return the key value itself.
- return *((int*) key);
-}
-
-bool hashmapIntEquals(void* keyA, void* keyB) {
- int a = *((int*) keyA);
- int b = *((int*) keyB);
- return a == b;
-}
diff --git a/libcutils/include/cutils/hashmap.h b/libcutils/include/cutils/hashmap.h
index 5cb344c..9cfd669 100644
--- a/libcutils/include/cutils/hashmap.h
+++ b/libcutils/include/cutils/hashmap.h
@@ -16,6 +16,9 @@
/**
* Hash map.
+ *
+ * Use std::map or std::unordered_map instead.
+ * https://en.cppreference.com/w/cpp/container
*/
#ifndef __HASHMAP_H
@@ -68,38 +71,17 @@
void* hashmapGet(Hashmap* map, void* key);
/**
- * Returns true if the map contains an entry for the given key.
- */
-bool hashmapContainsKey(Hashmap* map, void* key);
-
-/**
- * Gets the value for a key. If a value is not found, this function gets a
- * value and creates an entry using the given callback.
- *
- * If memory allocation fails, the callback is not called, this function
- * returns NULL, and errno is set to ENOMEM.
- */
-void* hashmapMemoize(Hashmap* map, void* key,
- void* (*initialValue)(void* key, void* context), void* context);
-
-/**
* Removes an entry from the map. Returns the removed value or NULL if no
* entry was present.
*/
void* hashmapRemove(Hashmap* map, void* key);
/**
- * Gets the number of entries in this map.
- */
-size_t hashmapSize(Hashmap* map);
-
-/**
* Invokes the given callback on each entry in the map. Stops iterating if
* the callback returns false.
*/
-void hashmapForEach(Hashmap* map,
- bool (*callback)(void* key, void* value, void* context),
- void* context);
+void hashmapForEach(Hashmap* map, bool (*callback)(void* key, void* value, void* context),
+ void* context);
/**
* Concurrency support.
@@ -115,36 +97,8 @@
*/
void hashmapUnlock(Hashmap* map);
-/**
- * Key utilities.
- */
-
-/**
- * Hashes int keys. 'key' is a pointer to int.
- */
-int hashmapIntHash(void* key);
-
-/**
- * Compares two int keys for equality.
- */
-bool hashmapIntEquals(void* keyA, void* keyB);
-
-/**
- * For debugging.
- */
-
-/**
- * Gets current capacity.
- */
-size_t hashmapCurrentCapacity(Hashmap* map);
-
-/**
- * Counts the number of entry collisions.
- */
-size_t hashmapCountCollisions(Hashmap* map);
-
#ifdef __cplusplus
}
#endif
-#endif /* __HASHMAP_H */
+#endif /* __HASHMAP_H */
diff --git a/libcutils/include/cutils/open_memstream.h b/libcutils/include/cutils/open_memstream.h
deleted file mode 100644
index c1a81eb..0000000
--- a/libcutils/include/cutils/open_memstream.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef __CUTILS_OPEN_MEMSTREAM_H__
-#define __CUTILS_OPEN_MEMSTREAM_H__
-
-#include <stdio.h>
-
-#if defined(__APPLE__)
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-FILE* open_memstream(char** bufp, size_t* sizep);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __APPLE__ */
-
-#endif /*__CUTILS_OPEN_MEMSTREAM_H__*/
diff --git a/libcutils/include_vndk/cutils/open_memstream.h b/libcutils/include_vndk/cutils/open_memstream.h
deleted file mode 120000
index c894084..0000000
--- a/libcutils/include_vndk/cutils/open_memstream.h
+++ /dev/null
@@ -1 +0,0 @@
-../../include/cutils/open_memstream.h
\ No newline at end of file
diff --git a/libcutils/open_memstream.c b/libcutils/open_memstream.c
deleted file mode 100644
index 9183266..0000000
--- a/libcutils/open_memstream.c
+++ /dev/null
@@ -1,373 +0,0 @@
-/*
- * 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.
- */
-
-#if defined(__APPLE__)
-
-/*
- * Implementation of the POSIX open_memstream() function, which Linux has
- * but BSD lacks.
- *
- * Summary:
- * - Works like a file-backed FILE* opened with fopen(name, "w"), but the
- * backing is a chunk of memory rather than a file.
- * - The buffer expands as you write more data. Seeking past the end
- * of the file and then writing to it zero-fills the gap.
- * - The values at "*bufp" and "*sizep" should be considered read-only,
- * and are only valid immediately after an fflush() or fclose().
- * - A '\0' is maintained just past the end of the file. This is not included
- * in "*sizep". (The behavior w.r.t. fseek() is not clearly defined.
- * The spec says the null byte is written when a write() advances EOF,
- * but it looks like glibc ensures the null byte is always found at EOF,
- * even if you just seeked backwards. The example on the opengroup.org
- * page suggests that this is the expected behavior. The null must be
- * present after a no-op fflush(), which we can't see, so we have to save
- * and restore it. Annoying, but allows file truncation.)
- * - After fclose(), the caller must eventually free(*bufp).
- *
- * This is built out of funopen(), which BSD has but Linux lacks. There is
- * no flush() operator, so we need to keep the user pointers up to date
- * after each operation.
- *
- * I don't think Windows has any of the above, but we don't need to use
- * them there, so we just supply a stub.
- */
-#include <cutils/open_memstream.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <assert.h>
-
-#if 0
-# define DBUG(x) printf x
-#else
-# define DBUG(x) ((void)0)
-#endif
-
-/*
- * Definition of a seekable, write-only memory stream.
- */
-typedef struct {
- char** bufp; /* pointer to buffer pointer */
- size_t* sizep; /* pointer to eof */
-
- size_t allocSize; /* size of buffer */
- size_t eof; /* furthest point we've written to */
- size_t offset; /* current write offset */
- char saved; /* required by NUL handling */
-} MemStream;
-
-#define kInitialSize 1024
-
-/*
- * Ensure that we have enough storage to write "size" bytes at the
- * current offset. We also have to take into account the extra '\0'
- * that we maintain just past EOF.
- *
- * Returns 0 on success.
- */
-static int ensureCapacity(MemStream* stream, int writeSize)
-{
- DBUG(("+++ ensureCap off=%d size=%d\n", stream->offset, writeSize));
-
- size_t neededSize = stream->offset + writeSize + 1;
- if (neededSize <= stream->allocSize)
- return 0;
-
- size_t newSize;
-
- if (stream->allocSize == 0) {
- newSize = kInitialSize;
- } else {
- newSize = stream->allocSize;
- newSize += newSize / 2; /* expand by 3/2 */
- }
-
- if (newSize < neededSize)
- newSize = neededSize;
- DBUG(("+++ realloc %p->%p to size=%d\n",
- stream->bufp, *stream->bufp, newSize));
- char* newBuf = (char*) realloc(*stream->bufp, newSize);
- if (newBuf == NULL)
- return -1;
-
- *stream->bufp = newBuf;
- stream->allocSize = newSize;
- return 0;
-}
-
-/*
- * Write data to a memstream, expanding the buffer if necessary.
- *
- * If we previously seeked beyond EOF, zero-fill the gap.
- *
- * Returns the number of bytes written.
- */
-static int write_memstream(void* cookie, const char* buf, int size)
-{
- MemStream* stream = (MemStream*) cookie;
-
- if (ensureCapacity(stream, size) < 0)
- return -1;
-
- /* seeked past EOF earlier? */
- if (stream->eof < stream->offset) {
- DBUG(("+++ zero-fill gap from %d to %d\n",
- stream->eof, stream->offset-1));
- memset(*stream->bufp + stream->eof, '\0',
- stream->offset - stream->eof);
- }
-
- /* copy data, advance write pointer */
- memcpy(*stream->bufp + stream->offset, buf, size);
- stream->offset += size;
-
- if (stream->offset > stream->eof) {
- /* EOF has advanced, update it and append null byte */
- DBUG(("+++ EOF advanced to %d, appending nul\n", stream->offset));
- assert(stream->offset < stream->allocSize);
- stream->eof = stream->offset;
- } else {
- /* within previously-written area; save char we're about to stomp */
- DBUG(("+++ within written area, saving '%c' at %d\n",
- *(*stream->bufp + stream->offset), stream->offset));
- stream->saved = *(*stream->bufp + stream->offset);
- }
- *(*stream->bufp + stream->offset) = '\0';
- *stream->sizep = stream->offset;
-
- return size;
-}
-
-/*
- * Seek within a memstream.
- *
- * Returns the new offset, or -1 on failure.
- */
-static fpos_t seek_memstream(void* cookie, fpos_t offset, int whence)
-{
- MemStream* stream = (MemStream*) cookie;
- off_t newPosn = (off_t) offset;
-
- if (whence == SEEK_CUR) {
- newPosn += stream->offset;
- } else if (whence == SEEK_END) {
- newPosn += stream->eof;
- }
-
- if (newPosn < 0 || ((fpos_t)((size_t) newPosn)) != newPosn) {
- /* bad offset - negative or huge */
- DBUG(("+++ bogus seek offset %ld\n", (long) newPosn));
- errno = EINVAL;
- return (fpos_t) -1;
- }
-
- if (stream->offset < stream->eof) {
- /*
- * We were pointing to an area we'd already written to, which means
- * we stomped on a character and must now restore it.
- */
- DBUG(("+++ restoring char '%c' at %d\n",
- stream->saved, stream->offset));
- *(*stream->bufp + stream->offset) = stream->saved;
- }
-
- stream->offset = (size_t) newPosn;
-
- if (stream->offset < stream->eof) {
- /*
- * We're seeked backward into the stream. Preserve the character
- * at EOF and stomp it with a NUL.
- */
- stream->saved = *(*stream->bufp + stream->offset);
- *(*stream->bufp + stream->offset) = '\0';
- *stream->sizep = stream->offset;
- } else {
- /*
- * We're positioned at, or possibly beyond, the EOF. We want to
- * publish the current EOF, not the current position.
- */
- *stream->sizep = stream->eof;
- }
-
- return newPosn;
-}
-
-/*
- * Close the memstream. We free everything but the data buffer.
- */
-static int close_memstream(void* cookie)
-{
- free(cookie);
- return 0;
-}
-
-/*
- * Prepare a memstream.
- */
-FILE* open_memstream(char** bufp, size_t* sizep)
-{
- FILE* fp;
- MemStream* stream;
-
- if (bufp == NULL || sizep == NULL) {
- errno = EINVAL;
- return NULL;
- }
-
- stream = (MemStream*) calloc(1, sizeof(MemStream));
- if (stream == NULL)
- return NULL;
-
- fp = funopen(stream,
- NULL, write_memstream, seek_memstream, close_memstream);
- if (fp == NULL) {
- free(stream);
- return NULL;
- }
-
- *sizep = 0;
- *bufp = NULL;
- stream->bufp = bufp;
- stream->sizep = sizep;
-
- return fp;
-}
-
-
-
-
-#if 0
-#define _GNU_SOURCE
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-/*
- * Simple regression test.
- *
- * To test on desktop Linux with valgrind, it's possible to make a simple
- * change to open_memstream() to use fopencookie instead:
- *
- * cookie_io_functions_t iofuncs =
- * { NULL, write_memstream, seek_memstream, close_memstream };
- * fp = fopencookie(stream, "w", iofuncs);
- *
- * (Some tweaks to seek_memstream are also required, as that takes a
- * pointer to an offset rather than an offset, and returns 0 or -1.)
- */
-int testMemStream(void)
-{
- FILE *stream;
- char *buf;
- size_t len;
- off_t eob;
-
- printf("Test1\n");
-
- /* std example */
- stream = open_memstream(&buf, &len);
- fprintf(stream, "hello my world");
- fflush(stream);
- printf("buf=%s, len=%zu\n", buf, len);
- eob = ftello(stream);
- fseeko(stream, 0, SEEK_SET);
- fprintf(stream, "good-bye");
- fseeko(stream, eob, SEEK_SET);
- fclose(stream);
- printf("buf=%s, len=%zu\n", buf, len);
- free(buf);
-
- printf("Test2\n");
-
- /* std example without final seek-to-end */
- stream = open_memstream(&buf, &len);
- fprintf(stream, "hello my world");
- fflush(stream);
- printf("buf=%s, len=%zu\n", buf, len);
- eob = ftello(stream);
- fseeko(stream, 0, SEEK_SET);
- fprintf(stream, "good-bye");
- //fseeko(stream, eob, SEEK_SET);
- fclose(stream);
- printf("buf=%s, len=%zu\n", buf, len);
- free(buf);
-
- printf("Test3\n");
-
- /* fancy example; should expand buffer with writes */
- static const int kCmpLen = 1024 + 128;
- char* cmp = malloc(kCmpLen);
- memset(cmp, 0, 1024);
- memset(cmp+1024, 0xff, kCmpLen-1024);
- sprintf(cmp, "This-is-a-tes1234");
- sprintf(cmp + 1022, "abcdef");
-
- stream = open_memstream (&buf, &len);
- setvbuf(stream, NULL, _IONBF, 0); /* note: crashes in glibc with this */
- fprintf(stream, "This-is-a-test");
- fseek(stream, -1, SEEK_CUR); /* broken in glibc; can use {13,SEEK_SET} */
- fprintf(stream, "1234");
- fseek(stream, 1022, SEEK_SET);
- fputc('a', stream);
- fputc('b', stream);
- fputc('c', stream);
- fputc('d', stream);
- fputc('e', stream);
- fputc('f', stream);
- fflush(stream);
-
- if (memcmp(buf, cmp, len+1) != 0) {
- printf("mismatch\n");
- } else {
- printf("match\n");
- }
-
- printf("Test4\n");
- stream = open_memstream (&buf, &len);
- fseek(stream, 5000, SEEK_SET);
- fseek(stream, 4096, SEEK_SET);
- fseek(stream, -1, SEEK_SET); /* should have no effect */
- fputc('x', stream);
- if (ftell(stream) == 4097)
- printf("good\n");
- else
- printf("BAD: offset is %ld\n", ftell(stream));
-
- printf("DONE\n");
-
- return 0;
-}
-
-/* expected output:
-Test1
-buf=hello my world, len=14
-buf=good-bye world, len=14
-Test2
-buf=hello my world, len=14
-buf=good-bye, len=8
-Test3
-match
-Test4
-good
-DONE
-*/
-
-#endif
-
-#endif /* __APPLE__ */
diff --git a/libcutils/str_parms.cpp b/libcutils/str_parms.cpp
index f5a52a7..d818c51 100644
--- a/libcutils/str_parms.cpp
+++ b/libcutils/str_parms.cpp
@@ -354,12 +354,8 @@
char *str_parms_to_str(struct str_parms *str_parms)
{
char *str = NULL;
-
- if (hashmapSize(str_parms->map) > 0)
- hashmapForEach(str_parms->map, combine_strings, &str);
- else
- str = strdup("");
- return str;
+ hashmapForEach(str_parms->map, combine_strings, &str);
+ return (str != NULL) ? str : strdup("");
}
static bool dump_entry(void* key, void* value, void* /*context*/) {
diff --git a/libnativeloader/include/nativeloader/native_loader.h b/libnativeloader/include/nativeloader/native_loader.h
index 3563fc1..19a1783 100644
--- a/libnativeloader/include/nativeloader/native_loader.h
+++ b/libnativeloader/include/nativeloader/native_loader.h
@@ -53,8 +53,21 @@
#if defined(__ANDROID__)
// Look up linker namespace by class_loader. Returns nullptr if
// there is no namespace associated with the class_loader.
+// TODO(b/79940628): move users to FindNativeLoaderNamespaceByClassLoader and remove this function.
__attribute__((visibility("default")))
android_namespace_t* FindNamespaceByClassLoader(JNIEnv* env, jobject class_loader);
+// That version works with native bridge namespaces, but requires use of OpenNativeLibrary.
+class NativeLoaderNamespace;
+__attribute__((visibility("default")))
+NativeLoaderNamespace* FindNativeLoaderNamespaceByClassLoader(
+ JNIEnv* env, jobject class_loader);
+// Load library. Unlinke OpenNativeLibrary above couldn't create namespace on demand, but does
+// not require access to JNIEnv either.
+__attribute__((visibility("default")))
+void* OpenNativeLibrary(NativeLoaderNamespace* ns,
+ const char* path,
+ bool* needs_native_bridge,
+ std::string* error_msg);
#endif
__attribute__((visibility("default")))
diff --git a/libnativeloader/native_loader.cpp b/libnativeloader/native_loader.cpp
index 7fef106..67c1c10 100644
--- a/libnativeloader/native_loader.cpp
+++ b/libnativeloader/native_loader.cpp
@@ -29,6 +29,7 @@
#include "nativebridge/native_bridge.h"
#include <algorithm>
+#include <list>
#include <memory>
#include <mutex>
#include <string>
@@ -150,15 +151,14 @@
public:
LibraryNamespaces() : initialized_(false) { }
- bool Create(JNIEnv* env,
- uint32_t target_sdk_version,
- jobject class_loader,
- bool is_shared,
- bool is_for_vendor,
- jstring java_library_path,
- jstring java_permitted_path,
- NativeLoaderNamespace* ns,
- std::string* error_msg) {
+ NativeLoaderNamespace* Create(JNIEnv* env,
+ uint32_t target_sdk_version,
+ jobject class_loader,
+ bool is_shared,
+ bool is_for_vendor,
+ jstring java_library_path,
+ jstring java_permitted_path,
+ std::string* error_msg) {
std::string library_path; // empty string by default.
if (java_library_path != nullptr) {
@@ -182,10 +182,10 @@
}
if (!initialized_ && !InitPublicNamespace(library_path.c_str(), error_msg)) {
- return false;
+ return nullptr;
}
- bool found = FindNamespaceByClassLoader(env, class_loader, nullptr);
+ bool found = FindNamespaceByClassLoader(env, class_loader);
LOG_ALWAYS_FATAL_IF(found,
"There is already a namespace associated with this classloader");
@@ -199,13 +199,12 @@
namespace_type |= ANDROID_NAMESPACE_TYPE_GREYLIST_ENABLED;
}
- NativeLoaderNamespace parent_ns;
- bool found_parent_namespace = FindParentNamespaceByClassLoader(env, class_loader, &parent_ns);
+ NativeLoaderNamespace* parent_ns = FindParentNamespaceByClassLoader(env, class_loader);
bool is_native_bridge = false;
- if (found_parent_namespace) {
- is_native_bridge = !parent_ns.is_android_namespace();
+ if (parent_ns != nullptr) {
+ is_native_bridge = !parent_ns->is_android_namespace();
} else if (!library_path.empty()) {
is_native_bridge = NativeBridgeIsPathSupported(library_path.c_str());
}
@@ -251,15 +250,17 @@
NativeLoaderNamespace native_loader_ns;
if (!is_native_bridge) {
+ android_namespace_t* android_parent_ns =
+ parent_ns == nullptr ? nullptr : parent_ns->get_android_ns();
android_namespace_t* ns = android_create_namespace(namespace_name,
nullptr,
library_path.c_str(),
namespace_type,
permitted_path.c_str(),
- parent_ns.get_android_ns());
+ android_parent_ns);
if (ns == nullptr) {
*error_msg = dlerror();
- return false;
+ return nullptr;
}
// Note that when vendor_ns is not configured this function will return nullptr
@@ -269,49 +270,50 @@
if (!android_link_namespaces(ns, nullptr, system_exposed_libraries.c_str())) {
*error_msg = dlerror();
- return false;
+ return nullptr;
}
if (vndk_ns != nullptr && !system_vndksp_libraries_.empty()) {
// vendor apks are allowed to use VNDK-SP libraries.
if (!android_link_namespaces(ns, vndk_ns, system_vndksp_libraries_.c_str())) {
*error_msg = dlerror();
- return false;
+ return nullptr;
}
}
if (!vendor_public_libraries_.empty()) {
if (!android_link_namespaces(ns, vendor_ns, vendor_public_libraries_.c_str())) {
*error_msg = dlerror();
- return false;
+ return nullptr;
}
}
native_loader_ns = NativeLoaderNamespace(ns);
} else {
+ native_bridge_namespace_t* native_bridge_parent_namespace =
+ parent_ns == nullptr ? nullptr : parent_ns->get_native_bridge_ns();
native_bridge_namespace_t* ns = NativeBridgeCreateNamespace(namespace_name,
nullptr,
library_path.c_str(),
namespace_type,
permitted_path.c_str(),
- parent_ns.get_native_bridge_ns());
-
+ native_bridge_parent_namespace);
if (ns == nullptr) {
*error_msg = NativeBridgeGetError();
- return false;
+ return nullptr;
}
native_bridge_namespace_t* vendor_ns = NativeBridgeGetVendorNamespace();
if (!NativeBridgeLinkNamespaces(ns, nullptr, system_exposed_libraries.c_str())) {
*error_msg = NativeBridgeGetError();
- return false;
+ return nullptr;
}
if (!vendor_public_libraries_.empty()) {
if (!NativeBridgeLinkNamespaces(ns, vendor_ns, vendor_public_libraries_.c_str())) {
*error_msg = NativeBridgeGetError();
- return false;
+ return nullptr;
}
}
@@ -320,24 +322,19 @@
namespaces_.push_back(std::make_pair(env->NewWeakGlobalRef(class_loader), native_loader_ns));
- *ns = native_loader_ns;
- return true;
+ return &(namespaces_.back().second);
}
- bool FindNamespaceByClassLoader(JNIEnv* env, jobject class_loader, NativeLoaderNamespace* ns) {
+ NativeLoaderNamespace* FindNamespaceByClassLoader(JNIEnv* env, jobject class_loader) {
auto it = std::find_if(namespaces_.begin(), namespaces_.end(),
[&](const std::pair<jweak, NativeLoaderNamespace>& value) {
return env->IsSameObject(value.first, class_loader);
});
if (it != namespaces_.end()) {
- if (ns != nullptr) {
- *ns = it->second;
- }
-
- return true;
+ return &it->second;
}
- return false;
+ return nullptr;
}
void Initialize() {
@@ -557,24 +554,23 @@
return env->CallObjectMethod(class_loader, get_parent);
}
- bool FindParentNamespaceByClassLoader(JNIEnv* env,
- jobject class_loader,
- NativeLoaderNamespace* ns) {
+ NativeLoaderNamespace* FindParentNamespaceByClassLoader(JNIEnv* env, jobject class_loader) {
jobject parent_class_loader = GetParentClassLoader(env, class_loader);
while (parent_class_loader != nullptr) {
- if (FindNamespaceByClassLoader(env, parent_class_loader, ns)) {
- return true;
+ NativeLoaderNamespace* ns;
+ if ((ns = FindNamespaceByClassLoader(env, parent_class_loader)) != nullptr) {
+ return ns;
}
parent_class_loader = GetParentClassLoader(env, parent_class_loader);
}
- return false;
+ return nullptr;
}
bool initialized_;
- std::vector<std::pair<jweak, NativeLoaderNamespace>> namespaces_;
+ std::list<std::pair<jweak, NativeLoaderNamespace>> namespaces_;
std::string system_public_libraries_;
std::string vendor_public_libraries_;
std::string oem_public_libraries_;
@@ -614,7 +610,6 @@
std::lock_guard<std::mutex> guard(g_namespaces_mutex);
std::string error_msg;
- NativeLoaderNamespace ns;
bool success = g_namespaces->Create(env,
target_sdk_version,
class_loader,
@@ -622,8 +617,7 @@
is_for_vendor,
library_path,
permitted_path,
- &ns,
- &error_msg);
+ &error_msg) != nullptr;
if (!success) {
return env->NewStringUTF(error_msg.c_str());
}
@@ -649,43 +643,24 @@
}
std::lock_guard<std::mutex> guard(g_namespaces_mutex);
- NativeLoaderNamespace ns;
+ NativeLoaderNamespace* ns;
- if (!g_namespaces->FindNamespaceByClassLoader(env, class_loader, &ns)) {
+ if ((ns = g_namespaces->FindNamespaceByClassLoader(env, class_loader)) == nullptr) {
// This is the case where the classloader was not created by ApplicationLoaders
// In this case we create an isolated not-shared namespace for it.
- if (!g_namespaces->Create(env,
- target_sdk_version,
- class_loader,
- false /* is_shared */,
- false /* is_for_vendor */,
- library_path,
- nullptr,
- &ns,
- error_msg)) {
+ if ((ns = g_namespaces->Create(env,
+ target_sdk_version,
+ class_loader,
+ false /* is_shared */,
+ false /* is_for_vendor */,
+ library_path,
+ nullptr,
+ error_msg)) == nullptr) {
return nullptr;
}
}
- if (ns.is_android_namespace()) {
- android_dlextinfo extinfo;
- extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
- extinfo.library_namespace = ns.get_android_ns();
-
- void* handle = android_dlopen_ext(path, RTLD_NOW, &extinfo);
- if (handle == nullptr) {
- *error_msg = dlerror();
- }
- *needs_native_bridge = false;
- return handle;
- } else {
- void* handle = NativeBridgeLoadLibraryExt(path, RTLD_NOW, ns.get_native_bridge_ns());
- if (handle == nullptr) {
- *error_msg = NativeBridgeGetError();
- }
- *needs_native_bridge = true;
- return handle;
- }
+ return OpenNativeLibrary(ns, path, needs_native_bridge, error_msg);
#else
UNUSED(env, target_sdk_version, class_loader);
@@ -741,18 +716,45 @@
}
#if defined(__ANDROID__)
+void* OpenNativeLibrary(NativeLoaderNamespace* ns, const char* path, bool* needs_native_bridge,
+ std::string* error_msg) {
+ if (ns->is_android_namespace()) {
+ android_dlextinfo extinfo;
+ extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
+ extinfo.library_namespace = ns->get_android_ns();
+
+ void* handle = android_dlopen_ext(path, RTLD_NOW, &extinfo);
+ if (handle == nullptr) {
+ *error_msg = dlerror();
+ }
+ *needs_native_bridge = false;
+ return handle;
+ } else {
+ void* handle = NativeBridgeLoadLibraryExt(path, RTLD_NOW, ns->get_native_bridge_ns());
+ if (handle == nullptr) {
+ *error_msg = NativeBridgeGetError();
+ }
+ *needs_native_bridge = true;
+ return handle;
+ }
+}
+
// native_bridge_namespaces are not supported for callers of this function.
// This function will return nullptr in the case when application is running
// on native bridge.
android_namespace_t* FindNamespaceByClassLoader(JNIEnv* env, jobject class_loader) {
std::lock_guard<std::mutex> guard(g_namespaces_mutex);
- NativeLoaderNamespace ns;
- if (g_namespaces->FindNamespaceByClassLoader(env, class_loader, &ns)) {
- return ns.is_android_namespace() ? ns.get_android_ns() : nullptr;
+ NativeLoaderNamespace* ns = g_namespaces->FindNamespaceByClassLoader(env, class_loader);
+ if (ns != nullptr) {
+ return ns->is_android_namespace() ? ns->get_android_ns() : nullptr;
}
return nullptr;
}
+NativeLoaderNamespace* FindNativeLoaderNamespaceByClassLoader(JNIEnv* env, jobject class_loader) {
+ std::lock_guard<std::mutex> guard(g_namespaces_mutex);
+ return g_namespaces->FindNamespaceByClassLoader(env, class_loader);
+}
#endif
}; // android namespace