Watchdog memantau kondisi layanan vendor dan layanan VHAL, serta
menghentikan proses yang tidak responsif. Ketika proses yang tidak responsif
dihentikan, {i>Watchdog<i}
membuang status proses ke /data/anr
seperti dengan Aplikasi Tidak Merespons lainnya
dump (ANR). Tindakan ini akan memudahkan proses debug.
Pemantauan kondisi layanan vendor
Layanan vendor dipantau di sisi native dan Java. Untuk Vendor layanan yang dipantau, layanan harus mendaftarkan proses health check dengan Watchdog dengan menentukan waktu tunggu yang telah ditentukan sebelumnya. Watchdog memonitor kondisi proses health check terdaftar dengan melakukan ping pada suatu interval sesuai dengan waktu tunggu yang ditentukan selama pendaftaran. Jika proses yang di-ping tidak merespons dalam waktu tunggu, proses tersebut dianggap tidak responsif.
Pemantauan kondisi layanan native
Menentukan makefile AIDL Watchdog
- Sertakan
carwatchdog_aidl_interface-ndk_platform
dishared_libs
.Android.bp
cc_binary { name: "sample_native_client", srcs: [ "src/*.cpp" ], shared_libs: [ "carwatchdog_aidl_interface-ndk_platform", "libbinder_ndk", ], vendor: true, }
Menambahkan kebijakan SELinux
- Untuk menambahkan kebijakan SELinux, izinkan domain layanan vendor menggunakan binder
(makro
binder_use
) dan tambahkan domain layanan vendor ke domain kliencarwatchdog
(makrocarwatchdog_client_domain
). Lihat kode di bawah untuksample_client.te
danfile_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
Mengimplementasikan class klien dengan mewarisi BnCarWatchdogClient
- Di
checkIfAlive
, lakukan health check. Salah satu pilihan adalah untuk memposting ke pengendali loop thread. Jika responsif, panggilICarWatchdog::tellClientAlive
. Lihat kode di bawah untukSampleNativeClient.h
danSampleNativeClient.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); }
Memulai thread binder dan mendaftarkan klien
Nama antarmuka {i>daemon<i} watchdog mobil adalah
android.automotive.watchdog.ICarWatchdog/default
.
- Telusuri daemon dengan nama dan panggil
ICarWatchdog::registerClient
. Lihat kode di bawah untukmain.cpp
danSampleNativeClient.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); }
Pemantauan kondisi layanan Java
Mengimplementasikan klien dengan mewarisi CarWatchdogClientCallback
- Edit file baru sebagai berikut:
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() {} };
Mendaftarkan klien
- Panggil
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); }
Membatalkan pendaftaran klien
- Panggil
CarWatchdogManager.unregisterClient()
saat layanan selesai:private void finishClient() { CarWatchdogManager manager = (CarWatchdogManager) car.getCarManager( Car.CAR_WATCHDOG_SERVICE); manager.unregisterClient(mClientCallback); }
Pemantauan kondisi VHAL
Tidak seperti pemantauan kondisi layanan vendor, Watchdog memantau kondisi layanan
VHAL dengan berlangganan properti kendaraan VHAL_HEARTBEAT
.
Watchdog mengharapkan nilai properti ini diperbarui setiap N detik sekali.
Ketika denyut jantung tidak diperbarui dalam waktu tunggu ini, Watchdog akan menghentikan VHAL
layanan.
Catatan: Watchdog hanya memantau kondisi layanan VHAL jika
properti kendaraan VHAL_HEARTBEAT
didukung oleh layanan VHAL.
Implementasi internal VHAL dapat bervariasi menurut vendor. Gunakan contoh kode berikut sebagai referensi.
- Daftarkan properti kendaraan
VHAL_HEARTBEAT
.Saat memulai layanan VHAL, daftarkan properti kendaraan
VHAL_HEARTBEAT
. Pada contoh di bawah,unordered_map
yang memetakan ID properti ke konfigurasi adalah untuk menyimpan semua konfigurasi yang didukung. Konfigurasi untukVHAL_HEARTBEAT
ditambahkan ke peta, sehingga saatVHAL_HEARTBEAT
dikueri, konfigurasi yang sesuai akan dikembalikan.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; }
- Perbarui properti kendaraan
VHAL_HEARTBEAT
.Berdasarkan frekuensi health check VHAL (dijelaskan dalam Menentukan frekuensi health check VHAL"), perbarui properti kendaraan
VHAL_HEARTBEAT
sekali setiap N detik. Salah satu cara untuk melakukannya adalah dengan menggunakanRecurrentTimer
untuk memanggil tindakan yang memeriksa status VHAL dan memperbarui properti kendaraanVHAL_HEARTBEAT
dalam waktu tunggu.Berikut adalah contoh implementasi yang menggunakan
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)); } }
- (Opsional) Tentukan frekuensi health check VHAL.
Properti produk
ro.carwatchdog.vhal_healthcheck.interval
hanya baca Watchdog menentukan frekuensi health check VHAL. Health check default frekuensi (jika properti ini tidak ditentukan) adalah tiga detik. Jika tiga detik tidak yang memadai agar layanan VHAL dapat memperbarui properti kendaraanVHAL_HEARTBEAT
, menentukan frekuensi health check VHAL tergantung pada responsivitas layanan.
Men-debug proses tidak responsif yang dihentikan oleh Watchdog
Watchdog membuang status proses dan menghentikan proses yang tidak sehat. Saat menghentikan
proses yang tidak responsif, Watchdog mencatat teks carwatchdog terminated
<process name> (pid:<process id>)
ke logcat. Baris log ini
memberikan informasi tentang proses yang dihentikan seperti nama proses dan ID
proses.
- Logcat dapat dicari untuk teks yang disebutkan di atas dengan menjalankan:
$ adb logcat -s CarServiceHelper | fgrep "carwatchdog killed"
Misalnya, saat aplikasi KitchenSink adalah klien Watchdog terdaftar dan tidak responsif terhadap ping Watchdog, Watchdog akan mencatat baris seperti baris di bawah saat menghentikan proses KitchenSink terdaftar.
05-01 09:50:19.683 578 5777 W CarServiceHelper: carwatchdog killed com.google.android.car.kitchensink (pid: 5574)
- Untuk mengidentifikasi akar penyebab ketidakresponsif, gunakan dump
proses yang disimpan di
/data/anr
seperti yang akan Anda gunakan untuk kasus ANR aktivitas. Untuk mengambil file dump untuk proses yang dihentikan, gunakan perintah di bawah.$ adb root $ adb shell grep -Hn "pid process_pid" /data/anr/*
Contoh output berikut khusus untuk aplikasi 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 -----
File {i>dump<i} untuk proses KitchenSink yang dihentikan terletak di
/data/anr/anr_2020-05-01-09-50-18-290
. Mulailah analisis Anda menggunakan file dump ANR proses yang dihentikan.