1 //******************************************************************
3 // Copyright 2014 Intel Corporation All Rights Reserved.
4 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
6 // ============================================================================
8 // ============================================================================
10 //#include "DeviceImpl.h"
11 #include "SimpleLogger.h"
16 // ============================================================================
18 // ============================================================================
23 static const char TAG[] = "ModelImpl";
25 // ============================================================================
26 // GetDevicesResult Implementation Class
27 // ============================================================================
28 class GetDeviceSuccess : public GetDevicesResult {
30 virtual ~GetDeviceSuccess() {}
32 // ============================================================
34 // ============================================================
36 virtual QueryResultType getResult() const {
40 virtual const std::list<Device::SharedPtr>& getDeviceList() const {
45 std::list<Device::SharedPtr> deviceList_;
48 // ============================================================================
49 // DeviceEvent Implementation Class
50 // ============================================================================
51 class DeviceEventSuccess : public DeviceEvent {
52 // ============================================================
53 // Constructor & Destructor
54 // ============================================================
56 DeviceEventSuccess() {
57 deviceObserverHandle_ = INVALID_DEVICE_OBSERVER_HANDLE;
59 virtual ~DeviceEventSuccess() {}
61 // ============================================================
63 // ============================================================
65 virtual QueryResultType getResult() const {
69 virtual DeviceObserverHandle getObserverHandle() const {
70 return deviceObserverHandle_;
73 virtual const std::list<DeviceEventInfo>& getDeviceIdList() const {
74 return deviceInfoList_;
78 DeviceObserverHandle deviceObserverHandle_;
79 std::list<DeviceEventInfo> deviceInfoList_;
82 // ============================================================================
84 // ============================================================================
85 Model::SharedPtr Model::createModel() {
86 logDebug(TAG, "Entering Model::createModel");
87 return ModelImpl::createModel();
90 ModelImpl::SharedPtr ModelImpl::createModel() {
91 // Get singleton of ModelImpl.
92 logDebug(TAG, "Entering ModelImpl::createModel");
93 static SharedPtr instance = std::make_shared<ModelImpl>();
97 // ============================================================================
98 // Constructors & Destructors
99 // ============================================================================
100 ModelImpl::ModelImpl() {
101 logDebug(TAG, "Entering ModelImpl::ModelImpl");
103 // initialize random seed for use with random protocol handles
107 ModelImpl::~ModelImpl() {
108 logDebug(TAG, "Entering ModelImpl::~ModelImpl");
109 protocolMap_.clear();
111 deviceObserverMap_.clear();
114 // ============================================================================
116 // ============================================================================
118 void ModelImpl::getDevices(GetDevicesFunction& asyncReturnFunc) {
119 logDebug(TAG, "Entering ModelImpl::getDevices");
121 mutex_lock_guard lock(deviceListMutex_);
123 GetDeviceSuccess result;
124 // Insert from the model device list to the result device list
125 result.deviceList_.insert(result.deviceList_.end(), deviceList_.begin(), deviceList_.end());
127 // Invoke the callback
128 asyncReturnFunc(result);
131 // Add/remove device observer
132 void ModelImpl::removeDeviceObserver(DeviceObserverHandle observerHandle) {
133 logDebug(TAG, "Entering ModelImpl::removeDeviceObserver");
135 mutex_lock_guard lock(deviceObserverMapMutex_);
136 for (auto iter = deviceObserverMap_.begin(); iter != deviceObserverMap_.end(); ++iter) {
137 if (iter->first == observerHandle) {
139 deviceObserverMap_.erase(iter);
140 logDebug(TAG, "ModelImpl::removeDeviceObserver, removed observer handle %d", (uint32_t)observerHandle);
146 void ModelImpl::setDeviceObserver(DeviceEventFunction& asyncEventFunction) {
147 // TODO: anyway to ensure that asyncEventFunction is valid? nullptr check?
148 logDebug(TAG, "Entering ModelImpl::setDeviceObserver");
150 // Create a local scope here so that the mutex will be released at the end of the scope
152 mutex_lock_guard lock(deviceObserverMapMutex_);
153 // Get a handle that is not already in use
154 DeviceObserverHandle observerHandle;
156 observerHandle = generateDeviceObserverHandle();
157 } while (isDeviceObserverHandleInUse(observerHandle));
159 // Add observer to the map.
160 // Insert returns a pair with the second a bool set to true if a new element
161 // was inserted or false if an equivalent key already existed.
162 if (deviceObserverMap_.insert(DeviceObserverMap::value_type(observerHandle, asyncEventFunction)).second) {
163 logDebug(TAG, "Entering ModelImpl::setDeviceObserver, observer added");
166 logDebug(TAG, "ModelImpl::setDeviceObserver: Error inserting observer");
170 // Notify the observers
171 DeviceIdList deviceIdList = getDeviceIdList();
172 notifyDeviceObservers(DeviceEvent::DeviceChange::DEVICE_CURRENT_COLLECTION, deviceIdList);
175 const Protocols::Protocol::Handle ModelImpl::registerProtocol(const Protocols::Protocol::SharedPtr& protocol) {
176 logDebug(TAG, "Entering ModelImpl::registerProtocol");
181 logDebug(TAG, "ModelImpl::registerProtocol, trying to register protocol %s", protocol->getName().c_str());
183 // Iterate through map and ensure that the protocol is not already registered
184 Protocols::Protocol::Handle handle = Protocols::Protocol::INVALID_HANDLE;
185 bool protocolRegistered = false;
187 mutex_lock_guard lock(protocolMapMutex_);
189 for (auto iter = protocolMap_.begin(); iter != protocolMap_.end(); ++iter) {
190 // TODO: need to handle a protocol that no longer is in scope.
191 // Remove from map and maybe notify apps that devices and/or connections are no longer present
192 Protocols::Protocol::SharedPtr sharedProtocol = iter->second.lock();
193 if (sharedProtocol) {
194 if (sharedProtocol->getName() == protocol->getName()) {
195 logDebug(TAG, "ModelImpl::registerProtocol, protocol %s already registered", protocol->getName().c_str());
196 protocolRegistered = true;
202 // If the protocol isn't registered, create a new handle and add
203 // the protocol to the map
204 if (!protocolRegistered) {
206 // Get a handle that is not already in use
208 handle = generateProtocolHandle();
209 } while (isHandleInUse(handle));
211 // Add protocol to the map.
212 // Insert returns a pair with the second a bool set to true if a new element
213 // was inserted or false if an equivalent key already existed.
214 Protocols::Protocol::WeakPtr weakProtocol = protocol;
215 if (!protocolMap_.insert(ProtocolMap::value_type(handle, weakProtocol)).second) {
216 logDebug(TAG, "ModelImpl::registerProtocol: Error inserting protocol %s", protocol->getName().c_str());
217 handle = Protocols::Protocol::INVALID_HANDLE;
220 logDebug(TAG, "ModelImpl::registerProtocol: registered protocol = %s", protocol->getName().c_str());
221 protocol->setHandle(handle);
228 bool ModelImpl::unregisterProtocol(const Protocols::Protocol::Handle protocolHandle) {
229 logDebug(TAG, "Entering ModelImpl::unregisterProtocol");
231 bool handleFound = false;
233 mutex_lock_guard lock(protocolMapMutex_);
235 for (auto iter = protocolMap_.begin(); iter != protocolMap_.end(); ++iter) {
236 if (iter->first == protocolHandle) {
239 protocolMap_.erase(iter);
240 logDebug(TAG, "ModelImpl::unregisterProtocol, unregistering protocol handle %d", (uint32_t)protocolHandle);
248 Device::SharedPtr ModelImpl::getDevice(const UUID_t& deviceId) {
249 logDebug(TAG, "Entering ModelImpl::getDevice");
251 // Get a device from the device list. If the device already exists, return that
252 // device. If not, create a new device with the specified device id, add it to
253 // the device list, and then return the device
254 mutex_lock_guard lock(deviceListMutex_);
255 if (deviceList_.empty())
257 logDebug(TAG, "ModelImpl::getDevice, device list empty, adding device");
258 return addDeviceToList(deviceId);
261 // Search list for the device based on device id
262 for (auto iter = deviceList_.begin(); iter != deviceList_.end(); ++iter) {
263 Device::SharedPtr device = *iter;
264 if (device->getId() == deviceId) {
265 logDebug(TAG, "ModelImpl::getDevice, device found in list");
270 // If here, device not found in list, so add and return
271 logDebug(TAG, "ModelImpl::getDevice, device not found in list, adding device");
272 return addDeviceToList(deviceId);
275 void ModelImpl::signalDeviceChange(const UUID_t& deviceId, DeviceEvent::DeviceChange deviceEvent) {
278 DeviceIdList deviceIdList;
279 bool sendNotification = false;
281 // Create a local scope so that the deviceListMutex_ will be released at the end
282 // of the local scope
284 mutex_lock_guard lock(deviceListMutex_);
285 // Search list for the device based on device id
286 for (auto iter = deviceList_.begin(); iter != deviceList_.end(); ++iter) {
287 Device::SharedPtr device = *iter;
288 if (device->getId() == deviceId) {
289 linkCount = device->getLinkCount();
290 logDebug(TAG, "ModelImpl::signalDeviceChange, device found, number of links = %d", linkCount);
292 if (deviceEvent == DeviceEvent::DeviceChange::DEVICE_ADDED) {
293 // If DEVICE_ADDED and only one link, then that indicates that this is the first
294 // time that the device was found by a protocol, so a notification must be sent.
295 // Multiple links in the device indicate that that the device was previously found
296 // by other protocols, so a notification is not required
297 if (linkCount == 1) {
298 deviceIdList.push_back(deviceId);
299 sendNotification = true;
302 else if (deviceEvent == DeviceEvent::DeviceChange::DEVICE_REMOVED) {
303 // If DEVICE_REMOVED and no links remain in the device, then the
304 // device needs to be removed from the device list and
305 // a device removal notification must be sent.
306 if (linkCount == 0) {
307 deviceIdList.push_back(deviceId);
308 deviceList_.erase(iter);
309 sendNotification = true;
317 // Since a device was added or removed, notify the device observers
318 if (sendNotification) {
319 notifyDeviceObservers(deviceEvent, deviceIdList);
323 // ============================================================================
325 // ============================================================================
326 const Protocols::Protocol::Handle ModelImpl::generateProtocolHandle() {
327 // Handle between 1 and (RAND_MAX -1)
328 Protocols::Protocol::Handle handle = (Protocols::Protocol::Handle)(rand() % (RAND_MAX - 1) + 1);
333 bool ModelImpl::isHandleInUse(Protocols::Protocol::Handle handle) {
334 bool handleFound = false;
336 for (auto iter = protocolMap_.begin(); iter != protocolMap_.end(); ++iter) {
337 if (iter->first == handle) {
345 Device::SharedPtr ModelImpl::addDeviceToList(const UUID_t& deviceId) {
346 logDebug(TAG, "Entering ModelImpl::addDeviceToList");
348 deviceList_.push_back(std::make_shared<Device>(deviceId));
349 return deviceList_.back();
352 DeviceObserverHandle ModelImpl::generateDeviceObserverHandle() {
353 // Handle between 1 and (RAND_MAX -1)
354 DeviceObserverHandle handle = (DeviceObserverHandle)(rand() % (RAND_MAX - 1) + 1);
359 bool ModelImpl::isDeviceObserverHandleInUse(DeviceObserverHandle observerHandle) {
360 bool handleFound = false;
362 for (auto iter = deviceObserverMap_.begin(); iter != deviceObserverMap_.end(); ++iter) {
363 if (iter->first == observerHandle) {
371 void ModelImpl::notifyDeviceObservers(DeviceEvent::DeviceChange event, const DeviceIdList& deviceIdList) {
372 logDebug(TAG, "Entering ModelImpl::notifyDeviceObservers");
374 // Iterate through the device id list that was passed to the notifier
375 // and create a list of DeviceEvent::DeviceEventInfo objects.
376 // Set the device id and the event in the DeviceEvent::DeviceEventInfo object
377 std::list<DeviceEvent::DeviceEventInfo> deviceEventInfoList;
378 DeviceEvent::DeviceEventInfo info;
379 for (auto iter = deviceIdList.begin(); iter != deviceIdList.end(); ++iter) {
380 info.deviceId = *iter;
381 info.deviceChange = event;
383 deviceEventInfoList.push_back(info);
386 mutex_lock_guard lock(deviceObserverMapMutex_);
388 // Nothing to do if there are no observers
389 if (deviceObserverMap_.empty()) {
393 DeviceObserverHandle observerHandle;
394 DeviceEventFunction eventFunction;
396 // For every observer in the observer map:
397 for (auto iter = deviceObserverMap_.begin(); iter != deviceObserverMap_.end(); ++iter) {
398 observerHandle = iter->first;
399 eventFunction = iter->second;
401 // 1. Create a DeviceEventSuccess object and set the observer handle
402 DeviceEventSuccess deviceEventSuccess;
403 deviceEventSuccess.deviceObserverHandle_ = observerHandle;
405 // 2. Insert the deviceEventInfoList into the DeviceEventSuccess object list
406 deviceEventSuccess.deviceInfoList_.insert(deviceEventSuccess.deviceInfoList_.end(), deviceEventInfoList.begin(), deviceEventInfoList.end());
408 // 3. Invoke the observer's callback function
409 eventFunction(deviceEventSuccess);
414 ModelImpl::DeviceIdList ModelImpl::getDeviceIdList() {
416 mutex_lock_guard lock(deviceListMutex_);
418 DeviceIdList deviceIdList;
420 // Search list for the device based on device id
421 for (auto iter = deviceList_.begin(); iter != deviceList_.end(); ++iter) {
422 Device::SharedPtr device = *iter;
423 deviceIdList.push_back(device->getId());