Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5e13e25d authored by John Wu's avatar John Wu
Browse files

[Ravenwood] Use native system property implementation

System properties are not only used by Java code, but also native code.
To make the property values consistent across Java and native code, make
the "source of truth" of property values on the native side.

In order to achieve this, we have to introduce a new native library
"libravenwood_sysprops" that does NOT link against libbase, and load
that library first. By doing so, we can override the low-level sysprop
function symbols with our own implementation.

Once that is done, all existing native code accessing system properties,
regardless whether they use the libbase/libcutils wrappers or the raw
sysprop functions will go through Ravenwood's implementation.

Other than improving system properties, this provides the infrastructure
to override/implement C functions that is used in native code.

Bug: 292141694
Flag: EXEMPT host test change only
Test: $ANDROID_BUILD_TOP/frameworks/base/ravenwood/scripts/run-ravenwood-tests.sh
Merged-in: I14678e2ac52ace0b23bd53df7b6092a1cbb881b3
Change-Id: I14678e2ac52ace0b23bd53df7b6092a1cbb881b3
parent 98346163
Loading
Loading
Loading
Loading
+12 −33
Original line number Diff line number Diff line
@@ -21,13 +21,10 @@ import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.ravenwood.annotation.RavenwoodKeepWholeClass;
import android.ravenwood.annotation.RavenwoodRedirect;
import android.ravenwood.annotation.RavenwoodRedirectionClass;
import android.util.Log;
import android.util.MutableInt;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.ravenwood.RavenwoodEnvironment;

import dalvik.annotation.optimization.CriticalNative;
import dalvik.annotation.optimization.FastNative;
@@ -40,8 +37,6 @@ import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Predicate;

/**
 * Gives access to the system properties store.  The system properties
@@ -58,7 +53,6 @@ import java.util.function.Predicate;
 */
@SystemApi
@RavenwoodKeepWholeClass
@RavenwoodRedirectionClass("SystemProperties_host")
public class SystemProperties {
    private static final String TAG = "SystemProperties";
    private static final boolean TRACK_KEY_ACCESS = false;
@@ -76,7 +70,7 @@ public class SystemProperties {

    @UnsupportedAppUsage
    @GuardedBy("sChangeCallbacks")
    static final ArrayList<Runnable> sChangeCallbacks = new ArrayList<Runnable>();
    private static final ArrayList<Runnable> sChangeCallbacks = new ArrayList<Runnable>();

    @GuardedBy("sRoReads")
    private static final HashMap<String, MutableInt> sRoReads =
@@ -102,19 +96,6 @@ public class SystemProperties {
        }
    }

    /** @hide */
    @RavenwoodRedirect
    public static void init$ravenwood(Map<String, String> values,
            Predicate<String> keyReadablePredicate, Predicate<String> keyWritablePredicate) {
        throw RavenwoodEnvironment.notSupportedOnDevice();
    }

    /** @hide */
    @RavenwoodRedirect
    public static void reset$ravenwood() {
        throw RavenwoodEnvironment.notSupportedOnDevice();
    }

