final AccessMessage parseSegmentedAccessLowerTransportPDU(final int ttl,
                                                              @NonNull final byte[] pdu,
                                                              final int ivIndex,
                                                              @NonNull final byte[] sequenceNumber) {
        final byte header = pdu[10]; //Lower transport pdu starts here
        final int akf = (header >> 6) & 0x01;
        final int aid = header & 0x3F;

        final int szmic = (pdu[11] >> 7) & 0x01;
        final int seqZero = ((pdu[11] & 0x7F) << 6) | ((pdu[12] & 0xFC) >> 2);
        final int segO = ((pdu[12] & 0x03) << 3) | ((pdu[13] & 0xE0) >> 5);
        final int segN = ((pdu[13]) & 0x1F);

        final byte[] src = MeshParserUtils.getSrcAddress(pdu);
        final byte[] dst = MeshParserUtils.getDstAddress(pdu);

        final int blockAckSrc = MeshParserUtils.unsignedBytesToInt(dst[1], dst[0]); //Destination of the received packet would be the source for the ack
        final int blockAckDst = MeshParserUtils.unsignedBytesToInt(src[1], src[0]); //Source of the received packet would be the destination for the ack

        MeshLogger.verbose(TAG, "SEG O: " + segO);
        MeshLogger.verbose(TAG, "SEG N: " + segN);

        final int seqNumber = getTransportLayerSequenceNumber(MeshParserUtils.convert24BitsToInt(sequenceNumber), seqZero);
        final int seqAuth = ivIndex << 24 | seqNumber;
        final Integer lastSeqAuth = mMeshNode.getSeqAuth(blockAckDst);
        if (lastSeqAuth != null)
            MeshLogger.verbose(TAG, "Last SeqAuth value " + lastSeqAuth);

        MeshLogger.verbose(TAG, "Current SeqAuth value " + seqAuth);

        final int payloadLength = pdu.length - 10;
        final ByteBuffer payloadBuffer = ByteBuffer.allocate(payloadLength);
        payloadBuffer.put(pdu, 10, payloadLength);

        //Check if the current SeqAuth value is greater than the last and if the incomplete timer has not started, start it!
        if ((lastSeqAuth == null || lastSeqAuth < seqAuth)) {
            // We do not need to rely on the sequence number here
            // Setting hte sequence number here will reset the already incremented sequence number for a message sent to all nodes.
            // mMeshNode.setSequenceNumber(seqNumber);
            segmentedAccessMessageMap.clear();
            segmentedAccessMessageMap.put(segO, payloadBuffer.array());
            mMeshNode.setSeqAuth(blockAckDst, seqAuth);

            MeshLogger.verbose(TAG, "Starting incomplete timer for src: " + MeshAddress.formatAddress(blockAckDst, false));
            initIncompleteTimer();

            // Start acknowledgement calculation and timer only for messages directed to a unicast address.
            if (MeshAddress.isValidUnicastAddress(dst)) {
                // Calculate the initial block acknowledgement value
                mSegmentedAccessBlockAck = BlockAcknowledgementMessage.calculateBlockAcknowledgement(null, segO);
                //Start the block acknowledgement timer irrespective of which segment was received first
                initSegmentedAccessAcknowledgementTimer(seqZero, ttl, blockAckSrc, blockAckDst, segN);
            }

            // We need to ensure there could be an unsegmented message that could be sent as a
            // segmented message i.e. segO = 0 and segN = 0. This will ensure the multi-segmented
            // messages that may not arrive in order will be reassembled correctly or rather ignored.
            if (segO == 0 && segN == 0) {
                if (MeshAddress.isValidUnicastAddress(dst)) {
                    mSegmentedAccessBlockAck = BlockAcknowledgementMessage.calculateBlockAcknowledgement(mSegmentedAccessBlockAck, segO);
                    handleImmediateBlockAcks(seqZero, ttl, blockAckSrc, blockAckDst, segN);
                } else {
                    //We should cancel the incomplete timer since we have received all segments
                    cancelIncompleteTimer();
                }

                final AccessMessage accessMessage = new AccessMessage();
                accessMessage.setAszmic(szmic);
                accessMessage.setSequenceNumber(MeshParserUtils.getSequenceNumberBytes(seqNumber));
                accessMessage.setAkf(akf);
                accessMessage.setAid(aid);
                accessMessage.setSegmented(true);
                final SparseArray<byte[]> segmentedMessages = segmentedAccessMessageMap.clone();
                accessMessage.setLowerTransportAccessPdu(segmentedMessages);
                return accessMessage;
            }

        } else {
            //if the seqauth values are the same and the init complete timer has already started for a received segmented message, we need to restart the incomplete timer
            if (lastSeqAuth == seqAuth) {
                if (mIncompleteTimerStarted) {
                    if (segmentedAccessMessageMap.get(segO) == null) {
                        segmentedAccessMessageMap.put(segO, payloadBuffer.array());
                    }
                    final int receivedSegmentedMessageCount = segmentedAccessMessageMap.size();
                    MeshLogger.verbose(TAG, "Received segment message count: " + receivedSegmentedMessageCount);
                    //Add +1 to segN since its zero based
                    if (receivedSegmentedMessageCount != (segN + 1)) {
                        restartIncompleteTimer();
                        mSegmentedAccessBlockAck = BlockAcknowledgementMessage.calculateBlockAcknowledgement(mSegmentedAccessBlockAck, segO);
                        MeshLogger.verbose(TAG, "Restarting incomplete timer for src: " + MeshAddress.formatAddress(blockAckDst, false));

                        //Start acknowledgement calculation and timer only for messages directed to a unicast address.
                        //We also have to make sure we restart the acknowledgement timer only if the acknowledgement timer is not active and the incomplete timer is active
                        if (MeshAddress.isValidUnicastAddress(dst) && !mSegmentedAccessAcknowledgementTimerStarted) {
                            MeshLogger.verbose(TAG, "Restarting block acknowledgement timer for src: " + MeshAddress.formatAddress(blockAckDst, false));
                            //Start the block acknowledgement timer irrespective of which segment was received first
                            initSegmentedAccessAcknowledgementTimer(seqZero, ttl, blockAckSrc, blockAckDst, segN);
                        }
                    } else {
                        if (MeshAddress.isValidUnicastAddress(dst)) {
                            mSegmentedAccessBlockAck = BlockAcknowledgementMessage.calculateBlockAcknowledgement(mSegmentedAccessBlockAck, segO);
                            handleImmediateBlockAcks(seqZero, ttl, blockAckSrc, blockAckDst, segN);
                        } else {
                            //We should cancel the incomplete timer since we have received all segments
                            cancelIncompleteTimer();
                        }

                        final AccessMessage accessMessage = new AccessMessage();
                        accessMessage.setAszmic(szmic);
                        accessMessage.setSequenceNumber(MeshParserUtils.getSequenceNumberBytes(seqNumber));
                        accessMessage.setAkf(akf);
                        accessMessage.setAid(aid);
                        accessMessage.setSegmented(true);
                        final SparseArray<byte[]> segmentedMessages = segmentedAccessMessageMap.clone();
                        accessMessage.setLowerTransportAccessPdu(segmentedMessages);
                        return accessMessage;
                    }
                } else {
                    MeshLogger.verbose(TAG, "Ignoring message since the incomplete timer has expired and all messages have been received");
                }
            }
        }
        return null;
    }
Parses a segmented lower transport access pdu.

@param ttl            TTL of the acknowledgement
@param pdu            The complete pdu was received from the node. This is already de-obfuscated and decrypted at network layer.
@param ivIndex        Current IV Index of the network
@param sequenceNumber Sequence number
mesh/src/main/java/no/nordicsemi/android/mesh/transport/LowerTransportLayer.java