@Override
		public void onCharacteristicRead(@NonNull final BluetoothGatt gatt,
										 @NonNull final BluetoothGattCharacteristic characteristic,
										 @NonNull byte[] data, int status) {
			if (status == BluetoothGatt.GATT_SUCCESS) {
				log(Log.INFO, () ->
						"Read Response received from " + characteristic.getUuid() +
						", value: " + ParserUtils.parse(data));

				BleManagerHandler.this.onCharacteristicRead(gatt, characteristic);
				if (request instanceof final ReadRequest rr) {
					final boolean matches = rr.matches(data);
					if (matches) {
						rr.notifyValueChanged(gatt.getDevice(), data);
					}
					if (!matches || rr.hasMore()) {
						enqueueFirst(rr);
					} else {
						rr.notifySuccess(gatt.getDevice());
					}
				}
			} else if (status == 137 /* GATT AUTH FAIL */) {
				// Bonding failed or was cancelled.
				Log.w(TAG, "Reading failed with status " + status);
				// The bond state receiver will fail the request. Stop here.
				return;
			} else if (status == BluetoothGatt.GATT_INSUFFICIENT_AUTHENTICATION
					|| status == 8 /* GATT INSUF AUTHORIZATION */) {
				// This is called when bonding attempt failed, but the app is still trying to read.
				// We need to cancel the request here, as bonding won't start.
				log(Log.WARN, () -> "Authentication required (" + status + ")");
				if (gatt.getDevice().getBondState() == BluetoothDevice.BOND_BONDED) {
					// This should never happen but it used to: http://stackoverflow.com/a/20093695/2115352
					Log.w(TAG, ERROR_AUTH_ERROR_WHILE_BONDED);
					postCallback(c -> c.onError(gatt.getDevice(), ERROR_AUTH_ERROR_WHILE_BONDED, status));
				}
				if (request instanceof final ReadRequest wr) {
					wr.notifyFail(gatt.getDevice(), status);
				}
			} else {
				Log.e(TAG, "onCharacteristicRead error " + status + ", bond state: " + gatt.getDevice().getBondState());
				if (request instanceof final ReadRequest rr) {
					rr.notifyFail(gatt.getDevice(), status);
				}
				awaitingRequest = null;
				onError(gatt.getDevice(), ERROR_READ_CHARACTERISTIC, status);
			}
			checkCondition();
			nextRequest(true);
		}
Callback indicating service changed event is received.
<p>
Receiving this event means that the GATT database is out of sync with the remote device.
<p>
Requires API 31+.
ble/src/main/java/no/nordicsemi/android/ble/BleManagerHandler.java