com.umundus.service.NCallServiceOld.java Source code

Java tutorial

Introduction

Here is the source code for com.umundus.service.NCallServiceOld.java

Source

/*
 * Copyright (C) 2013 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.umundus.service;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Calendar;
import java.util.List;
import java.util.UUID;

import android.app.AlarmManager;
import android.app.Instrumentation;
import android.app.Notification;
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.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.BitmapFactory;
import android.os.Binder;
import android.os.IBinder;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import android.view.KeyEvent;
import com.umundus.javable.R;
import com.umundus.javable.R.drawable;

/**
 * Service for managing connection and data communication with a GATT server hosted on a
 * given Bluetooth LE device.
 */
public class NCallServiceOld extends Service {
    private final static String TAG = "BLESVC_TAG";

    private BluetoothManager mBluetoothManager;
    private BluetoothAdapter mBluetoothAdapter;
    private String mBluetoothDeviceAddress;
    private BluetoothGatt mBluetoothGatt;
    private int mConnectionState = STATE_DISCONNECTED;

    private static final int STATE_DISCONNECTED = 0;
    private static final int STATE_CONNECTING = 1;
    private static final int STATE_CONNECTED = 2;
    private final static int STATE_DISCOVERED = 3; // indicates that services were discovered
    private final static int STATE_DISCONNECTING = 4;
    private final static int STATE_CLOSED = 5;

    public final static String ACTION_GATT_CONNECTED = "com.umundus.javable.ACTION_GATT_CONNECTED";
    public final static String ACTION_GATT_DISCONNECTED = "com.umundus.javable.ACTION_GATT_DISCONNECTED";
    public final static String ACTION_GATT_SERVICES_DISCOVERED = "com.umundus.javable.ACTION_GATT_SERVICES_DISCOVERED";
    public final static String ACTION_DATA_AVAILABLE = "com.umundus.javable.ACTION_DATA_AVAILABLE";
    public final static String EXTRA_DATA = "com.umundus.javable.EXTRA_DATA";
    public final static String DEVICE_DOES_NOT_SUPPORT_SRC = "com.umundus.javable.DEVICE_DOES_NOT_SUPPORT_SRC";
    public final static String PROGRESS_SET_VISIBLE = "com.umundus.javable.PROGRESS_SET_VISIBLE";
    public final static String PROGRESS_SET_INVISIBLE = "com.umundus.javable.PROGRESS_SET_INVISIBLE";

    public final static String BATTERY_VALUE = "com.umundus.javable.BATTERY_VALUE";
    public final static String KEY_INPUT_DATA = "com.umundus.javable.KEY_INPUT_DATA";
    public final static String LED_INPUT_DATA = "com.umundus.javable.LED_INPUT_DATA";
    public final static String VERSION_INPUT_DATA = "com.umundus.javable.VERSION_INPUT_DATA";
    public final static String SCENARIO_STATUS_DATA = "com.umundus.javable.SCENARIO_STATUS_DATA";
    public final static String RSSI_VALUE = "com.umundus.javable.RSSI_VALUE";
    public final static String MANUFACTURER_NAME = "com.umundus.javable.MANUFACTURER_NAME";
    public final static String MODEL_NAME = "com.umundus.javable.MODEL_NAME";
    public final static String FIRMWARE_REVISON = "com.umundus.javable.FIRMWARE_REVISON";
    public final static String HARDWARE_REVISON = "com.umundus.javable.HARDWARE_REVISON";

    public Object mLock = new Object();

    public final static String ACTION_LED_TELEPHONE = "com.umundus.javable.MODEINCALL";
    public final static String ACTION_LED_SMS = "android.provider.Telephony.SMS_RECEIVED";
    public final static String ACTION_LED_KAKAOTALK = "com.kakao.talk";

    public static final UUID CCCD = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");
    public static final UUID DEVICE_INFOMATION_SERVICE = UUID.fromString("0000180a-0000-1000-8000-00805f9b34fb");
    public static final UUID MANUFACTURER_NAME_UUID = UUID.fromString("00002a29-0000-1000-8000-00805f9b34fb");
    public static final UUID MODEL_NAME_UUID = UUID.fromString("00002a24-0000-1000-8000-00805f9b34fb");
    public static final UUID FIRMWARE_REVISON_UUID = UUID.fromString("00002a26-0000-1000-8000-00805f9b34fb");
    public static final UUID HARDWARE_REVISON_UUID = UUID.fromString("00002a27-0000-1000-8000-00805f9b34fb");

    public static final UUID BATTERY_SERVICE = UUID.fromString("0000180F-0000-1000-8000-00805f9b34fb");
    public static final UUID BATTERY_CHARACTERISTIC = UUID.fromString("00002A19-0000-1000-8000-00805f9b34fb");

    public static final UUID NCALL_REMOCON_SERVICE = UUID.fromString("6e407aa1-b5a3-f393-e0a9-e50e24dcca9e");
    public static final UUID NCALL_REMOCON_SEND_DATA_CHARACTERISTIC = UUID
            .fromString("6e407aa2-b5a3-f393-e0a9-e50e24dcca9e");
    public static final UUID NCALL_REMOCON_KEY_NOTI_CHARACTERISTIC = UUID
            .fromString("6e407aa3-b5a3-f393-e0a9-e50e24dcca9e");
    public static final UUID NCALL_REMOCON_SEND_PATTERN_CHARACTERISTIC = UUID
            .fromString("6e407aa4-b5a3-f393-e0a9-e50e24dcca9e");

    private final static int RESPONSE_PATRERN_DATA_WRITE_ERROR = 255;
    private final static int RESPONSE_PATRERN_DATA_WRITE_START = 0;
    private final static int RESPONSE_PATRERN_DATA_WRITE_END = 2;

    private final static int MAX_PACKET_SIZE = 20;
    private byte[] mBuffer = new byte[MAX_PACKET_SIZE];
    private InputStream mInputStream = null;
    private int mImageSizeInBytes;
    private int mBytesSent = 0;
    private int patternCount = 0;
    private boolean batteryflag = false;
    private boolean patternflag = false;

    private boolean mRequestCompleted = false;

    private boolean mPatternSendFaild = false; //   ? ? true .
    byte[] pattern1024 = null;

    //MODE
    public static int MODE_LED_OFF = 10;
    public static int MODE_CLOCK = 11;
    public static int MODE_PATTERN = 12;
    public static int MODE_MISSED_CALL_SMS = 13;

