1e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev/*
2e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev * Copyright (C) 2016 The Android Open Source Project
3e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev *
4e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev * Licensed under the Apache License, Version 2.0 (the "License");
5e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev * you may not use this file except in compliance with the License.
6e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev * You may obtain a copy of the License at
7e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev *
8e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev *      http://www.apache.org/licenses/LICENSE-2.0
9e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev *
10e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev * Unless required by applicable law or agreed to in writing, software
11e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev * distributed under the License is distributed on an "AS IS" BASIS,
12e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev * See the License for the specific language governing permissions and
14e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev * limitations under the License.
15e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev */
16e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev
172579fb792b4d47555515459f372f63c4305ee2caPavel Maltsev#define LOG_TAG "automotive.vehicle@2.0-impl"
18e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev
190e0a925aea98a63120e3ce81e6f9ca83441a7b1fPavel Maltsev#include "SubscriptionManager.h"
200e0a925aea98a63120e3ce81e6f9ca83441a7b1fPavel Maltsev
21e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev#include <cmath>
228ab96e3874baa572f10e314ef6e0614042b8305fPavel Maltsev#include <inttypes.h>
23e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev
240e0a925aea98a63120e3ce81e6f9ca83441a7b1fPavel Maltsev#include <android/log.h>
25e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev
26e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev#include "VehicleUtils.h"
27e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev
28e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsevnamespace android {
29e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsevnamespace hardware {
302579fb792b4d47555515459f372f63c4305ee2caPavel Maltsevnamespace automotive {
31e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsevnamespace vehicle {
32e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsevnamespace V2_0 {
33e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev
34e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsevbool mergeSubscribeOptions(const SubscribeOptions &oldOpts,
35e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev                           const SubscribeOptions &newOpts,
36e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev                           SubscribeOptions *outResult) {
37e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev    float updatedRate = std::max(oldOpts.sampleRate, newOpts.sampleRate);
38fbd346636fe1b61fce69b5a0d9ceb2ffe7d81939Scott Randolph    SubscribeFlags updatedFlags = SubscribeFlags(oldOpts.flags | newOpts.flags);
39e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev
401ae977d6e87a88e1689d406636982e8296d68175Steve Paik    bool updated = (updatedRate > oldOpts.sampleRate) || (updatedFlags != oldOpts.flags);
41e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev    if (updated) {
42e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev        *outResult = oldOpts;
43e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev        outResult->sampleRate = updatedRate;
44e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev        outResult->flags = updatedFlags;
45e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev    }
46e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev
47e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev    return updated;
48e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev}
49e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev
50e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsevvoid HalClient::addOrUpdateSubscription(const SubscribeOptions &opts)  {
518ab96e3874baa572f10e314ef6e0614042b8305fPavel Maltsev    ALOGI("%s opts.propId: 0x%x", __func__, opts.propId);
528ab96e3874baa572f10e314ef6e0614042b8305fPavel Maltsev
53e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev    auto it = mSubscriptions.find(opts.propId);
54e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev    if (it == mSubscriptions.end()) {
55e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev        mSubscriptions.emplace(opts.propId, opts);
56e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev    } else {
57e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev        const SubscribeOptions& oldOpts = it->second;
58e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev        SubscribeOptions updatedOptions;
59e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev        if (mergeSubscribeOptions(oldOpts, opts, &updatedOptions)) {
60e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev            mSubscriptions.erase(it);
61e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev            mSubscriptions.emplace(opts.propId, updatedOptions);
62e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev        }
63e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev    }
64e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev}
65e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev
668e624b323c9808c6454cd2e76ffd3ca2ede5679cPavel Maltsevbool HalClient::isSubscribed(int32_t propId,
678e624b323c9808c6454cd2e76ffd3ca2ede5679cPavel Maltsev                             SubscribeFlags flags) {
68e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev    auto it = mSubscriptions.find(propId);
69e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev    if (it == mSubscriptions.end()) {
70e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev        return false;
71e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev    }
72e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev    const SubscribeOptions& opts = it->second;
731ae977d6e87a88e1689d406636982e8296d68175Steve Paik    bool res = (opts.flags & flags);
74e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev    return res;
75e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev}
76e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev
778ab96e3874baa572f10e314ef6e0614042b8305fPavel Maltsevstd::vector<int32_t> HalClient::getSubscribedProperties() const {
788ab96e3874baa572f10e314ef6e0614042b8305fPavel Maltsev    std::vector<int32_t> props;
798ab96e3874baa572f10e314ef6e0614042b8305fPavel Maltsev    for (const auto& subscription : mSubscriptions) {
808ab96e3874baa572f10e314ef6e0614042b8305fPavel Maltsev        ALOGI("%s propId: 0x%x, propId: 0x%x", __func__, subscription.first, subscription.second.propId);
818ab96e3874baa572f10e314ef6e0614042b8305fPavel Maltsev        props.push_back(subscription.first);
828ab96e3874baa572f10e314ef6e0614042b8305fPavel Maltsev    }
838ab96e3874baa572f10e314ef6e0614042b8305fPavel Maltsev    return props;
848ab96e3874baa572f10e314ef6e0614042b8305fPavel Maltsev}
858ab96e3874baa572f10e314ef6e0614042b8305fPavel Maltsev
868ab96e3874baa572f10e314ef6e0614042b8305fPavel MaltsevStatusCode SubscriptionManager::addOrUpdateSubscription(
8741a000da5862af5f2ca8d1bcc87a7a8937ad75b5Pavel Maltsev        ClientId clientId,
88e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev        const sp<IVehicleCallback> &callback,
898ab96e3874baa572f10e314ef6e0614042b8305fPavel Maltsev        const hidl_vec<SubscribeOptions> &optionList,
908ab96e3874baa572f10e314ef6e0614042b8305fPavel Maltsev        std::list<SubscribeOptions>* outUpdatedSubscriptions) {
918ab96e3874baa572f10e314ef6e0614042b8305fPavel Maltsev    outUpdatedSubscriptions->clear();
92e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev
93e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev    MuxGuard g(mLock);
94e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev
958ab96e3874baa572f10e314ef6e0614042b8305fPavel Maltsev    ALOGI("SubscriptionManager::addOrUpdateSubscription, callback: %p", callback.get());
968ab96e3874baa572f10e314ef6e0614042b8305fPavel Maltsev
9741a000da5862af5f2ca8d1bcc87a7a8937ad75b5Pavel Maltsev    const sp<HalClient>& client = getOrCreateHalClientLocked(clientId, callback);
988ab96e3874baa572f10e314ef6e0614042b8305fPavel Maltsev    if (client.get() == nullptr) {
998ab96e3874baa572f10e314ef6e0614042b8305fPavel Maltsev        return StatusCode::INTERNAL_ERROR;
1008ab96e3874baa572f10e314ef6e0614042b8305fPavel Maltsev    }
101e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev
102e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev    for (size_t i = 0; i < optionList.size(); i++) {
103e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev        const SubscribeOptions& opts = optionList[i];
1048ab96e3874baa572f10e314ef6e0614042b8305fPavel Maltsev        ALOGI("SubscriptionManager::addOrUpdateSubscription, prop: 0x%x", opts.propId);
105e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev        client->addOrUpdateSubscription(opts);
106e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev
107e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev        addClientToPropMapLocked(opts.propId, client);
108e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev
10928b9f8be0b849c58e905c4a67358036a1fa82c65Steve Paik        if (SubscribeFlags::EVENTS_FROM_CAR & opts.flags) {
110e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev            SubscribeOptions updated;
111e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev            if (updateHalEventSubscriptionLocked(opts, &updated)) {
1128ab96e3874baa572f10e314ef6e0614042b8305fPavel Maltsev                outUpdatedSubscriptions->push_back(updated);
113e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev            }
114e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev        }
115e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev    }
116e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev
1178ab96e3874baa572f10e314ef6e0614042b8305fPavel Maltsev    return StatusCode::OK;
118e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev}
119e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev
120e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsevstd::list<HalClientValues> SubscriptionManager::distributeValuesToClients(
121e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev        const std::vector<recyclable_ptr<VehiclePropValue>>& propValues,
122e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev        SubscribeFlags flags) const {
123e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev    std::map<sp<HalClient>, std::list<VehiclePropValue*>> clientValuesMap;
124e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev
125e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev    {
126e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev        MuxGuard g(mLock);
127e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev        for (const auto& propValue: propValues) {
128e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev            VehiclePropValue* v = propValue.get();
1291ae977d6e87a88e1689d406636982e8296d68175Steve Paik            auto clients = getSubscribedClientsLocked(v->prop, flags);
130e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev            for (const auto& client : clients) {
131e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev                clientValuesMap[client].push_back(v);
132e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev            }
133e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev        }
134e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev    }
135e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev
136e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev    std::list<HalClientValues> clientValues;
137e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev    for (const auto& entry : clientValuesMap) {
138e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev        clientValues.push_back(HalClientValues {
139e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev            .client = entry.first,
140e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev            .values = entry.second
141e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev        });
142e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev    }
143e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev
144e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev    return clientValues;
145e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev}
146e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev
1471ae977d6e87a88e1689d406636982e8296d68175Steve Paikstd::list<sp<HalClient>> SubscriptionManager::getSubscribedClients(int32_t propId,
1481ae977d6e87a88e1689d406636982e8296d68175Steve Paik                                                                   SubscribeFlags flags) const {
149e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev    MuxGuard g(mLock);
1501ae977d6e87a88e1689d406636982e8296d68175Steve Paik    return getSubscribedClientsLocked(propId, flags);
151e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev}
152e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev
153e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsevstd::list<sp<HalClient>> SubscriptionManager::getSubscribedClientsLocked(
1541ae977d6e87a88e1689d406636982e8296d68175Steve Paik    int32_t propId, SubscribeFlags flags) const {
155e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev    std::list<sp<HalClient>> subscribedClients;
156e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev
157e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev    sp<HalClientVector> propClients = getClientsForPropertyLocked(propId);
158e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev    if (propClients.get() != nullptr) {
159e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev        for (size_t i = 0; i < propClients->size(); i++) {
160e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev            const auto& client = propClients->itemAt(i);
1611ae977d6e87a88e1689d406636982e8296d68175Steve Paik            if (client->isSubscribed(propId, flags)) {
162e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev                subscribedClients.push_back(client);
163e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev            }
164e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev        }
165e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev    }
166e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev
167e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev    return subscribedClients;
168e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev}
169e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev
170e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsevbool SubscriptionManager::updateHalEventSubscriptionLocked(
171e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev        const SubscribeOptions &opts, SubscribeOptions *outUpdated) {
172e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev    bool updated = false;
173e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev    auto it = mHalEventSubscribeOptions.find(opts.propId);
174e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev    if (it == mHalEventSubscribeOptions.end()) {
175e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev        *outUpdated = opts;
176e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev        mHalEventSubscribeOptions.emplace(opts.propId, opts);
177e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev        updated = true;
178e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev    } else {
179e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev        const SubscribeOptions& oldOpts = it->second;
180e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev
181e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev        if (mergeSubscribeOptions(oldOpts, opts, outUpdated)) {
182e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev            mHalEventSubscribeOptions.erase(opts.propId);
183e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev            mHalEventSubscribeOptions.emplace(opts.propId, *outUpdated);
184e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev            updated = true;
185e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev        }
186e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev    }
187e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev
188e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev    return updated;
189e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev}
190e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev
191e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsevvoid SubscriptionManager::addClientToPropMapLocked(
1928e624b323c9808c6454cd2e76ffd3ca2ede5679cPavel Maltsev        int32_t propId, const sp<HalClient> &client) {
193e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev    auto it = mPropToClients.find(propId);
194e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev    sp<HalClientVector> propClients;
195e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev    if (it == mPropToClients.end()) {
196e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev        propClients = new HalClientVector();
197e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev        mPropToClients.insert(std::make_pair(propId, propClients));
198e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev    } else {
199e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev        propClients = it->second;
200e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev    }
201e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev    propClients->addOrUpdate(client);
202e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev}
203e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev
204e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsevsp<HalClientVector> SubscriptionManager::getClientsForPropertyLocked(
2058e624b323c9808c6454cd2e76ffd3ca2ede5679cPavel Maltsev        int32_t propId) const {
206e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev    auto it = mPropToClients.find(propId);
207e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev    return it == mPropToClients.end() ? nullptr : it->second;
208e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev}
209e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev
210e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsevsp<HalClient> SubscriptionManager::getOrCreateHalClientLocked(
21141a000da5862af5f2ca8d1bcc87a7a8937ad75b5Pavel Maltsev        ClientId clientId, const sp<IVehicleCallback>& callback) {
21241a000da5862af5f2ca8d1bcc87a7a8937ad75b5Pavel Maltsev    auto it = mClients.find(clientId);
21341a000da5862af5f2ca8d1bcc87a7a8937ad75b5Pavel Maltsev
214e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev    if (it == mClients.end()) {
21541a000da5862af5f2ca8d1bcc87a7a8937ad75b5Pavel Maltsev        uint64_t cookie = reinterpret_cast<uint64_t>(clientId);
2168ab96e3874baa572f10e314ef6e0614042b8305fPavel Maltsev        ALOGI("Creating new client and linking to death recipient, cookie: 0x%" PRIx64, cookie);
2178ab96e3874baa572f10e314ef6e0614042b8305fPavel Maltsev        auto res = callback->linkToDeath(mCallbackDeathRecipient, cookie);
2188ab96e3874baa572f10e314ef6e0614042b8305fPavel Maltsev        if (!res.isOk()) {  // Client is already dead?
2198ab96e3874baa572f10e314ef6e0614042b8305fPavel Maltsev            ALOGW("%s failed to link to death, client %p, err: %s",
2208ab96e3874baa572f10e314ef6e0614042b8305fPavel Maltsev                  __func__, callback.get(), res.description().c_str());
2218ab96e3874baa572f10e314ef6e0614042b8305fPavel Maltsev            return nullptr;
2228ab96e3874baa572f10e314ef6e0614042b8305fPavel Maltsev        }
223270aeae9f4aa06389d0f752ba05c4325a8690cddPavel Maltsev
224270aeae9f4aa06389d0f752ba05c4325a8690cddPavel Maltsev        sp<HalClient> client = new HalClient(callback);
22541a000da5862af5f2ca8d1bcc87a7a8937ad75b5Pavel Maltsev        mClients.insert({clientId, client});
226e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev        return client;
227e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev    } else {
228e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev        return it->second;
229e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev    }
230e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev}
231e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev
23241a000da5862af5f2ca8d1bcc87a7a8937ad75b5Pavel Maltsevvoid SubscriptionManager::unsubscribe(ClientId clientId,
2338e624b323c9808c6454cd2e76ffd3ca2ede5679cPavel Maltsev                                      int32_t propId) {
234e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev    MuxGuard g(mLock);
235e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev    auto propertyClients = getClientsForPropertyLocked(propId);
23641a000da5862af5f2ca8d1bcc87a7a8937ad75b5Pavel Maltsev    auto clientIter = mClients.find(clientId);
237e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev    if (clientIter == mClients.end()) {
238e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev        ALOGW("Unable to unsubscribe: no callback found, propId: 0x%x", propId);
239e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev    } else {
240e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev        auto client = clientIter->second;
241e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev
242e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev        if (propertyClients != nullptr) {
243e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev            propertyClients->remove(client);
244e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev
245e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev            if (propertyClients->isEmpty()) {
246e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev                mPropToClients.erase(propId);
247e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev            }
248e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev        }
249e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev
250e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev        bool isClientSubscribedToOtherProps = false;
251e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev        for (const auto& propClient : mPropToClients) {
252e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev            if (propClient.second->indexOf(client) >= 0) {
253e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev                isClientSubscribedToOtherProps = true;
254e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev                break;
255e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev            }
256e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev        }
257e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev
258e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev        if (!isClientSubscribedToOtherProps) {
2598ab96e3874baa572f10e314ef6e0614042b8305fPavel Maltsev            auto res = client->getCallback()->unlinkToDeath(mCallbackDeathRecipient);
2608ab96e3874baa572f10e314ef6e0614042b8305fPavel Maltsev            if (!res.isOk()) {
2618ab96e3874baa572f10e314ef6e0614042b8305fPavel Maltsev                ALOGW("%s failed to unlink to death, client: %p, err: %s",
2628ab96e3874baa572f10e314ef6e0614042b8305fPavel Maltsev                      __func__, client->getCallback().get(), res.description().c_str());
2638ab96e3874baa572f10e314ef6e0614042b8305fPavel Maltsev            }
264e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev            mClients.erase(clientIter);
265e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev        }
266e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev    }
267e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev
2688ab96e3874baa572f10e314ef6e0614042b8305fPavel Maltsev    if (propertyClients == nullptr || propertyClients->isEmpty()) {
2698ab96e3874baa572f10e314ef6e0614042b8305fPavel Maltsev        mHalEventSubscribeOptions.erase(propId);
2708ab96e3874baa572f10e314ef6e0614042b8305fPavel Maltsev        mOnPropertyUnsubscribed(propId);
2718ab96e3874baa572f10e314ef6e0614042b8305fPavel Maltsev    }
2728ab96e3874baa572f10e314ef6e0614042b8305fPavel Maltsev}
2738ab96e3874baa572f10e314ef6e0614042b8305fPavel Maltsev
2748ab96e3874baa572f10e314ef6e0614042b8305fPavel Maltsevvoid SubscriptionManager::onCallbackDead(uint64_t cookie) {
2758ab96e3874baa572f10e314ef6e0614042b8305fPavel Maltsev    ALOGI("%s, cookie: 0x%" PRIx64, __func__, cookie);
27641a000da5862af5f2ca8d1bcc87a7a8937ad75b5Pavel Maltsev    ClientId clientId = cookie;
2778ab96e3874baa572f10e314ef6e0614042b8305fPavel Maltsev
2788ab96e3874baa572f10e314ef6e0614042b8305fPavel Maltsev    std::vector<int32_t> props;
2798ab96e3874baa572f10e314ef6e0614042b8305fPavel Maltsev    {
2808ab96e3874baa572f10e314ef6e0614042b8305fPavel Maltsev        MuxGuard g(mLock);
28141a000da5862af5f2ca8d1bcc87a7a8937ad75b5Pavel Maltsev        const auto& it = mClients.find(clientId);
2828ab96e3874baa572f10e314ef6e0614042b8305fPavel Maltsev        if (it == mClients.end()) {
2838ab96e3874baa572f10e314ef6e0614042b8305fPavel Maltsev            return;  // Nothing to do here, client wasn't subscribed to any properties.
2848ab96e3874baa572f10e314ef6e0614042b8305fPavel Maltsev        }
2858ab96e3874baa572f10e314ef6e0614042b8305fPavel Maltsev        const auto& halClient = it->second;
2868ab96e3874baa572f10e314ef6e0614042b8305fPavel Maltsev        props = halClient->getSubscribedProperties();
2878ab96e3874baa572f10e314ef6e0614042b8305fPavel Maltsev    }
2888ab96e3874baa572f10e314ef6e0614042b8305fPavel Maltsev
2898ab96e3874baa572f10e314ef6e0614042b8305fPavel Maltsev    for (int32_t propId : props) {
29041a000da5862af5f2ca8d1bcc87a7a8937ad75b5Pavel Maltsev        unsubscribe(clientId, propId);
2918ab96e3874baa572f10e314ef6e0614042b8305fPavel Maltsev    }
292e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev}
293e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev
294e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev
295e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev}  // namespace V2_0
296e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev}  // namespace vehicle
2972579fb792b4d47555515459f372f63c4305ee2caPavel Maltsev}  // namespace automotive
298e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev}  // namespace hardware
299e2603e3d52dbd505cdda20a8111f45bf833d674aPavel Maltsev}  // namespace android
300