/** * Copyright (c) 2020, The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include "AIBinderDeathRegistrationWrapper.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace android { namespace automotive { namespace watchdog { // Forward declaration for testing use only. namespace internal { class WatchdogProcessServicePeer; } // namespace internal class WatchdogServiceHelperInterface; class PackageInfoResolverInterface; class WatchdogProcessServiceInterface : virtual public android::RefBase { public: virtual android::base::Result start() = 0; virtual void terminate() = 0; virtual void onDump(int fd) = 0; virtual void onDumpProto(android::util::ProtoOutputStream& outProto) = 0; virtual void doHealthCheck(int what) = 0; virtual void handleBinderDeath(void* cookie) = 0; virtual ndk::ScopedAStatus registerClient( const std::shared_ptr& client, aidl::android::automotive::watchdog::TimeoutLength timeout) = 0; virtual ndk::ScopedAStatus unregisterClient( const std::shared_ptr& client) = 0; virtual ndk::ScopedAStatus registerCarWatchdogService( const ndk::SpAIBinder& binder, const android::sp& helper) = 0; virtual void unregisterCarWatchdogService(const ndk::SpAIBinder& binder) = 0; virtual ndk::ScopedAStatus registerMonitor( const std::shared_ptr< aidl::android::automotive::watchdog::internal::ICarWatchdogMonitor>& monitor) = 0; virtual ndk::ScopedAStatus unregisterMonitor( const std::shared_ptr< aidl::android::automotive::watchdog::internal::ICarWatchdogMonitor>& monitor) = 0; virtual ndk::ScopedAStatus tellClientAlive( const std::shared_ptr& client, int32_t sessionId) = 0; virtual ndk::ScopedAStatus tellCarWatchdogServiceAlive( const std::shared_ptr< aidl::android::automotive::watchdog::internal::ICarWatchdogServiceForSystem>& service, const std::vector& clientsNotResponding, int32_t sessionId) = 0; virtual ndk::ScopedAStatus tellDumpFinished( const std::shared_ptr< aidl::android::automotive::watchdog::internal::ICarWatchdogMonitor>& monitor, const aidl::android::automotive::watchdog::internal::ProcessIdentifier& processIdentifier) = 0; virtual void setEnabled(bool isEnabled) = 0; virtual void onUserStateChange(userid_t userId, bool isStarted) = 0; virtual void onAidlVhalPidFetched(int32_t) = 0; }; class WatchdogProcessService final : public WatchdogProcessServiceInterface { public: explicit WatchdogProcessService(const android::sp& handlerLooper); WatchdogProcessService( const std::function()>& tryCreateVhalClientFunc, const std::function()>& tryGetHidlServiceManagerFunc, const std::function& getStartTimeForPidFunc, const std::chrono::nanoseconds& vhalPidCachingRetryDelayNs, const sp& handlerLooper, const sp& deathRegistrationWrapper); ~WatchdogProcessService(); android::base::Result start() override; void terminate() override; void onDump(int fd) override; void onDumpProto(util::ProtoOutputStream& outProto) override; void doHealthCheck(int what) override; void handleBinderDeath(void* cookie) override; ndk::ScopedAStatus registerClient( const std::shared_ptr& client, aidl::android::automotive::watchdog::TimeoutLength timeout) override; ndk::ScopedAStatus unregisterClient( const std::shared_ptr& client) override; ndk::ScopedAStatus registerCarWatchdogService( const ndk::SpAIBinder& binder, const android::sp& helper) override; void unregisterCarWatchdogService(const ndk::SpAIBinder& binder) override; ndk::ScopedAStatus registerMonitor( const std::shared_ptr< aidl::android::automotive::watchdog::internal::ICarWatchdogMonitor>& monitor) override; ndk::ScopedAStatus unregisterMonitor( const std::shared_ptr< aidl::android::automotive::watchdog::internal::ICarWatchdogMonitor>& monitor) override; ndk::ScopedAStatus tellClientAlive( const std::shared_ptr& client, int32_t sessionId) override; ndk::ScopedAStatus tellCarWatchdogServiceAlive( const std::shared_ptr< aidl::android::automotive::watchdog::internal::ICarWatchdogServiceForSystem>& service, const std::vector& clientsNotResponding, int32_t sessionId) override; ndk::ScopedAStatus tellDumpFinished( const std::shared_ptr< aidl::android::automotive::watchdog::internal::ICarWatchdogMonitor>& monitor, const aidl::android::automotive::watchdog::internal::ProcessIdentifier& processIdentifier) override; void setEnabled(bool isEnabled) override; void onUserStateChange(userid_t userId, bool isStarted) override; void onAidlVhalPidFetched(int32_t) override; private: enum ClientType { Regular, Service, }; class ClientInfo { public: ClientInfo(const std::shared_ptr& client, pid_t pid, userid_t userId, uint64_t startTimeMillis, const WatchdogProcessService& service) : kPid(pid), kUserId(userId), kStartTimeMillis(startTimeMillis), kType(ClientType::Regular), kService(service), kClient(client) {} ClientInfo(const android::sp& helper, const ndk::SpAIBinder& binder, pid_t pid, userid_t userId, uint64_t startTimeMillis, const WatchdogProcessService& service) : kPid(pid), kUserId(userId), kStartTimeMillis(startTimeMillis), kType(ClientType::Service), kService(service), kWatchdogServiceHelper(helper), kWatchdogServiceBinder(binder) {} std::string toString() const; AIBinder* getAIBinder() const; ndk::ScopedAStatus linkToDeath(AIBinder_DeathRecipient* recipient) const; ndk::ScopedAStatus unlinkToDeath(AIBinder_DeathRecipient* recipient) const; ndk::ScopedAStatus checkIfAlive( aidl::android::automotive::watchdog::TimeoutLength timeout) const; ndk::ScopedAStatus prepareProcessTermination() const; const pid_t kPid; const userid_t kUserId; const int64_t kStartTimeMillis; const ClientType kType; const WatchdogProcessService& kService; const std::shared_ptr kClient; const android::sp kWatchdogServiceHelper; const ndk::SpAIBinder kWatchdogServiceBinder; int sessionId; std::string packageName; }; struct HeartBeat { int64_t eventTime; int64_t value; }; typedef std::unordered_map PingedClientMap; class PropertyChangeListener final : public android::frameworks::automotive::vhal::ISubscriptionCallback { public: explicit PropertyChangeListener(const android::sp& service) : kService(service) {} void onPropertyEvent(const std::vector< std::unique_ptr>& values) override; void onPropertySetError( const std::vector& errors) override; private: const android::sp kService; }; class MessageHandlerImpl final : public MessageHandler { public: explicit MessageHandlerImpl(const android::sp& service) : kService(service) {} void handleMessage(const Message& message) override; private: const android::sp kService; }; private: android::base::Result registerClient( const ClientInfo& clientInfo, aidl::android::automotive::watchdog::TimeoutLength timeout); ndk::ScopedAStatus unregisterClientLocked( const std::vector& timeouts, const ndk::SpAIBinder& binder, ClientType clientType); ndk::ScopedAStatus tellClientAliveLocked(const ndk::SpAIBinder& binder, int32_t sessionId); android::base::Result startHealthCheckingLocked( aidl::android::automotive::watchdog::TimeoutLength timeout); android::base::Result dumpAndKillClientsIfNotResponding( aidl::android::automotive::watchdog::TimeoutLength timeout); android::base::Result dumpAndKillAllProcesses( const std::vector& processesNotResponding, bool reportToVhal); int32_t getNewSessionId(); android::base::Result updateVhal( const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value); android::base::Result connectToVhal(); void subscribeToVhalHeartBeat(); const sp getWatchdogServiceHelperLocked(); void cacheVhalProcessIdentifier(); void cacheVhalProcessIdentifierForPid(int32_t pid); android::base::Result requestAidlVhalPid(); void reportWatchdogAliveToVhal(); void reportTerminatedProcessToVhal( const std::vector& processesNotResponding); android::base::Result readProcCmdLine(int32_t pid); void handleVhalDeath(); void queryVhalProperties(); void updateVhalHeartBeat(int64_t value); void checkVhalHealth(); void resetVhalInfoLocked(); void terminateVhal(); using ClientInfoMap = std::unordered_map; using Processor = std::function; bool findClientAndProcessLocked( const std::vector& timeouts, AIBinder* binder, const Processor& processor); bool findClientAndProcessLocked( const std::vector& timeouts, uintptr_t binderPtrId, const Processor& processor); std::chrono::nanoseconds getTimeoutDurationNs( const aidl::android::automotive::watchdog::TimeoutLength& timeout); static int toProtoClientType(ClientType clientType); private: const std::function()> kTryCreateVhalClientFunc; const std::function()> kTryGetHidlServiceManagerFunc; const std::function kGetStartTimeForPidFunc; const std::chrono::nanoseconds kVhalPidCachingRetryDelayNs; android::sp mHandlerLooper; android::sp mMessageHandler; ndk::ScopedAIBinder_DeathRecipient mClientBinderDeathRecipient; std::unordered_set mNotSupportedVhalProperties; std::shared_ptr mPropertyChangeListener; // mLastSessionId is accessed only within main thread. No need for mutual-exclusion. int32_t mLastSessionId; bool mServiceStarted; std::chrono::milliseconds mVhalHealthCheckWindowMillis; std::optional mOverriddenClientHealthCheckWindowNs; std::shared_ptr mVhalBinderDiedCallback; android::sp mDeathRegistrationWrapper; std::shared_ptr mPackageInfoResolver; android::Mutex mMutex; std::unordered_map mClientsByTimeout GUARDED_BY(mMutex); std::unordered_map mPingedClients GUARDED_BY(mMutex); std::unordered_set mStoppedUserIds GUARDED_BY(mMutex); std::shared_ptr mMonitor GUARDED_BY(mMutex); bool mIsEnabled GUARDED_BY(mMutex); std::shared_ptr mVhalService GUARDED_BY(mMutex); std::optional mVhalProcessIdentifier GUARDED_BY(mMutex); int32_t mTotalVhalPidCachingAttempts GUARDED_BY(mMutex); HeartBeat mVhalHeartBeat GUARDED_BY(mMutex); // For unit tests. friend class internal::WatchdogProcessServicePeer; }; } // namespace watchdog } // namespace automotive } // namespace android