Android 12 Watchdog monitor实现

Posted pecuyu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 12 Watchdog monitor实现相关的知识,希望对你有一定的参考价值。

文章托管在gitee上 Android Notes , 同步csdn

这一篇看一些系统模块的monitor实现。接下来看3个比较典型的场景:

  • ActivityManagerService的monitor实现
  • InputManagerService的monitor实现,涉及native检查
  • Binder线程的monitor实现

Watchdog.Monitor定义如下,实现该接口的类,可以注册到Watchdog作为一个被监听的对象:

public interface Monitor 
    void monitor();

ActivityManagerService的monitor实现

首先看一下AMS的实现,从继承结构看,它需要继承Watchdog.Monitor

public class ActivityManagerService extends IActivityManager.Stub
        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback, ActivityManagerGlobalLock 

注册到Watchdog

public ActivityManagerService(Context systemContext, ActivityTaskManagerService atm) 
...
  mHandlerThread = new ServiceThread(TAG,
          THREAD_PRIORITY_FOREGROUND, false /*allowIo*/);
  mHandlerThread.start();
  mHandler = new MainHandler(mHandlerThread.getLooper());
  ...
  Watchdog.getInstance().addMonitor(this); // 添加AMS到监控队列
  Watchdog.getInstance().addThread(mHandler); // 添加线程到Watchdog监控列表mHandlerCheckers
  ...

添加monitor对象和监控线程:

// 添加monitor对象
public void addMonitor(Monitor monitor) 
    synchronized (mLock) 
      // 添加到mMonitorChecker,在每轮检查的时候在HandlerChecker的run会调用Monitor#monitor
        mMonitorChecker.addMonitorLocked(monitor);
    

// 添加线程监控,通过handler向消息队列投递消息,监测线程是否畅通
public void addThread(Handler thread) 
    addThread(thread, DEFAULT_TIMEOUT);


public void addThread(Handler thread, long timeoutMillis) 
    synchronized (mLock) 
        final String name = thread.getLooper().getThread().getName();
        // 对于没有线程都会创建一个HandlerChecker
        mHandlerCheckers.add(new HandlerChecker(thread, name, timeoutMillis));
    

AMS#monitor

接下来看monitor方法的实现。AMS的monitor方法比较简单,就是在方法里面尝试获取同步锁,此处的锁对象就是AMS对象本身。如果锁空闲,则此调用会很快返回,如果锁对象被其他地方使用,则此处会卡住。当卡住过久,那么Watchdog会检查到AMS卡了,则会执行重启。

/** In this method we try to acquire our lock to make sure that we have not deadlocked */
public void monitor() 
    synchronized (this)  

InputManagerService的monitor实现

和AMS类似,也是继承Watchdog.Monitor,并且在其start方法中注册自身到Watchdog

/*
 * Wraps the C++ InputManager and provides its callbacks.
 */
public class InputManagerService extends IInputManager.Stub
        implements Watchdog.Monitor 

    public void start() 
      Slog.i(TAG, "Starting input manager");
      nativeStart(mPtr);

      // Add ourself to the Watchdog monitors.
      Watchdog.getInstance().addMonitor(this); // 注册到Watchdog
    


IMS#monitor

接下来直接看其monitor实现,它的实现比AMS稍复杂,除了检查Java同步锁,还会调用native方法去检查底层的运行状态。

// Called by the heartbeat to ensure locks are not held indefinitely (for deadlock detection).
@Override
public void monitor() 
    synchronized (mInputFilterLock)  
    synchronized (mAssociationsLock)  /* Test if blocked by associations lock. */
    synchronized (mLidSwitchLock)  /* Test if blocked by lid switch lock. */ 
    nativeMonitor(mPtr); // 检查native

nativeMonitor 的native实现

nativeMonitor 是一个 native 方法,它的jni层实现在 com_android_server_input_InputManagerService.cpp