    // The one-argument version of native_get used to be a regular native function. Nowadays,
    // we use the two-argument form of native_get all the time, but we can't just delete the
    // one-argument overload: apps use it via reflection, as the UnsupportedAppUsage annotation
@@ -126,46 +107,34 @@ public class SystemProperties {

    @FastNative
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
    @RavenwoodRedirect
    private static native String native_get(String key, String def);
    @FastNative
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
    @RavenwoodRedirect
    private static native int native_get_int(String key, int def);
    @FastNative
    @UnsupportedAppUsage
    @RavenwoodRedirect
    private static native long native_get_long(String key, long def);
    @FastNative
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
    @RavenwoodRedirect
    private static native boolean native_get_boolean(String key, boolean def);

    @FastNative
    @RavenwoodRedirect
    private static native long native_find(String name);
    @FastNative
    @RavenwoodRedirect
    private static native String native_get(long handle);
    @CriticalNative
    @RavenwoodRedirect
    private static native int native_get_int(long handle, int def);
    @CriticalNative
    @RavenwoodRedirect
    private static native long native_get_long(long handle, long def);
    @CriticalNative
    @RavenwoodRedirect
    private static native boolean native_get_boolean(long handle, boolean def);

    // _NOT_ FastNative: native_set performs IPC and can block
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
    @RavenwoodRedirect
    private static native void native_set(String key, String def);

    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
    @RavenwoodRedirect
    private static native void native_add_change_callback();
    @RavenwoodRedirect
    private static native void native_report_sysprop_change();

    /**
@@ -301,7 +270,7 @@ public class SystemProperties {
    }

    @SuppressWarnings("unused")  // Called from native code.
    static void callChangeCallbacks() {
    private static void callChangeCallbacks() {
        ArrayList<Runnable> callbacks = null;
        synchronized (sChangeCallbacks) {
            //Log.i("foo", "Calling " + sChangeCallbacks.size() + " change callbacks!");
@@ -326,6 +295,16 @@ public class SystemProperties {
        }
    }

    /**
     * Clear all callback changes.
     * @hide
     */
    public static void clearChangeCallbacksForTest() {
        synchronized (sChangeCallbacks) {
            sChangeCallbacks.clear();
        }
    }

    /**
     * Notifies listeners that a system property has changed
     * @hide
+0 −20
Original line number Diff line number Diff line
@@ -34,8 +34,6 @@

#if defined(__BIONIC__)
# include <sys/system_properties.h>
#else
struct prop_info;
#endif

namespace android {
@@ -46,7 +44,6 @@ using android::base::ParseBoolResult;
template<typename Functor>
void ReadProperty(const prop_info* prop, Functor&& functor)
{
#if defined(__BIONIC__)
    auto thunk = [](void* cookie,
                    const char* /*name*/,
                    const char* value,
@@ -54,9 +51,6 @@ void ReadProperty(const prop_info* prop, Functor&& functor)
        std::forward<Functor>(*static_cast<Functor*>(cookie))(value);
    };
    __system_property_read_callback(prop, thunk, &functor);
#else
    LOG(FATAL) << "fast property access supported only on device";
#endif
}

template<typename Functor>
@@ -66,16 +60,11 @@ void ReadProperty(JNIEnv* env, jstring keyJ, Functor&& functor)
    if (!key.c_str()) {
        return;
    }
#if defined(__BIONIC__)
    const prop_info* prop = __system_property_find(key.c_str());
    if (!prop) {
        return;
    }
    ReadProperty(prop, std::forward<Functor>(functor));
#else
    std::forward<Functor>(functor)(
        android::base::GetProperty(key.c_str(), "").c_str());
#endif
}

