/* * Copyright (C) 2021 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. */ #ifndef android_hardware_automotive_vehicle_aidl_impl_vhal_include_DefaultVehicleHal_H_ #define android_hardware_automotive_vehicle_aidl_impl_vhal_include_DefaultVehicleHal_H_ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace android { namespace hardware { namespace automotive { namespace vehicle { class DefaultVehicleHal final : public aidl::android::hardware::automotive::vehicle::BnVehicle { public: using CallbackType = std::shared_ptr; explicit DefaultVehicleHal(std::unique_ptr hardware); ~DefaultVehicleHal(); ndk::ScopedAStatus getAllPropConfigs( aidl::android::hardware::automotive::vehicle::VehiclePropConfigs* returnConfigs) override; ndk::ScopedAStatus getValues( const CallbackType& callback, const aidl::android::hardware::automotive::vehicle::GetValueRequests& requests) override; ndk::ScopedAStatus setValues( const CallbackType& callback, const aidl::android::hardware::automotive::vehicle::SetValueRequests& requests) override; ndk::ScopedAStatus getPropConfigs( const std::vector& props, aidl::android::hardware::automotive::vehicle::VehiclePropConfigs* returnConfigs) override; ndk::ScopedAStatus subscribe( const CallbackType& callback, const std::vector& options, int32_t maxSharedMemoryFileCount) override; ndk::ScopedAStatus unsubscribe(const CallbackType& callback, const std::vector& propIds) override; ndk::ScopedAStatus returnSharedMemory(const CallbackType& callback, int64_t sharedMemoryId) override; binder_status_t dump(int fd, const char** args, uint32_t numArgs) override; IVehicleHardware* getHardware(); private: // friend class for unit testing. friend class DefaultVehicleHalTest; using GetValuesClient = GetSetValuesClient; using SetValuesClient = GetSetValuesClient; // A thread safe class to maintain an increasing request ID for each subscribe client. This // class is safe to pass to async callbacks. class SubscribeIdByClient { public: int64_t getId(const CallbackType& callback); private: std::mutex mLock; std::unordered_map mIds GUARDED_BY(mLock); }; // A thread safe class to store all subscribe clients. This class is safe to pass to async // callbacks. class SubscriptionClients { public: SubscriptionClients(std::shared_ptr pool) : mPendingRequestPool(pool) {} std::shared_ptr maybeAddClient(const CallbackType& callback); std::shared_ptr getClient(const CallbackType& callback); void removeClient(const AIBinder* clientId); size_t countClients(); private: std::mutex mLock; std::unordered_map> mClients GUARDED_BY(mLock); // PendingRequestPool is thread-safe. std::shared_ptr mPendingRequestPool; }; // A wrapper for binder operations to enable stubbing for test. class IBinder { public: virtual ~IBinder() = default; virtual binder_status_t linkToDeath(AIBinder* binder, AIBinder_DeathRecipient* recipient, void* cookie) = 0; virtual bool isAlive(const AIBinder* binder) = 0; }; // A real implementation for IBinder. class AIBinderImpl final : public IBinder { public: binder_status_t linkToDeath(AIBinder* binder, AIBinder_DeathRecipient* recipient, void* cookie) override; bool isAlive(const AIBinder* binder) override; }; // OnBinderDiedContext is a type used as a cookie passed deathRecipient. The deathRecipient's // onBinderDied function takes only a cookie as input and we have to store all the contexts // as the cookie. struct OnBinderDiedContext { DefaultVehicleHal* vhal; const AIBinder* clientId; }; // BinderDiedUnlinkedEvent represents either an onBinderDied or an onBinderUnlinked event. struct BinderDiedUnlinkedEvent { // true for onBinderDied, false for onBinderUnlinked. bool onBinderDied; const AIBinder* clientId; }; // The default timeout of get or set value requests is 30s. // TODO(b/214605968): define TIMEOUT_IN_NANO in IVehicle and allow getValues/setValues/subscribe // to specify custom timeouts. static constexpr int64_t TIMEOUT_IN_NANO = 30'000'000'000; // heart beat event interval: 3s static constexpr int64_t HEART_BEAT_INTERVAL_IN_NANO = 3'000'000'000; std::unique_ptr mVehicleHardware; // mConfigsByPropId and mConfigFile are only modified during initialization, so no need to // lock guard them. std::unordered_map mConfigsByPropId; // Only modified in constructor, so thread-safe. std::unique_ptr mConfigFile; // PendingRequestPool is thread-safe. std::shared_ptr mPendingRequestPool; // SubscriptionManager is thread-safe. std::shared_ptr mSubscriptionManager; std::mutex mLock; std::unordered_map> mOnBinderDiedContexts GUARDED_BY(mLock); std::unordered_map> mGetValuesClients GUARDED_BY(mLock); std::unordered_map> mSetValuesClients GUARDED_BY(mLock); // SubscriptionClients is thread-safe. std::shared_ptr mSubscriptionClients; // mBinderImpl is only going to be changed in test. std::unique_ptr mBinderImpl; // Only initialized once. std::shared_ptr> mRecurrentAction; // RecurrentTimer is thread-safe. RecurrentTimer mRecurrentTimer; ndk::ScopedAIBinder_DeathRecipient mDeathRecipient; // ConcurrentQueue is thread-safe. ConcurrentQueue mBinderEvents; // A thread to handle onBinderDied or onBinderUnlinked event. std::thread mOnBinderDiedUnlinkedHandlerThread; android::base::Result checkProperty( const aidl::android::hardware::automotive::vehicle::VehiclePropValue& propValue); android::base::Result> checkDuplicateRequests( const std::vector& requests); android::base::Result> checkDuplicateRequests( const std::vector& requests); VhalResult checkSubscribeOptions( const std::vector& options); VhalResult checkReadPermission( const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value) const; VhalResult checkWritePermission( const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value) const; android::base::Result getConfig(int32_t propId) const; void onBinderDiedWithContext(const AIBinder* clientId); void onBinderUnlinkedWithContext(const AIBinder* clientId); // Registers a onBinderDied callback for the client if not already registered. // Returns true if the client Binder is alive, false otherwise. bool monitorBinderLifeCycleLocked(const AIBinder* clientId) REQUIRES(mLock); bool checkDumpPermission(); // The looping handler function to process all onBinderDied or onBinderUnlinked events in // mBinderEvents. void onBinderDiedUnlinkedHandler(); // Gets or creates a {@code T} object for the client to or from {@code clients}. template static std::shared_ptr getOrCreateClient( std::unordered_map>* clients, const CallbackType& callback, std::shared_ptr pendingRequestPool); static void onPropertyChangeEvent( std::weak_ptr subscriptionManager, const std::vector& updatedValues); static void checkHealth(IVehicleHardware* hardware, std::weak_ptr subscriptionManager); static void onBinderDied(void* cookie); static void onBinderUnlinked(void* cookie); // Test-only // Set the default timeout for pending requests. void setTimeout(int64_t timeoutInNano); // Test-only void setBinderImpl(std::unique_ptr impl); }; } // namespace vehicle } // namespace automotive } // namespace hardware } // namespace android #endif // android_hardware_automotive_vehicle_aidl_impl_vhal_include_DefaultVehicleHal_H_