/// @frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
static void nativeMonitor(JNIEnv* /* env */, jclass /* clazz */, jlong ptr) 
    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);

    im->getInputManager()->getReader()->monitor(); // 检查 InputReader 的状态
    im->getInputManager()->getDispatcher()->monitor(); // 检查 InputDispatcher 的状态

InputReader 状态检查,比如判断是否出现死锁

void InputReader::monitor() 
    // Acquire and release the lock to ensure that the reader has not deadlocked.
    std::unique_lock<std::mutex> lock(mLock);
    mEventHub->wake();
    mReaderIsAliveCondition.wait(lock);
    // Check the EventHub
    mEventHub->monitor(); // EventHub 状态检查

EventHub 状态检查

void EventHub::monitor() 
    // Acquire and release the lock to ensure that the event hub has not deadlocked.
    std::unique_lock<std::mutex> lock(mLock);

InputDispatcher 状态检查, 判断是否出现死锁


void InputDispatcher::monitor() 
    // Acquire and release the lock to ensure that the dispatcher has not deadlocked.
    std::unique_lock _l(mLock);
    mLooper->wake();
    mDispatcherIsAlive.wait(_l);

Binder 线程监控

接下来是系统进程的binder线程的监控实现。BinderThreadMonitor类也是继承自Watchdog.Monitor,通过调用其monitor方法,来测试binder线程状态

/** Monitor for checking the availability of binder threads. The monitor will block until
 * there is a binder thread available to process in coming IPCs to make sure other processes
 * can still communicate with the service.
 */
private static final class BinderThreadMonitor implements Watchdog.Monitor 
    @Override
    public void monitor() 
        Binder.blockUntilThreadAvailable(); // 调用native方法
    

blockUntilThreadAvailable是native方法,是用来检查正在执行的线程数是否小于最大允许的数量,防止binder线程长时间处于starve状态。

/**
 * Call blocks until the number of executing binder threads is less
 * than the maximum number of binder threads allowed for this process.
 * @hide
 */
public static final native void blockUntilThreadAvailable();

它的实现在 android_util_Binder.cpp , 下面是其jni注册信息。

/// frameworks/base/core/jni/android_util_Binder.cpp
 "blockUntilThreadAvailable", "()V", (void*)android_os_Binder_blockUntilThreadAvailable ,

根据jni注册信息可知其对应的jni函数是 android_os_Binder_blockUntilThreadAvailable。

static void android_os_Binder_blockUntilThreadAvailable(JNIEnv* env, jobject clazz)

    return IPCThreadState::self()->blockUntilThreadAvailable();

接下来看 IPCThreadState::blockUntilThreadAvailable,从实现可知,当binder线程数处于满载状态,则检测线程会处于wait状态,当长时间处于wait状态则会触发Watchdog。

void  IPCThreadState::blockUntilThreadAvailable()

    pthread_mutex_lock(&mProcess->mThreadCountLock);
    mProcess->mWaitingForThreads++;
    while (mProcess->mExecutingThreadsCount >= mProcess->mMaxThreads)  // 判断正在执行的线程数是否小于最大数
        ALOGW("Waiting for thread to be free. mExecutingThreadsCount=%lu mMaxThreads=%lu\\n",
                static_cast<unsigned long>(mProcess->mExecutingThreadsCount),
                static_cast<unsigned long>(mProcess->mMaxThreads));
        // 如果在执行的线程已满载运行,则会等待有空闲线程
        pthread_cond_wait(&mProcess->mThreadCountDecrement, &mProcess->mThreadCountLock);
    
    mProcess->mWaitingForThreads--;
    pthread_mutex_unlock(&mProcess->mThreadCountLock);

以上是关于Android 12 Watchdog monitor实现的主要内容,如果未能解决你的问题,请参考以下文章

Android 12 Watchdog 案例分析集

Android 12 Watchdog 案例分析集

Android 12 Watchdog 介绍与启动

Android 12 Watchdog 介绍与启动

Android 12 Watchdog monitor实现

Android 12 Watchdog monitor实现