Home | History | Annotate | Download | only in libutils
      1 /*
      2  * Copyright (C) 2005 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 #define LOG_TAG "misc"
     18 
     19 #include <utils/misc.h>
     20 
     21 #include <pthread.h>
     22 
     23 #include <utils/Log.h>
     24 #include <utils/Vector.h>
     25 
     26 #if defined(__ANDROID__)
     27 #include <dlfcn.h>
     28 #include <vndksupport/linker.h>
     29 #endif
     30 
     31 extern "C" void do_report_sysprop_change();
     32 
     33 using namespace android;
     34 
     35 namespace android {
     36 
     37 struct sysprop_change_callback_info {
     38     sysprop_change_callback callback;
     39     int priority;
     40 };
     41 
     42 #if !defined(_WIN32)
     43 static pthread_mutex_t gSyspropMutex = PTHREAD_MUTEX_INITIALIZER;
     44 static Vector<sysprop_change_callback_info>* gSyspropList = NULL;
     45 #endif
     46 
     47 #if !defined(_WIN32)
     48 void add_sysprop_change_callback(sysprop_change_callback cb, int priority) {
     49     pthread_mutex_lock(&gSyspropMutex);
     50     if (gSyspropList == NULL) {
     51         gSyspropList = new Vector<sysprop_change_callback_info>();
     52     }
     53     sysprop_change_callback_info info;
     54     info.callback = cb;
     55     info.priority = priority;
     56     bool added = false;
     57     for (size_t i=0; i<gSyspropList->size(); i++) {
     58         if (priority >= gSyspropList->itemAt(i).priority) {
     59             gSyspropList->insertAt(info, i);
     60             added = true;
     61             break;
     62         }
     63     }
     64     if (!added) {
     65         gSyspropList->add(info);
     66     }
     67     pthread_mutex_unlock(&gSyspropMutex);
     68 }
     69 #else
     70 void add_sysprop_change_callback(sysprop_change_callback, int) {}
     71 #endif
     72 
     73 #if defined(__ANDROID__)
     74 void (*get_report_sysprop_change_func())() {
     75     void (*func)() = nullptr;
     76     void* handle = android_load_sphal_library("libutils.so", RTLD_NOW);
     77     if (handle != nullptr) {
     78         func = reinterpret_cast<decltype(func)>(dlsym(handle, "do_report_sysprop_change"));
     79     }
     80 
     81     return func;
     82 }
     83 #endif
     84 
     85 void report_sysprop_change() {
     86     do_report_sysprop_change();
     87 
     88 #if defined(__ANDROID__)
     89     // libutils.so is double loaded; from the default namespace and from the
     90     // 'sphal' namespace. Redirect the sysprop change event to the other instance
     91     // of libutils.so loaded in the 'sphal' namespace so that listeners attached
     92     // to that instance is also notified with this event.
     93     static auto func = get_report_sysprop_change_func();
     94     if (func != nullptr) {
     95         (*func)();
     96     }
     97 #endif
     98 }
     99 
    100 };  // namespace android
    101 
    102 void do_report_sysprop_change() {
    103 #if !defined(_WIN32)
    104     pthread_mutex_lock(&gSyspropMutex);
    105     Vector<sysprop_change_callback_info> listeners;
    106     if (gSyspropList != NULL) {
    107         listeners = *gSyspropList;
    108     }
    109     pthread_mutex_unlock(&gSyspropMutex);
    110 
    111     //ALOGI("Reporting sysprop change to %d listeners", listeners.size());
    112     for (size_t i=0; i<listeners.size(); i++) {
    113         listeners[i].callback();
    114     }
    115 #endif
    116 }
    117