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__) && !defined(__ANDROID_RECOVERY__) 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 = nullptr; 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 == nullptr) { 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__) && !defined(__ANDROID_RECOVERY__) 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__) && !defined(__ANDROID_RECOVERY__) 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 != nullptr) { 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