Watchdog بر سلامت سرویس های فروشنده و سرویس VHAL نظارت می کند و هر فرآیند ناسالم را خاتمه می دهد. هنگامی که یک فرآیند ناسالم خاتمه مییابد، Watchdog وضعیت فرآیند را مانند سایر برنامههای تخلیهشده Application Not Responding (ANR) به /data/anr
میریزد. انجام این کار فرآیند اشکال زدایی را تسهیل می کند.
نظارت بر سلامت خدمات فروشنده
خدمات فروشنده در هر دو سمت بومی و جاوا نظارت می شود. برای اینکه یک سرویس فروشنده نظارت شود، این سرویس باید با تعیین یک بازه زمانی از پیش تعریف شده، یک فرآیند بررسی سلامت را در Watchdog ثبت کند. Watchdog سلامت یک فرآیند بررسی سلامت ثبت شده را با پینگ کردن آن در یک بازه زمانی نسبت به زمانی که در طول ثبت نام مشخص شده است، نظارت می کند. هنگامی که یک فرآیند پینگ در مدت زمان پاسخ نمی دهد، فرآیند ناسالم در نظر گرفته می شود.
پایش سلامت خدمات بومی
فایل ساخت Watchdog AIDL را مشخص کنید
- شامل
carwatchdog_aidl_interface-ndk_platform
درshared_libs
.Android.bp
cc_binary { name: "sample_native_client", srcs: [ "src/*.cpp" ], shared_libs: [ "carwatchdog_aidl_interface-ndk_platform", "libbinder_ndk", ], vendor: true, }
یک خط مشی SELinux اضافه کنید
- برای افزودن یک خطمشی SELinux، به دامنه سرویس فروشنده اجازه دهید از binder (ماکرو
binder_use
) استفاده کند و دامنه سرویس فروشنده را به دامنه مشتریcarwatchdog
(macrocarwatchdog_client_domain
) اضافه کنید. کد زیر را برایsample_client.te
وfile_contexts
ببینید:sample_client.te
type sample_client, domain; type sample_client_exec, exec_type, file_type, vendor_file_type; carwatchdog_client_domain(sample_client) init_daemon_domain(sample_client) binder_use(sample_client)
file_contexts
/vendor/bin/sample_native_client u:object_r:sample_client_exec:s0
با به ارث بردن BnCarWatchdogClient یک کلاس کلاینت را پیاده سازی کنید
- در
checkIfAlive
، یک بررسی سلامتی انجام دهید. یکی از گزینه ها ارسال به کنترل کننده حلقه موضوع است. اگر سالم هستید، باICarWatchdog::tellClientAlive
تماس بگیرید. کد زیر را برایSampleNativeClient.h
وSampleNativeClient.cpp
ببینید:SampleNativeClient.h
class SampleNativeClient : public BnCarWatchdogClient { public: ndk::ScopedAStatus checkIfAlive(int32_t sessionId, TimeoutLength timeout) override; ndk::ScopedAStatus prepareProcessTermination() override; void initialize(); private: void respondToDaemon(); private: ::android::sp<::android::Looper> mHandlerLooper; std::shared_ptr<ICarWatchdog> mWatchdogServer; std::shared_ptr<ICarWatchdogClient> mClient; int32_t mSessionId; };
SampleNativeClient.cpp
ndk::ScopedAStatus WatchdogClient::checkIfAlive(int32_t sessionId, TimeoutLength timeout) { mHandlerLooper->removeMessages(mMessageHandler, WHAT_CHECK_ALIVE); mSessionId = sessionId; mHandlerLooper->sendMessage(mMessageHandler, Message(WHAT_CHECK_ALIVE)); return ndk::ScopedAStatus::ok(); } // WHAT_CHECK_ALIVE triggers respondToDaemon from thread handler void WatchdogClient::respondToDaemon() { // your health checking method here ndk::ScopedAStatus status = mWatchdogServer->tellClientAlive(mClient, mSessionId); }
یک thread بایندر راه اندازی کنید و مشتری را ثبت کنید
نام واسط شبح نگهبان خودرو android.automotive.watchdog.ICarWatchdog/default
است.
- دیمون را با نام جستجو کنید و با
ICarWatchdog::registerClient
تماس بگیرید. کد زیر را برایmain.cpp
وSampleNativeClient.cpp
ببینید:main.cpp
int main(int argc, char** argv) { sp<Looper> looper(Looper::prepare(/*opts=*/0)); ABinderProcess_setThreadPoolMaxThreadCount(1); ABinderProcess_startThreadPool(); std::shared_ptr<SampleNativeClient> client = ndk::SharedRefBase::make<SampleNatvieClient>(looper); // The client is registered in initialize() client->initialize(); ... }
SampleNativeClient.cpp
void SampleNativeClient::initialize() { ndk::SpAIBinder binder(AServiceManager_getService( "android.automotive.watchdog.ICarWatchdog/default")); std::shared_ptr<ICarWatchdog> server = ICarWatchdog::fromBinder(binder); mWatchdogServer = server; ndk::SpAIBinder binder = this->asBinder(); std::shared_ptr<ICarWatchdogClient> client = ICarWatchdogClient::fromBinder(binder) mClient = client; server->registerClient(client, TimeoutLength::TIMEOUT_NORMAL); }
نظارت بر سلامت سرویس جاوا
با به ارث بردن CarWatchdogClientCallback یک مشتری را پیاده سازی کنید
- فایل جدید را به صورت زیر ویرایش کنید:
private final CarWatchdogClientCallback mClientCallback = new CarWatchdogClientCallback() { @Override public boolean onCheckHealthStatus(int sessionId, int timeout) { // Your health check logic here // Returning true implies the client is healthy // If false is returned, the client should call // CarWatchdogManager.tellClientAlive after health check is // completed } @Override public void onPrepareProcessTermination() {} };
مشتری را ثبت کنید
- با
CarWatchdogManager.registerClient()
تماس بگیرید:private void startClient() { CarWatchdogManager manager = (CarWatchdogManager) car.getCarManager( Car.CAR_WATCHDOG_SERVICE); // Choose a proper executor according to your health check method ExecutorService executor = Executors.newFixedThreadPool(1); manager.registerClient(executor, mClientCallback, CarWatchdogManager.TIMEOUT_NORMAL); }
مشتری را لغو ثبت کنید
- پس از اتمام سرویس، با
CarWatchdogManager.unregisterClient()
تماس بگیرید:private void finishClient() { CarWatchdogManager manager = (CarWatchdogManager) car.getCarManager( Car.CAR_WATCHDOG_SERVICE); manager.unregisterClient(mClientCallback); }
نظارت بر سلامت VHAL
برخلاف نظارت بر سلامت سرویس فروشنده، Watchdog با عضویت در ویژگی خودرو VHAL_HEARTBEAT
سلامت سرویس VHAL را نظارت می کند. Watchdog انتظار دارد که ارزش این ویژگی هر N ثانیه یک بار به روز شود. هنگامی که ضربان قلب در این بازه زمانی به روز نمی شود، Watchdog سرویس VHAL را خاتمه می دهد.
توجه: Watchdog سلامت سرویس VHAL را تنها زمانی نظارت می کند که ویژگی وسیله نقلیه VHAL_HEARTBEAT
توسط سرویس VHAL پشتیبانی شود.
پیاده سازی داخلی VHAL می تواند بسته به فروشنده متفاوت باشد. از نمونه کدهای زیر به عنوان مرجع استفاده کنید.
- دارایی خودرو
VHAL_HEARTBEAT
را ثبت کنید.هنگام شروع سرویس VHAL، ویژگی خودرو
VHAL_HEARTBEAT
را ثبت کنید. در مثال زیر، یکunordered_map
، که شناسه ویژگی را به پیکربندی نگاشت میکند، برای نگهداری تمام تنظیمات پشتیبانی شده استفاده میشود. پیکربندی برایVHAL_HEARTBEAT
به نقشه اضافه می شود، به طوری که وقتیVHAL_HEARTBEAT
پرس و جو می شود، پیکربندی مربوطه برگردانده می شود.void registerVhalHeartbeatProperty() { const VehiclePropConfig config = { .prop = toInt(VehicleProperty::VHAL_HEARTBEAT), .access = VehiclePropertyAccess::READ, .changeMode = VehiclePropertyChangeMode::ON_CHANGE, }; // mConfigsById is declared as std::unordered_map<int32_t, VehiclePropConfig>. mConfigsById[config.prop] = config; }
- ویژگی وسیله نقلیه
VHAL_HEARTBEAT
را به روز کنید.بر اساس فرکانس بررسی سلامت VHAL (توضیح داده شده در تعریف فرکانس بررسی سلامت VHAL" )، ویژگی خودروی
VHAL_HEARTBEAT
را هر N ثانیه یک بار بهروزرسانی کنید. یکی از راههای انجام این کار استفاده ازRecurrentTimer
برای فراخوانی عملی است که سلامت VHAL را بررسی میکند و ویژگیVHAL_HEARTBEAT
وسیله نقلیه را در بازه زمانی بهروزرسانی میکند.در زیر نمونه ای از پیاده سازی با استفاده از
RecurrentTimer
نشان داده شده است:int main(int argc, char** argv) { RecurrentTimer recurrentTimer(updateVhalHeartbeat); recurrentTimer.registerRecurrentEvent(kHeartBeatIntervalNs, static_cast<int32_t>(VehicleProperty::VHAL_HEARTBEAT)); … Run service … recurrentTimer.unregisterRecurrentEvent( static_cast<int32_t>(VehicleProperty::VHAL_HEARTBEAT)); } void updateVhalHeartbeat(const std::vector<int32_t>& cookies) { for (int32_t property : cookies) { if (property != static_cast<int32_t>(VehicleProperty::VHAL_HEARTBEAT)) { continue; } // Perform internal health checking such as retrieving a vehicle property to ensure // the service is responsive. doHealthCheck(); // Construct the VHAL_HEARTBEAT property with system uptime. VehiclePropValuePool valuePool; VehicleHal::VehiclePropValuePtr propValuePtr = valuePool.obtainInt64(uptimeMillis()); propValuePtr->prop = static_cast<int32_t>(VehicleProperty::VHAL_HEARTBEAT); propValuePtr->areaId = 0; propValuePtr->status = VehiclePropertyStatus::AVAILABLE; propValuePtr->timestamp = elapsedRealtimeNano(); // Propagate the HAL event. onHalEvent(std::move(propValuePtr)); } }
- ( اختیاری ) فرکانس بررسی سلامت VHAL را تعریف کنید.
ویژگی محصول فقط خواندنی
ro.carwatchdog.vhal_healthcheck.interval
Watchdog فرکانس بررسی سلامت VHAL را تعریف می کند. فرکانس پیش فرض بررسی سلامت (زمانی که این ویژگی تعریف نشده باشد) سه ثانیه است. اگر سه ثانیه برای سرویس VHAL برای بهروزرسانی ویژگی خودرویVHAL_HEARTBEAT
کافی نیست، فرکانس بررسی سلامت VHAL را بسته به پاسخگویی سرویس تعریف کنید.
اشکال زدایی فرآیندهای ناسالم پایان یافته توسط Watchdog
Watchdog وضعیت فرآیند را تخلیه می کند و فرآیندهای ناسالم را خاتمه می دهد. هنگام پایان دادن به یک فرآیند ناسالم، Watchdog متن carwatchdog terminated <process name> (pid:<process id>)
در logcat ثبت می کند. این خط ورود اطلاعاتی در مورد فرآیند خاتمه یافته مانند نام فرآیند و شناسه فرآیند ارائه می دهد.
- logcat را می توان با اجرای زیر برای متن فوق جستجو کرد:
$ adb logcat -s CarServiceHelper | fgrep "carwatchdog killed"
برای مثال، وقتی برنامه KitchenSink یک مشتری ثبتشده Watchdog است و به پینگهای Watchdog پاسخ نمیدهد، Watchdog خطی مانند خط زیر را هنگام پایان دادن به فرآیند KitchenSink ثبتشده ثبت میکند.
05-01 09:50:19.683 578 5777 W CarServiceHelper: carwatchdog killed com.google.android.car.kitchensink (pid: 5574)
- برای شناسایی علت اصلی عدم پاسخگویی، از فرآیند تخلیه ذخیره شده در
/data/anr
استفاده کنید، همانطور که برای موارد ANR فعالیت استفاده می کنید. برای بازیابی فایل dump برای فرآیند خاتمه یافته از دستورات زیر استفاده کنید.$ adb root $ adb shell grep -Hn "pid process_pid" /data/anr/*
خروجی نمونه زیر مختص برنامه KitchenSink است:
$ adb shell su root grep -Hn "pid 5574" /data/anr/*.
/data/anr/anr_2020-05-01-09-50-18-290:3:----- pid 5574 at 2020-05-01 09:50:18 ----- /data/anr/anr_2020-05-01-09-50-18-290:285:----- Waiting Channels: pid 5574 at 2020-05-01 09:50:18 -----
فایل dump برای فرآیند KitchenSink خاتمه یافته در
/data/anr/anr_2020-05-01-09-50-18-290
قرار دارد. تجزیه و تحلیل خود را با استفاده از فایل dump ANR فرآیند خاتمه یافته شروع کنید.