jstring SystemProperties_getSS(JNIEnv* env, jclass clazz, jstring keyJ,
@@ -132,17 +121,12 @@ jboolean SystemProperties_get_boolean(JNIEnv *env, jclass, jstring keyJ,

jlong SystemProperties_find(JNIEnv* env, jclass, jstring keyJ)
{
#if defined(__BIONIC__)
    ScopedUtfChars key(env, keyJ);
    if (!key.c_str()) {
        return 0;
    }
    const prop_info* prop = __system_property_find(key.c_str());
    return reinterpret_cast<jlong>(prop);
#else
    LOG(FATAL) << "fast property access supported only on device";
    __builtin_unreachable();  // Silence warning
#endif
}

jstring SystemProperties_getH(JNIEnv* env, jclass clazz, jlong propJ)
@@ -198,11 +182,7 @@ void SystemProperties_set(JNIEnv *env, jobject clazz, jstring keyJ,
    // request" failures).
    errno = 0;
    bool success;
#if defined(__BIONIC__)
    success = !__system_property_set(key.c_str(), value_c_str);
#else
    success = android::base::SetProperty(key.c_str(), value_c_str);
#endif
    if (!success) {
        if (errno != 0) {
            jniThrowExceptionFmt(env, "java/lang/RuntimeException",
+10 −9
Original line number Diff line number Diff line
@@ -23,11 +23,10 @@ import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import android.platform.test.ravenwood.RavenwoodRule;
import android.platform.test.ravenwood.RavenwoodConfig;

import androidx.test.filters.SmallTest;

import org.junit.Rule;
import org.junit.Test;

import java.util.Objects;
@@ -35,17 +34,19 @@ import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

public class SystemPropertiesTest {
    @Rule
    public final RavenwoodRule mRavenwood = new RavenwoodRule.Builder()
    private static final String KEY = "sys.testkey";
    private static final String UNSET_KEY = "Aiw7woh6ie4toh7W";
    private static final String PERSIST_KEY = "persist.sys.testkey";
    private static final String NONEXIST_KEY = "doesnotexist_2341431";

    @RavenwoodConfig.Config
    public static final RavenwoodConfig mRavenwood = new RavenwoodConfig.Builder()
            .setSystemPropertyMutable(KEY, null)
            .setSystemPropertyMutable(UNSET_KEY, null)
            .setSystemPropertyMutable(PERSIST_KEY, null)
            .setSystemPropertyImmutable(NONEXIST_KEY, null)
            .build();

    private static final String KEY = "sys.testkey";
    private static final String UNSET_KEY = "Aiw7woh6ie4toh7W";
    private static final String PERSIST_KEY = "persist.sys.testkey";

    @Test
    @SmallTest
    public void testStressPersistPropertyConsistency() throws Exception {
@@ -117,7 +118,7 @@ public class SystemPropertiesTest {
    @SmallTest
    public void testHandle() throws Exception {
        String value;
        SystemProperties.Handle handle = SystemProperties.find("doesnotexist_2341431");
        SystemProperties.Handle handle = SystemProperties.find(NONEXIST_KEY);
        assertNull(handle);
        SystemProperties.set(KEY, "abc");
        handle = SystemProperties.find(KEY);
+25 −9
Original line number Diff line number Diff line
@@ -267,25 +267,39 @@ filegroup {
    visibility: ["//frameworks/base"],
}

cc_library_shared {
    name: "libravenwood_runtime",
    host_supported: true,

cc_defaults {
    name: "ravenwood_jni_defaults",
    cflags: [
        "-Wall",
        "-Werror",
        "-Wno-unused-parameter",
        "-Wthread-safety",
    ],
    static_libs: [
        "libnativehelper_jvm",
    ],
    shared_libs: [
        "liblog",
    ],
}

// We need this as a separate library because we need to overload the
// sysprop symbols before libbase is loaded into the process
cc_library_host_shared {
    name: "libravenwood_sysprop",
    defaults: ["ravenwood_jni_defaults"],
    srcs: ["runtime-jni/ravenwood_sysprop.cpp"],
}

cc_library_host_shared {
    name: "libravenwood_runtime",
    defaults: ["ravenwood_jni_defaults"],
    srcs: [
        "runtime-jni/*.cpp",
        "runtime-jni/ravenwood_runtime.cpp",
        "runtime-jni/ravenwood_os_constants.cpp",
    ],

    shared_libs: [
        "libbase",
        "liblog",
        "libnativehelper",
        "libutils",
        "libcutils",
    ],
@@ -377,8 +391,10 @@ android_ravenwood_libgroup {
        "z00-all-updatable-modules-system-stubs",
    ],
    jni_libs: [
        "libandroid_runtime",
        // Libraries has to be loaded in the following order
        "libravenwood_sysprop",
        "libravenwood_runtime",
        "libandroid_runtime",
    ],
}

+1 −0
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@ public final class RavenwoodNativeLoader {
            android.util.Log.class,
            android.os.Parcel.class,
            android.os.Binder.class,
            android.os.SystemProperties.class,
            android.content.res.ApkAssets.class,
            android.content.res.AssetManager.class,
            android.content.res.StringBlock.class,
Loading