public byte[] constructBytesFromScanRecord(@Nullable ScanRecord scanRecord) throws UnsupportedEncodingException,
            IllegalArgumentException {
        if (scanRecord == null) {
            return new byte[0];
        }

        advertisementPacket = new ByteArrayOutputStream();
        scanResponsePacket = new ByteArrayOutputStream();

        if (scanRecord.getAdvertiseFlags() != -1) {
            addField(AdvDataType.Flags, new byte[] {(byte) scanRecord.getAdvertiseFlags()});
        }

        String name = scanRecord.getDeviceName();
        if (name != null) {
            byte[] nameBytes = name.getBytes("UTF-8");
            int nameLength = nameBytes.length;
            AdvDataType type;
            if (nameLength > DEVICE_NAME_MAX) {
                nameLength = DEVICE_NAME_MAX;
                type = AdvDataType.LocalNameShort;
            } else {
                type = AdvDataType.LocalNameComplete;
            }
            addField(type, Arrays.copyOfRange(nameBytes, 0, nameLength));
        }
        SparseArray<byte[]> manuData = scanRecord.getManufacturerSpecificData();
        for (int i = 0; i < manuData.size(); i++) {
            int manufacturerId = manuData.keyAt(i);
            byte[] manufacturerData = manuData.get(manufacturerId);
            int dataLen = 2 + (manufacturerData == null ? 0 : manufacturerData.length);
            byte[] concatenated = new byte[dataLen];
            // First two bytes are manufacturer id in little-endian.
            concatenated[0] = (byte) (manufacturerId & 0xFF);
            concatenated[1] = (byte) ((manufacturerId >> 8) & 0xFF);
            if (manufacturerData != null) {
                System.arraycopy(manufacturerData, 0, concatenated, 2, manufacturerData.length);
            }
            addField(AdvDataType.ManufacturerSpecificData, concatenated);
        }
        if (scanRecord.getTxPowerLevel() != Integer.MIN_VALUE) {
            addField(AdvDataType.TxPowerLevel,
                    new byte[] {(byte) scanRecord.getTxPowerLevel()});
        }
        if (scanRecord.getServiceUuids() != null) {
            ByteArrayOutputStream serviceUuids16 = new ByteArrayOutputStream();
            ByteArrayOutputStream serviceUuids32 = new ByteArrayOutputStream();
            ByteArrayOutputStream serviceUuids128 = new ByteArrayOutputStream();
            for (ParcelUuid parcelUuid : scanRecord.getServiceUuids()) {
                byte[] uuid = uuidToBytes(parcelUuid);
                if (uuid.length == UUID_BYTES_16_BIT) {
                    serviceUuids16.write(uuid, 0, uuid.length);
                } else if (uuid.length == UUID_BYTES_32_BIT) {
                    serviceUuids32.write(uuid, 0, uuid.length);
                } else /*if (uuid.length == UUID_BYTES_128_BIT)*/ {
                    serviceUuids128.write(uuid, 0, uuid.length);
                }
            }
            if (serviceUuids16.size() != 0) {
                addField(AdvDataType.ServiceUuids16BitComplete, serviceUuids16.toByteArray());
            }
            if (serviceUuids32.size() != 0) {
                addField(AdvDataType.ServiceUuids32BitComplete, serviceUuids32.toByteArray());
            }
            if (serviceUuids128.size() != 0) {
                addField(AdvDataType.ServiceUuids128BitComplete, serviceUuids128.toByteArray());
            }
        }
        Map<ParcelUuid, byte[]> serviceData = scanRecord.getServiceData();
        if (!serviceData.isEmpty()) {
            for (ParcelUuid parcelUuid : serviceData.keySet()) {
                byte[] serviceDataBytes = serviceData.get(parcelUuid);
                byte[] uuid = uuidToBytes(parcelUuid);
                int uuidLen = uuid.length;
                int dataLen = uuidLen + (serviceDataBytes == null ? 0 : serviceDataBytes.length);
                byte[] concatenated = new byte[dataLen];
                System.arraycopy(uuid, 0, concatenated, 0, uuidLen);
                if (serviceDataBytes != null) {
                    System.arraycopy(serviceDataBytes, 0, concatenated, uuidLen, serviceDataBytes.length);
                }
                if (uuid.length == UUID_BYTES_16_BIT) {
                    addField(AdvDataType.ServiceData16Bit, concatenated);
                } else if (uuid.length == UUID_BYTES_32_BIT) {
                    addField(AdvDataType.ServiceData32Bit, concatenated);
                } else /*if (uuid.length == UUID_BYTES_128_BIT)*/ {
                    addField(AdvDataType.ServiceData128Bit, concatenated);
                }
            }
        }
        if (requireLegacyDataLength) {
            // pad adv data and scan response to 31 bytes
            if (advertisementPacket.size() < LEGACY_MAX_DATA_LENGTH) {
                byte[] padding = new byte[LEGACY_MAX_DATA_LENGTH - advertisementPacket.size()];
                advertisementPacket.write(padding, 0, padding.length);
            }
            if (scanResponsePacket.size() < LEGACY_MAX_DATA_LENGTH) {
                byte[] padding = new byte[LEGACY_MAX_DATA_LENGTH - scanResponsePacket.size()];
                scanResponsePacket.write(padding, 0, padding.length);
            }
            advertisementPacket.write(scanResponsePacket.toByteArray(), 0, LEGACY_MAX_DATA_LENGTH);
        }
        return advertisementPacket.toByteArray();
    }
Construct the byte array for a given scan record. Copied and modified from Android source.
@param scanRecord The scan record to encode
@return The constructed scan record data
@throws UnsupportedEncodingException If the device name could not be encoded
@throws IllegalArgumentException If the data could not fit in legacy packets
mockrxandroidble/src/main/java/com/polidea/rxandroidble2/mockrxandroidble/internal/ScanRecordDataConstructor.java