SystemProperties源碼分析 獲取 Android WIFI接口

**SystemProperties.java這個類是@hide的,**因此不對外公開,通常開發者是訪問不到的,可是咱們能夠經過反射機制來使用。經過反射取得wifi的接口名爲例!java

<!-- lang: java -->
public class SystemInfo{
    private Method methodGetProperty;
    private static SystemInfo instance = new SystemInfo();

    public static SystemInfo getInstance() {
      	return instance;
      }

    private SystemInfo(){
        Class classSystemProperties = Class.forName("android.os.SystemProperties");
         methodGetProperty = classSystemProperties.getMethod("get", String.class);
    }

    public String getProperty(String property) {
        if(methodGetProperty == null) return null;
      	try {

      	  return (String)methodGetProperty.invoke(null, property);

      	} catch(IllegalAccessException e) {
      	  Log.w(TAG, "Failed to get property");
      	} catch(InvocationTargetException e) {
      	  Log.w(TAG, "Exception thrown while getting property");
      	}
      	return null;
   }

   public static void main()
    {
        String interfaceName = 
                        SystemInfo.getInstance().getProperty("wifi.interface");
    }
}

下面經過Android源碼講解SystemProperties.javaandroid

SystemProperties.java 在android源碼的位置:frameworks/base/core/java/android/os/SystemProperties;shell

<!-- lang: java -->
public class SystemProperties
{
    public static final int PROP_NAME_MAX = 31;
    public static final int PROP_VALUE_MAX = 91;

    private static native String native_get(String key);
    private static native String native_get(String key, String def);
    private static native int native_get_int(String key, int def);
    private static native long native_get_long(String key, long def);
    private static native boolean native_get_boolean(String key, boolean def);
    private static native void native_set(String key, String def);
    
    public static String get(String key) {
        if (key.length() > PROP_NAME_MAX) {
            throw new IllegalArgumentException("key.length > " + PROP_NAME_MAX);
        }
        return native_get(key);
    }
    public static String get(String key, String def) {
        if (key.length() > PROP_NAME_MAX) {
            throw new IllegalArgumentException("key.length > " + PROP_NAME_MAX);
        }
        return native_get(key, def);
    }
}

這邊使用JNI調用了本地方法,這些方法位於:"frameworks/base/core/jni/android_os_SystemProperties.cpp"app

<!-- lang: cpp -->
#include "cutils/properties.h"
#include "jni.h"
#include "android_runtime/AndroidRuntime.h"
#include <nativehelper/JNIHelp.h>

namespace android
{
    static jstring SystemProperties_getSS(JNIEnv *env, jobject clazz,
                                          jstring keyJ, jstring defJ)
    {
        int len;
        const char* key;
        char buf[PROPERTY_VALUE_MAX];
        jstring rvJ = NULL;
    
        if (keyJ == NULL) {
            jniThrowNullPointerException(env, "key must not be null.");
            goto error;
        }
        key = env->GetStringUTFChars(keyJ, NULL);
        len = property_get(key, buf, "");
        if ((len <= 0) && (defJ != NULL)) {
            rvJ = defJ;
        } else if (len >= 0) {
            rvJ = env->NewStringUTF(buf);
        } else {
            rvJ = env->NewStringUTF("");
        }  
        env->ReleaseStringUTFChars(keyJ, key);
    error:
        return rvJ;
    }
    
    static jstring SystemProperties_getS(JNIEnv *env, jobject clazz,
                                          jstring keyJ)
    {
        return SystemProperties_getSS(env, clazz, keyJ, NULL);
    }
    
    static JNINativeMethod method_table[] = {
        { "native_get", "(Ljava/lang/String;)Ljava/lang/String;",
          (void*) SystemProperties_getS },
        { "native_get", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;",
          (void*) SystemProperties_getSS },
        { "native_get_int", "(Ljava/lang/String;I)I",
          (void*) SystemProperties_get_int },
        { "native_get_long", "(Ljava/lang/String;J)J",
          (void*) SystemProperties_get_long },
        { "native_get_boolean", "(Ljava/lang/String;Z)Z",
          (void*) SystemProperties_get_boolean },
        { "native_set", "(Ljava/lang/String;Ljava/lang/String;)V",
          (void*) SystemProperties_set },
    };
    int register_android_os_SystemProperties(JNIEnv *env)
    {
        return AndroidRuntime::registerNativeMethods(
            env, "android/os/SystemProperties",
            method_table, NELEM(method_table));
    }
    
};

