Watchdog memantau kesehatan layanan vendor dan layanan VHAL, dan menghentikan proses yang tidak sehat. Ketika proses yang tidak sehat dihentikan, Watchdog membuang status proses ke /data/anr
seperti dump Aplikasi Tidak Merespons (ANR) lainnya. Melakukannya akan memfasilitasi proses debugging.
Pemantauan kesehatan layanan vendor
Layanan vendor dipantau di sisi asli dan Java. Agar layanan Vendor dapat dipantau, layanan tersebut harus mendaftarkan proses pemeriksaan kesehatan ke Watchdog dengan menentukan batas waktu yang telah ditentukan sebelumnya. Watchdog memantau kesehatan proses pemeriksaan kesehatan yang terdaftar dengan melakukan ping pada interval yang relatif terhadap batas waktu yang ditentukan selama pendaftaran. Ketika proses yang di-ping tidak merespons dalam waktu tunggu, proses tersebut dianggap tidak sehat.
Pemantauan kesehatan layanan asli
Tentukan makefile Watchdog AIDL
- 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, }
Tambahkan kebijakan SELinux
- Untuk menambahkan kebijakan SELinux, izinkan domain layanan vendor menggunakan pengikat ( 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
Implementasikan kelas klien dengan mewarisi BnCarWatchdogClient
- Di
checkIfAlive
, lakukan pemeriksaan kesehatan. Salah satu opsinya adalah memposting ke pengendali loop thread. Jika sehat, hubungiICarWatchdog::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); }
Mulai utas pengikat dan daftarkan klien
Nama antarmuka daemon pengawas mobil adalah android.automotive.watchdog.ICarWatchdog/default
.
- Cari 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 kesehatan layanan Java
Implementasikan 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() {} };
Daftarkan klien
- Hubungi
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); }
Batalkan pendaftaran klien
- Panggil
CarWatchdogManager.unregisterClient()
ketika layanan selesai:private void finishClient() { CarWatchdogManager manager = (CarWatchdogManager) car.getCarManager( Car.CAR_WATCHDOG_SERVICE); manager.unregisterClient(mClientCallback); }
Pemantauan kesehatan VHAL
Tidak seperti pemantauan kesehatan layanan vendor, Watchdog memantau kesehatan layanan VHAL dengan berlangganan properti kendaraan VHAL_HEARTBEAT
. Watchdog mengharapkan nilai properti ini diperbarui setiap N detik. Ketika detak jantung tidak diperbarui dalam batas waktu ini, Watchdog menghentikan layanan VHAL.
Catatan: Watchdog memantau kesehatan layanan VHAL hanya ketika 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
. Dalam contoh di bawah,unordered_map
, yang memetakan ID properti ke konfigurasi digunakan untuk menampung semua konfigurasi yang didukung. Konfigurasi untukVHAL_HEARTBEAT
ditambahkan ke peta, sehingga ketikaVHAL_HEARTBEAT
ditanyakan, 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 pemeriksaan kesehatan VHAL (dijelaskan dalam Menentukan frekuensi pemeriksaan kesehatan VHAL" ), perbarui properti kendaraan
VHAL_HEARTBEAT
setiap N detik. Salah satu cara untuk melakukannya adalah dengan menggunakanRecurrentTimer
untuk memanggil tindakan yang memeriksa kesehatan VHAL dan memperbarui properti kendaraanVHAL_HEARTBEAT
dalam waktu habis.Di bawah ini adalah contoh implementasi 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 pemeriksaan kesehatan VHAL.
Properti produk read-only
ro.carwatchdog.vhal_healthcheck.interval
Watchdog menentukan frekuensi pemeriksaan kesehatan VHAL. Frekuensi pemeriksaan kesehatan default (bila properti ini tidak ditentukan) adalah tiga detik. Jika tiga detik tidak cukup bagi layanan VHAL untuk memperbarui properti kendaraanVHAL_HEARTBEAT
, tentukan frekuensi pemeriksaan kesehatan VHAL bergantung pada respons layanan.
Debug proses yang tidak sehat dihentikan oleh Watchdog
Watchdog membuang status proses dan menghentikan proses yang tidak sehat. Saat menghentikan proses yang tidak sehat, 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 tersebut di atas dengan menjalankan:
$ adb logcat -s CarServiceHelper | fgrep "carwatchdog killed"
Misalnya, ketika aplikasi KitchenSink adalah klien Watchdog yang terdaftar dan menjadi tidak responsif terhadap ping Watchdog, Watchdog mencatat baris seperti baris di bawah ini ketika menghentikan proses KitchenSink yang terdaftar.
05-01 09:50:19.683 578 5777 W CarServiceHelper: carwatchdog killed com.google.android.car.kitchensink (pid: 5574)
- Untuk mengidentifikasi akar penyebab tidak responsifnya, gunakan dump proses yang disimpan di
/data/anr
seperti yang Anda gunakan untuk kasus aktivitas ANR. Untuk mengambil file dump untuk proses yang dihentikan, gunakan perintah di bawah ini.$ adb root $ adb shell grep -Hn "pid process_pid" /data/anr/*
Contoh keluaran 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 dump untuk proses KitchenSink yang dihentikan terletak di
/data/anr/anr_2020-05-01-09-50-18-290
. Mulai analisis Anda menggunakan file dump ANR dari proses yang dihentikan.