/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.dragonkeyboardfirmwareupdater;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanResult;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.PowerManager;
import android.preference.PreferenceManager;
import android.support.v4.app.NotificationCompat;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;

import java.lang.System;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.concurrent.TimeUnit;
import java.util.List;
import java.util.UUID;

import no.nordicsemi.android.dfu.DfuProgressListener;
import no.nordicsemi.android.dfu.DfuServiceListenerHelper;


public class KeyboardFirmwareUpdateService extends Service {
    private static final String TAG = KeyboardFirmwareUpdateService.class.getSimpleName();

    /* Actions for update status changes. */
    public static final String ACTION_KEYBOARD_UPDATE_CONFIRMED =
            "com.android.dragonkeyboardfirmwareupdater.action.KEYBOARD_UPDATE_CONFIRMED";
    public static final String ACTION_KEYBOARD_UPDATE_POSTPONED =
            "com.android.dragonkeyboardfirmwareupdater.action.KEYBOARD_UPDATE_POSTPONED";

    /* Extra information for UpdaterConfirmationActivity. */
    public static final String EXTRA_KEYBOARD_NAME =
            "com.android.dragonkeyboardfirmwareupdater.EXTRA_KEYBOARD_NAME";
    public static final String EXTRA_KEYBOARD_ADDRESS =
            "com.android.dragonkeyboardfirmwareupdater.EXTRA_KEYBOARD_ADDRESS";
    public static final String EXTRA_KEYBOARD_FIRMWARE_VERSION =
            "com.android.dragonkeyboardfirmwareupdater.EXTRA_KEYBOARD_FIRMWARE_VERSION";

    public static final String PREFERENCE_NEXT_UPDATE_TIME =
            "com.android.dragonkeyboardfirmwareupdater.PREFERENCE_NEXT_UPDATE_TIME";

    /**
     * Bluetooth connectivity. The Bluetooth LE connection maintained in this service is for
     * retrieving keyboard information, such as device manufacture and so on, and switching the
     * keyboard to Device Update Mode (DFU). Once the DFU service is started, the connection
     * maintained here and its corresponding variable should be cleaned up.
     */
    // Bluetooth Gatt connection state of the keyboard.
    private static final int GATT_STATE_DISCONNECTED = 0;
    private static final int GATT_STATE_CONNECTING = 1;
    private static final int GATT_STATE_CONNECTED = 2;
    private static final int GATT_STATE_DISCOVERING_SERVICES = 3;
    private static final int GATT_STATE_DISCONNECTING = 4;
    // Bluetooth system services.
    private static final long SCAN_PERIOD = 7000;  // 7 seconds
    private final IBinder mBinder = new LocalBinder();
    private int mGattConnectionState = GATT_STATE_DISCONNECTED;
    private int mGattOperationStatus = -1;
    private BluetoothManager mBluetoothManager;
    private BluetoothAdapter mBluetoothAdapter;
    private BluetoothLeScanner mBluetoothLeScanner;
    // Bluetooth Gatt connection bond with the keyboard.
    private BluetoothGatt mBluetoothGattClient;
    private String mKeyboardName;
    private String mKeyboardAddress;
    private String mKeyboardAddressInAppMode;
    private String mKeyboardFirmwareVersion;
    // Bluetooth Gatt services provided by the keyboard.
    private BluetoothGattService mBatteryService;
    private BluetoothGattService mDeviceInfoService;
    private BluetoothGattService mDfuService;
    private BluetoothGattCharacteristic mDfuChar;
    // Bluetooth LE scan retry flag.
    private boolean mLeScanRetried = false;
    private int mDfuStatus = DFU_STATE_NOT_STARTED;

    /* Handler for posting delayed tasks. */
    private Handler mHandler;

    /* Wake lock for DFU. */
    private PowerManager.WakeLock mWakeLock;

    /* Update notification. */
    private static final int UPDATE_NOTIFICATION_ID = 1248;
    private static final int BATTERY_WARNING_NOTIFICATION_ID = 8421;
    private Notification mUpdateNotification;

    /**
     * Keeps track of the status of DFU process.
     * DFU_STATE_NOT_STARTED: DFU not started
     * DFU_STATE_OBTAINING_INFO: DFU not started, obtaining manufacturer, firmware version and battery level
     * DFU_STATE_INFO_READY: DFU not started, manufacturer, firmware version and battery level obtained
     * DFU_STATE_SWITCHING_TO_DFU_MODE: DFU not started, waiting for the keyboard to reboot into DFU mode
     * DFU_STATE_MODE_SWITCHED: DFU not started, switched to DFU mode
     * DFU_STATE_UPDATING: DFU started, pushing the new firmware to the keyboard
     * DFU_STATE_UPDATE_COMPLETE: DFU finished correctly
     * DFU_STATE_INFO_NOT_SUITABLE: DFU not started, the keyboard is not suitable for update
     * DFU_STATE_OBTAIN_INFO_ERROR: DFU not started, error(s) occurred during obtaining information
     * DFU_STATE_SWITCH_TO_DFU_MODE_ERROR: DFU not started, failed to switch to DFU mode
     * DFU_STATE_UPDATE_ABORTED: DFU started but aborted by either users or errors during update
     */
    private static final int DFU_STATE_NOT_STARTED = 5;
    private static final int DFU_STATE_OBTAINING_INFO = 6;
    private static final int DFU_STATE_INFO_READY = 7;
    private static final int DFU_STATE_SWITCHING_TO_DFU_MODE = 8;
    private static final int DFU_STATE_MODE_SWITCHED = 9;
    private static final int DFU_STATE_UPDATING = 10;
    private static final int DFU_STATE_UPDATE_COMPLETE = 11;
    private static final int DFU_STATE_INFO_NOT_SUITABLE = 12;
    private static final int DFU_STATE_OBTAIN_INFO_ERROR = 13;
    private static final int DFU_STATE_SWITCH_TO_DFU_MODE_ERROR = 14;
    private static final int DFU_STATE_UPDATE_ABORTED = 15;