    int[] userPattern1 = { 0x80000000, 0x04004003, 0x04008006, 0x0401000C, 0x04020018, 0x04040030, 0x04080060,
            0x041000C0, 0x04200180, 0x04400300, 0x04800600, 0x04001C00, 0x04002801, 0xFFFFFFFF };

    int[] userPattern2 = { 0x80000000, 0x02002000, 0x05006000, 0x0500E000, 0x0501E000, 0x0503E000, 0x0507E000,
            0x050FE000, 0x051FE000, 0x0A3FE000, 0x027FC000, 0x02FF8000, 0x02FF1000, 0x02FE3000, 0x02FC7000,
            0x02F8F000, 0x02F1F000, 0x02E3F000, 0x02C7F000, 0x028FF000, 0x021FF000, 0x023FE000, 0x027FC000,
            0x02FF8000, 0x02000000, 0x02FF1000, 0x02000000, 0x02FE3000, 0x02000000, 0x02FC7000, 0x02000000,
            0x02F8F000, 0x02000000, 0x02F1F000, 0x02000000, 0x02E3F000, 0x02000000, 0x02C7F000, 0x02000000,
            0x028FF000, 0x02000000, 0x021FF000, 0x02000000, 0xFFFFFFFF };

    int[] defaultPattern1 = { // 
            0x80000000, 0x0A0004F9, 0x0A000020, 0x04050020, 0x040D8020, 0x041DC020, 0x043DE020, 0x047DF020,
            0x0A000020, 0x0A7DF020, 0x0A000020, 0x0A7DF020, 0xFFFFFFFF };

    int[] defaultPattern2 = { //
            0x80000000, 0x04421202, 0x04421306, 0x0442138E, 0x0A421000, 0xFFFFFFFF };

    int[] defaultPattern3 = { //?~
            0x80000000, 0x14401000, 0x04421000, 0x0A431000, 0xFFFFFFFF };

    int[] defaultPattern4 = { //
            0x80000000, 0x0A020202, 0x0A000202, 0xFFFFFFFF };

    int[] defaultPattern5 = { //
            0x80000000, 0x0A421000, 0x0A020000, 0xFFFFFFFF };

    int[] defaultPattern6 = { //?
            0x80000000, 0x0A5FD000, 0x0A5FC000, 0xFFFFFFFF };

    int[] defaultPattern7 = { //
            0x80000000, 0x015FD000, 0x01401000, 0xFFFFFFFF };

    int[] defaultPattern8 = { //? 
            0x80000000, 0x0A421000, 0x0A471000, 0x0A4F9000, 0x0A000000, 0x0A4F9000, 0x0A000000, 0x0A4F9000,
            0x0A000000, 0xFFFFFFFF };

    int[] defaultPattern9 = { //
            0x80000000, 0x284F9010, 0x04401000, 0x044F9010, 0x04401000, 0x044F9010, 0x04401000, 0xFFFFFFFF };

    int[] defaultPattern10 = { //
            0x80000000, 0x28421000, 0x28000000, 0xFFFFFFFF };

    int[] defaultPattern11 = { //??
            0x80000000, 0x0A000471, 0x0A104471, 0xFFFFFFFF };

    int[] defaultPattern12 = { //
            0x80000000, 0x0A439000, 0x0A000000, 0x0A439000, 0x0A000000, 0x04100000, 0x04300000, 0x04700000,
            0x04F00000, 0x04F01000, 0x04F03000, 0x04F07000, 0x04000000, 0x04004000, 0x04006000, 0x04007000,
            0x04807000, 0x04C07000, 0x04E07000, 0x04F07000, 0x04000000, 0x04100000, 0x04300000, 0x04700000,
            0x04F00000, 0x04F01000, 0x04F03000, 0x04F07000, 0x04000000, 0x04004000, 0x04006000, 0x04007000,
            0x04807000, 0x04C07000, 0x04E07000, 0x04F07000, 0xFFFFFFFF };

