blob: 610b3aa5028df9bbbe9a39ee26bf4437e6c95114 [file] [log] [blame]
khenaidoob9203542018-09-17 22:56:37 -04001/*
2 * Copyright 2018-present Open Networking Foundation
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 */
npujar1d86a522019-11-14 17:11:16 +053016
khenaidoob9203542018-09-17 22:56:37 -040017package core
18
19import (
npujar467fe752020-01-16 20:17:45 +053020 "context"
npujar1d86a522019-11-14 17:11:16 +053021 "github.com/opencord/voltha-go/rw_core/coreif"
serkant.uluderya2ae470f2020-01-21 11:13:09 -080022 "github.com/opencord/voltha-lib-go/v3/pkg/log"
23 "github.com/opencord/voltha-protos/v3/go/voltha"
khenaidoob9203542018-09-17 22:56:37 -040024)
25
npujar1d86a522019-11-14 17:11:16 +053026// DeviceType mentions type of device like parent, child
khenaidoob9203542018-09-17 22:56:37 -040027type DeviceType int32
28
29const (
30 parent DeviceType = 0
31 child DeviceType = 1
32 any DeviceType = 2
33)
34
khenaidoo442e7c72020-03-10 16:13:48 -040035type MatchResult uint8
36
37const (
38 noMatch MatchResult = iota // current state has not match in the transition table
39 currWildcardMatch // current state matches the wildcard *_UNKNOWN state in the transition table
40 currStateOnlyMatch // current state matches the current state and previous state matches the wildcard in the transition table
41 currPrevStateMatch // both current and previous states match in the transition table
42)
43
44// match is used to keep the current match states
45type match struct {
46 admin, oper, conn MatchResult
47}
48
49// toInt returns an integer representing the matching level of the match (the larger the number the better)
50func (m *match) toInt() int {
51 return int(m.admin<<4 | m.oper<<2 | m.conn)
52}
53
54// isExactMatch returns true if match is an exact match
55func (m *match) isExactMatch() bool {
56 return m.admin == currPrevStateMatch && m.oper == currPrevStateMatch && m.conn == currPrevStateMatch
57}
58
59// isBetterMatch returns true if newMatch is a worse match
60func (m *match) isBetterMatch(newMatch *match) bool {
61 return m.toInt() > newMatch.toInt()
62}
63
npujar1d86a522019-11-14 17:11:16 +053064// DeviceState has admin, operational and connection status of device
khenaidoob9203542018-09-17 22:56:37 -040065type DeviceState struct {
serkant.uluderya2ae470f2020-01-21 11:13:09 -080066 Admin voltha.AdminState_Types
67 Connection voltha.ConnectStatus_Types
68 Operational voltha.OperStatus_Types
khenaidoob9203542018-09-17 22:56:37 -040069}
70
khenaidoo442e7c72020-03-10 16:13:48 -040071// TransitionHandler function type which takes the current and previous device info as input parameter
72type TransitionHandler func(ctx context.Context, curr *voltha.Device, prev *voltha.Device) error
khenaidoob9203542018-09-17 22:56:37 -040073
npujar1d86a522019-11-14 17:11:16 +053074// Transition represent transition related attributes
khenaidoob9203542018-09-17 22:56:37 -040075type Transition struct {
76 deviceType DeviceType
77 previousState DeviceState
78 currentState DeviceState
khenaidoo92e62c52018-10-03 14:02:54 -040079 handlers []TransitionHandler
khenaidoob9203542018-09-17 22:56:37 -040080}
81
npujar1d86a522019-11-14 17:11:16 +053082// TransitionMap represent map of transitions and device manager
khenaidoob9203542018-09-17 22:56:37 -040083type TransitionMap struct {
84 transitions []Transition
npujar1d86a522019-11-14 17:11:16 +053085 dMgr coreif.DeviceManager
khenaidoob9203542018-09-17 22:56:37 -040086}
87
npujar1d86a522019-11-14 17:11:16 +053088// NewTransitionMap creates transition map
89func NewTransitionMap(dMgr coreif.DeviceManager) *TransitionMap {
khenaidoob9203542018-09-17 22:56:37 -040090 var transitionMap TransitionMap
khenaidoo0a822f92019-05-08 15:15:57 -040091 transitionMap.dMgr = dMgr
khenaidoob9203542018-09-17 22:56:37 -040092 transitionMap.transitions = make([]Transition, 0)
khenaidoo442e7c72020-03-10 16:13:48 -040093 transitionMap.transitions = append(
94 transitionMap.transitions,
khenaidoob9203542018-09-17 22:56:37 -040095 Transition{
khenaidoob9203542018-09-17 22:56:37 -040096 deviceType: parent,
khenaidoo59ef7be2019-06-21 12:40:28 -040097 previousState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING},
98 currentState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVE},
khenaidoo0a822f92019-05-08 15:15:57 -040099 handlers: []TransitionHandler{dMgr.CreateLogicalDevice}})
100 transitionMap.transitions = append(transitionMap.transitions,
101 Transition{
khenaidoo59ef7be2019-06-21 12:40:28 -0400102 deviceType: child,
103 previousState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_DISCOVERED},
khenaidoo442e7c72020-03-10 16:13:48 -0400104 currentState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING},
105 handlers: []TransitionHandler{}})
106 transitionMap.transitions = append(transitionMap.transitions,
107 Transition{
108 deviceType: child,
109 previousState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_DISCOVERED},
khenaidoo59ef7be2019-06-21 12:40:28 -0400110 currentState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVE},
111 handlers: []TransitionHandler{dMgr.SetupUNILogicalPorts}})
khenaidoob9203542018-09-17 22:56:37 -0400112 transitionMap.transitions = append(transitionMap.transitions,
113 Transition{
114 deviceType: child,
khenaidoo59ef7be2019-06-21 12:40:28 -0400115 previousState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING},
khenaidoo442e7c72020-03-10 16:13:48 -0400116 currentState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_DISCOVERED},
117 handlers: []TransitionHandler{}})
118 transitionMap.transitions = append(transitionMap.transitions,
119 Transition{
120 deviceType: child,
121 previousState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING},
khenaidoo59ef7be2019-06-21 12:40:28 -0400122 currentState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVE},
khenaidoo0a822f92019-05-08 15:15:57 -0400123 handlers: []TransitionHandler{dMgr.SetupUNILogicalPorts}})
khenaidoob9203542018-09-17 22:56:37 -0400124 transitionMap.transitions = append(transitionMap.transitions,
125 Transition{
khenaidoo4554f7c2019-05-29 22:13:15 -0400126 deviceType: any,
127 previousState: DeviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
128 currentState: DeviceState{Admin: voltha.AdminState_DELETED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
129 handlers: []TransitionHandler{dMgr.RunPostDeviceDelete}})
130 transitionMap.transitions = append(transitionMap.transitions,
131 Transition{
khenaidoo4d4802d2018-10-04 21:59:49 -0400132 deviceType: parent,
khenaidoo442e7c72020-03-10 16:13:48 -0400133 previousState: DeviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
khenaidoo4d4802d2018-10-04 21:59:49 -0400134 currentState: DeviceState{Admin: voltha.AdminState_DELETED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
Hardik Windlassc704def2020-02-26 18:23:19 +0000135 handlers: []TransitionHandler{dMgr.DisableAllChildDevices, dMgr.DeleteAllUNILogicalPorts, dMgr.DeleteAllChildDevices, dMgr.DeleteLogicalDevice, dMgr.RunPostDeviceDelete}})
khenaidoo0a822f92019-05-08 15:15:57 -0400136 transitionMap.transitions = append(transitionMap.transitions,
137 Transition{
Girish Gowdra408cd962020-03-11 14:31:31 -0700138 deviceType: parent,
139 previousState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_REACHABLE, Operational: voltha.OperStatus_ACTIVE},
140 currentState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNREACHABLE, Operational: voltha.OperStatus_UNKNOWN},
141 handlers: []TransitionHandler{dMgr.DeleteAllLogicalPorts, dMgr.DeleteLogicalDevice, dMgr.DeleteAllChildDevices, dMgr.DeleteAllDeviceFlows}})
142 transitionMap.transitions = append(transitionMap.transitions,
143 Transition{
144 deviceType: parent,
145 previousState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNREACHABLE, Operational: voltha.OperStatus_UNKNOWN},
146 currentState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_REACHABLE, Operational: voltha.OperStatus_ACTIVE},
147 handlers: []TransitionHandler{dMgr.CreateLogicalDevice}})
148 transitionMap.transitions = append(transitionMap.transitions,
149 Transition{
khenaidoo0a822f92019-05-08 15:15:57 -0400150 deviceType: child,
khenaidoo442e7c72020-03-10 16:13:48 -0400151 previousState: DeviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
khenaidoo0a822f92019-05-08 15:15:57 -0400152 currentState: DeviceState{Admin: voltha.AdminState_DELETED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
Chaitrashree G S543df3e2020-02-24 22:36:54 -0500153 handlers: []TransitionHandler{dMgr.ChildDeviceLost, dMgr.DeleteLogicalPorts, dMgr.RunPostDeviceDelete}})
154 transitionMap.transitions = append(transitionMap.transitions,
155 Transition{
156 deviceType: child,
157 previousState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
158 currentState: DeviceState{Admin: voltha.AdminState_DELETED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
159 handlers: []TransitionHandler{dMgr.ChildDeviceLost, dMgr.DeleteLogicalPorts, dMgr.RunPostDeviceDelete}})
khenaidoob9203542018-09-17 22:56:37 -0400160 transitionMap.transitions = append(transitionMap.transitions,
161 Transition{
162 deviceType: any,
khenaidoo59ef7be2019-06-21 12:40:28 -0400163 previousState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVE},
164 currentState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING},
165 handlers: []TransitionHandler{dMgr.NotifyInvalidTransition}})
166 transitionMap.transitions = append(transitionMap.transitions,
167 Transition{
168 deviceType: any,
169 previousState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING},
170 currentState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
171 handlers: []TransitionHandler{dMgr.NotifyInvalidTransition}})
172 transitionMap.transitions = append(transitionMap.transitions,
173 Transition{
174 deviceType: any,
175 previousState: DeviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
176 currentState: DeviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
177 handlers: []TransitionHandler{dMgr.NotifyInvalidTransition}})
178 transitionMap.transitions = append(transitionMap.transitions,
179 Transition{
180 deviceType: any,
181 previousState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
182 currentState: DeviceState{Admin: voltha.AdminState_DOWNLOADING_IMAGE, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
183 handlers: []TransitionHandler{dMgr.NotifyInvalidTransition}})
184 transitionMap.transitions = append(transitionMap.transitions,
185 Transition{
186 deviceType: any,
187 previousState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
188 currentState: DeviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
189 handlers: []TransitionHandler{dMgr.NotifyInvalidTransition}})
190 transitionMap.transitions = append(transitionMap.transitions,
191 Transition{
192 deviceType: parent,
193 previousState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVE},
194 currentState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING},
195 handlers: []TransitionHandler{dMgr.NotifyInvalidTransition}})
196 transitionMap.transitions = append(transitionMap.transitions,
197 Transition{
198 deviceType: any,
199 previousState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING},
200 currentState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
201 handlers: []TransitionHandler{dMgr.NotifyInvalidTransition}})
202 transitionMap.transitions = append(transitionMap.transitions,
203 Transition{
204 deviceType: any,
205 previousState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
206 currentState: DeviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
207 handlers: []TransitionHandler{dMgr.NotifyInvalidTransition}})
208 transitionMap.transitions = append(transitionMap.transitions,
209 Transition{
210 deviceType: child,
211 previousState: DeviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
212 currentState: DeviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
213 handlers: []TransitionHandler{dMgr.NotifyInvalidTransition}})
214 transitionMap.transitions = append(transitionMap.transitions,
215 Transition{
216 deviceType: any,
217 previousState: DeviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
218 currentState: DeviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
219 handlers: []TransitionHandler{dMgr.NotifyInvalidTransition}})
220 transitionMap.transitions = append(transitionMap.transitions,
221 Transition{
222 deviceType: any,
khenaidoob9203542018-09-17 22:56:37 -0400223 previousState: DeviceState{Admin: voltha.AdminState_DOWNLOADING_IMAGE, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
224 currentState: DeviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
khenaidoo0a822f92019-05-08 15:15:57 -0400225 handlers: []TransitionHandler{dMgr.NotifyInvalidTransition}})
khenaidoob9203542018-09-17 22:56:37 -0400226
227 return &transitionMap
228}
229
230func getDeviceStates(device *voltha.Device) *DeviceState {
231 return &DeviceState{Admin: device.AdminState, Connection: device.ConnectStatus, Operational: device.OperStatus}
232}
233
234// isMatched matches a state transition. It returns whether there is a match and if there is whether it is an exact match
khenaidoo442e7c72020-03-10 16:13:48 -0400235func getHandler(previous *DeviceState, current *DeviceState, transition *Transition) ([]TransitionHandler, *match) {
236 m := &match{}
khenaidoob9203542018-09-17 22:56:37 -0400237 // Do we have an exact match?
238 if *previous == transition.previousState && *current == transition.currentState {
khenaidoo442e7c72020-03-10 16:13:48 -0400239 return transition.handlers, &match{admin: currPrevStateMatch, oper: currPrevStateMatch, conn: currPrevStateMatch}
khenaidoob9203542018-09-17 22:56:37 -0400240 }
khenaidoo0a822f92019-05-08 15:15:57 -0400241
khenaidoo442e7c72020-03-10 16:13:48 -0400242 // Do we have Admin state match?
243 if current.Admin == transition.currentState.Admin && transition.currentState.Admin != voltha.AdminState_UNKNOWN {
244 if previous.Admin == transition.previousState.Admin {
245 m.admin = currPrevStateMatch
246 } else if transition.previousState.Admin == voltha.AdminState_UNKNOWN {
247 m.admin = currStateOnlyMatch
248 }
249 } else if current.Admin == transition.currentState.Admin && transition.currentState.Admin == voltha.AdminState_UNKNOWN {
250 if previous.Admin == transition.previousState.Admin || transition.previousState.Admin == voltha.AdminState_UNKNOWN {
251 m.admin = currWildcardMatch
252 }
253 }
254 if m.admin == noMatch {
255 // invalid transition - need to match on current admin state
256 return nil, m
khenaidoo0a822f92019-05-08 15:15:57 -0400257 }
258
khenaidoo442e7c72020-03-10 16:13:48 -0400259 // Do we have an operational state match?
260 if current.Operational == transition.currentState.Operational && transition.previousState.Operational != voltha.OperStatus_UNKNOWN {
261 if previous.Operational == transition.previousState.Operational || transition.previousState.Operational == voltha.OperStatus_UNKNOWN {
262 m.oper = currPrevStateMatch
263 } else {
264 m.oper = currStateOnlyMatch
265 }
266 } else if current.Operational == transition.currentState.Operational && transition.previousState.Operational == voltha.OperStatus_UNKNOWN {
267 if previous.Operational == transition.previousState.Operational || transition.previousState.Operational == voltha.OperStatus_UNKNOWN {
268 m.oper = currWildcardMatch
khenaidoob9203542018-09-17 22:56:37 -0400269 }
270 }
khenaidoo442e7c72020-03-10 16:13:48 -0400271
272 // Do we have an connection state match?
273 if current.Connection == transition.currentState.Connection && transition.previousState.Connection != voltha.ConnectStatus_UNKNOWN {
274 if previous.Connection == transition.previousState.Connection || transition.previousState.Connection == voltha.ConnectStatus_UNKNOWN {
275 m.conn = currPrevStateMatch
276 } else {
277 m.conn = currStateOnlyMatch
278 }
279 } else if current.Connection == transition.currentState.Connection && transition.previousState.Connection == voltha.ConnectStatus_UNKNOWN {
280 if previous.Connection == transition.previousState.Connection || transition.previousState.Connection == voltha.ConnectStatus_UNKNOWN {
281 m.conn = currWildcardMatch
khenaidoob9203542018-09-17 22:56:37 -0400282 }
283 }
khenaidoo442e7c72020-03-10 16:13:48 -0400284
285 return transition.handlers, m
khenaidoob9203542018-09-17 22:56:37 -0400286}
287
npujar1d86a522019-11-14 17:11:16 +0530288// GetTransitionHandler returns transition handler
khenaidoo92e62c52018-10-03 14:02:54 -0400289func (tMap *TransitionMap) GetTransitionHandler(pDevice *voltha.Device, cDevice *voltha.Device) []TransitionHandler {
khenaidoob9203542018-09-17 22:56:37 -0400290 //1. Get the previous and current set of states
291 pState := getDeviceStates(pDevice)
292 cState := getDeviceStates(cDevice)
khenaidoo442e7c72020-03-10 16:13:48 -0400293
294 // Do nothing is there are no states change
295 if *pState == *cState {
296 return nil
297 }
298
khenaidoo92e62c52018-10-03 14:02:54 -0400299 //log.Infow("DeviceType", log.Fields{"device": pDevice})
khenaidoob9203542018-09-17 22:56:37 -0400300 deviceType := parent
301 if !pDevice.Root {
302 log.Info("device is child")
303 deviceType = child
304 }
305 log.Infof("deviceType:%d-deviceId:%s-previous:%v-current:%v", deviceType, pDevice.Id, pState, cState)
306
307 //2. Go over transition array to get the right transition
khenaidoo92e62c52018-10-03 14:02:54 -0400308 var currentMatch []TransitionHandler
309 var tempHandler []TransitionHandler
khenaidoo442e7c72020-03-10 16:13:48 -0400310 var m *match
311 bestMatch := &match{}
khenaidoob9203542018-09-17 22:56:37 -0400312 for _, aTransition := range tMap.transitions {
313 // consider transition only if it matches deviceType or is a wild card - any
314 if aTransition.deviceType != deviceType && aTransition.deviceType != any {
315 continue
316 }
khenaidoo442e7c72020-03-10 16:13:48 -0400317 tempHandler, m = getHandler(pState, cState, &aTransition)
khenaidoob9203542018-09-17 22:56:37 -0400318 if tempHandler != nil {
khenaidoo442e7c72020-03-10 16:13:48 -0400319 if m.isExactMatch() && aTransition.deviceType == deviceType {
khenaidoob9203542018-09-17 22:56:37 -0400320 return tempHandler
khenaidoo442e7c72020-03-10 16:13:48 -0400321 } else if m.isExactMatch() || m.isBetterMatch(bestMatch) {
khenaidoo0a822f92019-05-08 15:15:57 -0400322 currentMatch = tempHandler
khenaidoo442e7c72020-03-10 16:13:48 -0400323 bestMatch = m
khenaidoob9203542018-09-17 22:56:37 -0400324 }
325 }
326 }
327 return currentMatch
328}