android提供了UEventObserver这个类来使java可以监听uevent事件,这个类是一个抽象类,使用这个类必须实现onUEvent函数。
一、监控过程
在UEventObserver这个类中做了一个单例的线程,
private static UEventThread getThread() {
synchronized (UEventObserver.class) {
if (sThread == null) {
sThread = new UEventThread();
sThread.start();
}
return sThread;
}
}
下面我们分析下这个UEventThread类的run函数
@Override
public void run() {
nativeSetup();
while (true) {
String message = nativeWaitForNextEvent();
if (message != null) {
if (DEBUG) {
Log.d(TAG, message);
}
sendEvent(message);
}
}
}
我们先来看nativeSetup函数
static void nativeSetup(JNIEnv *env, jclass clazz) {
if (!uevent_init()) {
jniThrowException(env, "java/lang/RuntimeException",
"Unable to open socket for UEventObserver");
}
}
而uevent_init函数,也是创建了一个Netlink socket和正常接收uevent事件流程一样。
int uevent_init()
{
struct sockaddr_nl addr;
int sz = 64*1024;
int s;
memset(&addr, 0, sizeof(addr));
addr.nl_family = AF_NETLINK;
addr.nl_pid = getpid();
addr.nl_groups = 0xffffffff;
s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
if(s < 0)
return 0;
setsockopt(s, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz));
if(bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
close(s);
return 0;
}
fd = s;
return (fd > 0);
}
然后在UEventThread一直循环调用nativeWaitForNextEvent函数
static jstring nativeWaitForNextEvent(JNIEnv *env, jclass clazz) {
char buffer[1024];
for (;;) {
int length = uevent_next_event(buffer, sizeof(buffer) - 1);
if (length <= 0) {
return NULL;
}
buffer[length] = '\0';
ALOGV("Received uevent message: %s", buffer);
if (isMatch(buffer, length)) {//是否匹配
// Assume the message is ASCII.
jchar message[length];
for (int i = 0; i < length; i++) {
message[i] = buffer[i];
}
return env->NewString(message, length);
}
}
}
uevent_next_event函数就是接收Netlink socket的数据
int uevent_next_event(char* buffer, int buffer_length)
{
while (1) {
struct pollfd fds;
int nr;
fds.fd = fd;
fds.events = POLLIN;
fds.revents = 0;
nr = poll(&fds, 1, -1);
if(nr > 0 && (fds.revents & POLLIN)) {
int count = recv(fd, buffer, buffer_length, 0);
if (count > 0) {
struct uevent_handler *h;
pthread_mutex_lock(&uevent_handler_list_lock);
LIST_FOREACH(h, &uevent_handler_list, list)
h->handler(h->handler_data, buffer, buffer_length);
pthread_mutex_unlock(&uevent_handler_list_lock);
return count;
}
}
}
// won't get here
return 0;
}
我们再来看isMatch函数,就是看数据和我们的gMatches中是否有匹配的
static bool isMatch(const char* buffer, size_t length) {
AutoMutex _l(gMatchesMutex);
for (size_t i = 0; i < gMatches.size(); i++) {
const String8& match = gMatches.itemAt(i);
// Consider all zero-delimited fields of the buffer.
const char* field = buffer;
const char* end = buffer + length + 1;
do {
if (strstr(field, match.string())) {
ALOGV("Matched uevent message with pattern: %s", match.string());
return true;
}
field += strlen(field) + 1;
} while (field != end);
}
return false;
}
最后由匹配的数据,我们再UEventThread中调用sendEvent函数
private void sendEvent(String message) {
synchronized (mKeysAndObservers) {
final int N = mKeysAndObservers.size();
for (int i = 0; i < N; i += 2) {
final String key = (String)mKeysAndObservers.get(i);
if (message.contains(key)) {//注册的observer时候有匹配的
final UEventObserver observer =
(UEventObserver)mKeysAndObservers.get(i + 1);//match的下一个就是Observer
mTempObserversToSignal.add(observer);//把匹配的Observer保存在临时变量中
}
}
}
if (!mTempObserversToSignal.isEmpty()) {
final UEvent event = new UEvent(message);
final int N = mTempObserversToSignal.size();
for (int i = 0; i < N; i++) {
final UEventObserver observer = mTempObserversToSignal.get(i);
observer.onUEvent(event);//遍历所有满足的Observer,调用器onUEvent函数
}
mTempObserversToSignal.clear();
}
}
二、注册监控
我们在调用startObserving后,就把我们的监控放入线程汇总
public final void startObserving(String match) {
if (match == null || match.isEmpty()) {
throw new IllegalArgumentException("match substring must be non-empty");
}
final UEventThread t = getThread();
t.addObserver(match, this);
}
UEventThread函数的addObserver函数,把match和Observer都放入了mKeysAndObservers中,在使用的时候我们取match的下一个就是Observer了
public void addObserver(String match, UEventObserver observer) {
synchronized (mKeysAndObservers) {
mKeysAndObservers.add(match);
mKeysAndObservers.add(observer);
nativeAddMatch(match);
}
}
我们再看下nativeAddMatch函数,在这个函数中把match直接接入到gMatches的全局变量中。
static void nativeAddMatch(JNIEnv* env, jclass clazz, jstring matchStr) {
ScopedUtfChars match(env, matchStr);
AutoMutex _l(gMatchesMutex);
gMatches.add(String8(match.c_str()));
}
注销监控过程比较简单就不说了。
三、实例
我们举个BatteryService中的实例
DEVPATH=/devices/virtual/switch/invalid_charger 就是我们监测的match
if (new File("/sys/devices/virtual/switch/invalid_charger/state").exists()) {
mInvalidChargerObserver.startObserving(
"DEVPATH=/devices/virtual/switch/invalid_charger");
}
onUEvent就是监测到之后的处理函数
private final UEventObserver mInvalidChargerObserver = new UEventObserver() {
@Override
public void onUEvent(UEventObserver.UEvent event) {
final int invalidCharger = "1".equals(event.get("SWITCH_STATE")) ? 1 : 0;
synchronized (mLock) {
if (mInvalidCharger != invalidCharger) {
mInvalidCharger = invalidCharger;
}
}
}
};