Home | History | Annotate | Download | only in os
      1 /*
      2  * Copyright (C) 2006 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.os;
     18 
     19 import android.util.Log;
     20 import android.util.MutableInt;
     21 
     22 import com.android.internal.annotations.GuardedBy;
     23 
     24 import java.util.ArrayList;
     25 import java.util.HashMap;
     26 
     27 
     28 /**
     29  * Gives access to the system properties store.  The system properties
     30  * store contains a list of string key-value pairs.
     31  *
     32  * {@hide}
     33  */
     34 public class SystemProperties {
     35     private static final String TAG = "SystemProperties";
     36     private static final boolean TRACK_KEY_ACCESS = false;
     37 
     38     /**
     39      * Android O removed the property name length limit, but com.amazon.kindle 7.8.1.5
     40      * uses reflection to read this whenever text is selected (http://b/36095274).
     41      */
     42     public static final int PROP_NAME_MAX = Integer.MAX_VALUE;
     43 
     44     public static final int PROP_VALUE_MAX = 91;
     45 
     46     private static final ArrayList<Runnable> sChangeCallbacks = new ArrayList<Runnable>();
     47 
     48     @GuardedBy("sRoReads")
     49     private static final HashMap<String, MutableInt> sRoReads;
     50     static {
     51         if (TRACK_KEY_ACCESS) {
     52             sRoReads = new HashMap<>();
     53         } else {
     54             sRoReads = null;
     55         }
     56     }
     57 
     58     private static void onKeyAccess(String key) {
     59         if (!TRACK_KEY_ACCESS) return;
     60 
     61         if (key != null && key.startsWith("ro.")) {
     62             synchronized (sRoReads) {
     63                 MutableInt numReads = sRoReads.getOrDefault(key, null);
     64                 if (numReads == null) {
     65                     numReads = new MutableInt(0);
     66                     sRoReads.put(key, numReads);
     67                 }
     68                 numReads.value++;
     69                 if (numReads.value > 3) {
     70                     Log.d(TAG, "Repeated read (count=" + numReads.value
     71                             + ") of a read-only system property '" + key + "'",
     72                             new Exception());
     73                 }
     74             }
     75         }
     76     }
     77 
     78     private static native String native_get(String key);
     79     private static native String native_get(String key, String def);
     80     private static native int native_get_int(String key, int def);
     81     private static native long native_get_long(String key, long def);
     82     private static native boolean native_get_boolean(String key, boolean def);
     83     private static native void native_set(String key, String def);
     84     private static native void native_add_change_callback();
     85     private static native void native_report_sysprop_change();
     86 
     87     /**
     88      * Get the value for the given key.
     89      * @return an empty string if the key isn't found
     90      */
     91     public static String get(String key) {
     92         if (TRACK_KEY_ACCESS) onKeyAccess(key);
     93         return native_get(key);
     94     }
     95 
     96     /**
     97      * Get the value for the given key.
     98      * @return if the key isn't found, return def if it isn't null, or an empty string otherwise
     99      */
    100     public static String get(String key, String def) {
    101         if (TRACK_KEY_ACCESS) onKeyAccess(key);
    102         return native_get(key, def);
    103     }
    104 
    105     /**
    106      * Get the value for the given key, and return as an integer.
    107      * @param key the key to lookup
    108      * @param def a default value to return
    109      * @return the key parsed as an integer, or def if the key isn't found or
    110      *         cannot be parsed
    111      */
    112     public static int getInt(String key, int def) {
    113         if (TRACK_KEY_ACCESS) onKeyAccess(key);
    114         return native_get_int(key, def);
    115     }
    116 
    117     /**
    118      * Get the value for the given key, and return as a long.
    119      * @param key the key to lookup
    120      * @param def a default value to return
    121      * @return the key parsed as a long, or def if the key isn't found or
    122      *         cannot be parsed
    123      */
    124     public static long getLong(String key, long def) {
    125         if (TRACK_KEY_ACCESS) onKeyAccess(key);
    126         return native_get_long(key, def);
    127     }
    128 
    129     /**
    130      * Get the value for the given key, returned as a boolean.
    131      * Values 'n', 'no', '0', 'false' or 'off' are considered false.
    132      * Values 'y', 'yes', '1', 'true' or 'on' are considered true.
    133      * (case sensitive).
    134      * If the key does not exist, or has any other value, then the default
    135      * result is returned.
    136      * @param key the key to lookup
    137      * @param def a default value to return
    138      * @return the key parsed as a boolean, or def if the key isn't found or is
    139      *         not able to be parsed as a boolean.
    140      */
    141     public static boolean getBoolean(String key, boolean def) {
    142         if (TRACK_KEY_ACCESS) onKeyAccess(key);
    143         return native_get_boolean(key, def);
    144     }
    145 
    146     /**
    147      * Set the value for the given key.
    148      * @throws IllegalArgumentException if the value exceeds 92 characters
    149      */
    150     public static void set(String key, String val) {
    151         if (val != null && val.length() > PROP_VALUE_MAX) {
    152             throw newValueTooLargeException(key, val);
    153         }
    154         if (TRACK_KEY_ACCESS) onKeyAccess(key);
    155         native_set(key, val);
    156     }
    157 
    158     public static void addChangeCallback(Runnable callback) {
    159         synchronized (sChangeCallbacks) {
    160             if (sChangeCallbacks.size() == 0) {
    161                 native_add_change_callback();
    162             }
    163             sChangeCallbacks.add(callback);
    164         }
    165     }
    166 
    167     static void callChangeCallbacks() {
    168         synchronized (sChangeCallbacks) {
    169             //Log.i("foo", "Calling " + sChangeCallbacks.size() + " change callbacks!");
    170             if (sChangeCallbacks.size() == 0) {
    171                 return;
    172             }
    173             ArrayList<Runnable> callbacks = new ArrayList<Runnable>(sChangeCallbacks);
    174             for (int i=0; i<callbacks.size(); i++) {
    175                 callbacks.get(i).run();
    176             }
    177         }
    178     }
    179 
    180     private static IllegalArgumentException newValueTooLargeException(String key, String value) {
    181         return new IllegalArgumentException("value of system property '" + key + "' is longer than "
    182                 + PROP_VALUE_MAX + " characters: " + value);
    183     }
    184 
    185     /*
    186      * Notifies listeners that a system property has changed
    187      */
    188     public static void reportSyspropChanged() {
    189         native_report_sysprop_change();
    190     }
    191 }
    192