    int[] defaultPattern13 = { //?
            0x80000000, 0x14421000, 0x04272000, 0x04252000, 0x04272000, 0x04252000, 0x04272000, 0x04252000,
            0x04272000, 0x04252000, 0x04272000, 0x04252000, 0x04272000, 0xFFFFFFFF };
    int[] defaultPattern14 = { //
            0x80000000, 0x04104000, 0x0438E000, 0x047DF000, 0x04FFF000, 0x0A000000, 0x047DF000, 0x0438E000,
            0x04104000, 0x04000000, 0xFFFFFFFF };
    int[] defaultPattern15 = { //?
            0x80000000, 0x0A471000, 0x0A000000, 0x0A471000, 0x0A000000, 0x0A020000, 0x0A421000, 0x04222000,
            0x04124000, 0x040A8000, 0x04070000, 0x0A471000, 0x04272000, 0x04174000, 0x040F8000, 0x0A4F9000,
            0x042FA000, 0x041FC000, 0x0A5FD000, 0x043FE000, 0x0A7FF000, 0x043FE000, 0x147FF000, 0x0A3FE000,
            0x0A1FC000, 0x0A0F8000, 0x0A070000, 0x0A020000, 0x0A000000, 0xFFFFFFFF };
    int[] defaultPattern16 = { //
            0x80000000, 0x0A421000, 0x0A000000, 0x0A421000, 0x0A000000, 0x0AFFF000, 0x0A000000, 0x0AFFF000,
            0x0A000000, 0x0AFFF000, 0x017FF000, 0x017FE000, 0x017FC000, 0x017F8000, 0x017F0000, 0x017E0000,
            0x0A000000, 0x0A7E0000, 0x0A000000, 0x0A7E0000, 0x0A000000, 0x0A7E0000, 0x14000000, 0xFFFFFFFF };
    int[] defaultPattern17 = { //?+
            0x80000000, 0x0A4F9000, 0x0A0D8000, 0x0A4F9000, 0x0A0D8000, 0x0AFFF000, 0x0A000000, 0x0AFFF000,
            0x0A000000, 0x0AFFF000, 0x147FF000, 0x143FE000, 0x141FC000, 0x140F8000, 0x14070000, 0x14020000,
            0x14000000, 0x14000000, 0xFFFFFFFF };
    int[] defaultPattern18 = { //??
            0x80000000, 0x02800000, 0x02000000, 0x02001000, 0x02000000, 0x02002000, 0x02000000, 0x02004000,
            0x02000000, 0x02008000, 0x02000000, 0x02010000, 0x02000000, 0x02020000, 0x02000000, 0x02040000,
            0x02000000, 0x02080000, 0x02000000, 0x02100000, 0x02000000, 0x02200000, 0x02000000, 0x02400000,
            0xFFFFFFFF };
    int[] defaultPattern19 = { //?
            0x80000000, 0x02800000, 0x02000000, 0x02002000, 0x02000000, 0x02004000, 0x02000000, 0x02008000,
            0x02000000, 0x02010000, 0x02000000, 0x02020000, 0x02000000, 0x02040000, 0x02000000, 0x02080000,
            0x02000000, 0x02100000, 0x02000000, 0x02200000, 0x02000000, 0x02400000, 0x02000000, 0x02800000,
            0x02000000, 0x02400000, 0x02000000, 0x02200000, 0x02000000, 0x02100000, 0x02000000, 0x02080000,
            0x02000000, 0x02040000, 0x02000000, 0x02020000, 0x02000000, 0x02010000, 0x02000000, 0x02008000,
            0x02000000, 0x02004000, 0x02000000, 0x02002000, 0x02000000, 0xFFFFFFFF };
    int[] defaultPattern20 = { //
            0x80000000, 0x02002000, 0x05006000, 0x0500E000, 0x0501E000, 0x0503E000, 0x0507E000, 0x050FE000,
            0x051FE000, 0x0A3FE000, 0x027FC000, 0x02FF8000, 0x02FF1000, 0x02FE3000, 0x02FC7000, 0x02F8F000,
            0x02F1F000, 0x02E3F000, 0x02C7F000, 0x028FF000, 0x021FF000, 0x023FE000, 0x021FE000, 0x020FE000,
            0x027FC000, 0x02FF8000, 0x02000000, 0x02FF1000, 0x02000000, 0x02FE3000, 0x02000000, 0x02FC7000,
            0x02000000, 0x02F8F000, 0x02000000, 0x02F1F000, 0x02000000, 0x02E3F000, 0x02000000, 0x02C7F000,
            0x02000000, 0x028FF000, 0x02000000, 0x021FF000, 0x02000000, 0xFFFFFFFF };
    int[] defaultPattern21 = { // 
            0x80000000, 0x0A000082, 0x0A000186, 0x0A00038E, 0x04000000, 0x0A000208, 0x0A00030C, 0x0A00038E,
            0x04000000, 0xFFFFFFFF };
    int[] defaultPattern22 = { //
            0x80000000, 0x04001000, 0x04003000, 0x04007000, 0x0400F000, 0x0401F000, 0x0403F000, 0x0407F000,
            0x040FF000, 0x041FF000, 0x043FF000, 0x047FF000, 0x04FFF000, 0x0A000000, 0xFFFFFFFF };
    int[] defaultPattern23 = { //?
            0x80000000, 0x04100000, 0x04380000, 0x047C0000, 0x04FE0000, 0x04FF1000, 0x04FFB000, 0x04FFF000,
            0x04EFF000, 0x04C7F000, 0x0483F000, 0x0401F000, 0x0400E000, 0x04004000, 0x04000000, 0xFFFFFFFF };
    int[] defaultPattern24 = { // ?
            0x80000000, 0x0AAAA000, 0x0A555000, 0x08AAA000, 0x08555000, 0x06AAA000, 0x06555000, 0x04AAA000,
            0x04555000, 0x02AAA000, 0x02555000, 0x02AAA000, 0x02555000, 0xFFFFFFFF };

    public static final String ACTION_START_PATTERN_SEND_DATA = "com.umundus.javable.ACTION_START_PATTERN_SEND_DATA";
    public static final String ACTION_END_PATTERN_SEND_DATA = "com.umundus.javable.ACTION_END_PATTERN_SEND_DATA";

    public final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            String intentAction;