    /* Handles Bluetooth LE scan results. Bluetooth LE scan occurs after DFU preparation is ready. */
    private ScanCallback mBluetoothLeScanCallback = new ScanCallback() {
        @Override
        public void onScanResult(int callbackType, ScanResult result) {
            BluetoothDevice device = result.getDevice();
            if (device == null || device.getName() == null) return;

            // Find the keyboard in DFU mode and start DFU process. The name of keyboard in DFU mode
            // is composed of the last three groups (G3:G4:G5) of its application mode address
            // (G0:G1:G2:G3:G4:G5).
            if (mKeyboardAddressInAppMode.endsWith(device.getName().toUpperCase()) &&
                    mDfuStatus != DFU_STATE_UPDATING) {
                Log.d(TAG, "onScanResult: Found target keyboard in DFU mode");

                scanLeDevice(false);

                // Start pushing new firmware to the keyboard.
                startDfuService(device.getName(), device.getAddress());
            }
        }

        @Override
        public void onScanFailed(int errorCode) {
            Log.w(TAG, "onScanFailed: Error Code: " + errorCode);
            if (!mLeScanRetried) {
                // Retry the scan once.
                mLeScanRetried = true;
                scanLeDevice(true);
            }
        }
    };

    /**
     * Handles Bluetooth Gatt client callback. Read/write operations should finish in a certain
     * order after DFU preparation starts.
     */
    private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
        private boolean retryFlag = true;

        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            assert gatt == mBluetoothGattClient;

