@Override
	public void onDataReceived(@NonNull final BluetoothDevice device, @NonNull final Data data) {
		super.onDataReceived(device, data);

		if (data.size() != 2 && data.size() != 4) {
			onInvalidDataReceived(device, data);
			return;
		}

		final int sessionRunTime = data.getIntValue(Data.FORMAT_UINT16_LE, 0);

		final boolean crcPresent = data.size() == 4;
		if (crcPresent) {
			final int actualCrc = CRC16.MCRF4XX(data.getValue(), 0, 2);
			final int expectedCrc = data.getIntValue(Data.FORMAT_UINT16_LE, 2);
			if (actualCrc != expectedCrc) {
				onContinuousGlucoseMonitorSessionRunTimeReceivedWithCrcError(device, data);
				return;
			}
		}

		onContinuousGlucoseMonitorSessionRunTimeReceived(device, sessionRunTime, crcPresent);
	}
@Test
	public void onInvalidDataReceived() {
		final DataReceivedCallback callback = new CGMSessionRunTimeDataCallback() {
			@Override
			public void onContinuousGlucoseMonitorSessionRunTimeReceived(@NonNull final BluetoothDevice device, final int sessionRunTime, final boolean secured) {
				assertEquals("Invalid packet but correct packet reported", 1, 2);
			}

			@Override
			public void onContinuousGlucoseMonitorSessionRunTimeReceivedWithCrcError(@NonNull final BluetoothDevice device, @NonNull final Data data) {
				assertEquals("Invalid packet but invalid CRC reported", 1, 2);
			}

			@Override
			public void onInvalidDataReceived(@NonNull final BluetoothDevice device, @NonNull final Data data) {
				called = true;
			}
		};
		final MutableData data = new MutableData(new byte[3]);
		assertTrue(data.setValue(2, Data.FORMAT_UINT16_LE, 0));
		assertTrue(data.setValue(1, Data.FORMAT_UINT8, 2));
		called = false;
		//noinspection DataFlowIssue
		callback.onDataReceived(null, data);
		assertTrue(called);
	}