Move property setting from libcutils to bionic.
All the other property stuff is already here. Property setting was only in libcutils previously to leverage a utility function / constant or two. Unfortunately in the process of fixing a race condition we would've had to do break abstraction boundaries and put some libc-internal details into libcutils so instead of that we'll just move this into bionic. Along with Iee1ca9b7, this now passes: $ adb shell am instrument -w -e class android.os.SystemPropertiesTest \ com.android.frameworks.coretests.systemproperties/android.test.InstrumentationTestRunner Bug: 3511230 Change-Id: I110b653a58f312fbe069dca59892a877ae9bc911
This commit is contained in:
parent
70828ae0ea
commit
4399df8f2e
@ -38,13 +38,14 @@
|
|||||||
#include <sys/select.h>
|
#include <sys/select.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
|
#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
|
||||||
#include <sys/_system_properties.h>
|
#include <sys/_system_properties.h>
|
||||||
|
|
||||||
#include <sys/atomics.h>
|
#include <sys/atomics.h>
|
||||||
|
|
||||||
static const char property_service_name[] = PROP_SERVICE_NAME;
|
static const char property_service_socket[] = "/dev/socket/" PROP_SERVICE_NAME;
|
||||||
|
|
||||||
static unsigned dummy_props = 0;
|
static unsigned dummy_props = 0;
|
||||||
|
|
||||||
@ -152,6 +153,114 @@ int __system_property_get(const char *name, char *value)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int send_prop_msg(prop_msg *msg)
|
||||||
|
{
|
||||||
|
struct sockaddr_un addr;
|
||||||
|
socklen_t alen;
|
||||||
|
size_t namelen;
|
||||||
|
int s;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
s = socket(AF_LOCAL, SOCK_STREAM, 0);
|
||||||
|
if(s < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&addr, 0, sizeof(addr));
|
||||||
|
namelen = strlen(property_service_socket);
|
||||||
|
strlcpy(addr.sun_path, property_service_socket, sizeof addr.sun_path);
|
||||||
|
addr.sun_family = AF_LOCAL;
|
||||||
|
alen = namelen + offsetof(struct sockaddr_un, sun_path) + 1;
|
||||||
|
|
||||||
|
if(TEMP_FAILURE_RETRY(connect(s, (struct sockaddr *) &addr, alen) < 0)) {
|
||||||
|
close(s);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = TEMP_FAILURE_RETRY(send(s, msg, sizeof(prop_msg), 0));
|
||||||
|
|
||||||
|
if(r == sizeof(prop_msg)) {
|
||||||
|
r = 0;
|
||||||
|
} else {
|
||||||
|
r = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
close(s);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
int __system_property_set(const char *key, const char *value)
|
||||||
|
{
|
||||||
|
unsigned old_serial;
|
||||||
|
volatile unsigned *serial;
|
||||||
|
prop_msg msg;
|
||||||
|
int err;
|
||||||
|
prop_area *pa = __system_property_area__;
|
||||||
|
int tries = 0;
|
||||||
|
int update_seen = 0;
|
||||||
|
|
||||||
|
if(key == 0) return -1;
|
||||||
|
if(value == 0) value = "";
|
||||||
|
if(strlen(key) >= PROP_NAME_MAX) return -1;
|
||||||
|
if(strlen(value) >= PROP_VALUE_MAX) return -1;
|
||||||
|
|
||||||
|
memset(&msg, 0, sizeof msg);
|
||||||
|
msg.cmd = PROP_MSG_SETPROP;
|
||||||
|
strlcpy(msg.name, key, sizeof msg.name);
|
||||||
|
strlcpy(msg.value, value, sizeof msg.value);
|
||||||
|
|
||||||
|
/* Note the system properties serial number before we do our update. */
|
||||||
|
const prop_info *pi = __system_property_find(key);
|
||||||
|
if(pi != NULL) {
|
||||||
|
serial = &pi->serial;
|
||||||
|
} else {
|
||||||
|
serial = &pa->serial;
|
||||||
|
}
|
||||||
|
old_serial = *serial;
|
||||||
|
|
||||||
|
err = send_prop_msg(&msg);
|
||||||
|
if(err < 0) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait for the shared memory page to be written back and be
|
||||||
|
* visible in our address space before returning to the caller
|
||||||
|
* who might reasonably expect subsequent reads to match what was
|
||||||
|
* just written.
|
||||||
|
*
|
||||||
|
* Sleep 5 ms after failed checks and only wait up to a 500 ms
|
||||||
|
* total, just in case the system property server fails to update
|
||||||
|
* for whatever reason.
|
||||||
|
*/
|
||||||
|
do {
|
||||||
|
struct timespec timeout;
|
||||||
|
timeout.tv_sec = 0;
|
||||||
|
timeout.tv_nsec = 2500000; // 2.5 ms
|
||||||
|
|
||||||
|
if(tries++ > 0) {
|
||||||
|
usleep(2500); // 2.5 ms
|
||||||
|
}
|
||||||
|
__futex_wait(serial, old_serial, &timeout);
|
||||||
|
if(pi != NULL) {
|
||||||
|
unsigned new_serial = *serial;
|
||||||
|
/* Waiting on a specific prop_info to be updated. */
|
||||||
|
if (old_serial != new_serial && !SERIAL_DIRTY(new_serial)) {
|
||||||
|
update_seen = 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Waiting for a prop_info to be created. */
|
||||||
|
const prop_info *new_pi = __system_property_find(key);
|
||||||
|
if(new_pi != NULL && !SERIAL_DIRTY(new_pi->serial)) {
|
||||||
|
update_seen = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (!update_seen && tries < 100);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int __system_property_wait(const prop_info *pi)
|
int __system_property_wait(const prop_info *pi)
|
||||||
{
|
{
|
||||||
unsigned n;
|
unsigned n;
|
||||||
|
@ -46,6 +46,10 @@ typedef struct prop_info prop_info;
|
|||||||
*/
|
*/
|
||||||
int __system_property_get(const char *name, char *value);
|
int __system_property_get(const char *name, char *value);
|
||||||
|
|
||||||
|
/* Set a system property by name.
|
||||||
|
**/
|
||||||
|
int __system_property_set(const char *key, const char *value);
|
||||||
|
|
||||||
/* Return a pointer to the system property named name, if it
|
/* Return a pointer to the system property named name, if it
|
||||||
** exists, or NULL if there is no such property. Use
|
** exists, or NULL if there is no such property. Use
|
||||||
** __system_property_read() to obtain the string value from
|
** __system_property_read() to obtain the string value from
|
||||||
|
Loading…
x
Reference in New Issue
Block a user