@Override
		public void onDescriptorWrite(final BluetoothGatt gatt,
									  final BluetoothGattDescriptor descriptor,
									  final int status) {
			final byte[] data = descriptor.getValue();

			if (status == BluetoothGatt.GATT_SUCCESS) {
				log(Log.INFO, () -> "Data written to descr. " + descriptor.getUuid());

				if (isServiceChangedCCCD(descriptor)) {
					log(Log.INFO, () -> "Service Changed notifications enabled");
				} else if (isCCCD(descriptor)) {
					if (data != null && data.length == 2 && data[1] == 0x00) {
						switch (data[0]) {
							case 0x00 -> log(Log.INFO, () -> "Notifications and indications disabled");
							case 0x01 -> log(Log.INFO, () -> "Notifications enabled");
							case 0x02 -> log(Log.INFO, () -> "Indications enabled");
						}
						BleManagerHandler.this.onDescriptorWrite(gatt, descriptor);
					}
				} else {
					BleManagerHandler.this.onDescriptorWrite(gatt, descriptor);
				}
				if (request instanceof final WriteRequest wr) {
					final boolean valid = wr.notifyPacketSent(gatt.getDevice(), data);
					if (!valid && requestQueue instanceof final ReliableWriteRequest rwr) {
						wr.notifyFail(gatt.getDevice(), FailCallback.REASON_VALIDATION);
						rwr.notifyAndCancelQueue(gatt.getDevice());
					} else if (wr.hasMore()) {
						enqueueFirst(wr);
					} else {
						wr.notifySuccess(gatt.getDevice());
					}
				}
			} else if (status == 137 /* GATT AUTH FAIL */) {
				// This never happens for Write operations, for some reason.
				Log.w(TAG, "Writing descriptor 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 write.
				// 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 WriteRequest wr) {
					wr.notifyFail(gatt.getDevice(), status);
				}
			} else {
				Log.e(TAG, "onDescriptorWrite error " + status + ", bond state: " + gatt.getDevice().getBondState());
				if (request instanceof final WriteRequest wr) {
					wr.notifyFail(gatt.getDevice(), status);
					// Automatically abort Reliable Write when write error happen
					if (requestQueue instanceof final ReliableWriteRequest rwr)
						rwr.notifyAndCancelQueue(gatt.getDevice());
				}
				awaitingRequest = null;
				onError(gatt.getDevice(), ERROR_WRITE_DESCRIPTOR, 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