com.nbplus.iotapp.service.IoTService.java Source code

Java tutorial

Introduction

Here is the source code for com.nbplus.iotapp.service.IoTService.java

Source

/*
 * Copyright (c) 2015. NB Plus (www.nbplus.co.kr)
 *
 * 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.nbplus.iotapp.service;

import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;

import com.nbplus.iotapp.bluetooth.BluetoothLeService;
import com.nbplus.iotapp.iotgateway.ThreadPooledServer;
import com.nbplus.iotapp.perferences.IoTServicePreference;
import com.nbplus.iotlib.data.IoTConstants;
import com.nbplus.iotlib.data.IoTDevice;
import com.nbplus.iotlib.data.IoTResultCodes;
import com.nbplus.iotlib.data.IoTServiceCommand;
import com.nbplus.iotlib.data.IoTServiceStatus;
import com.nbplus.iotlib.data.IoTHandleData;

import org.basdroid.common.NetworkUtils;
import org.basdroid.common.PackageUtils;
import org.basdroid.common.StringUtils;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;

/**
 * Created by basagee on 2015. 8. 6..
 */
public class IoTService extends Service {
    private static final String TAG = IoTService.class.getSimpleName();

    // internal constants
    private static final int HANDLER_MESSAGE_CONNECTIVITY_CHANGED = IoTServiceCommand.COMMAND_BASE_VALUE - 1;
    private static final int HANDLER_MESSAGE_BT_STATE_CHANGED = HANDLER_MESSAGE_CONNECTIVITY_CHANGED - 1;
    private static final int HANDLER_MESSAGE_CONNECTION_NOT_RESPOND = HANDLER_MESSAGE_BT_STATE_CHANGED - 1;

    private static final int CONNECTION_NOT_RESPOND_WAIT_TIME = 5 * 1000;

    // Wifi lock that we hold when streaming files from the internet, in order to prevent the
    // device from shutting off the Wifi radio
    WifiManager.WifiLock mWifiLock;
    boolean mLastConnectionStatus = false; // network status
    private BluetoothLeService mBluetoothLeService;
    boolean mUseIoTGateway = false;
    boolean mIsBleScanPeriodic = false;

    private IoTServiceHandler mHandler = new IoTServiceHandler(this);
    Messenger mServiceMessenger = null;

    private IoTServiceStatus mServiceStatus = IoTServiceStatus.STOPPED;
    private IoTResultCodes mErrorCodes = IoTResultCodes.INITIALIZING;

    // IoT   ? ? Messenger .
    // 2015.11.10  .
    // REGISTER_SERVICE ? ??, UNREGISTER_SERVICE ? ?.
    WeakReference<Messenger> mRegisteredAppMessenger = null;

    HashMap<String, IoTHandleData> mRequestHandleMap = new HashMap<>();
    ArrayList<String> mKeepAliveConnectionDeviceList = new ArrayList<>();
    ArrayList<String> mConnectedDeviceList = new ArrayList<>();
    boolean mIsDisconnectAllState = false;

    // IoT Gateway variables...
    ThreadPooledServer mThreadPooledServer;
    WeakReference<Messenger> mIoTGatewayWorkerMessengerRef = null;

    //  ? 
    private static class IoTServiceHandler extends Handler {
        private final WeakReference<IoTService> mService;

        public IoTServiceHandler(IoTService service) {
            mService = new WeakReference<>(service);
        }

        @Override
        public void handleMessage(Message msg) {
            IoTService service = mService.get();
            if (service != null) {
                service.handleMessage(msg);
            }
        }
    }