            if (newState == BluetoothProfile.STATE_CONNECTED) {
                intentAction = ACTION_GATT_CONNECTED;
                mConnectionState = STATE_CONNECTED;
                broadcastUpdate(intentAction);
                Log.i(TAG, "Connected to GATT server.");
                // Attempts to discover services after successful connection.
                Log.i(TAG, "Attempting to start service discovery:" + mBluetoothGatt.discoverServices());

            } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                intentAction = ACTION_GATT_DISCONNECTED;
                mConnectionState = STATE_DISCONNECTED;
                Log.i(TAG, "Disconnected from GATT server.");
                broadcastUpdate(intentAction);
            }

            // notify waiting thread
            synchronized (mLock) {
                mLock.notifyAll();
            }
        }

        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            if (status == BluetoothGatt.GATT_SUCCESS) {
                Log.w(TAG, "mBluetoothGatt = " + mBluetoothGatt);

                mConnectionState = STATE_DISCOVERED;

                broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
            } else {
                Log.w(TAG, "onServicesDiscovered received: " + status);
            }
            // notify waiting thread
            synchronized (mLock) {
                mLock.notifyAll();
            }
        }

        @Override
        public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic,
                int status) {
            if (status == BluetoothGatt.GATT_SUCCESS) {
                broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
            }

            mRequestCompleted = true;

            synchronized (mLock) {
                mLock.notifyAll();
            }
        }

        @Override
        public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
            if (NCALL_REMOCON_SEND_PATTERN_CHARACTERISTIC.equals(characteristic.getUuid())) {
                int status = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 1);

                Log.e("tag", "NCALL_REMOCON_SEND_PATTERN_CHARACTERISTIC+++++++++++++++++++++" + status);
            } else {
                broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
            }

            mRequestCompleted = true;

            synchronized (mLock) {
                mLock.notifyAll();
            }
        }

        @Override
        public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic,
                int status) {
            if (status == BluetoothGatt.GATT_SUCCESS) {
                if (NCALL_REMOCON_SEND_PATTERN_CHARACTERISTIC.equals(characteristic.getUuid())) {
                    mBytesSent += characteristic.getValue().length;

                    final boolean lastPackTramsfered = mBytesSent == mImageSizeInBytes;

                    if (lastPackTramsfered) {
                        sendBroadcast(new Intent(ACTION_END_PATTERN_SEND_DATA));
                    } else {
                        try {
                            final byte[] buffer = mBuffer;
                            final int size = mInputStream.read(buffer);

                            writePacket(gatt, characteristic, buffer, size);
                        } catch (Exception e) {
                        }
                    }
                }
            } else {
                showMessage("onCharacteristicWrite Error = " + status);
            }

            mRequestCompleted = true;

            synchronized (mLock) {
                mLock.notifyAll();
            }
        }

        @Override
        public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {

            // KeyInputNOtification & BatteryNotification ? wait ?? .
            mRequestCompleted = true;

            synchronized (mLock) {
                mLock.notifyAll();
            }
        }

        @Override
        public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {

            final Intent intent = new Intent(ACTION_DATA_AVAILABLE);

            //            Log.d(TAG, "onReadRemoteRssi() - address [" + gatt.getDevice().getAddress() + "], rssi = " + rssi);

            intent.putExtra(RSSI_VALUE, Integer.toString(rssi));

            sendBroadcast(intent);

            super.onReadRemoteRssi(gatt, rssi, status);
        }
    };

    public void writePacket(final BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic,
            final byte[] buffer, final int size) {
        byte[] locBuffer = buffer;
        if (buffer.length != size) {
            locBuffer = new byte[size];
            System.arraycopy(buffer, 0, locBuffer, 0, size);
        }
        characteristic.setValue(locBuffer);
        gatt.writeCharacteristic(characteristic);
        Log.i(TAG, "writePacket " + characteristic.getUuid());
    }

    public void broadcastUpdate(final String action) {
        final Intent intent = new Intent(action);
        sendBroadcast(intent);
    }

    public void broadcastUpdate(final String action, final BluetoothGattCharacteristic characteristic) {
        final Intent intent = new Intent(action);

        // This is special handling for the Heart Rate Measurement profile.  Data parsing is
        // carried out as per profile specifications:
        // http://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.heart_rate_measurement.xml
        if (BATTERY_CHARACTERISTIC.equals(characteristic.getUuid())) {

            int battery = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 0);
            Log.d(TAG, String.format("battery value : %d", battery));

            intent.putExtra(BATTERY_VALUE, battery);

        } else if (NCALL_REMOCON_KEY_NOTI_CHARACTERISTIC.equals(characteristic.getUuid())) {

            int cmd = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 0);

            if (cmd == 0x00) {

                intent.putExtra(KEY_INPUT_DATA, characteristic.getValue());

            } else if (cmd == 0x22) {

                int status = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 1);
                Log.d(TAG, String.format("scenario status : %d", status));
                intent.putExtra(SCENARIO_STATUS_DATA, status);

            } else if (cmd == 0x32) {
                intent.putExtra(LED_INPUT_DATA, characteristic.getValue());
            } else if (cmd == 0x42) {
                intent.putExtra(VERSION_INPUT_DATA, characteristic.getValue());
            } else if (cmd == 0x52) {
                int status = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 1);

                Log.i(TAG, "RESPONSE_PATRERN_DATA ++");

                if (status == RESPONSE_PATRERN_DATA_WRITE_ERROR) {
                    Log.e(TAG, "PATTERN_DATA_WRITE_ERROR");
                } else if (status == RESPONSE_PATRERN_DATA_WRITE_START) {
                    Log.i(TAG, "pattern data response ok!!!!!!!!!!!!!!!!!!!!!!!!!!!");
                    if (mBluetoothAdapter == null || mBluetoothGatt == null) {
                        Log.w(TAG, "writeRemoconCharacteristic BluetoothAdapter not initialized");
                        return;
                    }

                    BluetoothGattService RemoconService = mBluetoothGatt.getService(NCALL_REMOCON_SERVICE);
                    if (RemoconService == null) {
                        showMessage("NCALL_REMOCON_SERVICE = NULL");
                        return;
                    }

                    BluetoothGattCharacteristic RemoconChar = RemoconService
                            .getCharacteristic(NCALL_REMOCON_SEND_PATTERN_CHARACTERISTIC);
                    if (RemoconChar == null) {
                        showMessage("NCALL_REMOCON_SEND_PATTERN_CHARACTERISTIC = NULL");
                        return;
                    }

                    try {
                        final byte[] buffer = mBuffer;
                        final int size = mInputStream.read(buffer);

                        writePacket(mBluetoothGatt, RemoconChar, buffer, size);
                    } catch (Exception e) {
                        Log.e(TAG, "" + e);
                    }
                } else if (status == RESPONSE_PATRERN_DATA_WRITE_END) {
                    try {
                        patternCount++;
                        if (patternCount < 12) {
                            Log.w(TAG, "" + patternCount);
                            PatternTransferStart(patternCount);
                        } else {
                            broadcastUpdate(PROGRESS_SET_INVISIBLE);
                        }
                    } catch (Exception e) {
                        // TODO: handle exception
                    }
                }

                Log.i(TAG, "RESPONSE_PATRERN_DATA --");

            } else if (cmd == 0x62) {
                Log.i(TAG, "/  ack:" + characteristic.getValue());
            }
        } else if (MANUFACTURER_NAME_UUID.equals(characteristic.getUuid())) {
            byte getdata[] = characteristic.getValue();
            Log.i(TAG, "Manufacturer Name : " + new String(getdata, 0, getdata.length));
            intent.putExtra(MANUFACTURER_NAME, characteristic.getValue());
        } else if (MODEL_NAME_UUID.equals(characteristic.getUuid())) {
            byte getdata[] = characteristic.getValue();
            Log.i(TAG, "Model Number : " + new String(getdata, 0, getdata.length));
            intent.putExtra(MODEL_NAME, characteristic.getValue());
        } else if (FIRMWARE_REVISON_UUID.equals(characteristic.getUuid())) {
            byte getdata[] = characteristic.getValue();
            Log.i(TAG, "firmware vision = " + new String(getdata, 0, getdata.length));
            intent.putExtra(FIRMWARE_REVISON, characteristic.getValue());
        } else if (HARDWARE_REVISON_UUID.equals(characteristic.getUuid())) {
            byte getdata[] = characteristic.getValue();
            Log.i(TAG, "hardware revision = " + new String(getdata, 0, getdata.length));
            intent.putExtra(HARDWARE_REVISON, characteristic.getValue());
        }

        //        synchronized (mLock) {
        //           mLock.notifyAll();
        //      }
        sendBroadcast(intent);
    }

    public void onCreate() {
        Log.d(TAG, "[*]Service-onCreate");
        super.onCreate();

        IntentFilter filter = new IntentFilter(ACTION_START_PATTERN_SEND_DATA);
        filter.addAction(ACTION_END_PATTERN_SEND_DATA);
        registerReceiver(mBroadcastReceiver, filter);

        int myID = 1234;
        Intent intent = new Intent(this, NCallServiceOld.class);
        //PendingIntent pendIntent = PendingIntent.getActivity(this, 0, bindIntent, 0);
        PendingIntent pi = PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_NO_CREATE);
        Notification notice = new Notification.Builder(this).setContentTitle("(Rang)")
                .setContentText("(Rang)? .").setSmallIcon(R.drawable.ic_launcher)
                .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher)).setOngoing(true)
                .setContentIntent(pi).build();
        notice.flags |= Notification.FLAG_NO_CLEAR;
        notice.flags |= Notification.FLAG_ONGOING_EVENT;
        startForeground(myID, notice);

        AlarmManager al = (AlarmManager) this.getSystemService(this.ALARM_SERVICE);
        al.setRepeating(AlarmManager.RTC, System.currentTimeMillis(), 1000 * 15, pi);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        unregisterReceiver(mBroadcastReceiver);
    }

    public class LocalBinder extends Binder {
        public NCallServiceOld getService() {
            Log.d(TAG, "[*]Service-LocalBinder-getService():" + NCallServiceOld.this);
            return NCallServiceOld.this;
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        Log.d(TAG, "[*]Service-onBind:" + mBinder);
        return mBinder;
    }

    @Override
    public boolean onUnbind(Intent intent) {
        // After using a given device, you should make sure that BluetoothGatt.close() is called
        // such that resources are cleaned up properly.  In this particular example, close() is
        // invoked when the UI is disconnected from the Service.
        close();
        return super.onUnbind(intent);
    }

    public final IBinder mBinder = new LocalBinder();

    /**
     * Initializes a reference to the local Bluetooth adapter.
     *
     * @return Return true if the initialization is successful.
     */
    public boolean initialize() {
        // For API level 18 and above, get a reference to BluetoothAdapter through
        // BluetoothManager.
        Log.d(TAG, "[*]Service-initialize#1");
        if (mBluetoothManager == null) {
            mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
            if (mBluetoothManager == null) {
                Log.e(TAG, "[*]Unable to initialize BluetoothManager.");
                return false;
            }
        }

        Log.d(TAG, "[*]Service-initialize#2");
        mBluetoothAdapter = mBluetoothManager.getAdapter();
        if (mBluetoothAdapter == null) {
            Log.e(TAG, "[*]Unable to obtain a BluetoothAdapter.");
            return false;
        }

        return true;
    }

    /**
     * Connects to the GATT server hosted on the Bluetooth LE device.
     *
     * @param address The device address of the destination device.
     *
     * @return Return true if the connection is initiated successfully. The connection result
     *         is reported asynchronously through the
     *         {@code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)}
     *         callback.
     */
    public boolean connect(final String address) {
        Log.d(TAG, "[*]Service-connect:" + address);

        if (mBluetoothAdapter == null || address == null) {
            Log.w(TAG, "BluetoothAdapter not initialized or unspecified address.");
            return false;
        }

        // Previously connected device.  Try to reconnect.
        if (mBluetoothDeviceAddress != null && address.equals(mBluetoothDeviceAddress) && mBluetoothGatt != null) {
            Log.d(TAG, "Trying to use an existing mBluetoothGatt for connection.");
            if (mBluetoothGatt.connect()) {
                mConnectionState = STATE_CONNECTING;
                return true;
            } else {
                return false;
            }
        }

        final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
        if (device == null) {
            Log.w(TAG, "Device not found.  Unable to connect.");
            return false;
        }
        // We want to directly connect to the device, so we are setting the autoConnect
        // parameter to false.
        mBluetoothGatt = device.connectGatt(this, true, mGattCallback);
        Log.d(TAG, "Trying to create a new connection.");
        mBluetoothDeviceAddress = address;
        mConnectionState = STATE_CONNECTING;

        Log.d(TAG, "[*]Service-connect:" + address + ",state:" + mConnectionState);
        return true;
    }

    /**
     * Disconnects an existing connection or cancel a pending connection. The disconnection result
     * is reported asynchronously through the
     * {@code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)}
     * callback.
     */
    public void disconnect() {
        if (mBluetoothAdapter == null || mBluetoothGatt == null) {
            Log.w(TAG, "BluetoothAdapter not initialized");
            return;
        }
        mBluetoothGatt.disconnect();
    }

    /**
     * After using a given BLE device, the app must call this method to ensure resources are
     * released properly.
     */
    public void close() {
        if (mBluetoothGatt == null) {
            return;
        }
        Log.w(TAG, "mBluetoothGatt closed");
        mBluetoothDeviceAddress = null;
        mBluetoothGatt.close();
        mBluetoothGatt = null;
    }

    /**
     * Request a read on a given {@code BluetoothGattCharacteristic}. The read result is reported
     * asynchronously through the {@code BluetoothGattCallback#onCharacteristicRead(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int)}
     * callback.
     *
     * @param characteristic The characteristic to read from.
     */
    public void readCharacteristic(BluetoothGattCharacteristic characteristic) {
        if (mBluetoothAdapter == null || mBluetoothGatt == null) {
            Log.w(TAG, "BluetoothAdapter not initialized");
            return;
        }
        mBluetoothGatt.readCharacteristic(characteristic);
    }

    /**
     * Enable Key Button Notification
     * 
     */
    public void enableKeyInputNotification() {

        if (mBluetoothAdapter == null || mBluetoothGatt == null) {
            Log.w(TAG, "enableKeyInputNotification BluetoothAdapter not initialized");
            return;
        }

        BluetoothGattService KeyInputService = mBluetoothGatt.getService(NCALL_REMOCON_SERVICE);
        if (KeyInputService == null) {
            showMessage("key input service not found!");
            broadcastUpdate(DEVICE_DOES_NOT_SUPPORT_SRC);
            return;
        }

        // ?  KEY ? ?? .
        BluetoothGattCharacteristic KeyInputChar = KeyInputService
                .getCharacteristic(NCALL_REMOCON_KEY_NOTI_CHARACTERISTIC);
        if (KeyInputChar == null) {
            showMessage("Key input charateristic not found!");
            broadcastUpdate(DEVICE_DOES_NOT_SUPPORT_SRC);
            return;
        }

        mRequestCompleted = false;

        mBluetoothGatt.setCharacteristicNotification(KeyInputChar, true);

        BluetoothGattDescriptor descriptor = KeyInputChar.getDescriptor(CCCD);
        descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
        mBluetoothGatt.writeDescriptor(descriptor);

        synchronized (mLock) {
            if (!mRequestCompleted && mConnectionState == STATE_DISCOVERED) {
                try {
                    mLock.wait(); // onDescriptorWrite ? notify .
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }

    public void getVersionData() {
        byte[] sendBuf = new byte[2];
        Arrays.fill(sendBuf, (byte) 0x00);

        sendBuf[0] = (byte) 0x41;
        sendBuf[1] = (byte) 0x01;

        writeRemoconCharacteristic(sendBuf);
    }

    public void TimeSendData(int timecolor) {
        byte[] sendBuf = new byte[6];
        Arrays.fill(sendBuf, (byte) 0x00);

        final Calendar c = Calendar.getInstance();
        int mHour = c.get(Calendar.HOUR);
        int mMinute = c.get(Calendar.MINUTE);
        int mSecond = c.get(Calendar.SECOND);
        int mMilliSecond = c.get(Calendar.MILLISECOND) / 10;

        sendBuf[0] = (byte) 0x61;
        sendBuf[1] = (byte) timecolor;
        sendBuf[2] = (byte) mHour;
        sendBuf[3] = (byte) mMinute;
        sendBuf[4] = (byte) mSecond;
        sendBuf[5] = (byte) mMilliSecond;
        //------------------------------
        //sendBuf[6] = (byte)0x00;

        writeRemoconCharacteristic(sendBuf);
    }

    public void TimeSendData(int hColor, int mColor) {
        byte[] sendBuf = new byte[8];
        Arrays.fill(sendBuf, (byte) 0x00);

        final Calendar c = Calendar.getInstance();
        int mHour = c.get(Calendar.HOUR);
        int mMinute = c.get(Calendar.MINUTE);
        int mSecond = c.get(Calendar.SECOND);
        int mMilliSecond = c.get(Calendar.MILLISECOND) / 10;

        sendBuf[0] = (byte) 0x61;
        sendBuf[1] = (byte) hColor;
        sendBuf[2] = (byte) mColor;
        sendBuf[3] = (byte) mHour;
        sendBuf[4] = (byte) mMinute;
        sendBuf[5] = (byte) mSecond;
        sendBuf[6] = (byte) mMilliSecond;
        sendBuf[7] = (byte) 60; //  

        writeRemoconCharacteristic(sendBuf);
    }

    public void SendMissedCallSMS(int sms, int call) {
        byte[] sendBuf = new byte[11];
        Arrays.fill(sendBuf, (byte) 0x00);
        // cmd
        sendBuf[0] = (byte) 0x21; //cmd
        sendBuf[1] = (byte) 0x04; //sub cmd

        if (sms == 1 || call == 1) {
            // led
            sendBuf[2] = (byte) 0x00; //
            sendBuf[3] = (byte) 0x00; //
            sendBuf[4] = (call == 1 ? (byte) 0x80 : (byte) 0x00); // sms
            sendBuf[4] |= (sms == 1 ? (byte) 0x02 : (byte) 0x00); // call
            sendBuf[5] = (byte) 0x00; //
            // time
            sendBuf[6] = (byte) 0x05; //on time 10ms
            sendBuf[7] = (byte) 0x05; //off time 10ms
            sendBuf[8] = 60; //
            sendBuf[9] = 60; //off time 1000ms
            sendBuf[10] = (byte) 0x05; //
        }

        writeRemoconCharacteristic(sendBuf);
    }

    public void SendLEDSmaple1(byte[] ledbytedata, byte ontime) {
        byte[] sendBuf = new byte[7];
        Arrays.fill(sendBuf, (byte) 0x00);

        // cmd
        sendBuf[0] = (byte) 0x21;
        sendBuf[1] = (byte) 0x01;
        //led
        sendBuf[2] = ledbytedata[2];
        sendBuf[3] = ledbytedata[1];
        sendBuf[4] = ledbytedata[0];
        sendBuf[5] = (byte) 0x00; // tem

        sendBuf[6] = ontime;

        Log.e("tag",
                "led[2] = " + Integer.toHexString(0xff & ledbytedata[2]) + ", led[1] = "
                        + Integer.toHexString(0xff & ledbytedata[1]) + ", led[0] = "
                        + Integer.toHexString(0xff & ledbytedata[0]));

        writeRemoconCharacteristic(sendBuf);
    }

    public void SendLEDSmaple2(byte[] ledbytedata, byte ontime, byte offtime, byte count) {
        byte[] sendBuf = new byte[9];
        Arrays.fill(sendBuf, (byte) 0x00);

        // cmd
        sendBuf[0] = (byte) 0x21;
        sendBuf[1] = (byte) 0x02;
        //led
        sendBuf[2] = ledbytedata[2];
        sendBuf[3] = ledbytedata[1];
        sendBuf[4] = ledbytedata[0];
        sendBuf[5] = (byte) 0x00; // temp

        sendBuf[6] = ontime;
        sendBuf[7] = offtime;
        sendBuf[8] = count;

        Log.e("tag",
                "led[2] = " + Integer.toHexString(0xff & ledbytedata[2]) + ", led[1] = "
                        + Integer.toHexString(0xff & ledbytedata[1]) + ", led[0] = "
                        + Integer.toHexString(0xff & ledbytedata[0]));

        writeRemoconCharacteristic(sendBuf);
    }

    public void SendLEDSmaple3(byte[] ledbytedata1, byte[] ledbytedata2, byte interval, byte count) {
        byte[] sendBuf = new byte[12];
        Arrays.fill(sendBuf, (byte) 0x00);
        // cmd
        sendBuf[0] = (byte) 0x21;
        sendBuf[1] = (byte) 0x03;

        //led1
        sendBuf[2] = ledbytedata1[2];
        sendBuf[3] = ledbytedata1[1];
        sendBuf[4] = ledbytedata1[0];
        sendBuf[5] = (byte) 0x00; // temp

        //led2
        sendBuf[6] = ledbytedata2[2];
        sendBuf[7] = ledbytedata2[1];
        sendBuf[8] = ledbytedata2[0];
        sendBuf[9] = (byte) 0x00; // temp

        sendBuf[10] = interval;
        sendBuf[11] = count;

        Log.e("tag",
                "ledbytedata1[2] = " + Integer.toHexString(0xff & ledbytedata1[2]) + ", ledbytedata1[1] = "
                        + Integer.toHexString(0xff & ledbytedata1[1]) + ", ledbytedata1[0] = "
                        + Integer.toHexString(0xff & ledbytedata1[0]));
        Log.e("tag",
                "ledbytedata2[2] = " + Integer.toHexString(0xff & ledbytedata2[2]) + ", ledbytedata2[1] = "
                        + Integer.toHexString(0xff & ledbytedata2[1]) + ", ledbytedata2[0] = "
                        + Integer.toHexString(0xff & ledbytedata2[0]));

        writeRemoconCharacteristic(sendBuf);
    }

    public void PatternDisplay(int no) {
        //        byte[] sendBuf = new byte[3];
        //        Arrays.fill(sendBuf, (byte)0x00);

        //        sendBuf[0] = (byte)0x21;
        //        sendBuf[1] = (byte)0x05;
        //        sendBuf[2] = (byte)no;

        byte[] sendBuf = new byte[4];
        Arrays.fill(sendBuf, (byte) 0x00);

        sendBuf[0] = (byte) 0x21;
        sendBuf[1] = (byte) 0x05;
        sendBuf[2] = (byte) no;
        sendBuf[3] = (byte) 0x05; // , 0 ? 

        writeRemoconCharacteristic(sendBuf);
    }

    public void selectOnLED(byte[] ledbytedata) {
        byte[] sendBuf = new byte[6];
        Arrays.fill(sendBuf, (byte) 0x00);

        sendBuf[0] = (byte) 0x31;
        sendBuf[1] = (byte) 0x00;
        sendBuf[2] = ledbytedata[2];
        sendBuf[3] = ledbytedata[1];
        sendBuf[4] = ledbytedata[0];
        sendBuf[5] = (byte) 0x00;

        writeRemoconCharacteristic(sendBuf);
    }

    public void GoToDownloadMode() {
        byte[] sendBuf = new byte[2];
        Arrays.fill(sendBuf, (byte) 0x00);
        sendBuf[0] = (byte) 0xf9;
        sendBuf[1] = (byte) 0x00; // control end

        writeRemoconCharacteristic(sendBuf);
    }

    public void writeRemoconPatternCharacteristic(byte[] value) {

        if (mBluetoothAdapter == null || mBluetoothGatt == null) {
            Log.w(TAG, "writeRemoconCharacteristic BluetoothAdapter not initialized");
            return;
        }

        BluetoothGattService RemoconService = mBluetoothGatt.getService(NCALL_REMOCON_SERVICE);
        if (RemoconService == null) {
            showMessage("key input service not found!");
            broadcastUpdate(DEVICE_DOES_NOT_SUPPORT_SRC);
            return;
        }

        BluetoothGattCharacteristic RemoconChar = RemoconService
                .getCharacteristic(NCALL_REMOCON_SEND_DATA_CHARACTERISTIC);
        if (RemoconChar == null) {
            showMessage("remocon control charateristic not found!");
            broadcastUpdate(DEVICE_DOES_NOT_SUPPORT_SRC);
            return;
        }

        Log.i(TAG, "writeRemoconPatternCharacteristic ++");
        RemoconChar.setValue(value);
        boolean status = mBluetoothGatt.writeCharacteristic(RemoconChar);
        Log.i(TAG, "writeRemoconPatternCharacteristic --");
    }

    public void writeRemoconCharacteristic(byte[] value) {

        if (mBluetoothAdapter == null || mBluetoothGatt == null) {
            Log.w(TAG, "writeRemoconCharacteristic BluetoothAdapter not initialized");
            return;
        }

        BluetoothGattService RemoconService = mBluetoothGatt.getService(NCALL_REMOCON_SERVICE);
        if (RemoconService == null) {
            showMessage("key input service not found!");
            broadcastUpdate(DEVICE_DOES_NOT_SUPPORT_SRC);
            return;
        }

        BluetoothGattCharacteristic RemoconChar = RemoconService
                .getCharacteristic(NCALL_REMOCON_SEND_DATA_CHARACTERISTIC);
        if (RemoconChar == null) {
            showMessage("remocon control charateristic not found!");
            broadcastUpdate(DEVICE_DOES_NOT_SUPPORT_SRC);
            return;
        }

        mRequestCompleted = false;

        RemoconChar.setValue(value);
        boolean status = mBluetoothGatt.writeCharacteristic(RemoconChar);

        synchronized (mLock) {
            if (!mRequestCompleted && mConnectionState == STATE_DISCOVERED) {
                try {
                    mLock.wait(); // onCharacteristicWrite ? notify .
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * Enabl Battery Notification
     * 
     */
    public void enableBatteryNotification() {
        if (mBluetoothAdapter == null || mBluetoothGatt == null) {
            Log.w(TAG, "enableBatteryNotification BluetoothAdapter not initialized");
            return;
        }

        BluetoothGattService BatteryService = mBluetoothGatt.getService(BATTERY_SERVICE);
        if (BatteryService == null) {
            showMessage("Battery service not found!");
            broadcastUpdate(DEVICE_DOES_NOT_SUPPORT_SRC);
            return;
        }
        BluetoothGattCharacteristic BatteryChar = BatteryService.getCharacteristic(BATTERY_CHARACTERISTIC);
        if (BatteryChar == null) {
            showMessage("Battery charateristic not found!");
            broadcastUpdate(DEVICE_DOES_NOT_SUPPORT_SRC);
            return;
        }
        mBluetoothGatt.setCharacteristicNotification(BatteryChar, true);

        mRequestCompleted = false;

        BluetoothGattDescriptor descriptor = BatteryChar.getDescriptor(CCCD);
        descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
        mBluetoothGatt.writeDescriptor(descriptor);

        synchronized (mLock) {
            if (!mRequestCompleted && mConnectionState == STATE_DISCOVERED) {
                try {
                    mLock.wait(); // onDescriptorWrite ? notify .
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }

    public void RequestDeviceInfomationService(UUID RequestCharacteristic) {
        boolean result = false;
        if (mBluetoothGatt != null) {
            BluetoothGattService disService = mBluetoothGatt.getService(DEVICE_INFOMATION_SERVICE);
            if (disService == null) {
                showMessage("Dis service not found!");
                return;
            }

            BluetoothGattCharacteristic IdCharacteristic = disService.getCharacteristic(RequestCharacteristic);
            if (IdCharacteristic == null) {
                showMessage("dis service " + RequestCharacteristic.toString() + " charateristic not found!");
                return;
            }

            mRequestCompleted = false;
            result = mBluetoothGatt.readCharacteristic(IdCharacteristic);
            if (result == false) {
                showMessage(RequestCharacteristic.toString() + " reading is failed!");
            }

            synchronized (mLock) {
                if (!mRequestCompleted && mConnectionState == STATE_DISCOVERED) {
                    try {
                        mLock.wait(); // onDescriptorWrite ? notify .
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    /*
    public void DummyReadForSecLevelCheck() {
    boolean result = false;
    if (mBluetoothGatt != null) {
        BluetoothGattService disService = mBluetoothGatt.getService(DIS_UUID);
        if (disService == null) {
            showMessage("Dis service not found!");
            return;
        }
        
        BluetoothGattCharacteristic firmwareIdcharc = disService.getCharacteristic(FIRMWARE_REVISON_UUID);
        if (firmwareIdcharc == null) {
            showMessage("firmware revision charateristic not found!");
            return;
        }
        result = mBluetoothGatt.readCharacteristic(firmwareIdcharc);
        if (result == false) {
            showMessage("firmware revision reading is failed!");
        }
    }
        
    }
    */

    private void showMessage(String msg) {
        Log.e(TAG, msg);
    }

    /**
     * Retrieves a list of supported GATT services on the connected device. This should be
     * invoked only after {@code BluetoothGatt#discoverServices()} completes successfully.
     *
     * @return A {@code List} of supported services.
     */
    public List<BluetoothGattService> getSupportedGattServices() {
        if (mBluetoothGatt == null)
            return null;

        return mBluetoothGatt.getServices();
    }

    public boolean readRssi() {
        if (mBluetoothGatt == null)
            return false;

        mBluetoothGatt.readRemoteRssi();
        return true;
    }

    int mTransferPatternNo = 0;
    int mTransferPatternCount = 0;

    boolean generatePatternData(int PatternNo) {
        boolean bRet = false;
        int pos = 0;
        int packtcount = 0;

        int[] patternArray;
        switch (PatternNo) {
        case 0:
            patternArray = defaultPattern1;
            break;
        case 1:
            patternArray = userPattern2;
            break;
        case 2:
            patternArray = defaultPattern7;
            break;
        case 3:
            patternArray = defaultPattern4;
            break;
        case 4:
            patternArray = defaultPattern5;
            break;
        case 5:
            patternArray = defaultPattern6;
            break;
        case 6:
            patternArray = defaultPattern7;
            break;
        case 7:
            patternArray = defaultPattern8;
            break;
        case 8:
            patternArray = defaultPattern9;
            break;
        case 9:
            patternArray = defaultPattern10;
            break;
        case 10:
            patternArray = defaultPattern11;
            break;
        case 11:
            patternArray = defaultPattern12;
            break;
        default:
            patternArray = defaultPattern1;
            break;
        }

        Log.i(TAG, "pattern" + PatternNo + " length = " + patternArray.length);

        //   ? 1024  ? .
        if (patternArray.length * 4 <= 1024) {
            int length = ((patternArray.length - 1) / 4) + 1;

            pattern1024 = null;
            pattern1024 = new byte[length * 20];

            Arrays.fill(pattern1024, (byte) 0);

            for (int i = 0; i < length; i++) {
                pattern1024[pos++] = (byte) 0x51;
                pattern1024[pos++] = (byte) 0x01;
                pattern1024[pos++] = (byte) PatternNo;
                pattern1024[pos++] = (byte) packtcount++;

                for (int j = i * 4; j < i * 4 + 4; j++) {
                    if (patternArray.length > j) {
                        pattern1024[pos++] = (byte) ((patternArray[j] >>> 0) & 0xFF);
                        pattern1024[pos++] = (byte) ((patternArray[j] >>> 8) & 0xFF);
                        pattern1024[pos++] = (byte) ((patternArray[j] >>> 16) & 0xFF);
                        pattern1024[pos++] = (byte) ((patternArray[j] >>> 24) & 0xFF);
                    } else {
                        pattern1024[pos++] = (byte) 0xFF;
                        pattern1024[pos++] = (byte) 0xFF;
                        pattern1024[pos++] = (byte) 0xFF;
                        pattern1024[pos++] = (byte) 0xFF;
                    }
                }
            }
            bRet = true;
        }

        return bRet;
    }

    public void PatternTransferStart(int patternNo) {
        byte[] sendBuf = new byte[4];
        Arrays.fill(sendBuf, (byte) 0x00);
        mTransferPatternNo = patternNo;
        try {
            mBytesSent = 0;

            if (mInputStream != null) {
                mInputStream.close();
                mInputStream = null;
            }

            if (generatePatternData(mTransferPatternNo) == true) {
                ByteArrayInputStream bis = new ByteArrayInputStream(pattern1024);
                mInputStream = bis;
                mImageSizeInBytes = mInputStream.available();
                mTransferPatternCount = ((mImageSizeInBytes - 1) / 20) + 1;

                sendBuf[0] = (byte) 0x51;
                sendBuf[1] = (byte) 0x00;
                sendBuf[2] = (byte) mTransferPatternNo;
                sendBuf[3] = (byte) mTransferPatternCount;

                writeRemoconPatternCharacteristic(sendBuf);
            } else {
                // ? ..." ??  ."
                //
                // error display
            }
        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        }
    }

    public void PatternTransferEnd() {
        byte[] sendBuf = new byte[4];
        Arrays.fill(sendBuf, (byte) 0x00);
        sendBuf[0] = (byte) 0x51;
        sendBuf[1] = (byte) 0x02;
        sendBuf[2] = (byte) mTransferPatternNo;
        sendBuf[3] = (byte) mTransferPatternCount;

        writeRemoconCharacteristic(sendBuf);
    }

    private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {

        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();

            if (ACTION_START_PATTERN_SEND_DATA.equals(action)) {
                patternCount = 0;
                PatternTransferStart(patternCount);
                broadcastUpdate(PROGRESS_SET_VISIBLE);
            } else if (ACTION_END_PATTERN_SEND_DATA.equals(action)) {
                PatternTransferEnd();
            }
        }
    };

    public void takeCamera() {
        new Thread(new Runnable() {
            public void run() {
                new Instrumentation().sendKeyDownUpSync(KeyEvent.KEYCODE_VOLUME_DOWN);
            }
        }).start();
    }
}