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 31extern "C" void do_report_sysprop_change(); 32 33using namespace android; 34 35namespace android { 36 37struct sysprop_change_callback_info { 38 sysprop_change_callback callback; 39 int priority; 40}; 41 42#if !defined(_WIN32) 43static pthread_mutex_t gSyspropMutex = PTHREAD_MUTEX_INITIALIZER; 44static Vector<sysprop_change_callback_info>* gSyspropList = NULL; 45#endif 46 47void add_sysprop_change_callback(sysprop_change_callback cb, int priority) { 48#if !defined(_WIN32) 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#endif 69} 70 71#if defined(__ANDROID__) 72void (*get_report_sysprop_change_func())() { 73 void (*func)() = nullptr; 74 void* handle = android_load_sphal_library("libutils.so", RTLD_NOW); 75 if (handle != nullptr) { 76 func = reinterpret_cast<decltype(func)>(dlsym(handle, "do_report_sysprop_change")); 77 } 78 79 return func; 80} 81#endif 82 83void report_sysprop_change() { 84 do_report_sysprop_change(); 85 86#if defined(__ANDROID__) 87 // libutils.so is double loaded; from the default namespace and from the 88 // 'sphal' namespace. Redirect the sysprop change event to the other instance 89 // of libutils.so loaded in the 'sphal' namespace so that listeners attached 90 // to that instance is also notified with this event. 91 static auto func = get_report_sysprop_change_func(); 92 if (func != nullptr) { 93 (*func)(); 94 } 95#endif 96} 97 98}; // namespace android 99 100void do_report_sysprop_change() { 101#if !defined(_WIN32) 102 pthread_mutex_lock(&gSyspropMutex); 103 Vector<sysprop_change_callback_info> listeners; 104 if (gSyspropList != NULL) { 105 listeners = *gSyspropList; 106 } 107 pthread_mutex_unlock(&gSyspropMutex); 108 109 //ALOGI("Reporting sysprop change to %d listeners", listeners.size()); 110 for (size_t i=0; i<listeners.size(); i++) { 111 listeners[i].callback(); 112 } 113#endif 114} 115