其中JNINativeMethod是一個結構體,具體定義,請參考tcp

<!-- lang: cpp -->
#include "jni.h"

最後調用了 <!-- lang: cpp --> #include "android_runtime/AndroidRuntime.h"
中的方法:ionic

<!-- lang: cpp -->
int  register_android_os_SystemProperties(JNIEnv *env)

將本地方法註冊到虛擬機中ide

接下來咱們分析一下Android系統的Propertiesui

有一些特殊命名的屬性會有不一樣的效果spa

如ro.開頭的屬性是隻讀的debug

persist.開頭的屬性,即便重啓手機,仍然會存在

Android 的系統屬性包括兩部分:文件保存的持久屬性和每次開機導入的cache屬性。前者主要保存在下面幾個文件中(列出部分):

bionic/libc/include/sys/_system_properties.h

<!-- lang: cpp -->
#define PROP_SERVICE_NAME "property_service"
#define PROP_PATH_RAMDISK_DEFAULT  "/default.prop"
#define PROP_PATH_SYSTEM_BUILD     "/system/build.prop"
#define PROP_PATH_SYSTEM_DEFAULT   "/system/default.prop"
#define PROP_PATH_LOCAL_OVERRIDE   "/data/local.prop"

system/core/include/private/android_filesystem_config.h

<!-- lang: cpp -->
#define AID_ROOT             0  /* traditional unix root user */
#define AID_SYSTEM        1000  /* system server */
#define AID_RADIO         1001  /* telephony subsystem, RIL */
#define AID_DHCP          1014  /* dhcp client */
#define AID_SHELL         2000  /* adb and debug shell user */
#define AID_CACHE         2001  /* cache access */
#define AID_APP          10000 /* first app user */

system/core/init/property_service.c

系統屬性的命名必須如下面這些字段開頭,不一樣的字段須要不一樣的權限:

<!-- lang: cpp -->
struct {
    const char *prefix;
    unsigned int uid;
    unsigned int gid;
} property_perms[] = {
    { "net.rmnet0.",      AID_RADIO,    0 },
    { "net.gprs.",        AID_RADIO,    0 },
    { "net.ppp",          AID_RADIO,    0 },
    { "net.qmi",          AID_RADIO,    0 },
    { "net.lte",          AID_RADIO,    0 },
    { "net.cdma",         AID_RADIO,    0 },
    { "ril.",             AID_RADIO,    0 },
    { "gsm.",             AID_RADIO,    0 },
    { "persist.radio",    AID_RADIO,    0 },
    { "net.dns",          AID_RADIO,    0 },
    { "sys.usb.config",   AID_RADIO,    0 },
    { "net.",             AID_SYSTEM,   0 },
    { "dev.",             AID_SYSTEM,   0 },
    { "runtime.",         AID_SYSTEM,   0 },
    { "hw.",              AID_SYSTEM,   0 },
    { "sys.",             AID_SYSTEM,   0 },
    { "service.",         AID_SYSTEM,   0 },
    { "wlan.",            AID_SYSTEM,   0 },
    { "dhcp.",            AID_SYSTEM,   0 },
    { "dhcp.",            AID_DHCP,     0 },
    { "debug.",           AID_SHELL,    0 },
    { "log.",             AID_SHELL,    0 },
    { "service.adb.root", AID_SHELL,    0 },
    { "service.adb.tcp.port", AID_SHELL,    0 },
    { "persist.sys.",     AID_SYSTEM,   0 },
    { "persist.service.", AID_SYSTEM,   0 },
    { "persist.security.", AID_SYSTEM,   0 },
    { NULL, 0, 0 }
};
相關文章
相關標籤/搜索