1/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef android_hardware_automotive_vehicle_V2_0_SubscriptionManager_H_
18#define android_hardware_automotive_vehicle_V2_0_SubscriptionManager_H_
19
20#include <memory>
21#include <map>
22#include <set>
23#include <list>
24
25#include <android/log.h>
26#include <hidl/HidlSupport.h>
27#include <utils/SortedVector.h>
28
29#include <android/hardware/automotive/vehicle/2.0/IVehicle.h>
30
31#include "ConcurrentQueue.h"
32#include "VehicleObjectPool.h"
33
34namespace android {
35namespace hardware {
36namespace automotive {
37namespace vehicle {
38namespace V2_0 {
39
40class HalClient : public android::RefBase {
41public:
42    HalClient(const sp<IVehicleCallback> &callback)
43        : mCallback(callback) {}
44
45    virtual ~HalClient() {}
46public:
47    sp<IVehicleCallback> getCallback() const {
48        return mCallback;
49    }
50
51    void addOrUpdateSubscription(const SubscribeOptions &opts);
52    bool isSubscribed(int32_t propId, int32_t areaId, SubscribeFlags flags);
53    std::vector<int32_t> getSubscribedProperties() const;
54
55private:
56    const sp<IVehicleCallback> mCallback;
57
58    std::map<int32_t, SubscribeOptions> mSubscriptions;
59};
60
61class HalClientVector : private SortedVector<sp<HalClient>> , public RefBase {
62public:
63    virtual ~HalClientVector() {}
64
65    inline void addOrUpdate(const sp<HalClient> &client) {
66        SortedVector::add(client);
67    }
68
69    using SortedVector::remove;
70    using SortedVector::size;
71    using SortedVector::indexOf;
72    using SortedVector::itemAt;
73    using SortedVector::isEmpty;
74};
75
76struct HalClientValues {
77    sp<HalClient> client;
78    std::list<VehiclePropValue *> values;
79};
80
81using ClientId = uint64_t;
82
83class SubscriptionManager {
84public:
85    using OnPropertyUnsubscribed = std::function<void(int32_t)>;
86
87    /**
88     * Constructs SubscriptionManager
89     *
90     * @param onPropertyUnsubscribed - this callback function will be called when there are no
91     *                                    more client subscribed to particular property.
92     */
93    SubscriptionManager(const OnPropertyUnsubscribed& onPropertyUnsubscribed)
94            : mOnPropertyUnsubscribed(onPropertyUnsubscribed),
95                mCallbackDeathRecipient(new DeathRecipient(
96                    std::bind(&SubscriptionManager::onCallbackDead, this, std::placeholders::_1)))
97    {}
98
99    ~SubscriptionManager() = default;
100
101    /**
102     * Updates subscription. Returns the vector of properties subscription that
103     * needs to be updated in VehicleHAL.
104     */
105    StatusCode addOrUpdateSubscription(ClientId clientId,
106                                       const sp<IVehicleCallback>& callback,
107                                       const hidl_vec<SubscribeOptions>& optionList,
108                                       std::list<SubscribeOptions>* outUpdatedOptions);
109
110    /**
111     * Returns a list of IVehicleCallback -> list of VehiclePropValue ready for
112     * dispatching to its clients.
113     */
114    std::list<HalClientValues> distributeValuesToClients(
115            const std::vector<recyclable_ptr<VehiclePropValue>>& propValues,
116            SubscribeFlags flags) const;
117
118    std::list<sp<HalClient>> getSubscribedClients(int32_t propId,
119                                                  int32_t area,
120                                                  SubscribeFlags flags) const;
121    /**
122     * If there are no clients subscribed to given properties than callback function provided
123     * in the constructor will be called.
124     */
125    void unsubscribe(ClientId clientId, int32_t propId);
126private:
127    std::list<sp<HalClient>> getSubscribedClientsLocked(int32_t propId,
128                                                        int32_t area,
129                                                        SubscribeFlags flags) const;
130
131    bool updateHalEventSubscriptionLocked(const SubscribeOptions &opts, SubscribeOptions* out);
132
133    void addClientToPropMapLocked(int32_t propId, const sp<HalClient>& client);
134
135    sp<HalClientVector> getClientsForPropertyLocked(int32_t propId) const;
136
137    sp<HalClient> getOrCreateHalClientLocked(ClientId callingPid,
138                                             const sp<IVehicleCallback>& callback);
139
140    void onCallbackDead(uint64_t cookie);
141
142private:
143    using OnClientDead = std::function<void(uint64_t)>;
144
145    class DeathRecipient : public hidl_death_recipient {
146    public:
147        DeathRecipient(const OnClientDead& onClientDead)
148            : mOnClientDead(onClientDead) {}
149        ~DeathRecipient() = default;
150
151        DeathRecipient(const DeathRecipient& ) = delete;
152        DeathRecipient& operator=(const DeathRecipient&) = delete;
153
154        void serviceDied(uint64_t cookie,
155                         const wp<::android::hidl::base::V1_0::IBase>& /* who */) override {
156            mOnClientDead(cookie);
157        }
158    private:
159        OnClientDead mOnClientDead;
160    };
161
162private:
163    using MuxGuard = std::lock_guard<std::mutex>;
164
165    mutable std::mutex mLock;
166
167    std::map<ClientId, sp<HalClient>> mClients;
168    std::map<int32_t, sp<HalClientVector>> mPropToClients;
169    std::map<int32_t, SubscribeOptions> mHalEventSubscribeOptions;
170
171    OnPropertyUnsubscribed mOnPropertyUnsubscribed;
172    sp<DeathRecipient> mCallbackDeathRecipient;
173};
174
175
176}  // namespace V2_0
177}  // namespace vehicle
178}  // namespace automotive
179}  // namespace hardware
180}  // namespace android
181
182
183#endif // android_hardware_automotive_vehicle_V2_0_SubscriptionManager_H_
184