            switch (newState) {
                case BluetoothProfile.STATE_CONNECTED:
                    if (!checkOperationStatus(status)) {
                        Log.w(TAG, "BluetoothGattCallback: Transferring to new state: " + newState +
                                " failed with code: " + status);
                        return;
                    }

                    changeGattState(GATT_STATE_CONNECTED);
                    Log.i(TAG, "BluetoothGattCallback: Connected to Bluetooth Gatt server on " +
                            getKeyboardString());
                    // Start to discover services right after connection.
                    mBluetoothGattClient.discoverServices();
                    changeGattState(GATT_STATE_DISCOVERING_SERVICES);
                    Log.d(TAG, "BluetoothGattCallback: Start to discover services on " +
                            getKeyboardString());
                    break;

                case BluetoothProfile.STATE_DISCONNECTED:
                    Log.i(TAG, "BluetoothGattCallback: Disconnected from Bluetooth Gatt server on "
                            + getKeyboardString() + ", status: " + status);
                    if (mGattConnectionState != GATT_STATE_DISCONNECTED) {
                        changeGattState(GATT_STATE_DISCONNECTED);
                    }
                    break;
            }
        }

        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            assert gatt == mBluetoothGattClient;

            if (!checkOperationStatus(status)) {
                changeDfuStatus(DFU_STATE_NOT_STARTED);
                return;
            }

            if (!getGattServices()) return;

            changeGattState(GATT_STATE_CONNECTED);
            readBatteryLevel();
        }

        @Override
        public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            assert gatt == mBluetoothGattClient;

            if (!checkOperationStatus(status)) {
                changeDfuStatus(DFU_STATE_OBTAIN_INFO_ERROR);
                return;
            }

            UUID uuid = characteristic.getUuid();
            if (GattAttributeUUID.UUID_BATTERY_LEVEL_CHARACTERISTIC.equals(uuid)) {

                int batteryLevel = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 0);
                if (batteryLevel < Integer.parseInt(getString(R.string.target_battery_level))) {
                    Log.w(TAG, "onCharacteristicRead BATTERY_LEVEL_CHARACTERISTIC: " +getKeyboardString()
                            + " battery level(" + batteryLevel + "%) is too low:");
                    changeDfuStatus(DFU_STATE_INFO_NOT_SUITABLE);

                    showBatteryWarningNotification();

                    return;
                }

                readDeviceManufacturer();
            } else if (GattAttributeUUID.UUID_DEVICE_INFORMATION_MANUFACTURER_CHARACTERISTIC.equals(uuid)) {

                String manufacturer = new String(characteristic.getValue());
                if (!manufacturer.equals(getString(R.string.target_manufacturer))) {
                    Log.d(TAG, "onCharacteristicRead DEVICE_INFORMATION_MANUFACTURER_CHARACTERISTIC: Invalid manufacturer: "
                            + manufacturer);
                    changeDfuStatus(DFU_STATE_INFO_NOT_SUITABLE);
                    return;
                }

                readDeviceFirmwareVersion();
            } else if (GattAttributeUUID.UUID_DEVICE_INFORMATION_FIRMWARE_VERSION_CHARACTERISTIC.equals(uuid)) {

                mKeyboardFirmwareVersion = new String(characteristic.getValue());
                Log.d(TAG, "onCharacteristicRead DEVICE_INFORMATION_FIRMWARE_VERSION_CHARACTERISTIC: current: "
                        + mKeyboardFirmwareVersion + " new: " + getString(R.string.target_firmware_version));

                Float versionNumber = 0.0f;
                // Parse the firmware version into Float number for the following checks.
                try {
                    versionNumber = Float.parseFloat(mKeyboardFirmwareVersion);
                } catch(NumberFormatException e) {
                    Log.w(TAG, "onCharacteristicRead DEVICE_INFORMATION_FIRMWARE_VERSION_CHARACTERISTIC: " +
                          "firmware version parsing error");
                    changeDfuStatus(DFU_STATE_INFO_NOT_SUITABLE);
                    return;
                }

                // Check if the current firmware is updatable.
                if (versionNumber < Float.parseFloat(getString(R.string.target_min_updatable_firmware_version))) {
                    Log.d(TAG, "onCharacteristicRead DEVICE_INFORMATION_FIRMWARE_VERSION_CHARACTERISTIC: " +
                          "current firmware(" + mKeyboardFirmwareVersion + ") is not updatable");
                    changeDfuStatus(DFU_STATE_INFO_NOT_SUITABLE);
                    return;
                }

                // Check if the current firmware is up to date.
                if (versionNumber >= Float.parseFloat(getString(R.string.target_firmware_version))) {
                    Log.d(TAG, "onCharacteristicRead DEVICE_INFORMATION_FIRMWARE_VERSION_CHARACTERISTIC: " +
                            getKeyboardString() + " firmware(" + mKeyboardFirmwareVersion + ") is up to date");
                    changeDfuStatus(DFU_STATE_INFO_NOT_SUITABLE);
                    return;
                }

                changeDfuStatus(DFU_STATE_INFO_READY);
            }
        }

        @Override
        public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            assert gatt == mBluetoothGattClient;

            if (GattAttributeUUID.UUID_DFU_CONTROL_POINT_CHARACTERISTIC.equals(characteristic.getUuid())) {
                Log.d(TAG, "onCharacteristicWrite DFU_CONTROL_POINT_CHARACTERISTIC: status: " + status);
                changeDfuStatus(DFU_STATE_MODE_SWITCHED);
            }
        }

        @Override
        public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
            assert gatt == mBluetoothGattClient;

            if (GattAttributeUUID.UUID_DFU_CONTROL_POINT_DESCRIPTOR.equals(descriptor.getUuid())) {
                Log.d(TAG, "onDescriptorWrite: DFU_CONTROL_POINT_DESCRIPTOR, status: " + status);
                enableDfuMode();
            }
        }
    };

    /* Handles DfuService callback. DFU service starts after the keyboard is found in LE scan.*/
    private DfuProgressListener mDfuProgressListener = new DfuProgressListener() {
        private void cancelDfuServiceNotification() {
            // Wait a bit before cancelling notification.
            mHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    // If this activity is still open and upload process was completed, cancel the notification.
                    final NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
                    manager.cancel(DfuService.NOTIFICATION_ID);
                }
            }, 200);
        }

        @Override
        public void onDeviceConnecting(String deviceAddress) {
        }

        @Override
        public void onDeviceConnected(String deviceAddress) {
        }

        @Override
        public void onDfuProcessStarting(String deviceAddress) {
        }

        @Override
        public void onDfuProcessStarted(String deviceAddress) {
        }

        @Override
        public void onEnablingDfuMode(String deviceAddress) {
        }

        @Override
        public void onProgressChanged(
                String deviceAddress, int percent, float speed, float avgSpeed, int currentPart, int partsTotal) {
            if ((percent % 5) == 0) {
                Log.i(TAG, "DfuProgressListener: onProgressChanged: part" + currentPart + "/" +
                        partsTotal + ", " + percent + "%");
            }
        }

        @Override
        public void onFirmwareValidating(String deviceAddress) {
        }

        @Override
        public void onDeviceDisconnecting(String deviceAddress) {
        }

        @Override
        public void onDeviceDisconnected(String deviceAddress) {
        }

        @Override
        public void onDfuCompleted(String deviceAddress) {
            Log.d(TAG, "DfuProgressListener: onDfuCompleted");
            cancelDfuServiceNotification();
            changeDfuStatus(DFU_STATE_UPDATE_COMPLETE);
        }

        @Override
        public void onDfuAborted(String deviceAddress) {
            Log.e(TAG, "DfuProgressListener: onDfuAborted");
            cancelDfuServiceNotification();
            changeDfuStatus(DFU_STATE_UPDATE_ABORTED);
        }

        @Override
        public void onError(String deviceAddress, int error, int errorType, String message) {
            Log.e(TAG, "DfuProgressListener: onError: " + message);
            cancelDfuServiceNotification();
            changeDfuStatus(DFU_STATE_UPDATE_ABORTED);
        }
    };
    private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            onHandleIntent(context, intent);
        }
    };

    /* Dynamically creates intent filter for BroadcastReceiver. */
    private static IntentFilter makeIntentFilter() {
        IntentFilter intentFilter = new IntentFilter();

        intentFilter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);
        intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
        intentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
        intentFilter.addAction(ACTION_KEYBOARD_UPDATE_CONFIRMED);
        intentFilter.addAction(ACTION_KEYBOARD_UPDATE_POSTPONED);

        return intentFilter;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "onCreate: " + getString(R.string.app_name));
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d(TAG, "onStartCommand: " + getString(R.string.app_name));

        enableBluetoothConnectivity();
        DfuServiceListenerHelper.registerProgressListener(this, mDfuProgressListener);
        registerReceiver(mBroadcastReceiver, makeIntentFilter());
        mHandler = new Handler();

        final String deviceName = intent.getStringExtra(EXTRA_KEYBOARD_NAME);
        final String deviceAddress = intent.getStringExtra(EXTRA_KEYBOARD_ADDRESS);

        Log.d(TAG, "onStartCommand: device " + deviceName + "[" + deviceAddress + "]");

        if (isUpdateServiceInUse() || deviceAddress == null ||
                !getString(R.string.target_keyboard_name).equals(deviceName)) {
            terminateSelf();
            return START_NOT_STICKY;
        }

        // Check the next update time.
        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
        final long nextUpdateTime = preferences.getLong(PREFERENCE_NEXT_UPDATE_TIME + deviceAddress, 0);
        if (nextUpdateTime != 0 && System.currentTimeMillis() < nextUpdateTime) {
            SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy hh:mm:ss.SSS");
            Calendar calendar = Calendar.getInstance();
            calendar.setTimeInMillis(nextUpdateTime);
            Log.d(TAG, "onStartCommand: next update time: " + formatter.format(calendar.getTime()));
            terminateSelf();
            return START_NOT_STICKY;
        }

        if (nextUpdateTime != 0) {
            SharedPreferences.Editor editor = preferences.edit();
            editor.remove(PREFERENCE_NEXT_UPDATE_TIME + deviceAddress);
            editor.apply();
        }

        obtainKeyboardInfo(deviceName, deviceAddress);

        if (mDfuStatus != DFU_STATE_INFO_READY) {
            Log.w(TAG, "onHandleIntent: DFU preparation failed");
            changeDfuStatus(DFU_STATE_OBTAIN_INFO_ERROR);
            return START_NOT_STICKY;
        }

        // TODO(mcchou): Return proper flag.
        return START_NOT_STICKY;
    }

    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

    @Override
    public void onDestroy() {
        dismissUpdateNotification();
        handleGattAndDfuCleanup();
        cleanUpGattConnection();
        disableBluetoothConnectivity();
        DfuServiceListenerHelper.unregisterProgressListener(this, mDfuProgressListener);
        unregisterReceiver(mBroadcastReceiver);

        Log.d(TAG, "onDestroy: " + getString(R.string.app_name));
    }

    /* Terminates the service. */
    private void terminateSelf() {
        Log.d(TAG, "terminateSelf: DFU status: " + getDfuStateString(mDfuStatus));
        stopSelf();
    }

    /**
     * Handles intents ACTION_CONNECTION_STATE_CHANGED, ACTION_STATE_CHANGED,
     * ACTION_BOND_STATE_CHANGED, ACTION_KEYBOARD_UPDATE_CONFIRMED.
     * <p/>
     * [ACTION_STATE_CHANGED]
     * This action is used to keep track of ON/OFF state change on the system Bluetooth adapter.
     * The
     * purpose is to synchronize the local Bluetooth connectivity with system Bluetooth state.
     * <p/>
     * [ACTION_CONNECTION_STATE_CHANGED]
     * This action is used to keep track of the connection change on the target device. The purpose
     * is to synchronize the connection cycles of the local GATT connection and the system
     * Bluetooth
     * connection.
     * <p/>
     * [ACTION_BOND_STATE_CHANGED]
     * This action is used to keep track of the bond state change on the target device. The purpose
     * is to the connection cycles of the local GATT connection and the system Bluetooth
     * connection.
     * <p/>
     * [ACTION_KEYBOARD_UPDATE_CONFIRMED]
     * This action is used to receive the update confirmation from the user. The purpose is to
     * trigger DFU process.
     */
    private void onHandleIntent(Context context, Intent intent) {
        final String action = intent.getAction();
        Log.d(TAG, "onHandleIntent: Received action: " + action);

        if (BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED.equals(action)) {

            if (!isBluetoothEnabled()) {
                Log.w(TAG, "onHandleIntent: Bluetooth connectivity not enabled");
                return;
            }

            // Match the connected device with the default keyboard name.
            Bundle extras = intent.getExtras();
            if (extras == null) return;
            final BluetoothDevice device = extras.getParcelable(BluetoothDevice.EXTRA_DEVICE);
            final int deviceConnectionState = extras.getInt(BluetoothAdapter.EXTRA_CONNECTION_STATE);

            Log.d(TAG, "onHandleIntent: " + device.getName() + " [" + device.getAddress() +
                    "] change to state: " + deviceConnectionState);

            if (!isTargetKeyboard(device)) return;

            if (deviceConnectionState == BluetoothAdapter.STATE_DISCONNECTED) {
                if (mDfuStatus != DFU_STATE_SWITCHING_TO_DFU_MODE && mDfuStatus != DFU_STATE_MODE_SWITCHED) {
                    terminateSelf();
                }
            }

        } else if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) {
            final int adapterState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);

            if (adapterState == BluetoothAdapter.STATE_TURNING_OFF) {
                // Terminate update process and disable Bluetooth connectivity.
                // Since BluetoothAdapter has been disabled, the callback of disconnection would not
                // be called. Therefore a separate clean-up of GATT connection is need.
                terminateSelf();
            }

        } else if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)) {
            Bundle extras = intent.getExtras();
            if (extras == null) return;
            final BluetoothDevice device = extras.getParcelable(BluetoothDevice.EXTRA_DEVICE);
            final int deviceBondState = extras.getInt(BluetoothDevice.EXTRA_BOND_STATE);

            Log.d(TAG, "onHandleIntent: state change on device " + device.getName() + " [" +
                    device.getAddress() + "], bond state: " + deviceBondState);

            if (!isTargetKeyboard(device)) return;


            if (deviceBondState == BluetoothDevice.BOND_NONE) {
                terminateSelf();
            }

        } else if (ACTION_KEYBOARD_UPDATE_CONFIRMED.equals(action)) {
            dismissUpdateNotification();

            // Check if the incoming update confirmation is associated with the current keyboard.
            String keyboardName = intent.getStringExtra(EXTRA_KEYBOARD_NAME);
            String keyboardAddress = intent.getStringExtra(EXTRA_KEYBOARD_ADDRESS);
            if (!mKeyboardName.equals(keyboardName) || !mKeyboardAddress.equals(keyboardAddress)) {
                Log.w(TAG, "onHandleIntent: No DFU service associated with " + keyboardName + " [" +
                        keyboardAddress + "]");
                return;
            }

            if (mDfuStatus != DFU_STATE_INFO_READY || mDfuStatus == DFU_STATE_UPDATING) {
                Log.w(TAG, "onHandleIntent: DFP preparation not ready or DFU is in progress.");
                changeDfuStatus(DFU_STATE_UPDATE_ABORTED);
                return;
            }

            Log.d(TAG, "onHandleIntent: Start update process on " + keyboardName + " [" +
                    keyboardAddress + "]");
            changeDfuStatus(DFU_STATE_SWITCHING_TO_DFU_MODE);

        } else if (ACTION_KEYBOARD_UPDATE_POSTPONED.equals(action)) {
            dismissUpdateNotification();
            // TODO(mcchou): Update the preference when the Settings keyboard entry is available.
            Log.d(TAG, "onHandleIntent: Postpone the update");
            SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
            SharedPreferences.Editor editor = preferences.edit();
            editor.putLong(PREFERENCE_NEXT_UPDATE_TIME + mKeyboardAddress,
                    System.currentTimeMillis() + TimeUnit.MILLISECONDS.convert(7, TimeUnit.DAYS));
            editor.apply();
        }
    }

    /* Checks if Bluetooth connectivity is enabled. */
    private boolean isBluetoothEnabled() {
        return (mBluetoothManager != null && mBluetoothAdapter != null && mBluetoothLeScanner != null);
    }

    /* Checks if there is already a keyboard associated with the update service. */
    private boolean isUpdateServiceInUse() {
        return (mKeyboardName != null && mKeyboardAddress != null);
    }

    /* Returns a string including the keyboard name and address. */
    private String getKeyboardString() {
        return mKeyboardName + " [" + mKeyboardAddress + "]";
    }

    /* Checks if the device is the keyboard associated with the service. */
    private boolean isTargetKeyboard(BluetoothDevice device) {
        if (device == null) return false;
        return (mKeyboardName.equals(device.getName()) && mKeyboardAddress.equals(device.getAddress()));
    }

    /* Retrieves Bluetooth manager, adapter and scanner. */
    private boolean enableBluetoothConnectivity() {
        Log.d(TAG, "EnableBluetoothConnectivity");
        if (mBluetoothManager == null) {
            mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
            if (mBluetoothManager == null) {
                Log.w(TAG, "EnableBluetoothConnectivity: Failed to obtain BluetoothManager");
                return false;
            }
        }

        mBluetoothAdapter = mBluetoothManager.getAdapter();
        if (mBluetoothAdapter == null) {
            Log.w(TAG, "EnableBluetoothConnectivity: Failed to obtain BluetoothAdapter");
            return false;
        }

        mBluetoothLeScanner = mBluetoothAdapter.getBluetoothLeScanner();
        if (mBluetoothLeScanner == null) {
            Log.w(TAG, "EnableBluetoothConnectivity: Failed to obtain BluetoothLeScanner");
            return false;
        }

        return true;
    }

    /* Disables Bluetooth connectivity if exists. */
    private void disableBluetoothConnectivity() {
        Log.d(TAG, "disableBluetoothConnectivity");
        mBluetoothManager = null;
        mBluetoothAdapter = null;
        mBluetoothLeScanner = null;
    }

    /* Shows the update notification. */
    private void showUpdateNotification() {
        Log.d(TAG, "showUpdateNotification: " + getKeyboardString());

        // Intent for triggering the update confirmation page.
        Intent updateConfirmation = new Intent(this, UpdateConfirmationActivity.class);
        updateConfirmation.putExtra(EXTRA_KEYBOARD_NAME, mKeyboardName);
        updateConfirmation.putExtra(EXTRA_KEYBOARD_ADDRESS, mKeyboardAddress);
        updateConfirmation.putExtra(EXTRA_KEYBOARD_FIRMWARE_VERSION, mKeyboardFirmwareVersion);
        updateConfirmation.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

        // Intent for postponing update.
        Intent postponeUpdate = new Intent(ACTION_KEYBOARD_UPDATE_POSTPONED);

        // Wrap intents into pending intents for notification use.
        PendingIntent laterIntent = PendingIntent.getBroadcast(
                this, 0, postponeUpdate, PendingIntent.FLAG_UPDATE_CURRENT);
        PendingIntent installIntent = PendingIntent.getActivity(
                this, 0, updateConfirmation, PendingIntent.FLAG_CANCEL_CURRENT);

        // Create a notification object with two buttons (actions)
        mUpdateNotification = new NotificationCompat.Builder(this)
                .setCategory(Notification.CATEGORY_SYSTEM)
                .setContentTitle(getString(R.string.notification_update_title))
                .setContentText(getString(R.string.notification_update_text))
                .setSmallIcon(R.drawable.ic_keyboard)
                .addAction(new NotificationCompat.Action.Builder(
                        R.drawable.ic_later, getString(R.string.notification_update_later),
                        laterIntent).build())
                .addAction(new NotificationCompat.Action.Builder(
                        R.drawable.ic_install, getString(R.string.notification_update_install),
                        installIntent).build())
                .setAutoCancel(true)
                .setOnlyAlertOnce(true)
                .build();

        // Show the notification via notification manager
        NotificationManager notificationManager =
                (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        notificationManager.notify(UPDATE_NOTIFICATION_ID, mUpdateNotification);
    }

    /* Dismisses the udpate notification. */
    private void dismissUpdateNotification() {
        if (mUpdateNotification == null) return;
        Log.d(TAG, "dismissUpdateNotification");
        NotificationManager notificationManager =
                (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        notificationManager.cancel(UPDATE_NOTIFICATION_ID);
        mUpdateNotification = null;
    }

    /* Shows the keyboard battery warning notification. */
    private void showBatteryWarningNotification() {
        Log.d(TAG, "showBatteryWarningNotification: " + getKeyboardString());

        Notification batteryWarningNotification = new NotificationCompat.Builder(this)
                .setContentTitle(getString(R.string.notification_battery_warning_title))
                .setContentText(getString(R.string.notification_battery_warning_text))
                .setSmallIcon(R.drawable.ic_battery_warning)
                .setAutoCancel(true)
                .setOnlyAlertOnce(true)
                .setPriority(Notification.PRIORITY_HIGH)
                .setColor(Color.RED)
                .setStyle(new NotificationCompat.BigTextStyle().bigText(
                        getString(R.string.notification_battery_warning_text)))
                .build();

        // Show the notification via notification manager
        NotificationManager notificationManager =
                (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        notificationManager.notify(BATTERY_WARNING_NOTIFICATION_ID, batteryWarningNotification);
    }

    /* Connects to the GATT server hosted on the given Bluetooth LE device. */
    private boolean connectToKeyboard() {
        if (!isBluetoothEnabled() || !isUpdateServiceInUse()) {
            Log.w(TAG, "connectToKeyboard: Bluetooth connectivity not enabled or associated keyboard not found.");
            return false;
        }

        final BluetoothDevice keyboard = mBluetoothAdapter.getRemoteDevice(mKeyboardAddress);
        if (keyboard == null) {
            Log.w(TAG, "connectToKeyboard: " + getKeyboardString() + " not found. Unable to connect.");
            return false;
        }

        Log.d(TAG, "connectToKeyboard: Trying to create a new connection to " + getKeyboardString());
        mBluetoothGattClient = keyboard.connectGatt(this, false, mGattCallback);
        changeGattState(GATT_STATE_CONNECTING);
        mGattOperationStatus = BluetoothGatt.GATT_SUCCESS;

        return true;
    }

    /* Disconnects from the GATT server hosted on the given Bluetooth LE device. */
    private void disconnectFromKeyboard() {
        if (mGattConnectionState == GATT_STATE_DISCONNECTED) return;
        if (!isUpdateServiceInUse() || !isBluetoothEnabled() || mDfuStatus == DFU_STATE_NOT_STARTED) {
            Log.i(TAG, "disconnectFromKeyboard: Bluetooth connectivity not enabled");
            return;
        }

        Log.d(TAG, "disconnectFromKeyboard: " + getKeyboardString());

        mBluetoothGattClient.disconnect();
        changeGattState(GATT_STATE_DISCONNECTING);
        mGattOperationStatus = BluetoothGatt.GATT_SUCCESS;

        // Wait 2 seconds for GATT disconnection request to finish.
        try {
            Thread.sleep(2000);  // 2 seconds
            Log.d(TAG, "disconnectFromKeyboard: Wait for GATT disconnection");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * Cleans up Bluetooth GATT connection and the keyboard. This should be done before starting
     * DFU process.
     */
    private void cleanUpGattConnection() {
        Log.d(TAG, "cleanUpGattConnection");
        mKeyboardFirmwareVersion = null;
        mBluetoothGattClient = null;
        mBatteryService = null;
        mDeviceInfoService = null;
        mDfuService = null;
        mDfuChar = null;
        mLeScanRetried = false;
    }

    /* Starts to collect the information of the keyboard. */
    private void obtainKeyboardInfo(String keyboardName, String keyboardAddress) {
        Log.d(TAG, "obtainKeyboardInfo: Obtain the information of " + keyboardName + " [" +
                keyboardAddress + "]");

        // Connect to the keyboard and start to obtain its information.
        mKeyboardName = keyboardName;
        mKeyboardAddress = keyboardAddress.toUpperCase();
        mKeyboardAddressInAppMode = mKeyboardAddress;
        Log.d(TAG, "obtainKeyboardInfo: Associate DFU service with " + getKeyboardString());

        if (mGattConnectionState == GATT_STATE_CONNECTED) {
            Log.i(TAG, "obtainKeyboardInfo: Reuse previous GATT connection");
            readBatteryLevel();
        } else if (mGattConnectionState == GATT_STATE_DISCONNECTED) {
            changeDfuStatus(DFU_STATE_OBTAINING_INFO);
        } else {
            Log.w(TAG, "obtainKeyboardInfo: Failed to obtain keyboard information");
        }

        // Wait at most 10 seconds for the queries to GATT attributes to finish.
        int waitTimes = 5;
        while (mDfuStatus == DFU_STATE_OBTAINING_INFO && waitTimes > 0) {
            try {
                Thread.sleep(2000);  // 2 seconds
                waitTimes--;
                Log.d(TAG, "obtainKeyboardInfo: Wait for preparation completion");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    /* Starts/stops Bluetooth LE scan. */
    private void scanLeDevice(final boolean enable) {
        if (!isBluetoothEnabled()) {
            Log.w(TAG, "scanLeDevice: Bluetooth connectivity not enabled");
        }
        if (enable) {
            mHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    Log.d(TAG, "scanLeDevice: Stop scanning");
                    mBluetoothLeScanner.stopScan(mBluetoothLeScanCallback);
                }
            }, SCAN_PERIOD);
            Log.d(TAG, "scanLeDevice: Start scanning");
            mBluetoothLeScanner.startScan(mBluetoothLeScanCallback);
        } else {
            Log.d(TAG, "scanLeDevice: Stop scanning");
            mBluetoothLeScanner.stopScan(mBluetoothLeScanCallback);
        }
    }

    /**
     * Retrieves Battery Service, Device Information Service, Device Firmware Update(DFU) service
     * and DFU Control Point Characteristic.
     */
    private boolean getGattServices() {
        Log.d(TAG, "getDfuServiceAndChar");

        if (mBluetoothGattClient == null) {
            Log.w(TAG, "getDfuServiceAndChar: Bluetooth GATT connection not initiated");
            return false;
        }

        mBatteryService = mBluetoothGattClient.getService(GattAttributeUUID.UUID_BATTERY_SERVICE);
        if (mBatteryService == null) {
            Log.e(TAG, "getBatteryService: Failed to get Battery Service");
            return false;
        }
        mDeviceInfoService = mBluetoothGattClient.getService(GattAttributeUUID.UUID_DEVICE_INFORMATION_SERVICE);
        if (mDeviceInfoService == null) {
            Log.e(TAG, "getDeviceInfoService: Failed to get Device Information Service");
            return false;
        }

        mDfuService = mBluetoothGattClient.getService(GattAttributeUUID.UUID_DFU_SERVICE);
        if (mDfuService == null) {
            Log.e(TAG, "getDfuServiceAndChar: Failed to get Device Firmware Update Service");
            return false;
        }

        mDfuChar = mDfuService.getCharacteristic(GattAttributeUUID.UUID_DFU_CONTROL_POINT_CHARACTERISTIC);
        if (mDfuChar == null) {
            Log.e(TAG, "getDfuServiceAndChar: Failed to get DFU Control Point characteristic");
            return false;
        }

        return true;
    }

    /* Retrieves battery level of the connected keyboard. */
    private boolean readBatteryLevel() {
        Log.d(TAG, "readBatteryLevel");

        BluetoothGattCharacteristic batteryLevelChar = mBatteryService.getCharacteristic(
                GattAttributeUUID.UUID_BATTERY_LEVEL_CHARACTERISTIC);
        if (batteryLevelChar == null || !mBluetoothGattClient.readCharacteristic(batteryLevelChar)) {
            Log.e(TAG, "readBatteryLevel: Failed to init batter level read operation");
            return false;
        }
        return true;
    }

    /* Retrieves device manufacturer of the connected keyboard. */
    private boolean readDeviceManufacturer() {
        Log.d(TAG, "readDeviceManufacturer");

        BluetoothGattCharacteristic deviceManufacturerChar = mDeviceInfoService.getCharacteristic(
                GattAttributeUUID.UUID_DEVICE_INFORMATION_MANUFACTURER_CHARACTERISTIC);
        if (deviceManufacturerChar == null ||
                !mBluetoothGattClient.readCharacteristic(deviceManufacturerChar)) {
            Log.e(TAG, "readDeviceInfo: Failed to init device manufacturer characteristic read operation");
            return false;
        }
        return true;
    }

    /* Retrieves device firmware version of the connected keyboard. */
    private boolean readDeviceFirmwareVersion() {
        Log.d(TAG, "readDeviceFirmwareVersion");

        BluetoothGattCharacteristic deviceFirmwareVersionChar = mDeviceInfoService.getCharacteristic(
                GattAttributeUUID.UUID_DEVICE_INFORMATION_FIRMWARE_VERSION_CHARACTERISTIC);
        if (deviceFirmwareVersionChar == null ||
                !mBluetoothGattClient.readCharacteristic(deviceFirmwareVersionChar)) {
            Log.e(TAG, "readDeviceInfo: Failed to get device firmware revision characteristic");
            return false;
        }
        return true;
    }

    /* Enables device firmware update notification of the connected keyboard. */
    private boolean enableDfuNotification() {
        Log.d(TAG, "enableDfuNotification");

        if (mDfuChar == null) {
            Log.w(TAG, "enableDfuNotification: DFU control point characteristic not initiated");
            return false;
        }

        BluetoothGattDescriptor dfuDesc = mDfuChar.getDescriptor(
                GattAttributeUUID.UUID_DFU_CONTROL_POINT_DESCRIPTOR);
        if (dfuDesc == null ||
                !dfuDesc.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE) ||
                !mBluetoothGattClient.writeDescriptor(dfuDesc)) {
            Log.e(TAG, "enableDfuNotification: Failed to init DFU descriptor write operation");
            return false;
        }
        return true;
    }

    /* Switches the connected keyboard to DFU mode. */
    private boolean enableDfuMode() {
        Log.d(TAG, "enableDfuMode");

        if (mDfuChar == null) {
            Log.w(TAG, "enableDfuMode: DFU control point characteristic not initiated");
            return false;
        }

        // Opcode: 0x01 -> Start DFU mode.
        //         0x04 -> DFU type: application
        final byte dfuOpcodeWithTypeApplication[] = new byte[]{0x01, 0x04};
        if (!mDfuChar.setValue(dfuOpcodeWithTypeApplication) ||
                !mBluetoothGattClient.writeCharacteristic(mDfuChar)) {
            Log.e(TAG, "enableDfuMode: Failed to init DFU mode switch");
            return false;
        }
        return true;
    }

    /* Checks if a Bluetooth Gatt operation is finished correctly. */
    private boolean checkOperationStatus(int status) {
        mGattOperationStatus = status;
        if (mGattOperationStatus != BluetoothGatt.GATT_SUCCESS) {
            Log.d(TAG, "BluetoothGattCallback: GATT operation failure: " + mGattOperationStatus);
            return false;
        }
        return true;
    }

    /* Starts DFU process. */
    private void startDfuService(String keyboardName, String keyboardAddress) {
        Log.d(TAG, "startDfuService");

        changeDfuStatus(DFU_STATE_UPDATING);

        String packageName = getApplicationContext().getPackageName();
        int initResourceId = getResources().getIdentifier(
            getString(R.string.target_firmware_init_file_name), "raw", packageName);
        int imageResourceId = getResources().getIdentifier(
            getString(R.string.target_firmware_image_file_name), "raw", packageName);
        boolean keepBond = true;

        Log.d(TAG, "Name: " + keyboardName + "\n" +
                "Address: " + keyboardAddress + "\n" +
                "Init file: " + getString(R.string.target_firmware_init_file_name) + "\n" +
                "Image file: " + getString(R.string.target_firmware_image_file_name) + "\n" +
                "Image type: Application(" + DfuService.TYPE_APPLICATION + ")\n" +
                "Keep bond: " + keepBond);

        final Intent service = new Intent(this, DfuService.class);
        service.putExtra(DfuService.EXTRA_DEVICE_NAME, keyboardName);
        service.putExtra(DfuService.EXTRA_DEVICE_ADDRESS, keyboardAddress);
        service.putExtra(DfuService.EXTRA_INIT_FILE_RES_ID, initResourceId);
        service.putExtra(DfuService.EXTRA_FILE_RES_ID, imageResourceId);
        service.putExtra(DfuService.EXTRA_FILE_TYPE, DfuService.TYPE_APPLICATION);
        service.putExtra(DfuService.EXTRA_KEEP_BOND, true);

        startService(service);
    }

    /* Aborts DFU service if it is in progress. */
    public void abortDfu() {
        if (mDfuStatus != DFU_STATE_UPDATING) return;
        final Intent pauseAction = new Intent(DfuService.BROADCAST_ACTION);
        pauseAction.putExtra(DfuService.EXTRA_ACTION, DfuService.ACTION_ABORT);
        LocalBroadcastManager.getInstance(this).sendBroadcast(pauseAction);

        // Wait 2 seconds for DFU abort request to finish.
        try {
            Thread.sleep(2000);  // 2 seconds
            Log.d(TAG, "abortDfu: Wait for DFU to abort");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /* State setter of GATT connection. */
    private void changeGattState(int newStatus) {
        mGattConnectionState = newStatus;
        Log.i(TAG, "-- changeGattState: " + getGattStateString(mGattConnectionState));
    }

    /* Helper function for logging GATT state change. */
    private String getGattStateString(int state) {
        switch (state) {
            case GATT_STATE_DISCONNECTED:
                return "GATT_STATE_DISCONNECTED";
            case GATT_STATE_CONNECTING:
                return "GATT_STATE_CONNECTING";
            case GATT_STATE_CONNECTED:
                return "GATT_STATE_CONNECTED";
            case GATT_STATE_DISCOVERING_SERVICES:
                return "GATT_STATE_DISCOVERING_SERVICES";
            case GATT_STATE_DISCONNECTING:
                return "GATT_STATE_DISCONNECTING";
            default:
                return "Unknown state (" + state + ")";
        }
    }

    /* State flow for the updater service. */
    private void changeDfuStatus(int newStatus) {
        switch (newStatus) {
            case DFU_STATE_NOT_STARTED:
                break;
            case DFU_STATE_OBTAINING_INFO:
                connectToKeyboard();
                break;
            case DFU_STATE_INFO_READY:
                showUpdateNotification();
                break;
            case DFU_STATE_SWITCHING_TO_DFU_MODE:
                mHandler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        if (mDfuStatus == DFU_STATE_SWITCHING_TO_DFU_MODE)
                            changeDfuStatus(DFU_STATE_SWITCH_TO_DFU_MODE_ERROR);
                    }
                }, SCAN_PERIOD * 2);
                enableDfuNotification();
                break;
            case DFU_STATE_MODE_SWITCHED:
                scanLeDevice(true);
                break;
            case DFU_STATE_UPDATING:
                PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
                mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
                mWakeLock.acquire();
                break;
            case DFU_STATE_UPDATE_COMPLETE:
                mWakeLock.release();
                terminateSelf();
                break;
            case DFU_STATE_INFO_NOT_SUITABLE:
                terminateSelf();
                break;
            case DFU_STATE_OBTAIN_INFO_ERROR:
                terminateSelf();
                break;
            case DFU_STATE_SWITCH_TO_DFU_MODE_ERROR:
                terminateSelf();
                break;
            case DFU_STATE_UPDATE_ABORTED:
                mWakeLock.release();
                terminateSelf();
                break;
            default:
                break;
        }
        mDfuStatus = newStatus;
        Log.d(TAG, "---- changeDfuStatus: " + getDfuStateString(mDfuStatus));
    }

    /* Helper function for logging DFU state change. */
    private String getDfuStateString(int state) {
        switch (state) {
            case DFU_STATE_NOT_STARTED:
                return "DFU_STATE_NOT_STARTED";
            case DFU_STATE_OBTAINING_INFO:
                return "DFU_STATE_OBTAINING_INFO";
            case DFU_STATE_INFO_READY:
                return "DFU_STATE_INFO_READY";
            case DFU_STATE_SWITCHING_TO_DFU_MODE:
                return "DFU_STATE_SWITCHING_TO_DFU_MODE";
            case DFU_STATE_MODE_SWITCHED:
                return "DFU_STATE_MODE_SWITCHED";
            case DFU_STATE_UPDATING:
                return "DFU_STATE_UPDATING";
            case DFU_STATE_UPDATE_COMPLETE:
                return "DFU_STATE_UPDATE_COMPLETE";
            case DFU_STATE_INFO_NOT_SUITABLE:
                return "DFU_STATE_INFO_NOT_SUITABLE";
            case DFU_STATE_OBTAIN_INFO_ERROR:
                return "DFU_STATE_OBTAIN_INFO_ERROR";
            case DFU_STATE_SWITCH_TO_DFU_MODE_ERROR:
                return "DFU_STATE_SWITCH_TO_DFU_MODE_ERROR";
            case DFU_STATE_UPDATE_ABORTED:
                return "DFU_STATE_UPDATE_ABORTED";
            default:
                return "Unknown state (" + state + ")";
        }
    }

    /* Handles GATT disconnection and DFU aborting before the service terminate itself. */
    private void handleGattAndDfuCleanup() {
        Log.d(TAG, "handleGattAndDfuCleanup");
        if (mGattConnectionState == GATT_STATE_DISCONNECTED) return;

        // Handle update process termination based on the current DFU state.
        switch (mDfuStatus) {
            case DFU_STATE_SWITCHING_TO_DFU_MODE:
                scanLeDevice(false);
            case DFU_STATE_OBTAINING_INFO:
            case DFU_STATE_INFO_READY:
            case DFU_STATE_INFO_NOT_SUITABLE:
            case DFU_STATE_SWITCH_TO_DFU_MODE_ERROR:
                disconnectFromKeyboard();
            case DFU_STATE_NOT_STARTED:
            case DFU_STATE_MODE_SWITCHED:
            case DFU_STATE_UPDATE_COMPLETE:
            case DFU_STATE_UPDATE_ABORTED:
                break;
            case DFU_STATE_UPDATING:
                abortDfu();
                dismissUpdateNotification();
                break;
            default:
                break;
        }
        changeGattState(GATT_STATE_DISCONNECTED);
    }

    public class LocalBinder extends Binder {
        KeyboardFirmwareUpdateService getService() {
            return KeyboardFirmwareUpdateService.this;
        }
    }
}
