Home | History | Annotate | Download | only in shadows
      1 package org.robolectric.shadows;
      2 
      3 import android.os.SystemProperties;
      4 import com.google.common.base.Preconditions;
      5 import java.io.IOException;
      6 import java.io.InputStream;
      7 import java.net.URL;
      8 import java.util.Properties;
      9 import org.robolectric.annotation.Implementation;
     10 import org.robolectric.annotation.Implements;
     11 import org.robolectric.annotation.Resetter;
     12 
     13 @Implements(value = SystemProperties.class, isInAndroidSdk = false)
     14 public class ShadowSystemProperties {
     15   private static Properties buildProperties = null;
     16 
     17   @Implementation
     18   public static String native_get(String key) {
     19     return native_get(key, "");
     20   }
     21 
     22   @Implementation
     23   public static String native_get(String key, String def) {
     24     String value = getProperty(key);
     25     return value == null ? def : value;
     26   }
     27 
     28   @Implementation
     29   public static int native_get_int(String key, int def) {
     30     String stringValue = getProperty(key);
     31     return stringValue == null ? def : Integer.parseInt(stringValue);
     32   }
     33 
     34   @Implementation
     35   public static long native_get_long(String key, long def) {
     36     String stringValue = getProperty(key);
     37     return stringValue == null ? def : Long.parseLong(stringValue);
     38   }
     39 
     40   @Implementation
     41   public static boolean native_get_boolean(String key, boolean def) {
     42     String stringValue = getProperty(key);
     43     if (stringValue == null) {
     44       return def;
     45     }
     46 
     47     switch (stringValue) {
     48       case "1":
     49       case "y":
     50       case "on":
     51       case "yes":
     52       case "true":
     53         return true;
     54       default:
     55         return false;
     56     }
     57   }
     58 
     59   @Implementation
     60   public static void native_set(String key, String val) {
     61     if (val == null) {
     62       loadProperties().remove(key);
     63     } else {
     64       loadProperties().setProperty(key, val);
     65     }
     66   }
     67 
     68   // ignored/unimplemented methods
     69   // private static native void native_add_change_callback();
     70   // private static native void native_report_sysprop_change();
     71 
     72   private static synchronized String getProperty(String key) {
     73     return loadProperties().getProperty(key);
     74   }
     75 
     76   private static synchronized Properties loadProperties() {
     77     if (buildProperties == null) {
     78       // load the prop from classpath
     79       ClassLoader cl = SystemProperties.class.getClassLoader();
     80       try (InputStream is = cl.getResourceAsStream("build.prop")) {
     81         Preconditions.checkNotNull(is, "could not find build.prop");
     82         buildProperties = new Properties();
     83         buildProperties.load(is);
     84         setDefaults(buildProperties);
     85       } catch (IOException e) {
     86         throw new RuntimeException("failed to load build.prop", e);
     87       }
     88     }
     89     return buildProperties;
     90   }
     91 
     92   private static void setDefaults(Properties buildProperties) {
     93     // The default generated build.prop can make this look like the emulator.
     94     // Override common default properties to indicate platform is robolectric
     95     // TODO: put these values directly in build.prop generated from build system
     96     buildProperties.setProperty("ro.build.fingerprint", "robolectric");
     97     buildProperties.setProperty("ro.product.device", "robolectric");
     98     buildProperties.setProperty("ro.product.name", "robolectric");
     99     buildProperties.setProperty("ro.product.model", "robolectric");
    100     buildProperties.setProperty("ro.hardware", "robolectric");
    101     buildProperties.setProperty("ro.build.characteristics", "robolectric");
    102 
    103     // for backwards-compatibility reasons, set CPUS to unknown/ARM
    104     buildProperties.setProperty("ro.product.cpu.abi", "unknown");
    105     buildProperties.setProperty("ro.product.cpu.abi2", "unknown");
    106     buildProperties.setProperty("ro.product.cpu.abilist", "armeabi-v7a");
    107     buildProperties.setProperty("ro.product.cpu.abilist32", "armeabi-v7a,armeabi");
    108     buildProperties.setProperty("ro.product.cpu.abilist64", "armeabi-v7a,armeabi");
    109   }
    110 
    111   @Resetter
    112   public static synchronized void reset() {
    113     buildProperties = null;
    114   }
    115 }
    116