/* * 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 { namespace aidlvhal = ::aidl::android::hardware::automotive::vehicle; class DefaultVehicleHal final : public aidlvhal::BnVehicle { public: using CallbackType = std::shared_ptr; explicit DefaultVehicleHal(std::unique_ptr hardware); // Test-only DefaultVehicleHal(std::unique_ptr hardware, int32_t testInterfaceVersion); ~DefaultVehicleHal(); ndk::ScopedAStatus getAllPropConfigs(aidlvhal::VehiclePropConfigs* returnConfigs) override; ndk::ScopedAStatus getValues(const CallbackType& callback, const aidlvhal::GetValueRequests& requests) override; ndk::ScopedAStatus setValues(const CallbackType& callback, const aidlvhal::SetValueRequests& requests) override; ndk::ScopedAStatus getPropConfigs(const std::vector& props, aidlvhal::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 wrapper for binder lifecycle operations to enable stubbing for test. class BinderLifecycleInterface { public: virtual ~BinderLifecycleInterface() = 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 BinderLifecycleInterface. class BinderLifecycleHandler final : public BinderLifecycleInterface { 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 forOnBinderDied; 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; bool mShouldRefreshPropertyConfigs; std::unique_ptr mVehicleHardware; // PendingRequestPool is thread-safe. std::shared_ptr mPendingRequestPool; // SubscriptionManager is thread-safe. std::shared_ptr mSubscriptionManager; // ConcurrentQueue is thread-safe. std::shared_ptr> mBatchedEventQueue; // BatchingConsumer is thread-safe. std::shared_ptr> mPropertyChangeEventsBatchingConsumer; // Only set once during initialization. std::chrono::nanoseconds mEventBatchingWindow; // Only used for testing. int32_t mTestInterfaceVersion = 0; // mConfigsByPropId and mConfigFile is lazy initialized. mutable std::mutex mConfigInitLock; mutable bool mConfigInit GUARDED_BY(mConfigInitLock) = false; mutable std::unordered_map mConfigsByPropId GUARDED_BY(mConfigInitLock); mutable std::unique_ptr mConfigFile GUARDED_BY(mConfigInitLock); std::mutex mLock; std::unordered_map> mOnBinderDiedContexts GUARDED_BY(mLock); std::unordered_map> mGetValuesClients GUARDED_BY(mLock); std::unordered_map> mSetValuesClients GUARDED_BY(mLock); // mBinderLifecycleHandler is only going to be changed in test. std::unique_ptr mBinderLifecycleHandler; // 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 aidlvhal::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 checkPermissionHelper(const aidlvhal::VehiclePropValue& value, aidlvhal::VehiclePropertyAccess accessToTest) const; VhalResult checkReadPermission(const aidlvhal::VehiclePropValue& value) const; VhalResult checkWritePermission(const aidlvhal::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(); bool getAllPropConfigsFromHardwareLocked() const REQUIRES(mConfigInitLock); // The looping handler function to process all onBinderDied or onBinderUnlinked events in // mBinderEvents. void onBinderDiedUnlinkedHandler(); size_t countSubscribeClients(); // Handles the property change events in batch. void handleBatchedPropertyEvents(std::vector&& batchedEvents); int32_t getVhalInterfaceVersion() const; // Gets mConfigsByPropId, lazy init it if necessary. const std::unordered_map& getConfigsByPropId() const; // Gets mConfigFile, lazy init it if necessary. const ndk::ScopedFileDescriptor* getConfigFile() const; // Puts the property change events into a queue so that they can handled in batch. static void batchPropertyChangeEvent( const std::weak_ptr>& batchedEventQueue, std::vector&& updatedValues); // 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(const std::weak_ptr& subscriptionManager, std::vector&& updatedValues); static void onPropertySetErrorEvent( const std::weak_ptr& subscriptionManager, const std::vector& errorEvents); 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 setBinderLifecycleHandler(std::unique_ptr impl); }; } // namespace vehicle } // namespace automotive } // namespace hardware } // namespace android #endif // android_hardware_automotive_vehicle_aidl_impl_vhal_include_DefaultVehicleHal_H_