How do I listen to changes in System Properties?

5,245 views
Skip to first unread message

saranya gopal

unread,
Apr 23, 2014, 7:10:25 AM4/23/14
to android-...@googlegroups.com
I want to listen to a change in a system property from my custom system service.
Is there a way to do it?
I was thinking I could use SystemProperties.addChangeCallback method.
Is that the way or is there a way to listen to a particular system property alone?

shridutt kothari

unread,
Apr 28, 2014, 8:17:48 AM4/28/14
to android-...@googlegroups.com
Hi Saranya,

yes, you can use SystemProperties.addChangeCallback method.

There are two ways of listening to a change in SystemProperty from your custom service:

1. You can create a method in your service which should fetch any Systemproperty and that method should call Looper.loop(); so that that loop will poll for SystemProperty time to time
    This implementation may not be optimized way of doing this but it is used in Android 4.4.2, you can see here http://androidxref.com/4.4.2_r2/xref/frameworks/base/services/java/com/android/server/SystemServer.java
 you can see at above link:
202        boolean disableStorage = SystemProperties.getBoolean("config.disable_storage", false);
203        boolean disableMedia = SystemProperties.getBoolean("config.disable_media", false);
204        boolean disableBluetooth = SystemProperties.getBoolean("config.disable_bluetooth", false);
205        boolean disableTelephony = SystemProperties.getBoolean("config.disable_telephony", false);
206        boolean disableLocation = SystemProperties.getBoolean("config.disable_location", false);
207        boolean disableSystemUI = SystemProperties.getBoolean("config.disable_systemui", false);
208        boolean disableNonCoreServices = SystemProperties.getBoolean("config.disable_noncore", false);
209        boolean disableNetwork = SystemProperties.getBoolean("config.disable_network", false);

These boolean variables are being checked in initAndLoop() method with the help of Looper.loop(); here you can notify your other components on any change in even a single SystemProperty.

2. Another way is to create static callback and get call for any change in any of SystemProperty, see the master branch's code for SystemService here: https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/java/android/os/SystemService.java

you can see in above link what  following code is doing:

  1.     private static Object sPropertyLock = new Object();

  2.     static {
  3.         SystemProperties.addChangeCallback(new Runnable() {
  4.             @Override
  5.             public void run() {
  6.                 synchronized (sPropertyLock) {
  7.                     sPropertyLock.notifyAll();
  8.                 }
  9.             }
  10.         });
  11.     }

  1.     /**
  2.      * Wait until given service has entered specific state.
  3.      */
  4.     public static void waitForState(String service, State state, long timeoutMillis)
  5.             throws TimeoutException {
  6.         final long endMillis = SystemClock.elapsedRealtime() + timeoutMillis;
  7.         while (true) {
  8.             synchronized (sPropertyLock) {
  9.                 final State currentState = getState(service);
  10.                 if (state.equals(currentState)) {
  11.                     return;
  12.                 }

  13.                 if (SystemClock.elapsedRealtime() >= endMillis) {
  14.                     throw new TimeoutException("Service " + service + " currently " + currentState
  15.                             + "; waited " + timeoutMillis + "ms for " + state);
  16.                 }

  17.                 try {
  18.                     sPropertyLock.wait(timeoutMillis);
  19.                 } catch (InterruptedException e) {
  20.                 }
  21.             }
  22.         }
  23.     }

  24.     /**
  25.      * Wait until any of given services enters {@link State#STOPPED}.
  26.      */
  27.     public static void waitForAnyStopped(String... services)  {
  28.         while (true) {
  29.             synchronized (sPropertyLock) {
  30.                 for (String service : services) {
  31.                     if (State.STOPPED.equals(getState(service))) {
  32.                         return;
  33.                     }
  34.                 }

  35.                 try {
  36.                     sPropertyLock.wait();
  37.                 } catch (InterruptedException e) {
  38.                 }
  39.             }
  40.         }
  41.     }


So you can see this is the another way of listening to SystemProperties,

I guess second one would be the optimized way to getting update for SystemProperties. even the first one is replaced in master branch and will be applicable in next release.

Thanks,
Shridutt Kothari,
Impetus Infotech India Ltd.

Yong Ma

unread,
May 16, 2018, 11:17:27 AM5/16/18
to android-platform
SystemProperties.addChangeCallback doesn't work. 

It only works when the writer call 

David White

unread,
Dec 18, 2019, 12:06:49 PM12/18/19
to android-platform
I know this thread is a bit old. But I am in need of the same. I have written my own Android service class and I do not wish to poll for settings changes - I really want callbacks or some other notification mechanism.

I having read the above material above as well as several other postings and the code shown here, I remain confused and unsuccessful in getting any callbacks.

I am following the lead of using reflection in my SystemPropertiesProxy class to get at the SystemProperties class and to invoke its addChangeCallback() method handing it my Runnable (that only logs a line right now). I have tried to issue

    obj.transact(SYSPROPS_TRANSACTION, data, null, 0);

as suggested but maybe I am doing something wrong. I have tried using a Binder within my own service as the obj. I have tried following the lead in the fore-mentioned link and iterated over all of the services from the ServiceManager and using each of them as the obj. None of this seems to work.

I know that some of the gsm.* system properties get changed when I toggle airplane mode on my device. So I am expecting to get at least one callback when airplane mode is toggled on/off. Yet, I have not managed it.

So is a more complete answer available?

Tommaso Merciai

unread,
Dec 19, 2019, 10:00:25 AM12/19/19
to android-platform
From apk Activity you can create a method like this:

/*Read Native property that cannot be readed using System.getproperties*/

private String getSystemProperty(String propertyName) {
        String propertyValue = "[UNKNOWN]";

        try {
            Process getPropProcess = Runtime.getRuntime().exec("getprop " + propertyName);

            BufferedReader osRes =
                    new BufferedReader(new InputStreamReader(getPropProcess.getInputStream()));

            propertyValue = osRes.readLine();

            osRes.close();
        } catch (Exception e) {
            // Do nothing - can't get property value
        }

        return propertyValue;
    }

/*Usage*/
String property = getSystemProperty("vendor.mycustomproperty");

From Android OS you can use init (device/vendor/board/init.board.rc) append:

on property:vendor.customproperty=1
     do something

Usage:
$ setprop vendor.customproperty 1

To check use getprop:

$ getprop vendor.customproperty


Regards.
Tommaso Merciai

David White

unread,
Dec 19, 2019, 12:44:52 PM12/19/19
to android-platform
Hi and thanks Tommaso. I am aware that I can read property values this way. I can even read them with Java using reflection techniques and the hidden, SystemProperties class. But that class also exposes an API for getting a callback whenever any system property is changed called addChangeCallback() and that is what I am trying to use. Otherwise my app will have poll and get properties on a regular basis and that is too much overhead for my needs. In the above posts it seems like someone has had some success in using addChangeCallback() but I cannot get it to work. I can call it without any error being thrown. But the Runnable I pass to the method never gets called. Cheers
Reply all
Reply to author
Forward
0 new messages