    public void handleMessage(Message msg) {
        if (msg == null) {
            return;
        }
        Log.d(TAG, "handle message msg.what = " + msg.what);
        switch (msg.what) {
        // when using iot gateway
        case IoTServiceCommand.IOT_GATEWAY_CONNECTED: {
            Log.d(TAG, "IoTServiceCommand.IOT_GATEWAY_CONNECTED received...");
            mIoTGatewayWorkerMessengerRef = new WeakReference<>(msg.replyTo);
            // TODO : test handler
            if (mIoTGatewayWorkerMessengerRef != null) {
                try {
                    Messenger workerMessenger = mIoTGatewayWorkerMessengerRef.get();
                    if (workerMessenger != null) {
                        Message testMsg = new Message();
                        msg.what = IoTServiceCommand.IOT_GATEWAY_DISCONNECTED;
                        Log.d(TAG, "test IoTServiceCommand.IOT_GATEWAY_DISCONNECTED");
                        workerMessenger.send(testMsg);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

            break;
        }
        case IoTServiceCommand.SCANNING_START: {
            Bundle extras = msg.getData();
            if (extras == null) {
                Log.w(TAG, "Scanning bundle data is not found !!!");
                return;
            }
            boolean isPeriodic = extras.getBoolean(IoTServiceCommand.KEY_DATA);
            Log.d(TAG, "IoTServiceCommand.SCANNING_START called. periodic = " + isPeriodic);
            if (mUseIoTGateway) {

            } else {
                if (mBluetoothLeService != null && mServiceStatus == IoTServiceStatus.RUNNING) {
                    mIsBleScanPeriodic = isPeriodic;
                    mBluetoothLeService.scanLeDevicePeriodically(true, isPeriodic);
                }
            }
            break;
        }
        case IoTServiceCommand.SCANNING_STOP: {
            Bundle extras = msg.getData();
            if (extras == null) {
                Log.w(TAG, "Scanning bundle data is not found !!!");
                return;
            }
            //boolean isPeriodic = extras.getBoolean(IoTServiceCommand.KEY_DATA);
            Log.d(TAG, "IoTServiceCommand.SCANNING_STOP called.");
            if (mUseIoTGateway) {

            } else {
                if (mBluetoothLeService != null && mServiceStatus == IoTServiceStatus.RUNNING) {
                    mIsBleScanPeriodic = false;
                    mBluetoothLeService.scanLeDevicePeriodically(false, false);
                }
            }
            break;
        }
        case HANDLER_MESSAGE_CONNECTIVITY_CHANGED:
            final boolean isConnected = NetworkUtils.isConnected(this);
            Log.d(TAG, "HANDLER_MESSAGE_CONNECTIVITY_CHANGED received isConnected = " + isConnected);
            if (mLastConnectionStatus == isConnected) {
                Log.d(TAG, "mLastConnectionStatus == isConnected do not anything.");
                return;
            }

            mLastConnectionStatus = isConnected;
            if (mLastConnectionStatus) {
                Log.d(TAG, "HANDLER_MESSAGE_CONNECTIVITY_CHANGED network is connected !!!");
                // TODO : re-connect
                if (mServiceStatus == IoTServiceStatus.STOPPED) {

                }
            } else {
                Log.d(TAG, "HANDLER_MESSAGE_CONNECTIVITY_CHANGED network is disconnected !!!");
            }
            break;
        case HANDLER_MESSAGE_BT_STATE_CHANGED:
            Log.d(TAG, "HANDLER_MESSAGE_CONNECTIVITY_CHANGED received !!!");
            final int state = msg.arg1;
            if ((mLastConnectionStatus && state == BluetoothAdapter.STATE_ON)
                    || (!mLastConnectionStatus && state == BluetoothAdapter.STATE_OFF)) {
                return;
            }

            mLastConnectionStatus = (state == BluetoothAdapter.STATE_ON) ? true : false;
            if (mLastConnectionStatus) {
                Log.d(TAG, "HANDLER_MESSAGE_BT_STATE_CHANGED bluetooth is enabled !!!");

                if (mServiceStatus != IoTServiceStatus.RUNNING) {
                    final Intent gattServiceIntent = new Intent(this, BluetoothLeService.class);
                    if (!bindService(gattServiceIntent, mBluetoothServiceConnection, BIND_AUTO_CREATE)) {
                        Log.e(TAG, ">> bind BluetoothServiceConnection failed.... !!!");
                    }
                }
            } else {
                Log.d(TAG, "HANDLER_MESSAGE_BT_STATE_CHANGED bluetooth is disabled !!!");
                mErrorCodes = IoTResultCodes.BLUETOOTH_NOT_ENABLED;
                unbindService(mBluetoothServiceConnection);

                mServiceStatus = IoTServiceStatus.STOPPED;
                mHandler.removeMessages(HANDLER_MESSAGE_CONNECTION_NOT_RESPOND);
                mConnectedDeviceList.clear();
                mRequestHandleMap.clear();

                sendServiceStatusNotification();
            }
            break;
        case IoTServiceCommand.REGISTER_SERVICE: {
            Bundle b = msg.getData();
            if (msg.replyTo == null || b == null) {
                Log.e(TAG, "Invalid register args...");
                break;
            }

            String msgId = b.getString(IoTServiceCommand.KEY_MSGID, "");
            if (!StringUtils.isEmptyString(msgId)) {
                Log.d(TAG, "msgId == " + msgId);
                String[] strArrays = msgId.split("_");
                if (strArrays.length == 2) {
                    mRegisteredAppMessenger = new WeakReference<>(msg.replyTo);
                    sendResultToApplication(msg.replyTo, msgId, null, msg.what, IoTResultCodes.SUCCESS);

                    // ??  ??  ? ? .
                    sendServiceStatusNotification();
                } else {
                    Log.e(TAG, "Invalid register args...");
                    sendResultToApplication(msg.replyTo, msgId, null, msg.what,
                            IoTResultCodes.INVALID_REQUEST_ARGUMENTS);
                    break;
                }
            } else {
                Log.e(TAG, "Invalid register args...");
                sendResultToApplication(msg.replyTo, "", null, msg.what, IoTResultCodes.INVALID_REQUEST_ARGUMENTS);
                break;
            }

            break;
        }
        case IoTServiceCommand.UNREGISTER_SERVICE: {
            Bundle b = msg.getData();
            if (b == null) {
                Log.e(TAG, "Invalid register args...");
                break;
            }

            String msgId = b.getString(IoTServiceCommand.KEY_MSGID, "");
            if (!StringUtils.isEmptyString(msgId)) {
                String[] strArrays = msgId.split("_");
                if (strArrays.length == 2) {
                    Messenger clientMessenger = (mRegisteredAppMessenger == null) ? null
                            : mRegisteredAppMessenger.get();
                    if (clientMessenger != null) {
                        sendResultToApplication(clientMessenger, msgId, null, msg.what, IoTResultCodes.SUCCESS);
                        mRegisteredAppMessenger = null;
                    } else {
                        //??
                    }
                } else {
                    Log.e(TAG, "Invalid register args...");
                    break;
                }
            } else {
                Log.e(TAG, "Invalid un-register args...");
            }
            break;
        }

        case IoTServiceCommand.GET_DEVICE_LIST: {
            if (mUseIoTGateway) {
                // TODO
            } else {
                mBluetoothLeService.scanLeDevice(false);
                mBluetoothLeService.scanLeDevicePeriodically(true, mIsBleScanPeriodic);
            }
            break;
        }

        case IoTServiceCommand.DEVICE_DISCONNECT_ALL: {
            Bundle b = msg.getData();
            String msgId = b.getString(IoTServiceCommand.KEY_MSGID, "");
            b.setClassLoader(IoTHandleData.class.getClassLoader());
            IoTHandleData ioTHandleData = b.getParcelable(IoTServiceCommand.KEY_DATA);

            if (mConnectedDeviceList.size() > 0) {
                mIsDisconnectAllState = true;
                ioTHandleData.setMsgId(msgId);
                ioTHandleData.setRequestCommand(msg.what);

                String connectedDeviceId = mConnectedDeviceList.get(0);
                if (mUseIoTGateway) {
                    // TODO

                } else {
                    if (mBluetoothLeService != null) {
                        mBluetoothLeService.disconnect(connectedDeviceId);
                    } else {
                        Messenger clientMessenger = (mRegisteredAppMessenger == null) ? null
                                : mRegisteredAppMessenger.get();
                        sendResultToApplication(clientMessenger, msgId, ioTHandleData.getDeviceId(), msg.what,
                                IoTResultCodes.FAILED);
                    }
                }
            } else {
                Messenger clientMessenger = (mRegisteredAppMessenger == null) ? null
                        : mRegisteredAppMessenger.get();
                sendResultToApplication(clientMessenger, msgId, ioTHandleData.getDeviceId(), msg.what,
                        IoTResultCodes.SUCCESS);
            }
            break;
        }

        case IoTServiceCommand.DEVICE_CONNECT: {
            Bundle b = msg.getData();
            b.setClassLoader(IoTHandleData.class.getClassLoader());
            IoTHandleData ioTHandleData = b.getParcelable(IoTServiceCommand.KEY_DATA);
            String msgId = b.getString(IoTServiceCommand.KEY_MSGID, "");
            Messenger clientMessenger = (mRegisteredAppMessenger == null) ? null : mRegisteredAppMessenger.get();

            if (ioTHandleData == null) {
                sendResultToApplication(clientMessenger, msgId, null, msg.what, IoTResultCodes.FAILED);
                Log.w(TAG, "case READ_WRITE_SETNOTI : ioTHandleData is null");
                return;
            }

            if (mRequestHandleMap.get(ioTHandleData.getDeviceId()) != null) {
                Log.d(TAG, "Already previous command deviceid = " + ioTHandleData.getDeviceId() + ", command = "
                        + ioTHandleData.getRequestCommand());
                sendResultToApplication(clientMessenger, msgId, ioTHandleData.getDeviceId(), msg.what,
                        IoTResultCodes.FAILED);
                return;
            }

            if (mUseIoTGateway) {
            } else {
                if (mBluetoothLeService == null) {
                    sendResultToApplication(clientMessenger, msgId, ioTHandleData.getDeviceId(), msg.what,
                            IoTResultCodes.FAILED);
                    Log.w(TAG,
                            "case IoTServiceCommand.DEVICE_CONNECT : mBluetoothLeService or ioTHandleData is null");
                    return;
                }
                if (ioTHandleData.getDeviceTypeId() != IoTDevice.DEVICE_TYPE_ID_BT) {
                    sendResultToApplication(clientMessenger, msgId, ioTHandleData.getDeviceId(), msg.what,
                            IoTResultCodes.FAILED);
                    Log.w(TAG,
                            "case IoTServiceCommand.DEVICE_DISCONNECT : is not bt device... mUseIoTGateway == false");
                    return;
                }

                if (ioTHandleData.isKeepAliveDevice()) {
                    if (mKeepAliveConnectionDeviceList.contains(ioTHandleData.getDeviceId())) {
                        Log.d(TAG, "Keep alive device is already connected.. id = " + ioTHandleData.getDeviceId());
                        sendResultToApplication(clientMessenger, msgId, ioTHandleData.getDeviceId(), msg.what,
                                IoTResultCodes.SUCCESS);

                        // send to IoT interface module
                        Message connectedMsg = new Message();
                        connectedMsg.what = IoTServiceCommand.DEVICE_CONNECTED;
                        Bundle extras = new Bundle();
                        extras.putString(IoTServiceCommand.KEY_DEVICE_UUID, ioTHandleData.getDeviceId());
                        connectedMsg.setData(extras);

                        sendNotificationToApplication(connectedMsg);
                        return;
                    }
                }

                if (mBluetoothLeService.connect(ioTHandleData.getDeviceId())) {
                    ioTHandleData.setMsgId(msgId);
                    ioTHandleData.setRequestCommand(msg.what);

                    mRequestHandleMap.put(ioTHandleData.getDeviceId(), ioTHandleData);
                    sendResultToApplication(clientMessenger, msgId, ioTHandleData.getDeviceId(), msg.what,
                            IoTResultCodes.SUCCESS);
                    // ?... connect  ?  .
                    Message notRespondMsg = new Message();
                    notRespondMsg.what = HANDLER_MESSAGE_CONNECTION_NOT_RESPOND;
                    Bundle extras = new Bundle();
                    extras.putParcelable(IoTServiceCommand.KEY_DATA, ioTHandleData);
                    notRespondMsg.setData(extras);
                    mHandler.sendMessageDelayed(notRespondMsg, CONNECTION_NOT_RESPOND_WAIT_TIME);
                } else {
                    Log.w(TAG, "mBluetoothLeService.connect() return false");
                    sendResultToApplication(clientMessenger, msgId, ioTHandleData.getDeviceId(), msg.what,
                            IoTResultCodes.FAILED);
                }
            }
            break;
        }

        case HANDLER_MESSAGE_CONNECTION_NOT_RESPOND: {
            Log.d(TAG, "HANDLER_MESSAGE_CONNECTION_NOT_RESPOND ...");
            Bundle b = msg.getData();
            b.setClassLoader(IoTHandleData.class.getClassLoader());
            IoTHandleData ioTHandleData = b.getParcelable(IoTServiceCommand.KEY_DATA);
            if (mBluetoothLeService != null) {
                mBluetoothLeService.disconnect(ioTHandleData.getDeviceId());
            }
            mRequestHandleMap.remove(ioTHandleData.getDeviceId());
            Messenger clientMessenger = (mRegisteredAppMessenger == null) ? null : mRegisteredAppMessenger.get();
            sendResultToApplication(clientMessenger, ioTHandleData.getMsgId(), ioTHandleData.getDeviceId(),
                    IoTServiceCommand.DEVICE_CONNECT, IoTResultCodes.DEVICE_CONNECTION_NOT_RESPOND);
            break;
        }

        case IoTServiceCommand.DEVICE_DISCONNECT: {
            Bundle b = msg.getData();
            b.setClassLoader(IoTHandleData.class.getClassLoader());
            IoTHandleData ioTHandleData = b.getParcelable(IoTServiceCommand.KEY_DATA);
            String msgId = b.getString(IoTServiceCommand.KEY_MSGID, "");
            Messenger clientMessenger = (mRegisteredAppMessenger == null) ? null : mRegisteredAppMessenger.get();

            if (ioTHandleData == null) {
                sendResultToApplication(clientMessenger, msgId, null, msg.what, IoTResultCodes.FAILED);
                Log.w(TAG, "case READ_WRITE_SETNOTI : ioTHandleData is null");
                return;
            }

            if (mRequestHandleMap.get(ioTHandleData.getDeviceId()) != null) {
                Log.d(TAG, "Already previous command deviceid = " + ioTHandleData.getDeviceId() + ", command = "
                        + ioTHandleData.getRequestCommand());
                sendResultToApplication(clientMessenger, msgId, ioTHandleData.getDeviceId(), msg.what,
                        IoTResultCodes.FAILED);
                return;
            }

            if (mUseIoTGateway) {
            } else {
                if (mBluetoothLeService == null) {
                    sendResultToApplication(clientMessenger, msgId, ioTHandleData.getDeviceId(), msg.what,
                            IoTResultCodes.FAILED);
                    Log.w(TAG,
                            "case IoTServiceCommand.DEVICE_DISCONNECT : mBluetoothLeService or ioTHandleData is null");
                    return;
                }
                if (ioTHandleData.getDeviceTypeId() != IoTDevice.DEVICE_TYPE_ID_BT) {
                    sendResultToApplication(clientMessenger, msgId, ioTHandleData.getDeviceId(), msg.what,
                            IoTResultCodes.FAILED);
                    Log.w(TAG,
                            "case IoTServiceCommand.DEVICE_DISCONNECT : is not bt device... mUseIoTGateway == false");
                    return;
                }

                if (mConnectedDeviceList.contains(ioTHandleData.getDeviceId())
                        || mKeepAliveConnectionDeviceList.contains(ioTHandleData.getDeviceId())) {
                    ioTHandleData.setMsgId(msgId);
                    ioTHandleData.setRequestCommand(msg.what);

                    mRequestHandleMap.put(ioTHandleData.getDeviceId(), ioTHandleData);
                    sendResultToApplication(clientMessenger, msgId, ioTHandleData.getDeviceId(), msg.what,
                            IoTResultCodes.SUCCESS);
                    mBluetoothLeService.disconnect(ioTHandleData.getDeviceId());
                } else {
                    Log.w(TAG, "mConnectedDeviceList.contains(ioTHandleData.getDeviceId()) is false");
                    sendResultToApplication(clientMessenger, msgId, ioTHandleData.getDeviceId(), msg.what,
                            IoTResultCodes.FAILED);
                }
            }
            break;
        }

        case IoTServiceCommand.DEVICE_READ_DATA:
        case IoTServiceCommand.DEVICE_WRITE_DATA:
        case IoTServiceCommand.DEVICE_SET_NOTIFICATION: {
            Bundle b = msg.getData();
            b.setClassLoader(IoTHandleData.class.getClassLoader());
            IoTHandleData ioTHandleData = b.getParcelable(IoTServiceCommand.KEY_DATA);
            String msgId = b.getString(IoTServiceCommand.KEY_MSGID, "");
            Messenger clientMessenger = (mRegisteredAppMessenger == null) ? null : mRegisteredAppMessenger.get();

            if (ioTHandleData == null) {
                sendResultToApplication(clientMessenger, msgId, null, msg.what, IoTResultCodes.FAILED);
                Log.w(TAG, "case READ_WRITE_SETNOTI : ioTHandleData is null");
                return;
            }

            if (mRequestHandleMap.get(ioTHandleData.getDeviceId()) != null) {
                Log.d(TAG, "Already previous command deviceid = " + ioTHandleData.getDeviceId() + ", command = "
                        + ioTHandleData.getRequestCommand());
                sendResultToApplication(clientMessenger, msgId, ioTHandleData.getDeviceId(), msg.what,
                        IoTResultCodes.FAILED);
                return;
            }

            if (mUseIoTGateway) {
            } else {
                if (mBluetoothLeService == null) {
                    sendResultToApplication(clientMessenger, msgId, ioTHandleData.getDeviceId(), msg.what,
                            IoTResultCodes.FAILED);
                    Log.w(TAG, "case READ_WRITE_SETNOTI : ioTHandleData is null");
                    return;
                }

                if (ioTHandleData.getDeviceTypeId() != IoTDevice.DEVICE_TYPE_ID_BT) {
                    sendResultToApplication(clientMessenger, msgId, ioTHandleData.getDeviceId(), msg.what,
                            IoTResultCodes.FAILED);
                    Log.w(TAG, "case READ_WRITE_SETNOTI : is not bt device... mUseIoTGateway == false");
                    return;
                }

                if (mConnectedDeviceList.contains(ioTHandleData.getDeviceId())
                        || mKeepAliveConnectionDeviceList.contains(ioTHandleData.getDeviceId())) {
                    ioTHandleData.setMsgId(msgId);
                    ioTHandleData.setRequestCommand(msg.what);

                    boolean result = true;
                    switch (msg.what) {
                    case IoTServiceCommand.DEVICE_READ_DATA:
                        result = mBluetoothLeService.readCharacteristic(ioTHandleData.getDeviceId(),
                                ioTHandleData.getServiceUuid(), ioTHandleData.getCharacteristicUuid());
                        break;
                    case IoTServiceCommand.DEVICE_WRITE_DATA:
                        result = mBluetoothLeService.writeRemoteCharacteristic(ioTHandleData.getDeviceId(),
                                ioTHandleData.getServiceUuid(), ioTHandleData.getCharacteristicUuid(),
                                ioTHandleData.getValue());
                        break;
                    case IoTServiceCommand.DEVICE_SET_NOTIFICATION:
                        result = mBluetoothLeService.setCharacteristicNotification(ioTHandleData.getDeviceId(),
                                ioTHandleData.getServiceUuid(), ioTHandleData.getCharacteristicUuid(), true);
                        break;
                    }

                    if (result) {
                        mRequestHandleMap.put(ioTHandleData.getDeviceId(), ioTHandleData);
                        sendResultToApplication(clientMessenger, msgId, ioTHandleData.getDeviceId(), msg.what,
                                IoTResultCodes.SUCCESS);
                    } else {
                        sendResultToApplication(clientMessenger, msgId, ioTHandleData.getDeviceId(), msg.what,
                                IoTResultCodes.FAILED);
                    }
                } else {
                    Log.w(TAG, "mConnectedDeviceList.contains(ioTHandleData.getDeviceId()) is false");
                    sendResultToApplication(clientMessenger, msgId, ioTHandleData.getDeviceId(), msg.what,
                            IoTResultCodes.FAILED);
                }
            }
            break;
        }

        }
    }

    private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {

        @Override
        public void onReceive(Context context, Intent intent) {
            final String action = intent.getAction();
            if (ConnectivityManager.CONNECTIVITY_ACTION.equals(action)) {
                mHandler.sendEmptyMessage(HANDLER_MESSAGE_CONNECTIVITY_CHANGED);
            } else if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) {
                int btState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1);
                if (btState == BluetoothAdapter.STATE_OFF || btState == BluetoothAdapter.STATE_ON) {
                    Message msg = mHandler.obtainMessage(HANDLER_MESSAGE_BT_STATE_CHANGED, btState, 0);
                    mHandler.sendMessage(msg);
                }
            }
            /**
             * Bluetooth control.
             */
            else if (BluetoothLeService.ACTION_DEVICE_LIST.equals(action)) {
                Message notiMessage = new Message();
                notiMessage.what = IoTServiceCommand.DEVICE_LIST_NOTIFICATION;

                Bundle recvBundle = intent.getExtras();
                recvBundle.setClassLoader(IoTDevice.class.getClassLoader());
                HashMap<String, IoTDevice> devices = (HashMap<String, IoTDevice>) recvBundle
                        .getSerializable(IoTServiceCommand.KEY_DATA);
                if (recvBundle != null && devices != null) {
                    // ?? Bundle ? request command (int) result code (serializable)  ?.
                    Bundle b = new Bundle();
                    b.putString(IoTServiceCommand.KEY_MSGID, getPackageName() + "_" + System.currentTimeMillis());
                    b.putSerializable(IoTServiceCommand.KEY_DATA, devices);
                    notiMessage.setData(b);

                    sendNotificationToApplication(notiMessage);
                }
            }
            /**
             * when using bluetooth
             */
            else if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action)) {
                Log.d(TAG, "ACTION_GATT_CONNECTED received. Attempt to serviceDiscovery()");
                mHandler.removeMessages(HANDLER_MESSAGE_CONNECTION_NOT_RESPOND);
                if (mBluetoothLeService != null) {
                    Bundle b = intent.getExtras();
                    if (b == null) {
                        Log.w(TAG, "Bundle is not found!!");
                        return;
                    }

                    String address = b.getString(IoTServiceCommand.KEY_DEVICE_UUID, "");
                    if (StringUtils.isEmptyString(address)) {
                        Log.w(TAG, "Unknown address information... close it. ");
                        mBluetoothLeService.disconnect(address);
                        return;
                    }

                    IoTHandleData ioTHandleData = mRequestHandleMap.get(address);
                    //   ?  ?  .
                    if (ioTHandleData == null || !address.equals(ioTHandleData.getDeviceId())) {
                        Log.d(TAG, "Is not equal to mRequestHandleData..");
                        mBluetoothLeService.disconnect(address);
                        return;
                    }

                    if (ioTHandleData.isKeepAliveDevice()) {
                        for (int i = 0; i < mKeepAliveConnectionDeviceList.size(); i++) {
                            Log.d(TAG, ">> mKeepAliveConnectionDeviceList[" + i + "] = "
                                    + mKeepAliveConnectionDeviceList.get(i));
                        }

                        if (!mKeepAliveConnectionDeviceList.contains(address)) {
                            mKeepAliveConnectionDeviceList.add(address);
                            Log.d(TAG, address + " address is added to mKeepAliveConnectionDeviceList");
                        }
                    } else {
                        for (int i = 0; i < mConnectedDeviceList.size(); i++) {
                            Log.d(TAG, ">> mConnectedDeviceList[" + i + "] = " + mConnectedDeviceList.get(i));
                        }

                        if (!mConnectedDeviceList.contains(address)) {
                            mConnectedDeviceList.add(address);
                            Log.d(TAG, address + " address is added to mConnectedDeviceList");
                        }
                    }
                    mBluetoothLeService.discoveryServices(address);
                }
            } else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action)) {
                Log.d(TAG, "ACTION_GATT_DISCONNECTED received.");
                mHandler.removeMessages(HANDLER_MESSAGE_CONNECTION_NOT_RESPOND);
                Bundle b = intent.getExtras();
                if (b == null) {
                    Log.w(TAG, "Bundle is not found!!");
                    return;
                }

                String address = b.getString(IoTServiceCommand.KEY_DEVICE_UUID, "");
                if (StringUtils.isEmptyString(address)) {
                    Log.w(TAG, "Unknown address information.... ");
                    return;
                }

                // send to IoT interface module
                Message msg = new Message();
                msg.what = IoTServiceCommand.DEVICE_DISCONNECTED;
                Bundle extras = new Bundle();
                extras.putString(IoTServiceCommand.KEY_DEVICE_UUID, address);
                msg.setData(extras);

                //  ..
                mBluetoothLeService.close(address);

                if (mIsDisconnectAllState && mConnectedDeviceList.contains(address)) {
                    mConnectedDeviceList.remove(address);
                    if (mConnectedDeviceList.size() > 0) {
                        mBluetoothLeService.disconnect(mConnectedDeviceList.get(0));
                    } else {
                        Messenger clientMessenger = (mRegisteredAppMessenger == null) ? null
                                : mRegisteredAppMessenger.get();
                        if (clientMessenger != null) {
                            sendResultToApplication(clientMessenger,
                                    IoTServiceCommand.generateMessageId(IoTService.this), address,
                                    IoTServiceCommand.DEVICE_DISCONNECT_ALL, IoTResultCodes.SUCCESS);
                        }
                        mIsDisconnectAllState = false;
                    }
                    return;
                }

                IoTHandleData ioTHandleData = mRequestHandleMap.get(address);
                if (ioTHandleData == null || !address.equals(ioTHandleData.getDeviceId())) {
                    // send to all
                    sendNotificationToApplication(msg);
                    mConnectedDeviceList.remove(address);
                    mKeepAliveConnectionDeviceList.remove(address);
                } else {
                    if (ioTHandleData.isKeepAliveDevice()) {
                        mKeepAliveConnectionDeviceList.remove(address);
                        for (int i = 0; i < mKeepAliveConnectionDeviceList.size(); i++) {
                            Log.d(TAG, ">> mKeepAliveConnectionDeviceList[" + i + "] = "
                                    + mKeepAliveConnectionDeviceList.get(i));
                        }
                    } else {
                        mConnectedDeviceList.remove(address);
                        for (int i = 0; i < mConnectedDeviceList.size(); i++) {
                            Log.d(TAG, ">> mConnectedDeviceList[" + i + "] = " + mConnectedDeviceList.get(i));
                        }
                    }
                    // ? ? ? .
                    if (ioTHandleData.getRequestCommand() != IoTServiceCommand.DEVICE_DISCONNECT) {
                        //  ?? ?? .. disconnect    ?.(?.. connect ?...)
                        // ? ? ???? ? ?? ? ? ?  ?.
                        Log.w(TAG, address + " device connection is closed...");
                    }
                    sendNotificationToApplication(msg);
                    mRequestHandleMap.remove(address);
                }
            } else if (BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED.equals(action)) {
                Log.d(TAG, "ACTION_GATT_SERVICES_DISCOVERED received.");
                Bundle b = intent.getExtras();
                if (b == null) {
                    Log.w(TAG, "Bundle is not found!!");
                    return;
                }

                String address = b.getString(IoTServiceCommand.KEY_DEVICE_UUID, "");
                if (StringUtils.isEmptyString(address) || (!mConnectedDeviceList.contains(address)
                        && !mKeepAliveConnectionDeviceList.contains(address))) {
                    Log.w(TAG, "Unknown address information... close it. ");
                    mBluetoothLeService.disconnect(address);
                    return;
                }

                IoTHandleData ioTHandleData = mRequestHandleMap.get(address);
                // ? ? ? .
                //   ?  ?  .
                if (ioTHandleData == null || !address.equals(ioTHandleData.getDeviceId())) {
                    Log.d(TAG, "Is not equal to mRequestHandleData..");
                    mBluetoothLeService.disconnect(address);
                    return;
                }

                // ?  connect ? ?.
                //  disconnect  ? ?.
                if (ioTHandleData.getRequestCommand() != IoTServiceCommand.DEVICE_CONNECT) {
                    if (StringUtils.isEmptyString(address) || (!mConnectedDeviceList.contains(address)
                            && !mKeepAliveConnectionDeviceList.contains(address))) {
                        Log.w(TAG, "Unknown address information... close it. ");
                        mBluetoothLeService.disconnect(address);
                        mRequestHandleMap.remove(address);
                        return;
                    }
                }

                b.setClassLoader(ArrayList.class.getClassLoader());
                HashMap<String, ArrayList<String>> discoveredServices = (HashMap<String, ArrayList<String>>) b
                        .getSerializable(IoTServiceCommand.KEY_DATA);
                //device.setDiscoveredServices(discoveredServices);

                // send to IoT interface module
                Message msg = new Message();
                msg.what = IoTServiceCommand.DEVICE_CONNECTED;
                Bundle extras = new Bundle();
                extras.putString(IoTServiceCommand.KEY_DEVICE_UUID, ioTHandleData.getDeviceId());
                extras.putSerializable(IoTServiceCommand.KEY_DATA, discoveredServices);
                msg.setData(extras);

                sendNotificationToApplication(msg);
                mRequestHandleMap.remove(address);
            } else if (BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action)) {
                //Log.d(TAG, "ACTION_DATA_AVAILABLE received.");
                intent.setExtrasClassLoader(IoTHandleData.class.getClassLoader());
                IoTHandleData resultData = intent.getParcelableExtra(IoTServiceCommand.KEY_DATA);

                Message msg = new Message();
                msg.what = IoTServiceCommand.DEVICE_NOTIFICATION_DATA;
                Bundle extras = new Bundle();
                extras.putString(IoTServiceCommand.KEY_DEVICE_UUID, resultData.getDeviceId());
                if (resultData == null) {
                    Log.w(TAG, "result data not found");
                    extras.putSerializable(IoTServiceCommand.KEY_RESULT, IoTResultCodes.FAILED);
                } else {
                    if (resultData.getStatus() == IoTHandleData.STATUS_SUCCESS) {
                        extras.putSerializable(IoTServiceCommand.KEY_RESULT, IoTResultCodes.SUCCESS);
                        extras.putParcelable(IoTServiceCommand.KEY_DATA, resultData);
                    } else {
                        extras.putSerializable(IoTServiceCommand.KEY_RESULT, IoTResultCodes.FAILED);
                    }
                }
                msg.setData(extras);
                sendNotificationToApplication(msg);
            } else if (BluetoothLeService.ACTION_GATT_DESCRIPTOR_WRITE_SUCCESS.equals(action)) {
                Log.d(TAG, "ACTION_GATT_DESCRIPTOR_WRITE_SUCCESS received.");
                intent.setExtrasClassLoader(IoTHandleData.class.getClassLoader());
                IoTHandleData resultData = intent.getParcelableExtra(IoTServiceCommand.KEY_DATA);

                IoTHandleData ioTHandleData = mRequestHandleMap.get(resultData.getDeviceId());
                if (ioTHandleData == null) {
                    Log.w(TAG, "??? Really sent command = " + resultData.getDeviceId());
                } else {
                    Message msg = new Message();
                    msg.what = IoTServiceCommand.DEVICE_SET_NOTIFICATION_RESULT;
                    Bundle extras = new Bundle();
                    extras.putString(IoTServiceCommand.KEY_DEVICE_UUID, ioTHandleData.getDeviceId());
                    if (resultData == null) {
                        Log.w(TAG, "result data not found");
                        extras.putSerializable(IoTServiceCommand.KEY_RESULT, IoTResultCodes.FAILED);
                    } else {
                        if (resultData.getStatus() == IoTHandleData.STATUS_SUCCESS) {
                            extras.putSerializable(IoTServiceCommand.KEY_RESULT, IoTResultCodes.SUCCESS);
                            extras.putParcelable(IoTServiceCommand.KEY_DATA, resultData);
                        } else {
                            extras.putSerializable(IoTServiceCommand.KEY_RESULT, IoTResultCodes.FAILED);
                        }
                    }
                    msg.setData(extras);
                    sendNotificationToApplication(msg);
                }
                mRequestHandleMap.remove(resultData.getDeviceId());
            } else if (BluetoothLeService.ACTION_GATT_CHARACTERISTIC_WRITE_SUCCESS.equals(action)
                    || BluetoothLeService.ACTION_GATT_CHARACTERISTIC_READ_SUCCESS.equals(action)) {
                Log.d(TAG, "ACTION_GATT_CHARACTERISTIC_WRITE_or_READ_SUCCESS received.");
                intent.setExtrasClassLoader(IoTHandleData.class.getClassLoader());
                IoTHandleData resultData = intent.getParcelableExtra(IoTServiceCommand.KEY_DATA);

                IoTHandleData ioTHandleData = mRequestHandleMap.get(resultData.getDeviceId());
                if (ioTHandleData == null) {
                    Log.w(TAG, "??? Really sent command = " + resultData.getDeviceId());
                } else {
                    Message msg = new Message();
                    if (BluetoothLeService.ACTION_GATT_CHARACTERISTIC_WRITE_SUCCESS.equals(action)) {
                        msg.what = IoTServiceCommand.DEVICE_WRITE_DATA_RESULT;
                    } else {
                        msg.what = IoTServiceCommand.DEVICE_READ_DATA_RESULT;
                    }
                    Bundle extras = new Bundle();
                    extras.putString(IoTServiceCommand.KEY_DEVICE_UUID, ioTHandleData.getDeviceId());
                    if (resultData == null) {
                        Log.w(TAG, "result data not found");
                        extras.putSerializable(IoTServiceCommand.KEY_RESULT, IoTResultCodes.FAILED);
                    } else {
                        if (resultData.getStatus() == IoTHandleData.STATUS_SUCCESS) {
                            extras.putSerializable(IoTServiceCommand.KEY_RESULT, IoTResultCodes.SUCCESS);
                            extras.putParcelable(IoTServiceCommand.KEY_DATA, resultData);
                        } else {
                            extras.putSerializable(IoTServiceCommand.KEY_RESULT, IoTResultCodes.FAILED);
                        }
                    }
                    msg.setData(extras);
                    sendNotificationToApplication(msg);
                }
                mRequestHandleMap.remove(resultData.getDeviceId());
            }
        }

    };

    // Code to manage Service lifecycle.
    private final ServiceConnection mBluetoothServiceConnection = new ServiceConnection() {

        @Override
        public void onServiceConnected(ComponentName componentName, IBinder service) {
            Log.d(TAG, "mBluetoothServiceConnection onServiceConnected()");
            mBluetoothLeService = ((BluetoothLeService.LocalBinder) service).getService();

            mErrorCodes = mBluetoothLeService.initialize();
            if (!mErrorCodes.equals(IoTResultCodes.SUCCESS)) {
                Log.e(TAG, "Unable to initialize Bluetooth");
                //finish();
                mServiceStatus = IoTServiceStatus.STOPPED;
                return;
            }
            mServiceStatus = IoTServiceStatus.RUNNING;
            mErrorCodes = IoTResultCodes.SUCCESS;

            sendServiceStatusNotification();

            // start bluetooth scan.. periodically
            //mBluetoothLeService.scanLeDevicePeriodically(true);
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            Log.d(TAG, "mBluetoothServiceConnection onServiceDisconnected()");
            mBluetoothLeService = null;
            mServiceStatus = IoTServiceStatus.STOPPED;

            if (mLastConnectionStatus) {
                mErrorCodes = IoTResultCodes.SERVICE_DISCONNECTED;
            } else {
                // ??
            }

            sendServiceStatusNotification();
        }
    };

    @Override
    public void onCreate() {
        Log.i(TAG, "debug: Creating service");
        sendBroadcast(new Intent(IoTConstants.ACTION_SERVICE_CREATE_BROADCAST));
        /**
         * Target we publish for clients to send messages to IncomingHandler.Note
         * that calls to its binder are sequential!
         */
        mServiceMessenger = new Messenger(mHandler);

        mUseIoTGateway = IoTServicePreference.isUseIoTGateway(this);
        if (mUseIoTGateway) {
            Log.d(TAG, ">> Use IoT Gateway....");
            // Create the Wifi lock (this does not acquire the lock, this just creates it)
            mWifiLock = ((WifiManager) getSystemService(Context.WIFI_SERVICE))
                    .createWifiLock(WifiManager.WIFI_MODE_FULL, IoTService.class.getSimpleName() + "_lock");

            // check network status
            IntentFilter intentFilter = new IntentFilter();
            intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
            registerReceiver(mBroadcastReceiver, intentFilter);

            mLastConnectionStatus = NetworkUtils.isConnected(this);

            // TODO : connect to iot gateway
            if (mThreadPooledServer != null) {
                mThreadPooledServer.stop(false);
            }
            mThreadPooledServer = new ThreadPooledServer(mServiceMessenger, IoTConstants.IOT_GATEWAY_SERVER_PORT,
                    IoTConstants.IOT_GATEWAY_SERVER_THREAD_POOL_SIZE);
            new Thread(mThreadPooledServer).start();
        } else {
            Log.d(TAG, ">> Use internal blutooth....");
            // check bluetooth status
            IntentFilter intentFilter = new IntentFilter();
            intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
            registerReceiver(mBroadcastReceiver, intentFilter);

            // bluetooth local broadcast
            intentFilter = makeGattUpdateIntentFilter();
            LocalBroadcastManager.getInstance(this).registerReceiver(mBroadcastReceiver, intentFilter);

            // connect to ble service
            mErrorCodes = checkBluetoothEnabled();
            if (mErrorCodes.equals(IoTResultCodes.SUCCESS)) {
                try {
                    if (mBluetoothServiceConnection != null) {
                        unbindService(mBluetoothServiceConnection);
                    }
                } catch (Exception e) {

                }
                final Intent gattServiceIntent = new Intent(this, BluetoothLeService.class);
                bindService(gattServiceIntent, mBluetoothServiceConnection, BIND_AUTO_CREATE);
            } else {
                mServiceStatus = IoTServiceStatus.STOPPED;
                Log.d(TAG, "Internal bluetooth error = " + mErrorCodes);
            }
        }
    }

    private static IntentFilter makeGattUpdateIntentFilter() {
        final IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(BluetoothLeService.ACTION_DEVICE_LIST);
        intentFilter.addAction(BluetoothLeService.ACTION_GATT_CONNECTED);
        intentFilter.addAction(BluetoothLeService.ACTION_GATT_DISCONNECTED);
        intentFilter.addAction(BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED);
        intentFilter.addAction(BluetoothLeService.ACTION_DATA_AVAILABLE);
        intentFilter.addAction(BluetoothLeService.ACTION_GATT_DESCRIPTOR_WRITE_SUCCESS);
        intentFilter.addAction(BluetoothLeService.ACTION_GATT_CHARACTERISTIC_WRITE_SUCCESS);
        intentFilter.addAction(BluetoothLeService.ACTION_GATT_CHARACTERISTIC_WRITE_SUCCESS);
        return intentFilter;
    }

    /**
     * Called by the system to notify a Service that it is no longer used and is being removed.  The
     * service should clean up any resources it holds (threads, registered
     * receivers, etc) at this point.  Upon return, there will be no more calls
     * in to this Service object and it is effectively dead.  Do not call this method directly.
     */
    @Override
    public void onDestroy() {
        super.onDestroy();
        // we can also release the Wifi lock, if we're holding it
        if (mWifiLock != null && mWifiLock.isHeld())
            mWifiLock.release();
        mWifiLock = null;
        try {
            unregisterReceiver(mBroadcastReceiver);
            LocalBroadcastManager.getInstance(this).unregisterReceiver(mBroadcastReceiver);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Called when we receive an Intent. When we receive an intent sent to us via startService(),
     * this is the method that gets called. So here we react appropriately depending on the
     * Intent's action, which specifies what is being requested of us.
     */

    private static int num = 0;

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d(TAG, "onStartCommand in service ...");
        /**
         * ? ??? .
         */
        return Service.START_STICKY;//super.onStartCommand(intent, flags, startId);
    }

    @Override
    public IBinder onBind(Intent intent) {
        Log.d(TAG, "Binding to service ...");
        return mServiceMessenger.getBinder();
    }

    /**
     * ??  ? ,  enable  ? ? ?? .
     */
    public IoTResultCodes checkBluetoothEnabled() {
        // Use this check to determine whether BLE is supported on the device.  Then you can
        // selectively disable BLE-related features.
        if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
            return IoTResultCodes.BLE_NOT_SUPPORTED;
        }

        // Initializes a Bluetooth adapter.  For API level 18 and above, get a reference to
        // BluetoothAdapter through BluetoothManager.
        final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
        final BluetoothAdapter bluetoothAdapter = bluetoothManager.getAdapter();

        // Checks if Bluetooth is supported on the device.
        if (bluetoothAdapter == null) {
            return IoTResultCodes.BLUETOOTH_NOT_SUPPORTED;
        }

        // Ensures Bluetooth is enabled on the device.  If Bluetooth is not currently enabled,
        // fire an intent to display a dialog asking the user to grant permission to enable it.
        if (!bluetoothAdapter.isEnabled()) {
            return IoTResultCodes.BLUETOOTH_NOT_ENABLED;
        }

        mLastConnectionStatus = true;
        return IoTResultCodes.SUCCESS;
    }

    /**
     *  ??  ? ? .
     */
    private void sendServiceStatusNotification() {
        if (PackageUtils.isActivePackage(this, getApplicationContext().getPackageName() + ":remote")) {
            Log.d(TAG, "Remote process(RealtimeBroadcast..) is running...");
            return;
        }
        Messenger clientMessenger = (mRegisteredAppMessenger == null) ? null : mRegisteredAppMessenger.get();
        if (clientMessenger != null) {
            Message response = new Message();
            response.what = IoTServiceCommand.SERVICE_STATUS_NOTIFICATION;

            // ?? Bundle ? request command (int) result code (serializable)  ?.
            Bundle b = new Bundle();
            b.putString(IoTServiceCommand.KEY_MSGID,
                    /*this.getApplicationContext().*/getPackageName() + "_" + System.currentTimeMillis());
            b.putSerializable(IoTServiceCommand.KEY_SERVICE_STATUS, mServiceStatus);
            b.putSerializable(IoTServiceCommand.KEY_SERVICE_STATUS_CODE, mErrorCodes);
            response.setData(b);

            try {
                clientMessenger.send(response);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * ??  Request?   .
     * ? Async ? ? ? ? ? ? ?  ??   .
     *
     * @param clientMessenger
     * @param msgId
     * @param command
     * @param result
     */
    private void sendResultToApplication(Messenger clientMessenger, String msgId, String deviceId, int command,
            IoTResultCodes result) {
        if (clientMessenger != null) {
            Message response = new Message();
            response.what = IoTServiceCommand.COMMAND_RESPONSE;

            // ?? Bundle ? request command (int) result code (serializable)  ?.
            Bundle b = new Bundle();
            b.putString(IoTServiceCommand.KEY_MSGID, msgId);
            b.putInt(IoTServiceCommand.KEY_CMD, command);
            b.putString(IoTServiceCommand.KEY_DEVICE_UUID, deviceId);
            b.putSerializable(IoTServiceCommand.KEY_RESULT, result);
            response.setData(b);

            try {
                clientMessenger.send(response);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    }

    private void sendNotificationToApplication(Message message) {
        Messenger clientMessenger = (mRegisteredAppMessenger == null) ? null : mRegisteredAppMessenger.get();
        if (clientMessenger != null) {
            if (clientMessenger != null) {
                try {
                    clientMessenger.send(message);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}