Watchdog, satıcı hizmetlerinin ve VHAL hizmetinin durumunu izler ve sağlıksız süreçleri sonlandırır. Sağlıksız bir süreç sonlandırıldığında, Watchdog diğer Yanıt Vermeyen Uygulama (ANR) dökümlerinde olduğu gibi işlem durumunu /data/anr
dizinine aktarır. Bunu yapmak hata ayıklama işlemini kolaylaştırır.
Satıcı hizmet durumunun izlenmesi
Satıcı hizmetleri hem yerel hem de Java tarafında izlenir. Bir Satıcı hizmetinin izlenebilmesi için, hizmetin önceden tanımlanmış bir zaman aşımı belirterek Watchdog'a bir sağlık kontrolü süreci kaydetmesi gerekir. Watchdog, kayıt sırasında belirtilen zaman aşımına göre belirli bir aralıkta ping atarak kayıtlı bir sağlık kontrolü sürecinin durumunu izler. Pinglenen bir süreç zaman aşımı süresi içinde yanıt vermediğinde, sürecin sağlıksız olduğu kabul edilir.
Yerel hizmet durumu izleme
Watchdog AIDL makefile dosyasını belirtin
-
carwatchdog_aidl_interface-ndk_platform
shared_libs
ekleyin.Android.bp
cc_binary { name: "sample_native_client", srcs: [ "src/*.cpp" ], shared_libs: [ "carwatchdog_aidl_interface-ndk_platform", "libbinder_ndk", ], vendor: true, }
SELinux ilkesi ekleme
- Bir SELinux politikası eklemek için satıcı hizmet etki alanının bağlayıcıyı (
binder_use
makrosu) kullanmasına izin verin ve satıcı hizmet etki alanınıcarwatchdog
istemci etki alanına (carwatchdog_client_domain
makrosu) ekleyin.sample_client.te
vefile_contexts
için aşağıdaki koda bakın: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'i devralarak bir istemci sınıfı uygulayın
-
checkIfAlive
bir durum kontrolü gerçekleştirin. Bir seçenek iş parçacığı döngüsü işleyicisine göndermektir. SağlıklıysaICarWatchdog::tellClientAlive
arayın.SampleNativeClient.h
veSampleNativeClient.cpp
için aşağıdaki koda bakın: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); }
Bir ciltleyici iş parçacığı başlatın ve istemciyi kaydedin
Araba gözlemcisi arka plan programı arayüz adı android.automotive.watchdog.ICarWatchdog/default
şeklindedir.
- Adıyla birlikte arka plan programını arayın ve
ICarWatchdog::registerClient
öğesini arayın.main.cpp
veSampleNativeClient.cpp
için aşağıdaki koda bakın: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); }
Java hizmetinin durumunu izleme
CarWatchdogClientCallback'i devralarak bir istemci uygulayın
- Yeni dosyayı şu şekilde düzenleyin:
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() {} };
İstemciyi kaydedin
-
CarWatchdogManager.registerClient()
öğesini çağırın: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); }
İstemcinin kaydını iptal edin
- Hizmet tamamlandığında
CarWatchdogManager.unregisterClient()
öğesini çağırın:private void finishClient() { CarWatchdogManager manager = (CarWatchdogManager) car.getCarManager( Car.CAR_WATCHDOG_SERVICE); manager.unregisterClient(mClientCallback); }
VHAL sağlık takibi
Satıcı hizmet durumu izlemenin aksine Watchdog, VHAL_HEARTBEAT
araç özelliğine abone olarak VHAL hizmet durumunu izler. Watchdog, bu özelliğin değerinin her N saniyede bir güncellenmesini beklemektedir. Bu zaman aşımı süresi içerisinde kalp atışı güncellenmediğinde Watchdog VHAL hizmetini sonlandırır.
Not: Watchdog, VHAL hizmetinin durumunu yalnızca VHAL_HEARTBEAT
araç özelliği VHAL hizmeti tarafından desteklendiğinde izler.
VHAL dahili uygulaması satıcıya göre değişebilir. Aşağıdaki kod örneklerini referans olarak kullanın.
-
VHAL_HEARTBEAT
araç özelliğini kaydedin.VHAL hizmetini başlatırken
VHAL_HEARTBEAT
araç özelliğini kaydedin. Aşağıdaki örnekte, özellik kimliğini config ile eşleştirenunordered_map
, desteklenen tüm yapılandırmaları tutmak için kullanılır.VHAL_HEARTBEAT
için yapılandırma haritaya eklenir, böyleceVHAL_HEARTBEAT
sorgulandığında ilgili yapılandırma döndürülür.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
araç özelliğini güncelleyin.VHAL durum denetimi sıklığına bağlı olarak ( VHAL durum denetiminin sıklığını tanımlama" bölümünde açıklanmıştır),
VHAL_HEARTBEAT
araç özelliğini her N saniyede bir güncelleyin. Bunu yapmanın bir yolu, VHAL durumunu kontrol eden eylemi çağırmak içinRecurrentTimer
kullanmaktır veVHAL_HEARTBEAT
araç özelliğini zaman aşımı içerisinde günceller.Aşağıda
RecurrentTimer
kullanan örnek bir uygulama gösterilmektedir: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)); } }
- ( İsteğe bağlı ) VHAL durum kontrolünün sıklığını tanımlayın.
Watchdog'un
ro.carwatchdog.vhal_healthcheck.interval
salt okunur ürün özelliği, VHAL durum kontrolü sıklığını tanımlar. Varsayılan durum denetimi sıklığı (bu özellik tanımlanmadığında) üç saniyedir. VHAL hizmetininVHAL_HEARTBEAT
araç özelliğini güncellemesi için üç saniye yeterli değilse, hizmetin yanıt verme durumuna bağlı olarak VHAL durum denetimi sıklığını tanımlayın.
Watchdog tarafından sonlandırılan sağlıksız işlemlerde hata ayıklama
Watchdog süreç durumunu atar ve sağlıksız süreçleri sonlandırır. Sağlıksız bir süreci sonlandırırken Watchdog, carwatchdog terminated <process name> (pid:<process id>)
metnini logcat'e kaydeder. Bu günlük satırı, sonlandırılan işlem hakkında işlem adı ve işlem kimliği gibi bilgiler sağlar.
- Logcat yukarıda belirtilen metni aşağıdaki komutu çalıştırarak arayabilir:
$ adb logcat -s CarServiceHelper | fgrep "carwatchdog killed"
Örneğin, KitchenSink uygulaması kayıtlı bir Watchdog istemcisi olduğunda ve Watchdog ping'lerine yanıt vermediğinde, Watchdog kayıtlı KitchenSink işlemini sonlandırırken aşağıdaki satıra benzer bir satırı günlüğe kaydeder.
05-01 09:50:19.683 578 5777 W CarServiceHelper: carwatchdog killed com.google.android.car.kitchensink (pid: 5574)
- Yanıt vermemenin temel nedenini belirlemek için, etkinlik ANR vakalarında kullandığınız gibi
/data/anr
konumunda depolanan işlem dökümünü kullanın. Sonlandırılan işlemin döküm dosyasını almak için aşağıdaki komutları kullanın.$ adb root $ adb shell grep -Hn "pid process_pid" /data/anr/*
Aşağıdaki örnek çıktı KitchenSink uygulamasına özeldir:
$ 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 -----
Sonlandırılan KitchenSink işleminin döküm dosyası
/data/anr/anr_2020-05-01-09-50-18-290
konumunda bulunur. Sonlandırılan işlemin ANR döküm dosyasını kullanarak analizinizi başlatın.