@Override
    public final Message createNetworkLayerPDU(@NonNull final Message message) {
        final SecureUtils.K2Output k2Output = getK2Output(message);
        final int nid = k2Output.getNid();
        final byte[] encryptionKey = k2Output.getEncryptionKey();
        MeshLogger.verbose(TAG, "Encryption key: " + MeshParserUtils.bytesToHex(encryptionKey, false));

        final byte[] privacyKey = k2Output.getPrivacyKey();
        MeshLogger.verbose(TAG, "Privacy key: " + MeshParserUtils.bytesToHex(privacyKey, false));
        final int ctl = message.getCtl();
        final int ttl = message.getTtl();
        final int ivi = message.getIvIndex()[3] & 0x01; // least significant bit of IV Index
        final byte iviNID = (byte) ((ivi << 7) | (nid & 0x7F));
        final byte ctlTTL = (byte) ((ctl << 7) | (ttl & 0x7F));

        final int src = message.getSrc();
        final SparseArray<byte[]> lowerTransportPduMap;
        final SparseArray<byte[]> encryptedPduPayload = new SparseArray<>();
        final List<byte[]> sequenceNumbers = new ArrayList<>();

        final ProvisionedMeshNode node = mUpperTransportLayerCallbacks.getNode(message.getSrc());
        final int pduType = message.getPduType();
        switch (message.getPduType()) {
            case MeshManagerApi.PDU_TYPE_NETWORK:
                if (message instanceof AccessMessage) {
                    lowerTransportPduMap = ((AccessMessage) message).getLowerTransportAccessPdu();
                } else {
                    lowerTransportPduMap = ((ControlMessage) message).getLowerTransportControlPdu();
                }
                for (int i = 0; i < lowerTransportPduMap.size(); i++) {
                    final byte[] lowerTransportPdu = lowerTransportPduMap.get(i);
                    if (i != 0) {
                        node.setSequenceNumber(MeshParserUtils.convert24BitsToInt(message.getSequenceNumber()));
                        final byte[] sequenceNumber = MeshParserUtils.getSequenceNumberBytes(node.incrementSequenceNumber());
                        message.setSequenceNumber(sequenceNumber);
                    }
                    sequenceNumbers.add(message.getSequenceNumber());
                    MeshLogger.verbose(TAG, "Sequence Number: " + MeshParserUtils.bytesToHex(sequenceNumbers.get(i), false));
                    final byte[] nonce = createNetworkNonce(ctlTTL, sequenceNumbers.get(i), src, message.getIvIndex());
                    final byte[] encryptedPayload = encryptPdu(lowerTransportPdu, encryptionKey, nonce, message.getDst(), SecureUtils.getNetMicLength(message.getCtl()));
                    encryptedPduPayload.put(i, encryptedPayload);
                    MeshLogger.verbose(TAG, "Encrypted Network payload: " + MeshParserUtils.bytesToHex(encryptedPayload, false));
                }
                break;
            case MeshManagerApi.PDU_TYPE_PROXY_CONFIGURATION:
                lowerTransportPduMap = ((ControlMessage) message).getLowerTransportControlPdu();
                for (int i = 0; i < lowerTransportPduMap.size(); i++) {
                    final byte[] lowerTransportPdu = lowerTransportPduMap.get(i);
                    final byte[] sequenceNum = MeshParserUtils.getSequenceNumberBytes(node.incrementSequenceNumber());
                    message.setSequenceNumber(sequenceNum);
                    sequenceNumbers.add(message.getSequenceNumber());
                    final byte[] nonce = createProxyNonce(message.getSequenceNumber(), src, message.getIvIndex());
                    final byte[] encryptedPayload = encryptPdu(lowerTransportPdu, encryptionKey, nonce, message.getDst(), SecureUtils.getNetMicLength(message.getCtl()));
                    encryptedPduPayload.put(i, encryptedPayload);
                    MeshLogger.verbose(TAG, "Encrypted Network payload: " + MeshParserUtils.bytesToHex(encryptedPayload, false));
                }
                break;
        }

        final SparseArray<byte[]> pduArray = new SparseArray<>();
        for (int i = 0; i < encryptedPduPayload.size(); i++) {
            //Create the privacy random
            final byte[] encryptedPayload = encryptedPduPayload.get(i);
            final byte[] privacyRandom = createPrivacyRandom(encryptedPayload);
            //Next we create the PECB
            final byte[] pecb = createPECB(message.getIvIndex(), privacyRandom, privacyKey);

            final byte[] header = obfuscateNetworkHeader(ctlTTL, sequenceNumbers.get(i), src, pecb);
            final byte[] pdu = ByteBuffer.allocate(1 + 1 + header.length + encryptedPayload.length).order(ByteOrder.BIG_ENDIAN)
                    .put((byte) pduType)
                    .put(iviNID)
                    .put(header)
                    .put(encryptedPayload)
                    .array();
            pduArray.put(i, pdu);
            message.setNetworkLayerPdu(pduArray);
        }

        return message;
    }
Creates a vendor model mesh message

@param message Message could be of type access or control message.
mesh/src/main/java/no/nordicsemi/android/mesh/transport/NetworkLayer.java