Skip to content

#1952 P25 Traffic Channel Manager Aggregating Multiple Call Events Into One #1953

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 23, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ public class P25TrafficChannelManager extends TrafficChannelManager implements I
private static final LoggingSuppressor LOGGING_SUPPRESSOR = new LoggingSuppressor(mLog);
public static final String CHANNEL_START_REJECTED = "CHANNEL START REJECTED";
public static final String MAX_TRAFFIC_CHANNELS_EXCEEDED = "MAX TRAFFIC CHANNELS EXCEEDED";
private static final long STALE_EVENT_THRESHOLD_MS = 2000;

private Queue<Channel> mAvailablePhase1TrafficChannelQueue = new LinkedTransferQueue<>();
private List<Channel> mManagedPhase1TrafficChannels;
Expand Down Expand Up @@ -366,8 +367,28 @@ public void processP2CurrentUser(long frequency, int timeslot, Identifier identi

try
{
DecodeEvent event = timeslot == P25P1Message.TIMESLOT_1 ?
mTS1ChannelGrantEventMap.get(frequency) : mTS2ChannelGrantEventMap.get(frequency);
DecodeEvent event = null;

if(timeslot == P25P1Message.TIMESLOT_1)
{
event = mTS1ChannelGrantEventMap.get(frequency);

if(isStaleEvent(event, timestamp))
{
event = null;
mTS1ChannelGrantEventMap.remove(frequency);
}
}
else if(timeslot == P25P1Message.TIMESLOT_2)
{
event = mTS2ChannelGrantEventMap.get(frequency);

if(isStaleEvent(event, timestamp))
{
event = null;
mTS1ChannelGrantEventMap.remove(frequency);
}
}

if(event != null)
{
Expand Down Expand Up @@ -408,8 +429,28 @@ public IChannelDescriptor processP2CurrentUser(long frequency, int timeslot, ICh

try
{
DecodeEvent event = timeslot == P25P1Message.TIMESLOT_1 ?
mTS1ChannelGrantEventMap.get(frequency) : mTS2ChannelGrantEventMap.get(frequency);
DecodeEvent event = null;

if(timeslot == P25P1Message.TIMESLOT_1)
{
event = mTS1ChannelGrantEventMap.get(frequency);

if(isStaleEvent(event, timestamp))
{
event = null;
mTS1ChannelGrantEventMap.remove(frequency);
}
}
else if(timeslot == P25P1Message.TIMESLOT_2)
{
event = mTS2ChannelGrantEventMap.get(frequency);

if(isStaleEvent(event, timestamp))
{
event = null;
mTS2ChannelGrantEventMap.remove(frequency);
}
}

if(event != null)
{
Expand Down Expand Up @@ -751,10 +792,22 @@ public void processP1ChannelUpdate(APCO25Channel channel, ServiceOptions service
if(channel.isTDMAChannel() && channel.getTimeslot() == P25P1Message.TIMESLOT_2)
{
event = mTS2ChannelGrantEventMap.get(channel.getDownlinkFrequency());
// If the event is stale, remove it and allow a new event to be created.
if(isStaleEvent(event, timestamp))
{
event = null;
mTS2ChannelGrantEventMap.remove(channel.getDownlinkFrequency());
}
}
else
{
event = mTS1ChannelGrantEventMap.get(channel.getDownlinkFrequency());
// If the event is stale, remove it and allow a new event to be created.
if(isStaleEvent(event, timestamp))
{
event = null;
mTS1ChannelGrantEventMap.remove(channel.getDownlinkFrequency());
}
}

//If we have an event, update it. Otherwise, make sure we have the traffic channel allocated
Expand All @@ -763,8 +816,7 @@ public void processP1ChannelUpdate(APCO25Channel channel, ServiceOptions service
event.update(timestamp);
broadcast(event);
}
else if(channel.getDownlinkFrequency() > 0 &&
!mAllocatedTrafficChannelMap.containsKey(channel.getDownlinkFrequency()))
else
{
processP1ChannelGrant(channel, serviceOptions, ic, opcode, timestamp);
}
Expand Down Expand Up @@ -799,6 +851,24 @@ public void closeP1CallEvent(long frequency, long timestamp)
}
}

/**
* Indicates if the event is stale and should be replaced with a new decode event. Compares the event down time
* to the reference timestamp argument and indicates if that staleness exceeds a staleness threshold (2 seconds).
*
* Note: some decode events can remain in the channel grant event map if a traffic channel is not allocated for the
* event (ie tuner unavailable). The control channel only tells us that the traffic channel is active, but doesn't
* tell us when the traffic channel is torn down. So, we use this staleness evaluation to remove stale events that
* are left over from a previous traffic channel allocation.
*
* @param decodeEvent to evaluate
* @param timestamp for reference of event staleness.
* @return true if the event is stale.
*/
private static boolean isStaleEvent(DecodeEvent decodeEvent, long timestamp)
{
return decodeEvent != null && (timestamp - decodeEvent.getTimeEnd() > STALE_EVENT_THRESHOLD_MS);
}

/**
* Processes Phase 1 channel grants to allocate traffic channels and track overall channel usage. Generates
* decode events for each new channel that is allocated.
Expand All @@ -820,6 +890,13 @@ private void processPhase1ChannelGrant(APCO25Channel apco25Channel, ServiceOptio

P25ChannelGrantEvent event = mTS1ChannelGrantEventMap.get(frequency);

// If the event is stale, remove it and allow a new event to be created.
if(isStaleEvent(event, timestamp))
{
event = null;
mTS1ChannelGrantEventMap.remove(frequency);
}

if(event != null && isSameCallUpdate(identifierCollection, event.getIdentifierCollection()))
{
Identifier from = identifierCollection.getFromIdentifier();
Expand Down Expand Up @@ -973,10 +1050,22 @@ private DecodeEvent processPhase2ChannelGrant(APCO25Channel apco25Channel, Servi
if(timeslot == P25P1Message.TIMESLOT_0 || timeslot == P25P1Message.TIMESLOT_1)
{
event = mTS1ChannelGrantEventMap.get(frequency);
// If the event is stale, remove it and allow a new event to be created.
if(isStaleEvent(event, timestamp))
{
event = null;
mTS1ChannelGrantEventMap.remove(frequency);
}
}
else if(timeslot == P25P1Message.TIMESLOT_2)
{
event = mTS2ChannelGrantEventMap.get(frequency);
// If the event is stale, remove it and allow a new event to be created.
if(isStaleEvent(event, timestamp))
{
event = null;
mTS2ChannelGrantEventMap.remove(frequency);
}
}
else
{
Expand Down
Loading