package kr.co.icontrols.wallpadcall;

import android.annotation.SuppressLint;
import android.app.ActivityManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.Matrix;
import android.hardware.Camera;
import android.hardware.Camera.ErrorCallback;
import android.media.AudioManager;
import android.media.CamcorderProfile;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
import android.os.Build;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
import android.util.Log;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
import android.view.View;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.animation.TranslateAnimation;
import android.widget.Button;
import android.widget.ExpandableListView;
import android.widget.RelativeLayout;

import com.artncore.WallPadDataMgr.WallpadDeviceSet;
import com.artncore.WallPadDataMgr.WallpadSalesSampleData;
import com.artncore.WallPadDataMgr.WallpadStatusData;
import com.artncore.WallPadDataMgr.wallpaddbmgr;
import com.artncore.commons.API_Menu;
import com.artncore.commons.API_Menu.MenuListDataClass;
import com.artncore.commons.API_Menu.MenuListDataClass.ChildIDMapping;
import com.artncore.commons.define;
import com.artncore.wallpadapi.FP_DlockAPI;
import com.artncore.wallpadapi.IGW300API;
import com.artncore.wallpadapi.Sdb_LivingRoomLightAPI;
import com.artncore.wallpadapi.SmartKeyRfDoorAPI;
import com.artncore.wallpadapi.WallPadAPI;
import com.artncore.wallpadimap.RetProci;
import com.util.LogUtil;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;

import kr.co.icontrols.ReliefCall.ReliefCallInterface;
import kr.co.icontrols.callengine.engine.AudioRecordController;
import kr.co.icontrols.callengine.engine.CallController;
import kr.co.icontrols.callengine.engine.CallManager.CALLEVENTTYPE;
import kr.co.icontrols.callengine.engine.CallManager.CALLOWNER;
import kr.co.icontrols.callengine.engine.CallManager.CALLPATH;
import kr.co.icontrols.callengine.engine.CallManager.CALLSTATUS;
import kr.co.icontrols.callengine.engine.CallManager.CALLTYPE;
import kr.co.icontrols.callengine.engine.RemoteCallController;
import kr.co.icontrols.callengine.engine.VideoController;
import kr.co.icontrols.callengine.history.CallHistoryManager;
import kr.co.icontrols.callengine.history.VisitorPictureHistoryManager;
import kr.co.icontrols.callengine.pstn.ATCmds.PSTNHANDLERMSG;
import kr.co.icontrols.callengine.pstn.PSTNController;
import kr.co.icontrols.callengine.remotecall.DataSender;
import kr.co.icontrols.callengine.subphone.SubPhoneController;
import kr.co.icontrols.callengine.subwallpad.SubWallPadController;
import kr.co.icontrols.wallpadcall.declare.Common;
import kr.co.icontrols.wallpadcall.declare.DataClasses.RemoteIDInfo;
import kr.co.icontrols.wallpadcall.declare.DataClasses.SmartRFCamLEDMode;
import kr.co.icontrols.wallpadcall.declare.DataClasses.SmartRFCamStatusMode;
import kr.co.icontrols.wallpadcall.declare.Declare;
import kr.co.icontrols.wallpadcall.declare.Declare.CALLTRIGGER;
import kr.co.icontrols.wallpadcall.declare.Declare.IGW300CMD;
import kr.co.icontrols.wallpadcall.declare.Global;
import kr.co.icontrols.wallpadcall.declare.Global.BOARD_TYPE;
import kr.co.icontrols.wallpadcall.declare.Global.ConfigValues;
import kr.co.icontrols.wallpadcall.declare.Global.DOORLOCKTYPE;
import kr.co.icontrols.wallpadcall.declare.Global.FRONTCAMERATYPE;
import kr.co.icontrols.wallpadcall.declare.Global.SUBWALLPAD_PSTNTYPE;
import kr.co.icontrols.wallpadcall.declare.Global.WALLPADTYPE;
import kr.co.icontrols.wallpadcall.declare.ID;
import kr.co.icontrols.wallpadcall.imap.Request_check_sip_activation;
import kr.co.icontrols.wallpadcall.screen.InquiryCallHistory;
import kr.co.icontrols.wallpadcall.screen.InquiryVisitorPictureHistory;
import kr.co.icontrols.wallpadcall.screen.TalkFront;
import kr.co.icontrols.wallpadcall.screen.TalkGuard;
import kr.co.icontrols.wallpadcall.screen.TalkLobby;
import kr.co.icontrols.wallpadcall.screen.TalkPSTN;
import kr.co.icontrols.wallpadcall.screen.TalkResidence;
import kr.co.icontrols.wallpadcall.screen.VisitorPictureViewer;
import kr.co.icontrols.wallpadcall.subwallpadscreen.TalkFront_SubWallPad;
import kr.co.icontrols.wallpadcall.subwallpadscreen.TalkGuard_SubWallPad;
import kr.co.icontrols.wallpadcall.subwallpadscreen.TalkLobby_SubWallPad;
import kr.co.icontrols.wallpadcall.subwallpadscreen.TalkPSTN_SubWallPad;
import kr.co.icontrols.wallpadcall.subwallpadscreen.TalkResidence_SubWallPad;
import kr.co.icontrols.wallpadsupport.Version;
import kr.co.icontrols.wallpadsupport.Version.MODEL_TYPE;
import kr.co.icontrols.wallpadsupport.WpadActivity;
import kr.co.icontrols.wallpadsupport.WpadImageView;
import kr.co.icontrols.wallpadsupport.WpadImageView.TOUCH_KIND;
import kr.co.icontrols.wallpadsupport.WpadRelativeLayoutParams;
import kr.co.icontrols.wallpadsupport.WpadScale;
import kr.co.icontrols.wallpadsupport.WpadSound;
import kr.co.icontrols.wallpadsupport.WpadSound.SND;
import kr.co.icontrols.wallpadsupport.WpadTextView;
import kr.co.icontrols.wallpadsupport.WpadUtil;

import static kr.co.icontrols.wallpadcall.declare.Declare.BR.ACNAME_MAIN_NOTI;

/**
 * @description 월패드 [통화] 메인화면 이다.
 * 상단의 Top 메뉴, [홈] [돌아가기]
 * 좌측의 슬라이드 메뉴, [현관] [경비] [이웃] ... 등 선택 메뉴
 * 를 여기서 처리한다.
 */
public class MainActivity extends WpadActivity {
    private final static String TAG = "MainActivity";
//test
    /**
     * MoIP 영상통화시, FFMPEG 사용 여부 설정
     * true: FFMPEG 사용, MoIP 영상을 안드로이드 화면의 surface에 출력
     * false: FFMPEG 미사용, MoIP 영상을 OS에서 프레임버퍼에 직접 출력 (surface에 출력 안함)
     * FFMPEG 적용 모델
     *   - IHN-1020B-I
     */
    public static boolean bFFMPEGEnable = false;

    boolean bLOG = true;

    private void LOG(String log) {
        if (bLOG) Log.v(TAG, log);
    }

    boolean bLOG_DEBUG = false;

    private void LOG_DEBUG(String log) {
        if (bLOG_DEBUG) Log.d(TAG, log);
    }

    boolean bLOG_INFO = true;

    private void LOG_INFO(String log) {
        if (bLOG_INFO) Log.i(TAG, log);
    }

    boolean bLOG_WARN = true;

    private void LOG_WARN(String log) {
        if (bLOG_WARN) Log.w(TAG, log);
    }


    // =================================================================================================
    // [[ Declaration ]] region
    // =================================================================================================
    protected Context mContext = null;

    public Context getContext() {
        return mContext;
    }

    public WallPadAPI mWallPadAPI = null;
    public SmartKeyRfDoorAPI smartKeyRfDoorAPI;
    Sdb_LivingRoomLightAPI sdbLivingRoomLightAPI;
    public FP_DlockAPI fpDlockAPI;

    private int OPERATION_MODE = Common.MODE;

    // Layout
    private RelativeLayout AllLayout;        // 화면 전체
    private RelativeLayout TopLayout;        // 상단 메뉴
    private RelativeLayout MenuLayout;       // 메뉴 화면
    private RelativeLayout ScreenLayout;     // 제어기기 화면
    RelativeLayout SurfaceLayout;            // 영상표시 화면

    // SurfaceLayout 구성
    RelativeLayout MyVideoLayout;            // MoIP 카메라 영상 (월패드 전면 카메라)
//    SurfaceHolder MyVideoHolder;
    SurfaceView MyVideoSurface;
    RelativeLayout RemoteVideoLayout;        // MoIP 수신 영상 (로비/경비/이웃 영상)
//    SurfaceHolder RemoteVideoHolder;
    SurfaceView RemoteVideoSurface;
    WpadImageView IMG_REMOTE_VIDEO_PATCH;
    RelativeLayout FrontVideoLayout;         // 현관 카메라 영상
    SurfaceHolder FrontVideoHolder;
    SurfaceView FrontVideoSurface;

    WpadTextView TXT_REMOTE_ID;
    WpadImageView ScreenBackground;

    private static final int REQUEST_EXTERNAL_STORAGE = 100;

    // Top
    private WpadImageView TopBackground;
    private WpadTextView TopTitle;
    private WpadTextView SampleModeTitle;
    private WpadTextView TopStrangerRecodingNotice;
    private WpadTextView TopRemoteCallNotice;
    public WpadImageView TopHomeBtn;
    public WpadImageView TopBackBtn;
    private WpadImageView TopMenuBtn;
    private WpadImageView TopManualBtn;
    private WpadImageView TopSetBtn;
    private WpadImageView TopHideBtn;

    // Menu
    private WpadImageView MenuBackground;
    private WpadImageView MenuClose;
    private WpadTextView MenuTitle;
    private static ExpandableListView mListView;
    private Menu_AdptMain adptMain;
    private MenuListDataClass menuListDataClass;
    private Menu mMenu = null; // WPadAPI의 Menu class
    private boolean MenuOpen = false;

    public boolean mNewDanjiServer = false;

    // PopupActivityRun
    private static boolean PopupActivityRun = false;

    public static boolean getPopupActivityRun() {
        Log.d(TAG, "[getPopupActivityRun] PopupActivityRun [" + PopupActivityRun + "]");
        return PopupActivityRun;
    }

    public static void setPopupActivityRun(boolean run) {
        PopupActivityRun = run;
        Log.d(TAG, "[setPopupActivityRun] PopupActivityRun [" + PopupActivityRun + "]");
        if (!PopupActivityRun) resetCurrentPopUpScreenID();
    }


    // ManualActivityRun
    private static boolean ManualActivityRun = false;
    public static boolean getManualActivityRun() {
        Log.d(TAG, "[getManualActivityRun] ManualActivityRun: " + ManualActivityRun);
        return ManualActivityRun;
    }
    public static void setManualActivityRun(boolean run) {
        ManualActivityRun = run;
        if (!ManualActivityRun) resetCurrentManualScreenID();
    }

    // CurrentScreenId
    private int mCurrentScreenId = -1;
    private int mTempCurrentScreenId = -1;
    private static int mCurrentPopUpScreenId = -1;
    private static int mCurrentManualScreenId = -1;

    int allWidth, allHeight, screenWidth, screenHeight, topHeight, fontSize;

    // System Volume
    int nSysVolume = 0;
    int nTempSysVolume = 7;
    int nTempDTMFVolume = 11;
    int nTempReliefVolume = 11;
    int nTempDingDongVolume = 12;
    int nTempDingDongVolume_IDCHS100 = 10;

    // Screen
    private TalkFront ScreenTalkFront = null;   // 현관통화
    private TalkLobby ScreenTalkLobby = null;   // 로비통화
    private TalkGuard ScreenTalkGuard = null;   // 경비실통화
    private TalkResidence ScreenTalkResidence = null;   // 세대통화
    private TalkPSTN ScreenTalkPSTN = null;   // 국선통화
    private InquiryCallHistory ScreenInquiryCallHistory = null;   // 통화내역
    private InquiryVisitorPictureHistory ScreenInquiryVisitorPictureHistory = null;   // 방문자 사진
    private VisitorPictureViewer ScreenVisitorPictureViewer = null;   // 방문자 사진 뷰어

    // SubWallPad Screen
    private TalkFront_SubWallPad ScreenTalkFrontSub = null;
    private TalkLobby_SubWallPad ScreenTalkLobbySub = null;
    private TalkGuard_SubWallPad ScreenTalkGuardSub = null;
    private TalkResidence_SubWallPad ScreenResidenceSub = null;
    private TalkPSTN_SubWallPad ScreenPSTNSub = null;

    public static IOInterface mIOInterface;
    public static AudioManager mAudioManager;
    public static PowerManager mPowerManager;
    public static CallHistoryManager mCallHistoryManager;
    public static VisitorPictureHistoryManager mVisitorPictureHistoryManager;
    public static CallController mCallController;
    public static VideoController mVideoController;
    public static AudioRecordController mAudioRecordController;
    public static WpadSound mSound;
    public static PSTNController mPSTNController;
    public static SubPhoneController mSubPhoneController;
    public static SubWallPadController mSubWallPadController;
    public static RemoteCallController mRemoteCallController;

    // ***** 방문객 원격통화 솔루션 관련 *****
    public static DataSender mDataSender; // 영상 데이터를 SendMedia API를 통해 모바일쪽에 전달

    // ***** 안심통화 솔루션 관련 *****
    public static ReliefCallInterface mReliefCallIF;

    public boolean bBlockHomeBTN = false;
    public boolean bLCDReverse = false;

    public static boolean bFrontCallUse, bLobbyCallUse, bGuardCallUse, bResiCallUse, bPSTNCallUse, bCallHistoryUse, bVisitorPicUse;

    /* =================================================================================================
     * [ Activity Life Cycle ] region
     ================================================================================================ */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        try {
            Log.i(TAG, "=============== [START - MainActivity] ===============");

            registerWallPadCallLiveBRReceiver();

            Global.setGlobalContext(this);
            Global.getConfigValues();   // 디바이스 설정
            nSysVolume = Global.getConfigSystemVolume();

            if (ConfigValues.DEVICE_MODELTYPE == MODEL_TYPE.IHN_1020B_I) bFFMPEGEnable = true;
            else bFFMPEGEnable = false;
            Log.i(TAG, "[onCreate] bFFMPEGEnable [" + bFFMPEGEnable + "]");

            registerBRReceiver();

            if (ConfigValues.bReliefCall) {
                Log.i(TAG, "[onCreate] --------------- ReliefCallInterface ---------------");
                mReliefCallIF = new ReliefCallInterface();
            }

            // API 호출
            if (OPERATION_MODE == Common.MODE_NORMAL) {
                LOG_DEBUG("OperationMode = MODE_NORMAL");
                try {
                    mWallPadAPI = new WallPadAPI(this);
                    if (ConfigValues.DEVICE_BOARDTYPE == BOARD_TYPE.V40_IGW300 || ConfigValues.DEVICE_BOARDTYPE == BOARD_TYPE.V40_IGW300_NOUGAT) {
                        // IHN-D101 일 경우, 스마트폰 조명제어 사용여부 설정 제어하기 위함 (거실에너지미터 BT-Wifi 모듈이 마이크에 무선 노이즈를 발생시키므로)
                        mWallPadApiCheckHandler.sendEmptyMessage(2);
                    }

                    if (ConfigValues.eDoorLockType == DOORLOCKTYPE.FINGERPRINT) {
                        // 지문인식 도어락일경우, API 로딩
                        mWallPadApiCheckHandler.sendEmptyMessage(4);
                    }
                } catch (RuntimeException re) {
                    LogUtil.errorLogInfo("", TAG, re);
                } catch (Exception e) {
                    Log.e(TAG, "[ExceptionError] - new WallPadAPI : " + e);
                    //e.printStackTrace();
                    LogUtil.errorLogInfo("", TAG, e);
                }
            }
            else if (OPERATION_MODE == Common.MODE_BUSINESS_SAMPLE) {
                LOG_DEBUG("OperationMode = MODE_BUSINESS_SAMPLE");
            }

            checkDevService(); // 디바이스 서비스 실행여부를 확인하고, 실행중이 아니면 실행시킨다.
            initIOInterface();   // I/O 제어 JNI
            mSound = new WpadSound(this);

            if (ConfigValues.DEVICE_MODELTYPE == MODEL_TYPE.IHN_D101) LOG_INFO("[onCreate] Model Type [IHN_D101]");
            else if (ConfigValues.DEVICE_MODELTYPE == MODEL_TYPE.IHN_D101_I) LOG_INFO("[onCreate] Model Type [IHN_D101-I]");
            else if (ConfigValues.DEVICE_MODELTYPE == MODEL_TYPE.IHN_D101_I_LX2) LOG_INFO("[onCreate] Model Type [IHN_D101-I_LX2]");
            else if (ConfigValues.DEVICE_MODELTYPE == MODEL_TYPE.IHN_D101_I_OCF) LOG_INFO("[onCreate] Model Type [IHN_D101-I-OCF]");
            else if (ConfigValues.DEVICE_MODELTYPE == MODEL_TYPE.IHN_1010GL) LOG_INFO("[onCreate] Model Type [IHN_1010GL]");
            else if (ConfigValues.DEVICE_MODELTYPE == MODEL_TYPE.IHN_1010GL_I) LOG_INFO("[onCreate] Model Type [IHN_1010GL-I]");
            else if (ConfigValues.DEVICE_MODELTYPE == MODEL_TYPE.IHN_1010GL_I_2443) LOG_INFO("[onCreate] Model Type [IHN_1010GL-I-2443]");
            else if (ConfigValues.DEVICE_MODELTYPE == MODEL_TYPE.IHN_1010GL_I_6410) LOG_INFO("[onCreate] Model Type [IHN_1010GL-I-6410]");
            else if (ConfigValues.DEVICE_MODELTYPE == MODEL_TYPE.IHN_D101K) LOG_INFO("[onCreate] Model Type [IHN_D101K]");
            else if (ConfigValues.DEVICE_MODELTYPE == MODEL_TYPE.IHN_D101K_I) LOG_INFO("[onCreate] Model Type [IHN_D101K-I]");
            else if (ConfigValues.DEVICE_MODELTYPE == MODEL_TYPE.IHN_1010) {
                if (ConfigValues.eWallPadType == WALLPADTYPE.MAIN) LOG_INFO("[onCreate] Model Type [IHN_1010]");
                else LOG_INFO("[onCreate] Model Type [IHN_1010S]"); // 서브월패드
            }
            else if (ConfigValues.DEVICE_MODELTYPE == MODEL_TYPE.IHN_1010_I) {
                if (ConfigValues.eWallPadType == WALLPADTYPE.MAIN) LOG_INFO("[onCreate] Model Type [IHN_1010-I]");
                else LOG_INFO("[onCreate] Model Type [IHN_1010-IS]"); // 서브월패드
            }
            else if (ConfigValues.DEVICE_MODELTYPE == MODEL_TYPE.IHN_1010_I_LX2) LOG_INFO("[onCreate] Model Type [IHN_1010-I-LX2]");
            else if (ConfigValues.DEVICE_MODELTYPE == MODEL_TYPE.IHN_1030_I) LOG_INFO("[onCreate] Model Type [IHN_1030-I]");
            else if (ConfigValues.DEVICE_MODELTYPE == MODEL_TYPE.IHN_1040) LOG_INFO("[onCreate] Model Type [IHN_1040]");
            else if (ConfigValues.DEVICE_MODELTYPE == MODEL_TYPE.IHN_1040_I) LOG_INFO("[onCreate] Model Type [IHN_1040-I]");
            else if (ConfigValues.DEVICE_MODELTYPE == MODEL_TYPE.IHN_1050) LOG_INFO("[onCreate] Model Type [IHN_1050]");
            else if (ConfigValues.DEVICE_MODELTYPE == MODEL_TYPE.IHN_1050_I) LOG_INFO("[onCreate] Model Type [IHN_1050-I]");
            else if (ConfigValues.DEVICE_MODELTYPE == MODEL_TYPE.IHN_T1010) LOG_INFO("[onCreate] Model Type [IHN_T1010]");
            else if (ConfigValues.DEVICE_MODELTYPE == MODEL_TYPE.IHN_T1010_I) LOG_INFO("[onCreate] Model Type [IHN_T1010-I]");
            else if (ConfigValues.DEVICE_MODELTYPE == MODEL_TYPE.IHN_HS101) LOG_INFO("[onCreate] Model Type [IHN_HS101]");
            else if (ConfigValues.DEVICE_MODELTYPE == MODEL_TYPE.IHN_HS101_I) LOG_INFO("[onCreate] Model Type [IHN_HS101-I]");
            else if (ConfigValues.DEVICE_MODELTYPE == MODEL_TYPE.IHN_430) LOG_INFO("[onCreate] Model Type [IHN_430]");
            else if (ConfigValues.DEVICE_MODELTYPE == MODEL_TYPE.IHN_430_I) LOG_INFO("[onCreate] Model Type [IHN_430-I]");
            else if (ConfigValues.DEVICE_MODELTYPE == MODEL_TYPE.IHN_DW101_I) LOG_INFO("[onCreate] Model Type [IHN_DW101_I]");
            else if (ConfigValues.DEVICE_MODELTYPE == MODEL_TYPE.IHN_1020B_I) LOG_INFO("[onCreate] Model Type [IHN_1020B_I]");
            else if (ConfigValues.DEVICE_MODELTYPE == MODEL_TYPE.IHN_1303_I) LOG_INFO("[onCreate] Model Type [IHN_1303_I]");
            else LOG_INFO("[onCreate] ConfigValues.DEVICE_MODELTYPE [" + ConfigValues.DEVICE_MODELTYPE + "]");

            // @ AutoScale 설정
            WpadScale.setAutoScale(true);

            super.AppVersionLogOut();   // [APP Version] + [WallPadSupport Lib Version] 을 로그로 출력한다.
            LOG_INFO("[Create] WallPadAPI Version = [" + define.WALLPADAPI_VERSION + "]");

            mContext = this;
            ManualActivityRun = false;

//            setCallAppRunning(true);
            setPopupActivityRun(false);
//            checkMemoryUsage(); // 통화 앱 시작시 메모리 체크
            getCallFunctionUse();

            mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
            mPowerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
            Global.ctrlLCDOnOff(true);

            // ****************** VOLUME 값 확인 ******************
            Log.d(TAG, "[VOLUME TEST] nSysVolume [" + nSysVolume + "]");
//        Log.d(TAG, "[VOLUME TEST] STREAM_SYSTEM ---> Volume : " + mAudioManager.getStreamVolume(AudioManager.STREAM_SYSTEM));
//        Log.d(TAG, "[VOLUME TEST] STREAM_VOICE_CALL ---> Volume : " + mAudioManager.getStreamVolume(AudioManager.STREAM_VOICE_CALL));
//        Log.d(TAG, "[VOLUME TEST] STREAM_RING ---> Volume : " + mAudioManager.getStreamVolume(AudioManager.STREAM_RING));
//        Log.d(TAG, "[VOLUME TEST] STREAM_DTMF ---> Volume : " + mAudioManager.getStreamVolume(AudioManager.STREAM_DTMF));

            // 2. 자동 종료 셋팅
            LOG_INFO("[Create] - Step2 : Auto Finish Setting");
            //     2-1. 자동종료 타이머 셋팅
            super.setFinishTimerCreate(Common.FINISH_TIME_SEC);

            // 3. API 호출 -> 코드 이동

            // 4. Layout registration
            LOG_INFO("[Create] - Step4 : Layout registration");
            allWidth = WpadScale.getWidthPixels();
            allHeight = WpadScale.getHeightPixels();
            screenWidth = 1280;
            screenHeight = 800;
            topHeight = 110;
            fontSize = Common.fontsize._44;
            LOG("[Create] allWidth [" + allWidth + "], allHeight [" + allHeight + "]");

            //     4-1. mainLayout
            AllLayout = new RelativeLayout(this);
            RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(allWidth, allHeight);
            AllLayout.setLayoutParams(params);
            AllLayout.setId(ID.MAINACTIVITY.LAYOUT.ALL);
            super.setAllLayoutRegistration(AllLayout);

            //     4-2. TopLayout
            TopLayout = new RelativeLayout(this);
            WpadUtil.LayoutRegistration(AllLayout, TopLayout, screenWidth, topHeight, 0, 0, ID.MAINACTIVITY.LAYOUT.TOP);

            //     4-4. ScreenLayout
            ScreenLayout = new RelativeLayout(this);
            WpadUtil.LayoutRegistration(AllLayout, ScreenLayout, screenWidth, screenHeight - topHeight, 0, topHeight, ID.MAINACTIVITY.LAYOUT.SCREEN);

            ScreenBackground = new WpadImageView(this, TOUCH_KIND.NONE, screenWidth, screenHeight - topHeight, R.drawable.bg_body, R.drawable.bg_body, ID.MAINACTIVITY.IMAGE.SCREEN_BACKGROUND);
            ViewRegistration(ScreenLayout, ScreenBackground, 0, 0);

            SurfaceLayout = new RelativeLayout(this);
            WpadUtil.LayoutRegistration(AllLayout, SurfaceLayout, allWidth, allHeight, 0, 0, ID.MAINACTIVITY.LAYOUT.SURFACE);

            TXT_REMOTE_ID = new WpadTextView(this, false, 356, 50, Gravity.CENTER, Color.WHITE, 30, false, ID.MAINACTIVITY.TEXT.REMOTE_ID);
            ViewRegistration(AllLayout, TXT_REMOTE_ID, 273, 577);
//        Typeface typeface = Typeface.createFromAsset(getAssets(), "fonts/NanumGothicCoding.ttf");
//        TXT_REMOTE_ID.setTypeface(typeface);
            TXT_REMOTE_ID.setVisibility(View.INVISIBLE);

            initCallEngine();
            if (ConfigValues.eWallPadType == WALLPADTYPE.MAIN) {
                initCallHistoryDB();
                initVisitorPictureHistoryDB();
            }

            // 5. Top Menu - ImageView registration
            LOG_INFO("[Create] - Step5 : Top Menu - ImageView registration");
            TopBackground = new WpadImageView(this, TOUCH_KIND.NONE, screenWidth, topHeight, R.drawable.bg_topbar, 0, ID.TOP.IMAGE.TOP_BACKGROUND);
            ViewRegistration(TopLayout, TopBackground, 0, 0);

            TopTitle = new WpadTextView(this, false, 247 + 50, 80, Gravity.LEFT, Color.WHITE, fontSize, true, ID.TOP.TEXT.TITLE);
            ViewRegistration(TopLayout, TopTitle, 133, 15);

            TopHideBtn = new WpadImageView(this, TOUCH_KIND.BUTTON_LC, 110, 110, 0, 0, ID.TOP.BUTTON.HIDE);
            ViewRegistration(TopLayout, TopHideBtn, 250, 0);

            if (OPERATION_MODE == Common.MODE_BUSINESS_SAMPLE) {
                SampleModeTitle = new WpadTextView(this, false, 200, 72, Gravity.CENTER, Color.WHITE, Common.fontsize._26_DEFAULT, true, 0);
                ViewRegistration(TopLayout, SampleModeTitle, 316, 17);
                SampleModeTitle.setText("[영업샘플모드]");
            }
            else if (Common.MODE == Common.MODE_PRODUCTION) {
                SampleModeTitle = new WpadTextView(this, false, 200, 72, Gravity.CENTER, Color.WHITE, Common.fontsize._26_DEFAULT, true, 0);
                ViewRegistration(TopLayout, SampleModeTitle, 316, 17);
                SampleModeTitle.setText("[생산 검수 모드]");
            }

            if (getStrangerRecording()) {
                TopStrangerRecodingNotice = new WpadTextView(this, false, 640, 72, Gravity.CENTER, Color.parseColor("#FF8C00"), Common.fontsize._50, true, 0);
                ViewRegistration(TopLayout, TopStrangerRecodingNotice, 320, 17);
                TopStrangerRecodingNotice.setVisibility(View.INVISIBLE);
            }

            if (ConfigValues.bRemoteCall) {
                TopRemoteCallNotice = new WpadTextView(this, false, 640, 72, Gravity.CENTER, Color.parseColor("#FF8C00"), Common.fontsize._50, true, 0);
                ViewRegistration(TopLayout, TopRemoteCallNotice, 320, 17);
                TopRemoteCallNotice.setVisibility(View.INVISIBLE);
            }

            TopHomeBtn = new WpadImageView(this, TOUCH_KIND.BUTTON, 110, 110, R.drawable.topbar_icon_home_normal, R.drawable.topbar_icon_home_pressed, ID.TOP.BUTTON.HOME);
            ViewRegistration(TopLayout, TopHomeBtn, 1145, 0);

            TopBackBtn = new WpadImageView(this, TOUCH_KIND.BUTTON, 110, 110, R.drawable.topbar_icon_back_normal, R.drawable.topbar_icon_back_pressed, ID.TOP.BUTTON.BACK);
            ViewRegistration(TopLayout, TopBackBtn, 1019, 0);
            setTopBackBtnVisible(false);

            bBlockTopMenuBTN = true;
            sendHandlerMsgDelayed(HANDLERMSG.RELEASE_TOPMENUBTN_BLOCK, 0, 0, 2000);
            TopMenuBtn = new WpadImageView(this, TOUCH_KIND.BUTTON_LC, 110, 110, R.drawable.topbar_icon_menu_normal, R.drawable.topbar_icon_menu_pressed, ID.TOP.BUTTON.MENU);
            ViewRegistration(TopLayout, TopMenuBtn, 0, 0);
            setTopMenuBtnVisible(true);

            TopManualBtn = new WpadImageView(this, TOUCH_KIND.BUTTON, 110, 110, R.drawable.topbar_icon_manual_normal, R.drawable.topbar_icon_manual_pressed, ID.TOP.BUTTON.MANUAL);
            setManualBtnVisible(getManualUse(), 1019);
            setTopHideBtnVisible(false);

            // 6. Menu Loading
            LOG_INFO("[Create] - Step6 : Menu Loading");
            //     6-1. 메뉴 정보를 가져온다 (DB에서 가져온다)
            wallpaddbmgr mwallpaddbmgr = new wallpaddbmgr(getApplicationContext());
            mwallpaddbmgr.DeleteMenuList();

            ArrayList<ArrayList<Integer>> mGroupList = null;
            ArrayList<Integer> mChildList = null;

            mGroupList = new ArrayList<ArrayList<Integer>>();
            mChildList = new ArrayList<Integer>();
            if (ConfigValues.eWallPadType == WALLPADTYPE.MAIN) {
                if (bFrontCallUse) mChildList.add(API_Menu.SubMenuCall.Door);
                if (bLobbyCallUse) mChildList.add(API_Menu.SubMenuCall.Lobby);
                if (bGuardCallUse) mChildList.add(API_Menu.SubMenuCall.Guard);
                if (bResiCallUse) mChildList.add(API_Menu.SubMenuCall.Neighbor);
                if (bPSTNCallUse) mChildList.add(API_Menu.SubMenuCall.PSTN);
                if (bCallHistoryUse) mChildList.add(API_Menu.SubMenuCall.CallList);
                if (bVisitorPicUse) mChildList.add(API_Menu.SubMenuCall.Visitor);
            }
            else {
                if (bFrontCallUse) mChildList.add(ID.SCREEN.SCREEN_TALKFRONT_SUBWALLPAD);
                if (bLobbyCallUse) mChildList.add(ID.SCREEN.SCREEN_TALKLOBBY_SUBWALLPAD);
                if (bGuardCallUse) mChildList.add(ID.SCREEN.SCREEN_TALKGUARD_SUBWALLPAD);
                if (bResiCallUse) mChildList.add(ID.SCREEN.SCREEN_TALKRESIDENCE_SUBWALLPAD);
            }
            mGroupList.add(mChildList);
            mwallpaddbmgr.SetMenuList(mGroupList);

            menuListDataClass = mwallpaddbmgr.GetMenuList();
            mwallpaddbmgr.closeDB();

            if (menuListDataClass == null) {
                Log.e(TAG, "menueListDataClass == null, Load Default List");
                menuListDataClass = LoadDefaultMenuList();
            }

//            enableKaKaoiFunction(false);

            //     6-2. 시작 화면을 main APP으로 부터 받아서 처리한다.
            mMenu = StartMenuSetting();
            if (mMenu == null) {
                Log.w(TAG, "[onCreate] menu is null!!");
                mTempCurrentScreenId = API_Menu.SubMenuCall.Guard;
                if (!bGuardCallUse) {
                    if (bFrontCallUse) mTempCurrentScreenId = API_Menu.SubMenuCall.Door;
                    else if (bResiCallUse) mTempCurrentScreenId = API_Menu.SubMenuCall.Neighbor;
                    else if (bPSTNCallUse) mTempCurrentScreenId = API_Menu.SubMenuCall.PSTN;
                    else if (bCallHistoryUse) mTempCurrentScreenId = API_Menu.SubMenuCall.CallList;
                    else if (bVisitorPicUse) mTempCurrentScreenId = API_Menu.SubMenuCall.Visitor;
                }
                setChangeScreen(mTempCurrentScreenId, false); // 시작화면: 경비실
            }
            else {
                mTempCurrentScreenId = mMenu.getStartId();
                mWallPadApiCheckHandler.sendEmptyMessage(0);

                /** (JEFF, 2020.04.02)
                 * RS-485 통신을 이용하는 현관카메라의 경우에만 WallPadAPI 로딩 여부를 확인하게 되면, 일반 현관카메라의 경우에는
                 * WallPadAPI 연결이 늦은 경우 에러가 발생하므로 모든 경우에 WallPadAPI 연결확인을 진행한다.
                 * 여기에 구현되어 있던 현관카메라(통신) API 로딩 기능은 WallPadAPI 확인 핸들러에서 현관카메라 종류에 따라 API를 로딩하도록 수정함
                 */
//                if (ConfigValues.eFrontCameraType == FRONTCAMERATYPE.SMARTIOT || ConfigValues.eFrontCameraType == FRONTCAMERATYPE.SMART_HS || ConfigValues.eFrontCameraType == FRONTCAMERATYPE.SMART_DW) {
//                    mWallPadApiCheckHandler.sendEmptyMessage(0);
//                }
//                else {
//                    boolean result = setChangeScreen(mTempCurrentScreenId, false);
//                    if (!result) {
//                        setChangeScreen(API_Menu.SubMenuCall.Guard, false);
//                    }
//                }
            }

            // 7. Draw
            LOG_INFO("[Create] - Step7 : setContentView");
            setContentView(AllLayout);

            getCallTimeoutEnable();
            sendHandlerMsgDelayed(HANDLERMSG.CHECK_RECEIVINGCALL, 0, 0, 500);

            // 거주자 안전확인 서비스 사용여부 확인하고, 화면 WallPadSupport Lib.에 관련 설정을 한다.
            getResidentSafetyCheckSetting();

            // 8. Window Resize

            WallpadDeviceSet wallpadDeviceSet = new WallpadDeviceSet(getApplicationContext());
            mNewDanjiServer =  wallpadDeviceSet.GetNewDanjiServer();
            wallpadDeviceSet.closeDB();

            LOG_INFO("[Create] - Step8 : Window Resize");
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] onCreate(Bundle savedInstanceState)");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        }
    }

    public boolean getKakaoHomeCheck()
    {
        boolean result  = false;
        WallpadDeviceSet mWallpadDeviceSet = null;
        mWallpadDeviceSet = new WallpadDeviceSet(getContext());
        try {
            result = mWallpadDeviceSet.Get_KakaoUse();
        }
        catch (Exception e)
        {
            LogUtil.errorLogInfo("", TAG, e);
        }

        return result;
    }

    @Override
    protected void onDestroy() {
        LOG("=============== [onDestroy] ===============");
        sendBlockSIPCallBR();
        mSound.StopAll();
        mSound.Release();

        finishPopUp(ID.POPUP.POPUP_ALL);
        finishManual(ID.MANUAL.MANUAL_ALL);
        sendHandlerMsg(HANDLERMSG.RECOVER_SYSTEM_VOLUME, 0, 0);

        if (sdbLivingRoomLightAPI != null) {
            Log.d(TAG, "[onDestroy] sdbLivingRoomLightAPI.SetWifiModuleOnOff [TRUE]");
            sdbLivingRoomLightAPI.SetWifiModuleOnOff(true);
        }

        Global.ctrlLCDOnOff(false); // 절전모드 해제
        Global.stopMelodyRepeat();
        ctrlSmartIOTCamStatusMode(SmartRFCamStatusMode.STATUS_OFF);
        ctrlSmartIOTCamLEDMode(SmartRFCamLEDMode.LED_OFF);

        setChangeScreen(mCurrentScreenId, true);

        releaseCallEngine();
        if (ConfigValues.eWallPadType == WALLPADTYPE.MAIN) {
            releaseCallHistoryDB();
            releaseVisitorPictureHistoryDB();
        }

        if (mIOInterface != null) {
            mIOInterface.releaseIOInterface();
            mIOInterface = null;
        }

        unregisterWallPadCallLiveBRReceiver();

        // Handler 해제
        if (mWallPadApiCheckHandler != null) {
            mWallPadApiCheckHandler.removeMessages(0);
            mWallPadApiCheckHandler.removeMessages(1);
            mWallPadApiCheckHandler.removeMessages(2);
            mWallPadApiCheckHandler.removeMessages(3);
            mWallPadApiCheckHandler.removeMessages(4);
            mWallPadApiCheckHandler.removeMessages(5);
        }

        if (mFrontCamOpenCheckHandler != null) {
            mFrontCamOpenCheckHandler.removeMessages(0);
            mFrontCamOpenCheckHandler.removeMessages(1);
            mFrontCamOpenCheckHandler.removeMessages(2);
            mFrontCamOpenCheckHandler.removeMessages(3);
            mFrontCamOpenCheckHandler.removeMessages(4);
            mFrontCamOpenCheckHandler.removeMessages(5);
            mFrontCamOpenCheckHandler.removeMessages(6);
            mFrontCamOpenCheckHandler.removeMessages(7);
        }

        if (mCallPathCheckHandler != null) {
            mCallPathCheckHandler.removeMessages(0);
            mCallPathCheckHandler.removeMessages(1);
            mCallPathCheckHandler.removeMessages(2);
            mCallPathCheckHandler.removeMessages(3);
        }

        super.setFinishTimerDestroy();
        notifyAppFinish();
//        setCallAppRunning(false);

        Log.i(TAG, "*************************************************************");
        Log.i(TAG, "******************* [END   - MainActivity] ******************");
        Log.i(TAG, "*************************************************************");
        super.onDestroy();
    }

    @Override
    protected void onResume() {
        super.onResume();
        try {
            LOG_INFO("[onResume] ========== START ==========");
            if (mWallPadAPI != null) mWallPadAPI.Resume();
            registerBRReceiver();
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] onResume()");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        }
    }

    @Override
    protected void onPause() {
        try {
            LOG_INFO("[onPause] ========== START ==========");
            unregisterBRReceiver();
            if (mWallPadAPI != null) mWallPadAPI.Pause();
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] onResume()");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        }
        super.onPause();
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        Log.d(TAG, "[onActivityResult] requestCode [" + requestCode +"], resultCode [" + resultCode +"]");

        if (mCallController.mCallInfo.getIDLECnt() != mCallController.mCallInfo.IDLECNT_MAX) {
            super.setFinishTimerDestroy();
        }

        if (resultCode == RESULT_OK) {
            try {
                // PopupActivity 에서 FinishTimer 로 인하여 종료가 되었을 경우
                // MainActivity 도 즉시 종료시킨다.
                String code = (String) data.getExtras().get("Finish_Kind");
                Log.d(TAG, "Finish_Kind : " + code);
                if (code.equals("FinishTimer")) {
                    Log.d(TAG, "FinishTimer finish");
                    finish();
                }
            } catch (RuntimeException re) {
                LogUtil.errorLogInfo("", TAG, re);
            } catch (Exception e) {
                Log.e(TAG, "[Exception Error] [onActivityResult] - data.getExtras().get");
                //e.printStackTrace();
                LogUtil.errorLogInfo("", TAG, e);
            }
        }
    }

    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {
        if (Common.MODE == Common.MODE_PRODUCTION) {
            int KeyCode = event.getKeyCode();
            if (KeyCode == 221) {
                int Action = event.getAction();
                if (Action == KeyEvent.ACTION_DOWN) {
                    Log.i(TAG, "**************************");
                    Log.i(TAG, "   H/W Emergency BUTTON   ");
                    Log.i(TAG, "**************************");
                    mSound.PlayMent(SND.emergency.DEFAULT); // "[비상 상황]이 발생되었습니다" 비상 경고음
                    mTopBackgroundBlinkHandler.sendEmptyMessage(0);
                    return true;
                }
            }
        }

        return super.dispatchKeyEvent(event);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
        Log.d(TAG, "[onRequestPermissionsResult] requestCode: " + requestCode);
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch (requestCode) {
            case REQUEST_EXTERNAL_STORAGE: {
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    Log.d(TAG, "[onRequestPermissionsResult] PERMISSION_GRANTED");
                } else {
                    Log.d(TAG, "[onRequestPermissionsResult] PERMISSION_NOT_GRANTED");
                }
                return;
            }
        }
    }

    protected Handler mTopBackgroundBlinkHandler = new Handler() {
        int Count = 0;

        @SuppressLint("HandlerLeak")
        @Override
        public void handleMessage(Message msg) {
            if (msg.what == 0) {
                TopBackground.setImageResource(0);
                TopBackground.setBackgroundColor(Color.RED);
                mTopBackgroundBlinkHandler.sendEmptyMessageDelayed(1, 500);
                Count = 0;
            } else if (msg.what == 1) {
                TopBackground.setImageResource(R.drawable.bg_topbar);
                TopBackground.setBackgroundColor(0);
                if (++Count <= 4) mTopBackgroundBlinkHandler.sendEmptyMessageDelayed(2, 500);
            } else if (msg.what == 2) {
                TopBackground.setImageResource(0);
                TopBackground.setBackgroundColor(Color.RED);
                mTopBackgroundBlinkHandler.sendEmptyMessageDelayed(1, 500);
            }
        }
    };


    /* ================================================================================================
     * [BroadcastReceiver] Section
     ================================================================================================ */
    /**
     * BroadcastReceiver.onReceive for [WpadActivity]
     */
    @Override
    protected void onBrReceive(Intent intent) {
        super.onBrReceive(intent);
        LOG_INFO("[onBrReceive] Action : " + intent.getAction());
    }


    /* ================================================================================================
     * [Touch & Key Event] Section
     ================================================================================================ */
    private int LONGKEY_THRESHOLD = 30;
    private int nLongKeyCnt = 0;
    private int nPreviousTargetID = 0;
    private boolean bBlockTopMenuBTN = true;

    @Override
    protected void onTouchEvent(View v, MotionEvent event) {
        super.onTouchEvent(v, event);

        int TargetId = v.getId();
        int MoveEvent = event.getAction();
//        Log.d(TAG, "[onTouchEvent] TargetId [" + TargetId + "], MoveEvent [" + MoveEvent + "]");
        if (MoveEvent == MotionEvent.ACTION_UP) {
            Log.d(TAG, "[onTouchEvent] ACTION UP");
            if (TargetId == ID.TOP.BUTTON.HOME) {
                LOG_INFO("[onTouchEvent] [HOME] BUTTON");
                if (bBlockHomeBTN) return;
                bBlockHomeBTN = true;
                if (mMainEventListener != null) mMainEventListener.onMainTouchEvent(MAINEVENT.BTN_HOME);
                sendHandlerMsgDelayed(HANDLERMSG.REFRESH_HOMEICON, 0, 0, 3000);
            } else if (TargetId == ID.TOP.BUTTON.BACK) {
                LOG_INFO("[onTouchEvent] [BACK] BUTTON");
                mSound.Play(SND.effect.TOUCH_LATCHED);
                if (mCurrentScreenId == ID.SCREEN.SCREEN_VISITORPICTUREVIEWER) {
                    setChangeScreen(API_Menu.SubMenuCall.Visitor, false);
                }
            } else if (TargetId == ID.TOP.BUTTON.MENU) {
                LOG_INFO("[onTouchEvent] [MENU] BUTTON -> bBlockTopMenuBTN [" + bBlockTopMenuBTN + "], MenuOpen [" + MenuOpen + "]");
                if (bBlockTopMenuBTN) return;
                if (MenuOpen) {
                    return;
                }
                mSound.Play(SND.effect.TOUCH_LATCHED);
                OpenMenuLayout();
            } else if (TargetId == ID.MENU.BUTTON.CLOSE) {
                LOG_INFO("[onTouchEvent] [CLOSE] BUTTON");
                if (MenuOpen) {
                    mSound.Play(SND.effect.TOUCH_LATCHED);
                    CloseMenuLayout();
                }
            }
            else if (TargetId == ID.TOP.BUTTON.MANUAL) {
                LOG_INFO("[onTouchEvent] [MANUAL] BUTTON [mCurrentScreenId = " + mCurrentScreenId + "]");
                if (mCallController.mCallInfo.getTalkingCnt() <= 0)
                    mSound.Play(SND.effect.TOUCH_LATCHED); // 통화중인 경우 버튼 터치음 안나도록 설정
                if (mCurrentScreenId == API_Menu.SubMenuCall.Door) {
                    StartManual(ID.MANUAL.MANUAL_TALKFRONT);
                } else if (mCurrentScreenId == API_Menu.SubMenuCall.Lobby) {
                    StartManual(ID.MANUAL.MANUAL_TALKLOBBY);
                } else if (mCurrentScreenId == API_Menu.SubMenuCall.Guard) {
                    StartManual(ID.MANUAL.MANUAL_TALKGUARD);
                } else if (mCurrentScreenId == API_Menu.SubMenuCall.Neighbor) {
                    StartManual(ID.MANUAL.MANUAL_TALKRESIDENCE);
                } else if (mCurrentScreenId == API_Menu.SubMenuCall.PSTN) {
                    StartManual(ID.MANUAL.MANUAL_TALKPSTN);
                } else if (mCurrentScreenId == API_Menu.SubMenuCall.CallList) {
                    StartManual(ID.MANUAL.MANUAL_INQUIRYCALLHISTORY);
                } else if (mCurrentScreenId == API_Menu.SubMenuCall.Visitor) {
                    StartManual(ID.MANUAL.MANUAL_INQUIRYVISITORPICTUREHISTORY);
                } else if (mCurrentScreenId == ID.SCREEN.SCREEN_VISITORPICTUREVIEWER) {
                    StartManual(ID.MANUAL.MANUAL_VISITORPICTUREVIEWER);
                }
            }
        } else if (MoveEvent == MotionEvent.ACTION_POINTER_DOWN) {
            if (TargetId == ID.TOP.BUTTON.HIDE) {
                if (nPreviousTargetID == TargetId) {
                    if (getPopupActivityRun()) return;
                    else nLongKeyCnt++;
                    Log.v(TAG, "[onTouchEvent] TargetId [" + TargetId + "], nLongKeyCnt [" + nLongKeyCnt + "]");

                    if (nLongKeyCnt > LONGKEY_THRESHOLD) {
                        nLongKeyCnt = 0;
                        nPreviousTargetID = 0;
                        startHideMenu();
                    }
                } else {
                    nPreviousTargetID = TargetId;
                    nLongKeyCnt = 0;
                    Log.v(TAG, "[onTouchEvent] nPreviousTargetID [" + nPreviousTargetID + "], TargetId [" + TargetId + "]");
                }
            }
        }
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        Log.i(TAG, "[onKeyDown] keyCode : " + keyCode + ", Action : " + event.getAction());
        return super.onKeyDown(keyCode, event);
    }


	/* ================================================================================================
     * [TOP] Section
	 ================================================================================================ */
    /**
     * TOP 돌아가기 버튼 활성화 & 비활성화
     *
     * @param Enabled - true : 활성화,  false : 비활성화
     * @return (boolean) true : 성공,  false : 실패
     */
    public boolean setTopBackBtnVisible(boolean Enabled) {
        if (Enabled) {
            if (TopBackBtn.getVisibility() != View.VISIBLE) TopBackBtn.setVisibility(View.VISIBLE);
            TopBackBtn.bringToFront();
        } else {
            if (TopBackBtn.getVisibility() != View.INVISIBLE)
                TopBackBtn.setVisibility(View.INVISIBLE);
        }
        return true;
    }

    /**
     * TOP 메뉴 버튼 활성화 & 비활성화
     *
     * @param Enabled - true : 활성화,  false : 비활성화
     * @return (boolean) true : 성공,  false : 실패
     * 2017.11.20 SEULKI
     */
    public boolean setTopMenuBtnVisible(boolean Enabled) {
        if (Enabled) {
            if (TopMenuBtn.getVisibility() != View.VISIBLE) TopMenuBtn.setVisibility(View.VISIBLE);
            TopMenuBtn.bringToFront();
        } else {
            if (TopMenuBtn.getVisibility() != View.INVISIBLE)
                TopMenuBtn.setVisibility(View.INVISIBLE);
        }
        return true;
    }

    public boolean setTopHideBtnVisible(boolean Enabled) {
        if (Enabled) {
            if (TopHideBtn.getVisibility() != View.VISIBLE) TopHideBtn.setVisibility(View.VISIBLE);
            TopHideBtn.bringToFront();
        } else {
            if (TopHideBtn.getVisibility() != View.INVISIBLE)
                TopHideBtn.setVisibility(View.INVISIBLE);
        }
        return true;
    }


    /* ================================================================================================
     * [Popup Activity] Section
     ================================================================================================ */
    public static PopupActivity mPopupActivity;

    /**
     * Popup Activity 를 시작시킨다.
     *
     * @param ScreenId - 팝업시작시 Screen ID
     * @return (boolean) true : 성공,  false : 실패
     */
    public boolean StartPopup(int ScreenId) {
        Log.e(TAG, "[StartPopup] ScreenId [" + ScreenId + "], mCurrentPopUpScreenId [" + mCurrentPopUpScreenId + "]");
        if (getPopupActivityRun()) {
            mCurrentPopUpScreenId = ScreenId;
            return ((WpadActivity) (PopupActivity.getContext())).ChangeScreen(ScreenId);
        } else {
            if (mCurrentPopUpScreenId == ScreenId) return false;
            mCurrentPopUpScreenId = ScreenId;
            setPopupActivityRun(true);
            Intent intent = new Intent(mContext, PopupActivity.class);
            intent.putExtra("ScreenId", ScreenId);

            overridePendingTransition(0, 0);
            startActivityForResult(intent, 0);
            return true;
        }
    }

    /**
     * Popup Activity 를 시작시킨다. (시작시 Intent Type 데이터를 전달한다)
     *
     * @param ScreenId - 팝업시작시 Screen ID
     * @param data     - 전달할 데이터
     * @return (boolean) true : 성공,  false : 실패
     */
    public boolean startPopup(int ScreenId, Intent data) {
        if (getPopupActivityRun()) {
            return false;
        } else {
            if (mCurrentPopUpScreenId == ScreenId) return false;
            mCurrentPopUpScreenId = ScreenId;
            setPopupActivityRun(true);
            Intent intent = new Intent(mContext, PopupActivity.class);
            intent.putExtra("ScreenId", ScreenId);
            intent.putExtra("PopupScreenDataIntent", data);

            overridePendingTransition(0, 0);
            startActivityForResult(intent, 0);
            return true;
        }
    }

    public boolean startMultiCallPopup(int ScreenId) {
        LOG("[startMultiCallPopup] ScreenId [" + ScreenId + "]");
        if (getPopupActivityRun()) {
            return false;
        } else {
            if (mCurrentPopUpScreenId == ScreenId) return false;
            mCurrentPopUpScreenId = ScreenId;
            setPopupActivityRun(true);
            Intent intent = new Intent(mContext, PopupActivity.class);
            intent.putExtra("ScreenId", ScreenId);

            Intent data = new Intent();
            data.putExtra("BaseMultiCallType", mCallController.mCallInfo.getBaseMultiCallType().toString());
            data.putExtra("MultiCallType", mCallController.mCallInfo.getMultiCallType().toString());
            data.putExtra("MultiCallStatus", mCallController.mCallInfo.getMultiCallStatus().toString());
            data.putExtra("RemoteName", mCallController.mCallInfo.getMultiCall_Name());
            intent.putExtra("PopupScreenDataIntent", data);

            overridePendingTransition(0, 0);
            startActivityForResult(intent, 0);
            return true;
        }
    }

    public boolean startMultiCallPopup(int ScreenId, CALLSTATUS eCurrentCallStatus) {
        LOG("[startMultiCallPopup] ScreenId [" + ScreenId + "], eCurrentCallStatus [" + eCurrentCallStatus + "]");
        if (getPopupActivityRun()) {
            return false;
        } else {
            if (mCurrentPopUpScreenId == ScreenId) return false;
            mCurrentPopUpScreenId = ScreenId;
            setPopupActivityRun(true);
            Intent intent = new Intent(mContext, PopupActivity.class);
            intent.putExtra("ScreenId", ScreenId);

            Intent data = new Intent();
            data.putExtra("CurrentCallStatus", eCurrentCallStatus.toString());
            data.putExtra("MultiCallType", mCallController.mCallInfo.getMultiCallType().toString());
            data.putExtra("MultiCallStatus", mCallController.mCallInfo.getMultiCallStatus().toString());
            data.putExtra("RemoteName", mCallController.mCallInfo.getMultiCall_Name());
            intent.putExtra("PopupScreenDataIntent", data);

            overridePendingTransition(0, 0);
            startActivityForResult(intent, 0);
            return true;
        }
    }

    public static void resetCurrentPopUpScreenID() {
        try {
            mCurrentPopUpScreenId = -1;
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] resetCurrentPopUpScreenID()");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        }
    }

    public void finishPopUp(int ScreenId) {
        try {
            Log.e(TAG, "[finishPopUp] mCurrentPopUpScreenId [" + mCurrentPopUpScreenId + "], ScreenId [" + ScreenId + "]");
            if (ScreenId == ID.POPUP.POPUP_ALL) FinishPopupActivity();
            else {
                if (mCurrentPopUpScreenId != ScreenId) return;
                if (ScreenId == ID.POPUP.POPUP_NOTICE_SUBPHONETALK) {
                    Log.d(TAG, "[finishPopup] mCallController.mCallInfo.getCallOwner() [" + mCallController.mCallInfo.getCallOwner() + "]");
                    if (mCallController.mCallInfo.getCallOwner() != CALLOWNER.WALLPAD)
                        FinishPopupActivity();
                } else FinishPopupActivity();
            }
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] finishPopUp(int ScreenId)");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        }
    }

    /**
     * Popup Activity 를 종료시킨다
     */
    public void FinishPopupActivity() {
        try {
            if (mPopupActivity != null) {
                Log.i(TAG, "[FinishPopupActivity]");
                mCurrentPopUpScreenId = -1;
                mPopupActivity.finish();
            }
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] FinishPopupActivity()");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        }
    }


    /* ================================================================================================
     * [Manual Activity] Section
     ================================================================================================ */
    public static ManualActivity mManualActivity;

    public boolean StartManual(int screenId) {
        Log.d(TAG, "[StartManual] screenId [" + screenId + "], mCurrentManualScreenId [" + mCurrentManualScreenId + "]");
        if (getManualActivityRun()) {
            mCurrentManualScreenId = screenId;
            return ((WpadActivity) (ManualActivity.getContext())).ChangeScreen(screenId);
        }
        else {
            if (mCurrentManualScreenId == screenId) return false;
            mCurrentManualScreenId = screenId;
            setManualActivityRun(true);
            Intent intent = new Intent(mContext, ManualActivity.class);
            intent.putExtra("ScreenId", screenId);

            overridePendingTransition(0, 0);
            startActivityForResult(intent, 0);
            return true;
        }
    }

    public static void resetCurrentManualScreenID() {
        try {
            mCurrentManualScreenId = -1;
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] resetCurrentManualScreenID()");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        }
    }

    public void finishManual(int screenId) {
        try {
            Log.d(TAG, "[finishManual] mCurrentManualScreenId [" + mCurrentManualScreenId +"], screenId [" + screenId +"]");

            if (screenId == ID.MANUAL.MANUAL_ALL) FinishManualActivity();
            else {
                if (mCurrentManualScreenId != screenId) return;
                FinishManualActivity();
            }
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] finishManual(int screenId)");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        }
    }

    public static void FinishManualActivity() {
        Log.i(TAG, "[FinishManualActivity]");
        try {
            if (mManualActivity != null) {
                mCurrentManualScreenId = -1;
                mManualActivity.finish();
            }
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] FinishManualActivity()");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        }
    }

    /**
     * 매뉴얼 버튼 사용 유무
     * @return boolean 타입 - true: 사용, false: 미사용
     */
    public boolean getManualUse() {
        WallpadDeviceSet devSet = new WallpadDeviceSet(mContext);
        String[] DBinfo = devSet.GetSettingData("매뉴얼");
        devSet.closeDB();
        if (DBinfo != null) {
            if (DBinfo[1].indexOf("사용함") > 0) {
                Log.d(TAG, "[getManualUse] Use Manual");
                return true;
            } else {
                // 미사용
                Log.d(TAG, "[getManualUse] Not Use Manual [1]");
                return false;
            }
        } else {
            // 미사용
            Log.d(TAG, "[getManualUse] Not Use Manual [2]");
            return false;
        }
    }

    public void setManualBtnVisible(boolean bUse, int marginLeft) {
        try {
            Log.d(TAG, "[setManualBtnVisible] bUse [" + bUse + "], marginLeft [" + marginLeft + "]");
            if (bUse) TopManualBtn.setVisibility(View.VISIBLE);
            else TopManualBtn.setVisibility(View.INVISIBLE);
            TopLayout.removeView(TopManualBtn);
            ViewRegistration(TopLayout, TopManualBtn, marginLeft, 0);
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] setManualBtnVisible(boolean bEnable)");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        }
    }

    public void setTopSetBtnVisible(boolean Enabled) {
        if (TopSetBtn != null) {
            if (Enabled) {
                if (TopSetBtn.getVisibility() != View.VISIBLE) TopSetBtn.setVisibility(View.VISIBLE);
                TopSetBtn.bringToFront();

                if (TopSetBtn.getVisibility() == View.VISIBLE) {
                    WpadUtil.ViewMove(TopManualBtn, 893, 0);
                }
            } else {
                if (TopSetBtn.getVisibility() != View.INVISIBLE)
                    TopSetBtn.setVisibility(View.INVISIBLE);

                if (TopSetBtn.getVisibility() == View.INVISIBLE) {
                    WpadUtil.ViewMove(TopManualBtn, 1019, 0);
                }
            }
        }
    }


	/* ================================================================================================
     * [Screen] Section
	 ================================================================================================ */
    /**
     * Screen 에서 Screen 변경을 요청할 경우 호출된다.<br>
     * Override 사용하여 Screen 변경을  처리한다.<br>
     *
     * @param nScreenId - 변경할 Screen ID
     * @return (boolean) true : 성공, false : 실패
     */
    @Override
    protected boolean onChangeScreen(int nScreenId) {
        super.onChangeScreen(nScreenId);
        return setChangeScreen(nScreenId, false);
    }

    /**
     * Screen 등록자<br>
     * ScreenLayout 에 현재 Screen 을 삭제하고, 새로운 Screen 을 등록시킨다.
     *
     * @param nScreenId  - 변경할 Screen ID
     * @param OnlyRemove - 현재 Screen 을 삭제만 할 경우 (onDestroy 에서 사용)
     * @return (boolean) true : 성공,  false : 실패
     */
    public boolean setChangeScreen(int nScreenId, boolean OnlyRemove) {
        LOG_INFO("[setChangeScreen] OnlyRemove [" + OnlyRemove + "], CurrentLayoutId(mCurrentScreenId) [" + mCurrentScreenId + "], NextLayoutId(nScreenId) [" + nScreenId + "]");
        if (!OnlyRemove && mCurrentScreenId == nScreenId) {
            Log.w(TAG, "[setChangeScreen] mCurrentScreenId is same as nScreenId");
            setFinishTimerCreate(Common.FINISH_TIME_START_SCREEN);
            return true;
        }

        // 1. 현재 Layout 삭제
        if (mCurrentScreenId > 0) {
            ScreenLayout.removeAllViews();
            super.setCurrentScreen(null);
        }

        if (OnlyRemove) return true;

        mCurrentScreenId = nScreenId;

        // 2. 새로운 Layout 표시
        try {
            switch (nScreenId) {
                case API_Menu.SubMenuCall.Door:
                    setTitleText(API_Menu.SubMenuCall.Name_Door);
                    ScreenTalkFront = new TalkFront(this, ScreenLayout);
                    super.setCurrentScreen(ScreenTalkFront);
                    break;

                case API_Menu.SubMenuCall.Lobby:
                    setTitleText(API_Menu.SubMenuCall.Name_Lobby);
                    ScreenTalkLobby = new TalkLobby(this, ScreenLayout);
                    super.setCurrentScreen(ScreenTalkLobby);
                    break;

                case API_Menu.SubMenuCall.Guard:
                    setTitleText(API_Menu.SubMenuCall.Name_Guard);
                    ScreenTalkGuard = new TalkGuard(this, ScreenLayout);
                    super.setCurrentScreen(ScreenTalkGuard);
                    break;

                case API_Menu.SubMenuCall.Neighbor:
                    setTitleText(API_Menu.SubMenuCall.Name_Neighbor);
                    ScreenTalkResidence = new TalkResidence(this, ScreenLayout);
                    super.setCurrentScreen(ScreenTalkResidence);
                    break;

                case API_Menu.SubMenuCall.PSTN:
                    setTitleText(API_Menu.SubMenuCall.Name_PSTN);
                    ScreenTalkPSTN = new TalkPSTN(this, ScreenLayout, mWallPadAPI);
                    super.setCurrentScreen(ScreenTalkPSTN);
                    break;

                case API_Menu.SubMenuCall.CallList:
                    setTitleText(API_Menu.SubMenuCall.Name_CallList);
                    ScreenInquiryCallHistory = new InquiryCallHistory(this, ScreenLayout);
                    super.setCurrentScreen(ScreenInquiryCallHistory);
                    break;

                case API_Menu.SubMenuCall.Visitor:
                    setTitleText(API_Menu.SubMenuCall.Name_Visitor);
                    ScreenInquiryVisitorPictureHistory = new InquiryVisitorPictureHistory(this, ScreenLayout);
                    super.setCurrentScreen(ScreenInquiryVisitorPictureHistory);
                    break;

                case ID.SCREEN.SCREEN_VISITORPICTUREVIEWER:
                    ScreenVisitorPictureViewer = new VisitorPictureViewer(this, ScreenLayout);
                    super.setCurrentScreen(ScreenVisitorPictureViewer);
                    break;

                case ID.SCREEN.SCREEN_TALKFRONT_SUBWALLPAD:
                    setTitleText(API_Menu.SubMenuCall.Name_Door);
                    ScreenTalkFrontSub = new TalkFront_SubWallPad(this, ScreenLayout);
                    super.setCurrentScreen(ScreenTalkFrontSub);
                    break;

                case ID.SCREEN.SCREEN_TALKLOBBY_SUBWALLPAD:
                    setTitleText(API_Menu.SubMenuCall.Name_Lobby);
                    ScreenTalkLobbySub = new TalkLobby_SubWallPad(this, ScreenLayout);
                    super.setCurrentScreen(ScreenTalkLobbySub);
                    break;

                case ID.SCREEN.SCREEN_TALKGUARD_SUBWALLPAD:
                    setTitleText(API_Menu.SubMenuCall.Name_Guard);
                    ScreenTalkGuardSub = new TalkGuard_SubWallPad(this, ScreenLayout);
                    super.setCurrentScreen(ScreenTalkGuardSub);
                    break;

                case ID.SCREEN.SCREEN_TALKRESIDENCE_SUBWALLPAD:
                    setTitleText(API_Menu.SubMenuCall.Name_Neighbor);
                    ScreenResidenceSub = new TalkResidence_SubWallPad(this, ScreenLayout);
                    super.setCurrentScreen(ScreenResidenceSub);
                    break;

                case ID.SCREEN.SCREEN_TALKPSTN_SUBWALLPAD:
                    setTitleText(API_Menu.SubMenuCall.Name_PSTN);
                    ScreenPSTNSub = new TalkPSTN_SubWallPad(this, ScreenLayout);
                    super.setCurrentScreen(ScreenPSTNSub);
                    break;

                default:
                    Log.e(TAG, "[setChangeScreen] nScreenId Not found!!! [" + mCurrentScreenId + "]");
                    mCurrentScreenId = -1;
                    return false;
            }
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
            return false;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] setChangeScreen->Screen Create");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
            return false;
        }

        return true;
    }

    private void setTitleText(String setText) {
        if (setText != null)
            TopTitle.setText(setText);
    }

    /**
     * 통화기능 사용여부 판별
     */
    private void getCallFunctionUse() {
        WallpadDeviceSet devSet = new WallpadDeviceSet(mContext);
        bFrontCallUse = devSet.Get_FrontCallUse();
        bLobbyCallUse = devSet.Get_LobbyCallUse();
        bGuardCallUse = devSet.Get_GuardCallUse();
        bResiCallUse = devSet.Get_ResidenceCallUse();
        bPSTNCallUse = devSet.Get_PSTNCallUse();
        bCallHistoryUse = devSet.Get_CallHistoryUse();
        bVisitorPicUse = devSet.Get_VisitorPicUse();
        devSet.closeDB();

        LOG("[getCallFunctionUse] bFrontCallUse [" + bFrontCallUse + "], bLobbyCallUse [" + bLobbyCallUse + "], bGuardCallUse [" + bGuardCallUse + "], " +
                "bResiCallUse [" + bResiCallUse + "], bPSTNCallUse [" + bPSTNCallUse + "], bCallHistoryUse [" + bCallHistoryUse + "], bVisitorPicUse [" + bVisitorPicUse + "]");
    }


    /* ================================================================================================
     * [Menu Layout] Section
     ================================================================================================ */
    /**
     * 콜 호출에 의한 화면 변경시에만 호출
     **/
    public void changeMenuNScreen(int nMenuID) {
        try {
            LOG("[changeMenuNScreen] nMenuID [" + nMenuID + "]");

            int nScreenId;

            if (ConfigValues.eWallPadType == WALLPADTYPE.MAIN) {
                switch (nMenuID) {
                    case ID.MENU.MENU_TALKFRONT:
                        nScreenId = API_Menu.SubMenuCall.Door;
                        break;
                    case ID.MENU.MENU_TALKLOBBY:
                        nScreenId = API_Menu.SubMenuCall.Lobby;
                        break;
                    case ID.MENU.MENU_TALKGUARD:
                        nScreenId = API_Menu.SubMenuCall.Guard;
                        break;
                    case ID.MENU.MENU_TALKRESIDENCE:
                        nScreenId = API_Menu.SubMenuCall.Neighbor;
                        break;
                    case ID.MENU.MENU_TALKPSTN:
                        nScreenId = API_Menu.SubMenuCall.PSTN;
                        break;
                    case ID.MENU.MENU_INQUIRYCALLHISTORY:
                        nScreenId = API_Menu.SubMenuCall.CallList;
                        break;
                    case ID.MENU.MENU_INQUIRYVISITORPIC:
                        nScreenId = API_Menu.SubMenuCall.Visitor;
                        break;

                    default:
                        nScreenId = -1;
                        break;
                }
            }
            else {
                switch (nMenuID) {
                    case ID.MENU.MENU_TALKFRONT:
                        nScreenId = ID.SCREEN.SCREEN_TALKFRONT_SUBWALLPAD;
                        break;
                    case ID.MENU.MENU_TALKLOBBY:
                        nScreenId = ID.SCREEN.SCREEN_TALKLOBBY_SUBWALLPAD;
                        break;
                    case ID.MENU.MENU_TALKGUARD:
                        nScreenId = ID.SCREEN.SCREEN_TALKGUARD_SUBWALLPAD;
                        break;
                    case ID.MENU.MENU_TALKRESIDENCE:
                        nScreenId = ID.SCREEN.SCREEN_TALKRESIDENCE_SUBWALLPAD;
                        break;
                    case ID.MENU.MENU_TALKPSTN:
                        nScreenId = ID.SCREEN.SCREEN_TALKPSTN_SUBWALLPAD;
                        break;
                    default:
                        nScreenId = -1;
                        break;
                }
            }

            if (nScreenId > 0) {
                setChangeScreen(nScreenId, false);
            }
            else LOG_WARN("[changeMenuNScreen] nScreen id is less than zero!");
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] changeMenuNScreen(int nMenuID)");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        }
    }

    private int getScreenId(CALLTYPE eCallType) {
        try {
            Log.d(TAG, "[getScreenId]");
            if (ConfigValues.eWallPadType == WALLPADTYPE.MAIN) {
                if (eCallType == CALLTYPE.FRONT) return API_Menu.SubMenuCall.Door;
                else if (eCallType == CALLTYPE.LOBBY) return API_Menu.SubMenuCall.Lobby;
                else if (eCallType == CALLTYPE.GUARD) return API_Menu.SubMenuCall.Guard;
                else if (eCallType == CALLTYPE.RESIDENCE) return API_Menu.SubMenuCall.Neighbor;
                else if (eCallType == CALLTYPE.PSTN) return API_Menu.SubMenuCall.PSTN;
                else if (eCallType == CALLTYPE.HISTORY_CALL) return API_Menu.SubMenuCall.CallList;
                else if (eCallType == CALLTYPE.HISTORY_VISITORPIC) return API_Menu.SubMenuCall.Visitor;
                else return API_Menu.SubMenuCall.Guard;
            }
            else {
                if (eCallType == CALLTYPE.FRONT) return ID.SCREEN.SCREEN_TALKFRONT_SUBWALLPAD;
                else if (eCallType == CALLTYPE.LOBBY) return ID.SCREEN.SCREEN_TALKLOBBY_SUBWALLPAD;
                else if (eCallType == CALLTYPE.GUARD) return ID.SCREEN.SCREEN_TALKGUARD_SUBWALLPAD;
                else if (eCallType == CALLTYPE.RESIDENCE) return ID.SCREEN.SCREEN_TALKRESIDENCE_SUBWALLPAD;
                else if (eCallType == CALLTYPE.PSTN) return ID.SCREEN.SCREEN_TALKPSTN_SUBWALLPAD;
                else return ID.SCREEN.SCREEN_TALKGUARD_SUBWALLPAD;
            }
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
            return API_Menu.SubMenuCall.Guard;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] getScreenId");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
            return API_Menu.SubMenuCall.Guard;
        }
    }

    private int getConvertScreenId(int nScreenId) {
        try {
            switch (nScreenId) {
                case ID.SCREEN.SCREEN_TALKFRONT_SUBWALLPAD:
                    return API_Menu.SubMenuCall.Door;

                case ID.SCREEN.SCREEN_TALKLOBBY_SUBWALLPAD:
                    return API_Menu.SubMenuCall.Lobby;

                case ID.SCREEN.SCREEN_TALKGUARD_SUBWALLPAD:
                    return API_Menu.SubMenuCall.Guard;

                case ID.SCREEN.SCREEN_TALKRESIDENCE_SUBWALLPAD:
                    return API_Menu.SubMenuCall.Neighbor;

                default:
                    return API_Menu.SubMenuCall.Guard;

            }
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
            return API_Menu.SubMenuCall.Guard;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] int getConvertScreenId(int nScreenId)");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
            return API_Menu.SubMenuCall.Guard;
        }
    }

    private Menu StartMenuSetting() {
        Log.d(TAG, "[StartMenuSetting]");
        Menu mMenu = new Menu();

        Intent mIntent = getIntent();
        strCallOwner = mIntent.getStringExtra(CALLTRIGGER.CALLOWNER);
        strCallEvent = mIntent.getStringExtra(CALLTRIGGER.CALLEVENTTYPE);
        strCallType = mIntent.getStringExtra(CALLTRIGGER.CALLTYPE);
        strRemoteInfo = mIntent.getStringExtra(CALLTRIGGER.REMOTEINFO);

        int nStartScreenId = API_Menu.SubMenuCall.Guard;
        Log.d(TAG, "[StartMenuSetting] strCallOwner [" + strCallOwner + "], strCallEvent [" + strCallEvent + "], " + "strCallType [" + strCallType + "], strRemoteInfo [" + strRemoteInfo + "]");
        if (strCallEvent != null && strCallType != null) {
            nStartScreenId = getScreenId(CALLTYPE.getCALLTYPE(strCallType));
            Log.d(TAG, "[StartMenuSetting] strCallEvent [" + strCallEvent + "], nStartScreenId [" + nStartScreenId + "]");
        }

        mMenu.StartId = nStartScreenId;
        mMenu.Opiton = -1;

        return mMenu;
    }

    /**
     * 메뉴 레이아웃 생성
     **/
    private void OpenMenuLayout() {
        Log.d(TAG, "[OpenMenuLayout] MenuOpen [" + MenuOpen + "]");
        if (MenuOpen) {
            return;
        }

        if (menuListDataClass == null) {
            return;
        }

        //0. 현재 ID 및 리스트 불러오기
        String Title = null;
        String TempChildName = null;
        int ChooseGroup = 0;
        int ChooseChild = 0;

        if (ConfigValues.eWallPadType == WALLPADTYPE.MAIN) {
            Title = API_Menu.GetGroupNameByID((mCurrentScreenId / 1000) * 1000);
            for (int i = 0; i < menuListDataClass.arrayGroup.size(); i++) {
                if (menuListDataClass.arrayGroup.get(i).equals(Title)) {
                    ChooseGroup = i;
                    break;
                }
            }

            for (int i = 0; i < menuListDataClass.idMappingTable.length; i++) {
                if (menuListDataClass.idMappingTable[i].Id == mCurrentScreenId) {
                    TempChildName = menuListDataClass.idMappingTable[i].Name;
                    break;
                } else if (ID.SCREEN.SCREEN_VISITORPICTUREVIEWER == mCurrentScreenId) {
                    // 방문자사진 상세보기 화면에서 메뉴 버튼 클릭 기능 구현 seulki
                    Title = API_Menu.SubMenuCall.Name;
                    TempChildName = API_Menu.SubMenuCall.Name_Visitor;
                    break;
                }
            }
        }
        else {
            int convertScreenId = getConvertScreenId(mCurrentScreenId);
            Title = API_Menu.GetGroupNameByID((convertScreenId / 1000) * 1000);
            LOG("[OpenMenuLayout] mCurrentScreenId [" + convertScreenId + "], Title [" + Title + "]");

            for (int i = 0; i < menuListDataClass.arrayGroup.size(); i++) {
                if (menuListDataClass.arrayGroup.get(i).equals(Title)) {
                    ChooseGroup = i;
                    break;
                }
            }

            for (int i = 0; i < menuListDataClass.idMappingTable.length; i++) {
                if (menuListDataClass.idMappingTable[i].Id == mCurrentScreenId) {
                    TempChildName = menuListDataClass.idMappingTable[i].Name;
                    break;
                }
            }
        }

        if (TempChildName == null) {
            Log.e(TAG, "[OpenMenuLayout] TempChildName == null");
            return;
        }

        for (int i = 0; i < menuListDataClass.arrayChild.get(Title).size(); i++) {
            Log.d(TAG, "[OpenMenuLayout] menuListDataClass.arrayChild.get(Title).get(i): " + menuListDataClass.arrayChild.get(Title).get(i));
            if (menuListDataClass.arrayChild.get(Title).get(i).equals(TempChildName)) {
                ChooseChild = i;
                break;
            }
        }

        //1. 기존 화면 투명도 변경
        TopLayout.setAlpha(0.5f);
        ScreenLayout.setAlpha(0.5f);

        // 모티터링중 메뉴오픈시 겹침현상 해결 -> FRONT SurfaceView INVISIBLE
        if (FrontVideoSurface != null) {
            FrontVideoSurface.setVisibility(View.INVISIBLE);
        }

        //2. Layout 생성 및 처리 이벤트 등록
        MenuLayout = new RelativeLayout(this);
        WpadUtil.LayoutRegistration(AllLayout, MenuLayout, screenWidth, screenHeight, 0, 0, ID.MAINACTIVITY.LAYOUT.MENU);
        MenuLayout.setOnTouchListener(new Button.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                if (event.getAction() == MotionEvent.ACTION_UP) {
                    setFinishTimerReset();
                    CloseMenuLayout();
                }
                return true;
            }
        });

        //3. 배경 이미지 생성 및 에니메이션 등록
        MenuBackground = new WpadImageView(this, TOUCH_KIND.BUTTON, 460, 800, R.drawable.bg_menu, R.drawable.bg_menu, ID.MENU.IMAGE.BACKGROUND);
        TranslateAnimation anim = new TranslateAnimation(WpadScale.getWidth(-460), 0, 0, 0);
        anim.setDuration(200);
        anim.setInterpolator(new AccelerateInterpolator());
        MenuLayout.setAnimation(anim);
        ViewRegistration(MenuLayout, MenuBackground, 0, 0);

        //4. 타이틀 등록
        MenuTitle = new WpadTextView(this, false, 247, 80, Gravity.LEFT, Color.WHITE, fontSize, true, ID.TOP.TEXT.TITLE);
        ViewRegistration(MenuLayout, MenuTitle, 133, 15);
        MenuTitle.setText(Title);

        //5. 종료 버튼 등록
        MenuClose = new WpadImageView(this, TOUCH_KIND.BUTTON, 80, 80, R.drawable.topbar_icon_close_normal, R.drawable.topbar_icon_close_pressed, ID.MENU.BUTTON.CLOSE);
        MenuClose.setTouchDelayMs(1000);
        ViewRegistration(MenuLayout, MenuClose, 380, 15);

        //6. 리스트뷰 초기화 및 등록
        mListView = new ExpandableListView(this);
        ExpandableListView.LayoutParams params = new ExpandableListView.LayoutParams(WpadScale.getWidth(460), WpadScale.getHeight(690));
        mListView.setLayoutParams(params);
        mListView.setX(WpadScale.getWidth(0));
        mListView.setY(WpadScale.getHeight(112));
        mListView.setBackgroundColor(Color.BLACK);
        mListView.setId(ID.MENU.VIEW.LISTVIEW);
        mListView.setGroupIndicator(null);
        mListView.setDividerHeight(0);
        mListView.setDivider(null);
        mListView.setFocusable(true);
        mListView.setSmoothScrollbarEnabled(true);
        mListView.setTranscriptMode(android.widget.AbsListView.TRANSCRIPT_MODE_DISABLED);
        mListView.setScrollbarFadingEnabled(true);

        MenuLayout.addView(mListView);
        adptMain = new Menu_AdptMain(this, menuListDataClass.arrayGroup, menuListDataClass.arrayChild, ChooseGroup, ChooseChild);
        mListView.setAdapter(adptMain);

        //7. 선택된 그룹 열기
        mListView.setSelectedGroup(ChooseGroup);
        mListView.expandGroup(ChooseGroup);

        // 8. 리스트뷰 터치 이벤트 등록
        mListView.setOnTouchListener(new View.OnTouchListener() {

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                if ((event.getAction() == MotionEvent.ACTION_DOWN) ||
                        (event.getAction() == MotionEvent.ACTION_UP)) {
                    WpadActivity.setFinishTimerReset();
                }
                return false;
            }
        });

        // 9. 그룹 터치 이벤트 등록
        mListView.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
            @Override
            public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
                LOG_INFO("group click = " + groupPosition);
                WpadActivity.setFinishTimerReset();
                return false;
            }
        });

        /*
        // 10. 차일드 터치 이벤트 등록
        mListView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
            @Override
            public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
                LOG_INFO("onChildClick");
                LOG_INFO("groupPosition = " + groupPosition);
                LOG_INFO("childPosition = " + childPosition);
                WpadActivity.setFinishTimerReset();
                return false;
            }
        });
        */

        // 11. 그룹 열리는 경우 이벤트
        mListView.setOnGroupExpandListener(new ExpandableListView.OnGroupExpandListener() {
            @Override
            public void onGroupExpand(int groupPosition) {
                LOG_INFO("groupPosition Open Event = " + groupPosition);
                mSound.Play(SND.effect.TOUCH_LATCHED);
                WpadActivity.setFinishTimerReset();
            }
        });

        // 12. 그룹 닫히는 경우 이벤트
        mListView.setOnGroupCollapseListener(new ExpandableListView.OnGroupCollapseListener() {
            @Override
            public void onGroupCollapse(int groupPosition) {
                LOG_INFO("groupPosition Close Event = " + groupPosition);
                mSound.Play(SND.effect.TOUCH_LATCHED);
                WpadActivity.setFinishTimerReset();
            }
        });

        // 13. MenuOpen True 설정
        MenuOpen = true;
    }

    /**
     * 메뉴 layout 닫힘 처리
     **/
    private void CloseMenuLayout() {
        Log.d(TAG, "[CloseMenuLayout] MenuOpen [" + MenuOpen + "]");
        if (!MenuOpen) {
            return;
        }

        // 메뉴오픈시 INVISIBLE 처리했던 FRONT SurfaceView VISIBLE
        if (FrontVideoSurface != null) {
            FrontVideoSurface.setVisibility(View.VISIBLE);
        }

        TranslateAnimation anim = new TranslateAnimation(0, WpadScale.getWidth(-460), 0, 0);
        anim.setDuration(200);
        anim.setInterpolator(new AccelerateInterpolator());
        anim.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {
                MenuOpen = false;
            }

            @Override
            public void onAnimationRepeat(Animation animation) {
            }

            @Override
            public void onAnimationEnd(Animation animation) {
                AllLayout.removeView(MenuLayout);
                TopLayout.setAlpha(1.0f);
                ScreenLayout.setAlpha(1.0f);
            }
        });

        MenuLayout.startAnimation(anim);
    }

    /**
     * 메뉴 그룹 터치시 처리 (Menu_AdptMain에서 호출)
     **/
    public static void SetListViewGroupExpand_Collapse(int GroupId, boolean ExpandEnable) {
        if (ExpandEnable) {
            mListView.expandGroup(GroupId);
        } else {
            mListView.collapseGroup(GroupId);
        }
    }

    /**
     * Menu정보가 DB에 없을 경우 불러올 스크린 로딩
     *
     * @return MenuListDataClass 타입의 초기정보
     **/
    private MenuListDataClass LoadDefaultMenuList() {
        MenuListDataClass Temp_menuListDataClass = new MenuListDataClass();
        Temp_menuListDataClass.SetArrayGroup(API_Menu.SubMenuCall.Name);

        ArrayList<String> arrayList = new ArrayList<String>();

        int ChildCount = 0;

        //[수정필요]
        //추가 또는 수정해야할 부분 1. - Menu정보가 DB에 없을 경우 불러올 스크린 종류(시작)
        arrayList.add(API_Menu.SubMenuCall.Name_Door);
        ChildCount++;
        arrayList.add(API_Menu.SubMenuCall.Name_Lobby);
        ChildCount++;
        arrayList.add(API_Menu.SubMenuCall.Name_Guard);
        ChildCount++;
        arrayList.add(API_Menu.SubMenuCall.Name_Neighbor);
        ChildCount++;
        Temp_menuListDataClass.SetArrayChild(API_Menu.SubMenuCall.Name, arrayList);
        //추가 또는 수정해야할 부분 1. - Menu정보가 DB에 없을 경우 불러올 스크린 종류(끝)

        Temp_menuListDataClass.idMappingTable = new ChildIDMapping[ChildCount];
        for (int i = 0; i < ChildCount; i++) {
            Temp_menuListDataClass.idMappingTable[i] = new ChildIDMapping();

            //추가 또는 수정해야할 부분 2. - 불러올 스크린의 Id를 임의로 입력(시작)
            if (arrayList.get(i).equals(API_Menu.SubMenuCall.Name_Door)) {
//                Temp_menuListDataClass.idMappingTable[i].Id = API_Menu.SubMenuCall.Door;
                Temp_menuListDataClass.idMappingTable[i].Id = ID.SCREEN.SCREEN_TALKFRONT_SUBWALLPAD;
                Temp_menuListDataClass.idMappingTable[i].Name = API_Menu.SubMenuCall.Name_Door;
            } else if (arrayList.get(i).equals(API_Menu.SubMenuCall.Name_Lobby)) {
//                Temp_menuListDataClass.idMappingTable[i].Id = API_Menu.SubMenuCall.Lobby;
                Temp_menuListDataClass.idMappingTable[i].Id = ID.SCREEN.SCREEN_TALKLOBBY_SUBWALLPAD;
                Temp_menuListDataClass.idMappingTable[i].Name = API_Menu.SubMenuCall.Name_Lobby;
            } else if (arrayList.get(i).equals(API_Menu.SubMenuCall.Name_Guard)) {
//                Temp_menuListDataClass.idMappingTable[i].Id = API_Menu.SubMenuCall.Guard;
                Temp_menuListDataClass.idMappingTable[i].Id = ID.SCREEN.SCREEN_TALKGUARD_SUBWALLPAD;
                Temp_menuListDataClass.idMappingTable[i].Name = API_Menu.SubMenuCall.Name_Guard;
            } else if (arrayList.get(i).equals(API_Menu.SubMenuCall.Name_Neighbor)) {
//                Temp_menuListDataClass.idMappingTable[i].Id = API_Menu.SubMenuCall.Neighbor;
                Temp_menuListDataClass.idMappingTable[i].Id = ID.SCREEN.SCREEN_TALKRESIDENCE_SUBWALLPAD;
                Temp_menuListDataClass.idMappingTable[i].Name = API_Menu.SubMenuCall.Name_Neighbor;
            }
            LOG("[LoadDefaultMenuList] Temp_menuListDataClass.idMappingTable[" + i + "].id = " + Temp_menuListDataClass.idMappingTable[i].Id);
            LOG("[LoadDefaultMenuList] Temp_menuListDataClass.idMappingTable[" + i + "].Name = " + Temp_menuListDataClass.idMappingTable[i].Name);
            //추가 또는 수정해야할 부분 2. - 불러올 스크린의 Id를 임의로 입력(끝)
        }
        return Temp_menuListDataClass;
    }

    /**
     * Menu Event intent filter 등록
     **/
    private void reg_Receiver() {
        try {
            IntentFilter filter = new IntentFilter();
            filter.addAction("MENU_EVENT");
            registerReceiver(mWallPadAlertBR, filter);

            filter = new IntentFilter();
            filter.addAction(define.NOTIFY_DAIL);
            filter.addAction("WALLPAD_DIAL_GLOBALSCREEN_TOUCH");
            registerReceiver(mWallPadJogBR, filter);
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        }
    }

    /**
     * 조그버튼 입력 받을 시 처리
     **/
    BroadcastReceiver mWallPadJogBR = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            WpadActivity.setFinishTimerReset();
        }
    };

    /**
     * 메뉴에서 버튼 터치 처리
     **/
    BroadcastReceiver mWallPadAlertBR = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            int groupPosition = intent.getIntExtra("groupPosition", -1);
            int childPosition = intent.getIntExtra("childPosition", -1);

            // 메뉴 터치에 의해 현관화면 진입시 모니터링을 바로 시작하기 위한 플래그 설정
//            if (childPosition == 0) {
//                if (ConfigValues.eWallPadType == WALLPADTYPE.MAIN) Global.bFrontMonitoring = true;
//                else Global.bFrontMonitoring_SubWallPad = true;
//            } else {
//                if (ConfigValues.eWallPadType == WALLPADTYPE.MAIN) Global.bFrontMonitoring = false;
//                else Global.bFrontMonitoring_SubWallPad = false;
//            }

            LOG_INFO("[mWallPadAlertBR] bEnablePSTN [" + Global.bEnablePSTN + "]");
            if (bLobbyCallUse && (childPosition == 1)) return;  // 로비메뉴 화면전환 없음
            if (bPSTNCallUse && !Global.bEnablePSTN) return; // 국선통화 모뎀초기화 안될 경우 화면전환 없음
            if ((groupPosition >= 0) && (childPosition >= 0)) {
                if (MenuOpen) {
                    mSound.Play(SND.effect.TOUCH_LATCHED);
                    CloseMenuLayout();

                    if (menuListDataClass == null) {
                        return;
                    }
                    String childName = menuListDataClass.arrayChild.get(menuListDataClass.arrayGroup.get(groupPosition)).get(childPosition);
                    for (int i = 0; i < menuListDataClass.idMappingTable.length; i++) {
                        if (menuListDataClass.idMappingTable[i].Name.equals(childName)) {
                            API_Menu api_Menu = new API_Menu();
                            int TempId = api_Menu.GetMyGroupID(getApplicationContext().getPackageName());
                            int ChildId = menuListDataClass.idMappingTable[i].Id;
                            int ChildGroupId = (ChildId / 1000) * 1000;
                            if (ConfigValues.eWallPadType == WALLPADTYPE.SUB) ChildGroupId = (getConvertScreenId(ChildId) / 1000) * 1000;
                            Log.i(TAG, "[mWallPadAlertBR] Child Id  [" + ChildId + "], ChildGroupId [" + ChildGroupId + "]");

                            if (TempId == 0) {
                                return;
                            }

                            if (ChildGroupId == TempId) {
                                //해당 APP 내에서 스크린 전환 필요
                                boolean bResult = setChangeScreen(ChildId, false);
                                if (bResult) {
                                    if (API_Menu.SubMenuCall.Door == ChildId) {
                                        // 현관통화
                                        if (!bBlockFrontCall) {
                                            if (mCallController.mCallInfo.getFRONT() == CALLSTATUS.IDLE) {
                                                setBlockFrontCall();
                                                if (mCallController != null) mCallController.CallScenarioManager(CALLOWNER.WALLPAD, CALLEVENTTYPE.REQUEST_FRONT_MONITORING, CALLTYPE.FRONT, null, null, null);
                                                else Log.w(TAG, "[mWallPadAlertBR] mCallController is null!!");
                                            }
                                            else {
                                                Log.w(TAG, "[mWallPadAlertBR] Front call ignored!!! getFRONT() [" + mCallController.mCallInfo.getFRONT() + "]");
                                            }
                                        }
                                        else {
                                            Log.w(TAG, "[mWallPadAlertBR] Front call ignored!!! bBlockFrontCall [" + bBlockFrontCall + "]");
                                        }
                                    }
                                }
                                else {
                                    int nScreenID = API_Menu.SubMenuCall.Guard;
                                    if (!bGuardCallUse) {
                                        if (bFrontCallUse) nScreenID = API_Menu.SubMenuCall.Door;
                                        else if (bResiCallUse) nScreenID = API_Menu.SubMenuCall.Neighbor;
                                        else if (bPSTNCallUse) nScreenID = API_Menu.SubMenuCall.PSTN;
                                        else if (bCallHistoryUse) nScreenID = API_Menu.SubMenuCall.CallList;
                                        else if (bVisitorPicUse) nScreenID = API_Menu.SubMenuCall.Visitor;
                                    }
                                    setChangeScreen(nScreenID, false);
                                }
                                WpadActivity.setFinishTimerReset();
                            }
                            else {
                                //외부 앱 호출 후, 본 APP Finish 필요
                                api_Menu.startSubScreenActivity(getApplicationContext(), menuListDataClass.idMappingTable[i].Id, API_Menu.MENU_START_OPTION_1, api_Menu.GetAPK_Name_ByID(ChildGroupId));

                                Intent mIntent = new Intent();
                                mIntent.putExtra("Finish_Kind", "HomeButton");
                                MainActivity.this.setResult(RESULT_OK, mIntent);
                                finish();
                            }
                            break;
                        }
                    }
                }
            }
        }
    };

    // TAB 버튼 이벤트 -> MENU 버튼 이벤트 (2017.11.20 SEULKI)
    public void setMenuBTNEnable(boolean bEnable) {
        try {
            LOG("[setMenuBTNEnable] bEnable: " + bEnable);
            if (bEnable) TopMenuBtn.setButtonEventOffDisable();
            else TopMenuBtn.setButtonEventOffEnable();
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] setMenuBTNEnable(boolean bEnable)");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        }
    }

    /**
     * 디바이스 서비스 APP 을 체크하여 실행되어있지 않을시 실행시킨다.
     */
    private void checkDevService() {
        try {
            class checkDeviceService extends Thread {
                @Override
                public void run() {
                    super.run();
                    boolean DevServiceExist = false;

                    ActivityManager mActivityManager = (ActivityManager) getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE);
                    List<ActivityManager.RunningServiceInfo> mRunningServiceInfo = mActivityManager.getRunningServices(1000);

                    for (int i = 0; i < mRunningServiceInfo.size(); i++) {
                        ActivityManager.RunningServiceInfo rsi = mRunningServiceInfo.get(i);
                        if (rsi.service.getPackageName().equals("com.artncore.deviceservice")) {
                            Log.d(TAG, "[checkDevService] DeviceService already running!");
                            DevServiceExist = true;
                            break;
                        }
                    }

                    Log.d(TAG, "[checkDevService] DevServiceExist: " + DevServiceExist);
                    if (!DevServiceExist) {
                        Log.d(TAG, "[checkDevService] DeviceService manually started!!!");
                        Intent intent = new Intent("wallpaddevservice.ServiceMain");
                        startService(intent);
                    }
                }
            }

            checkDeviceService th_checkDeviceService = new checkDeviceService();
            th_checkDeviceService.run();

//            boolean DevServiceExist = false;
//
//            ActivityManager mActivityManager = (ActivityManager) getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE);
//            List<ActivityManager.RunningServiceInfo> mRunningServiceInfo = mActivityManager.getRunningServices(1000);
//
//            for (int i = 0; i < mRunningServiceInfo.size(); i++) {
//                ActivityManager.RunningServiceInfo rsi = mRunningServiceInfo.get(i);
//                if (rsi.service.getPackageName().equals("com.artncore.deviceservice")) {
//                    Log.d(TAG, "[checkDevService] DeviceService already running!");
//                    DevServiceExist = true;
//                    break;
//                }
//            }
//
//            Log.d(TAG, "[checkDevService] DevServiceExist: " + DevServiceExist);
//            if (!DevServiceExist) {
//                Log.d(TAG, "[checkDevService] DeviceService StartManal");
//                Intent intent = new Intent("wallpaddevservice.ServiceMain");
//                startService(intent);
//
//                try {
//                    Thread.sleep(3000);
//                } catch (Exception e) {
//                    Log.e(TAG, "[Exception] checkDevService.sleep()");
//                    e.printStackTrace();
//                }
//            }
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG,re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] checkDevService");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        }
    }

    public boolean initIOInterface() {
        try {
            LOG("[initIOInterface] ");
            // I/O 제어를 위한 라이브러리 사용
            mIOInterface = new IOInterface(ConfigValues.DEVICE_BOARDTYPE, mWallPadAPI);
            return true;
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
            return false;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] initIOInterface()");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
            return false;
        }
    }

    public boolean initCallEngine() {
        try {
            LOG("[initCallEngine]");
            mCallController = new CallController(mContext, mWallPadAPI);
            if (ConfigValues.bRemoteCall || ConfigValues.bReliefCall) {
               mAudioRecordController = new AudioRecordController(mContext);
                if (ConfigValues.bRemoteCall) mVideoController = new VideoController(mContext);
            }

            if (ConfigValues.eWallPadType == WALLPADTYPE.MAIN) {
                if (ConfigValues.bPSTNEnable) mPSTNController = new PSTNController(mContext);
                if (ConfigValues.bSubPhoneEnable) mSubPhoneController = new SubPhoneController(mContext);
                if (ConfigValues.bRemoteCall) {
                    mDataSender = new DataSender();
                    mRemoteCallController = new RemoteCallController(mContext);
                }
            }
            else {
                mSubWallPadController = new SubWallPadController(mContext);
                if (ConfigValues.eSubWallPadPSTNType == SUBWALLPAD_PSTNTYPE.DIRECT) {
                    mPSTNController = new PSTNController(mContext);
                    LOG_WARN("[initCallEngine] PSTNController is run!!");
                }
            }

            initVideoSurfaceLayout();
            return true;
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
            return false;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] initCallEngine()");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
            return false;
        }
    }

    public boolean releaseCallEngine() {
        try {
            LOG("[releaseCallEngine]");
            // Call Engine End!
            removeVideoSurfaceLayout();
            if (mVideoController != null) mVideoController.releaseVideoController();

            mCallController.releaseCallEventListener();
            mCallController.releaseCallController();

            if (mAudioRecordController != null) mAudioRecordController.releaseAudioRecordController();

            if (ConfigValues.eWallPadType == WALLPADTYPE.MAIN) {
                if (ConfigValues.bPSTNEnable) mPSTNController.releasePSTNController();
                if (ConfigValues.bSubPhoneEnable) mSubPhoneController.releaseSubPhoneController();
                if (ConfigValues.bRemoteCall) {
                    mRemoteCallController.releaseRemoteCallController();
                    mDataSender.interrupt();
                    mDataSender = null;
                }
            }
            else {
                mSubWallPadController.releaseSubWallPadController();
            }
            return true;
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
            return false;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] releaseCallEngine()");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
            return false;
        }
    }

    public boolean initCallHistoryDB() {
        try {
            LOG("[initCallHistoryDB]");
            mCallHistoryManager = new CallHistoryManager();
            return mCallHistoryManager.initCallHistory(mContext);
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
            return false;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] initCallHistoryDB()");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
            return false;
        }
    }

    public boolean releaseCallHistoryDB() {
        try {
            LOG("[releaseCallHistoryDB]");
            if (mCallHistoryManager != null) {
                return mCallHistoryManager.releaseCallHistory();
            }
            return false;
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
            return false;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] releaseCallHistoryDB()");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
            return false;
        }
    }

    public boolean initVisitorPictureHistoryDB() {
        try {
            LOG("[initVisitorPictureHistoryDB]");
            mVisitorPictureHistoryManager = new VisitorPictureHistoryManager();
            return mVisitorPictureHistoryManager.initVisitorPictureHistory(mContext);
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
            return false;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] initVisitorPictureHistoryDB()");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
            return false;
        }
    }

    public boolean releaseVisitorPictureHistoryDB() {
        try {
            LOG("[releaseVisitorPictureHistoryDB]");
            if (mVisitorPictureHistoryManager != null) {
                return mVisitorPictureHistoryManager.releaseVisitorPictureHistory();
            }
            return false;
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
            return false;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] releaseVisitorPictureHistoryDB()");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
            return false;
        }
    }

    private boolean send_check_sip_activation_request(final String strTargetIP) {
        try {
            Request_check_sip_activation check_sip_activation = new Request_check_sip_activation(mContext);
            if (check_sip_activation.send_check_sip_activation(strTargetIP, null)) {
                check_sip_activation.setResultCtrl(new RetProci() {

                    @Override
                    public void ProcSuccess() {
                        LOG_INFO("[send_check_sip_activation_request] ProcSuccess()");
                        mCallController.onSubPhoneEvent(CALLOWNER.KITCHEN_TV_01, CALLEVENTTYPE.REQUEST_FRONT_MONITORING, CALLTYPE.FRONT, strTargetIP, null);
                       // MainActivity.mCallController.mSIPInterface.requestCallForwardToStun(MainActivity.mCallController.makeCallForwarInfo(strTargetIP));
                    }

                    @Override
                    public void ProcError() {
                        LOG_INFO("[send_check_sip_activation_request] ProcError()");
                        mCallController.onSubPhoneEvent(CALLOWNER.KITCHEN_TV_01, CALLEVENTTYPE.REJECT_BUSY_CALL, CALLTYPE.FRONT, strTargetIP, null);
                       // MainActivity.mCallController.mSIPInterface.cancelCallForwardToStun();
                    }

                    @Override
                    public void ProcDoing() {
                        LOG_INFO("[send_check_sip_activation_request] ProcDoing()");
                    }
                });
                return true;
            }
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] send_check_sip_activation_request(String strTargetIP, String strMessage)");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
            MainActivity.mCallController.mSIPInterface.cancelCallForwardToStun();
        }
        return false;
    }

    String strCallOwner = "NONE";
    String strCallEvent = "NONE";
    String strCallType = "NONE";
    String strRemoteInfo = "NONE";

    private void generateCallEvent() {
        try {
            LOG_INFO("[generateCallEvent] ConfigValues.eWallPadType [" + ConfigValues.eWallPadType + "], strCallOwner [" + strCallOwner + "], strCallEvent [" + strCallEvent + "], strCallType [" + strCallType + "], strRemoteInfo [" + strRemoteInfo + "]");

            if (strCallEvent.equalsIgnoreCase("NONE")) setMenuBTNEnable(true);
            else setMenuBTNEnable(false);

            if (strCallOwner != null && strCallEvent != null && strCallType != null) {
                CALLOWNER callowner = CALLOWNER.getCALLOWNER(strCallOwner);
                CALLTYPE calltype = CALLTYPE.getCALLTYPE(strCallType);
                CALLEVENTTYPE calleventtype = CALLEVENTTYPE.getCALLEVENTTYPE(strCallEvent);
                Log.i(TAG, "[generateCallEvent] callowner [" + callowner + "], calltype [" + calltype + "], calleventtype [" + calleventtype + "]");

                if (ConfigValues.eWallPadType == WALLPADTYPE.MAIN) {
                    // 메인월패드
                    if (callowner == CALLOWNER.NONE) {
                        if (calltype == CALLTYPE.FRONT) {
                            if (calleventtype == CALLEVENTTYPE.RECEIVE_CALL) {
                                String strRemoteSIPID = mCallController.makeSIPID(strRemoteInfo);
                                if (mCallController != null) mCallController.CallScenarioManager(callowner, calleventtype, calltype, strRemoteInfo, strRemoteSIPID, null);
                                //if (mCallController != null) mCallController.CallScenarioManager(callowner, calleventtype, calltype, null, null, null);
                                else Log.w(TAG, "[generateCallEvent] mCallController is null!!");
                            }
                            else {
                                Log.w(TAG, "[generateCallEvent] not supported callevent!! -> " + calleventtype);
                            }
                        }
                        else if (calltype == CALLTYPE.PSTN) {
                            if (calleventtype == CALLEVENTTYPE.RECEIVE_CALL) {
                                if (ConfigValues.DEVICE_BOARDTYPE == BOARD_TYPE.V40_IGW300 || ConfigValues.DEVICE_BOARDTYPE == BOARD_TYPE.V40_IGW300_NOUGAT) {
                                    if (mCallController != null) mCallController.onPSTNEvent(CALLEVENTTYPE.RECEIVE_CALL, null, null);
                                    else Log.w(TAG, "[generateCallEvent] mCallController is null!!");
                                    if (ConfigValues.bPSTNEnable && ConfigValues.bARSEnable && ConfigValues.bUnoccupiedMode) {
                                        sendHandlerMsgDelayed(HANDLERMSG.SEND_PSTN_ARS_MODE, 0, 0, 3000);
                                    }
                                }
                                else {
                                    if (mPSTNController != null) mPSTNController.receivePSTNRing();
                                    else Log.w(TAG, "[generateCallEvent] mPSTNController is null!!");
                                }
                            }
                            else {
                                Log.w(TAG, "[generateCallEvent] not supported callevent!! -> " + calleventtype);
                            }
                        }
                        else {
                            if (calleventtype == CALLEVENTTYPE.RECEIVE_CALL) {
                                String strRemoteSIPID = mCallController.makeSIPID(strRemoteInfo);
                                if (mCallController != null) mCallController.CallScenarioManager(callowner, calleventtype, calltype, strRemoteInfo, strRemoteSIPID, null);
                                else Log.w(TAG, "[generateCallEvent] mCallController is null!!");
                            }
                            else {
                                Log.w(TAG, "[generateCallEvent] not supported callevent!! -> " + calleventtype);
                            }

                            Log.w(TAG, "[generateCallEvent] not supported calltype!! -> " + calltype);
                            RemoteIDInfo.strIP = strRemoteInfo;
                        }
                    }
                    else if (callowner == CALLOWNER.WALLPAD) {
                        if (calltype == CALLTYPE.FRONT) {
                            if (calleventtype == CALLEVENTTYPE.REQUEST_FRONT_MONITORING) {
                                if (mCallController != null) {
                                    mCallController.mCallInfo.setCallOwner(callowner);

//                                    strRemoteInfo = "10.1.0.11";
//                                    String strRemoteSIPID = mCallController.makeSIPID(strRemoteInfo);
//                                    RemoteIDInfo.strIP = strRemoteInfo;
//
//                                    if (send_check_sip_activation_request(strRemoteInfo))
//                                        mCallController.CallScenarioManager(callowner, calleventtype, calltype, strRemoteInfo, strRemoteSIPID, null);
//                                    else
//                                        Log.d(TAG, callowner.toString() + "REQUEST_FRONT_MONITORING check_sip_activation ERROR");
                                    mCallController.CallScenarioManager(callowner, calleventtype, calltype, null, null, null);
                                }
                                else Log.w(TAG, "[generateCallEvent] mCallController is null!!");
                            }
                        }
                        else if (calltype == CALLTYPE.PSTN) {
                            RemoteIDInfo.bAutoCall = true;
                            RemoteIDInfo.strPSTNInfo = strRemoteInfo;
                            if (mCallController != null) {
                                mCallController.mCallInfo.setCallOwner(callowner);
                                mCallController.CallScenarioManager(callowner, calleventtype, calltype, null, null, null);
                            }
                            else Log.w(TAG, "[generateCallEvent] mCallController is null!!");
                        }

//                        else if (calltype == CALLTYPE.LOBBY) {
//                            if (mCallController != null) {
//                                mCallController.mCallInfo.setCallOwner(callowner);
//                                mCallController.CallScenarioManager(callowner, calleventtype, calltype, strRemoteInfo, null, null);
//                            }
//                        }
                    }
                    else if (callowner == CALLOWNER.MOBILE) {
                        if (calltype == CALLTYPE.FRONT) {
                            // [방문객원격통화] 스마트폰에서 현관모니터링 요청
                            if (calleventtype == CALLEVENTTYPE.REQUEST_FRONT_MONITORING) {
                                if (mCallController != null) {
                                    mCallController.mCallInfo.setCallOwner(callowner);
                                    strRemoteInfo = "10.1.0.11";
                                    String strRemoteSIPID = mCallController.makeSIPID(strRemoteInfo);
                                    RemoteIDInfo.strIP = strRemoteInfo;

                                    if (send_check_sip_activation_request(strRemoteInfo))
                                        mCallController.CallScenarioManager(callowner, calleventtype, calltype, strRemoteInfo, strRemoteSIPID, null);
                                    else
                                        Log.d(TAG, callowner.toString() + "REQUEST_FRONT_MONITORING check_sip_activation ERROR");
                                }
                                else Log.w(TAG, "[generateCallEvent] mCallController is null!!");
                            }
                        }
                        else if (calltype == CALLTYPE.GUARD) {
                            // [방문객원격통화] 스마트폰에서 경비발신 요청
                            if (calleventtype == CALLEVENTTYPE.TRYING_CALL) {
                                if (mCallController != null) {
                                    mCallController.mCallInfo.setCallOwner(callowner);
                                    mCallController.tryMoIPCall(CALLTYPE.GUARD, RemoteIDInfo.strDong, RemoteIDInfo.strHo);
                                }
                                else Log.w(TAG, "[generateCallEvent] mCallController is null!!");
                            }
                        }
                        else if (calltype == CALLTYPE.RESIDENCE) {
                            // [방문객원격통화] 모바일에서 홈뷰어 요청
                            if (calleventtype == CALLEVENTTYPE.REQUEST_FRONT_MONITORING) {
                                if (mCallController != null) {
                                    mCallController.mCallInfo.setCallOwner(callowner);
                                    mCallController.CallScenarioManager(callowner, calleventtype, calltype, null, null, null);
                                }
                                else Log.w(TAG, "[generateCallEvent] mCallController is null!!");
                            }
                        }
                    }
                    else if (Global.getKitchenTVIdx(callowner) >= 0 || Global.getBathPhoneIdx(callowner) >= 0 || callowner == CALLOWNER.SUB_WALLPAD || Global.getBathTVIdx(callowner) >= 0) {
                        if (calltype == CALLTYPE.FRONT) {
                            if (mCallController != null)
                            {
                                strRemoteInfo = "10.1.0.11";
                                String strRemoteSIPID = mCallController.makeSIPID(strRemoteInfo);
                                RemoteIDInfo.strIP = strRemoteInfo;
                                send_check_sip_activation_request(strRemoteInfo);
                                //mCallController.onSubPhoneEvent(callowner, calleventtype, calltype, null, null);
//                                if (send_check_sip_activation_request(strRemoteInfo))
//                                    mCallController.onSubPhoneEvent(callowner, calleventtype, calltype, strRemoteSIPID, null);
//                                else
//                                    Log.d(TAG, callowner.toString() + "REQUEST_FRONT_MONITORING check_sip_activation ERROR");
                            }
                            else Log.w(TAG, "[generateCallEvent] mCallController is null!!");
                        }
                        else if (calltype == CALLTYPE.GUARD || calleventtype == CALLEVENTTYPE.TRYING_CALL) {
                            if (mCallController != null) mCallController.onSubPhoneEvent(callowner, calleventtype, calltype, strRemoteInfo, null);
                            else Log.w(TAG, "[generateCallEvent] mCallController is null!!");
                        }
                        else if (calltype == CALLTYPE.RESIDENCE || calleventtype == CALLEVENTTYPE.REQUEST_RESIDENCE_CALL) {
                            if (mCallController != null) mCallController.onSubPhoneEvent(callowner, calleventtype, calltype, strRemoteInfo, null);
                            else Log.w(TAG, "[generateCallEvent] mCallController is null!!");
                        }
                        else {
                            Log.w(TAG, "[generateCallEvent] nor supported calltype and callevent!! -> " + calltype + "/" + calleventtype);
                        }
                    }
                    else {
                        Log.w(TAG, "[generateCallEvent] not supported callowner!! -> " + callowner);
                    }
                }
                else {
                    // 서브월패드
                    if (callowner == CALLOWNER.NONE) {
                        if (calltype == CALLTYPE.FRONT || calltype == CALLTYPE.LOBBY || calltype == CALLTYPE.GUARD || calltype == CALLTYPE.RESIDENCE) {
                            if (calleventtype == CALLEVENTTYPE.RECEIVE_CALL) {
                                if (mCallController != null) mCallController.onSubWallPadEvent(callowner, calleventtype, calltype, null, null);
                                else Log.w(TAG, "[generateCallEvent] mCallController is null!!");
                            }
                            else Log.w(TAG, "[generateCallEvent] not supported calleventtype!! -> " + calleventtype);
                        }
//                        else if(calltype == CALLTYPE.HISTORY_CALL)
//                        {
//                            strRemoteInfo = "10.1.0.110";
//                            String strRemoteSIPID = mCallController.makeSIPID(strRemoteInfo);
//                            RemoteIDInfo.strIP = strRemoteInfo;
//
//                            if (send_check_sip_activation_request(strRemoteInfo))
//                                if (mCallController != null) mCallController.CallScenarioManager(callowner, calleventtype, calltype, strRemoteInfo, strRemoteSIPID, null);
//                            else
//                                Log.d(TAG, callowner.toString() + "REQUEST_FRONT_MONITORING check_sip_activation ERROR");
//                        }
                        else {
                            Log.w(TAG, "[generateCallEvent] not supported calltype!! -> " + callowner);
                            RemoteIDInfo.strIP = strRemoteInfo;
                        }
                    }
                    else if (callowner == CALLOWNER.SUB_WALLPAD) {
                        if (calleventtype == CALLEVENTTYPE.REQUEST_FRONT_MONITORING) {
                            if (mCallController != null) {
                                mCallController.mCallInfo.setCallOwner(callowner);
                                mCallController.onSubWallPadEvent(callowner, calleventtype, calltype, null, null);
                                mSubWallPadController.sendRequestFrontMonitoring(CALLOWNER.SUB_WALLPAD, CALLTYPE.FRONT);


                            }
                            else {
                                Log.w(TAG, "[generateCallEvent] mCallController is null!!");
                            }
                        }
                    }
                    else {
                        Log.w(TAG, "[generateCallEvent] not supported callowner!! -> " + callowner);
                    }
                }
            }
            else {
                Log.w(TAG, "[generateCallEvent] strCallOwner, strCallEvent, strCallType are nul!!");
            }
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] generateCallEvent()");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        }
    }


    int nNoticeTextColor_White = Color.WHITE;
    int nNoticeTextColor_Orange = Color.parseColor("#FF8C00");
    int nNoticeTextColor = nNoticeTextColor_Orange;

    /**
     * SEULKI, 2020.09.15
     * 모바일 통화중 알림
     * 방문객원격통화 모바일 통화중 상태를 사용자에게 알리기 위해, 화면 상단에 "모바일 통화종"이라는 문구를 표시한다.
     * 모바일 통화중 알림 문구는 색을 반전하며 표시된다.
     */
    static long lRemoteConnectionPeriod = 0;
    static int REMOTECALL_CONNECT_TIMEOUT = 1000 * 60; // 통화 시간 최대 1분
    boolean bRemoteCallProcessNoticeRun = false;
    private void startRemoteCallProcessNotice() {
        try {
            Log.v(TAG, "[startRemoteCallProcessNotice] bRemoteCallProcessNoticeRun [" + bRemoteCallProcessNoticeRun + "]");
            if (mRemoteCallProcessNoticeThread == null && !bRemoteCallProcessNoticeRun) {
                bRemoteCallProcessNoticeRun = true;
                mRemoteCallProcessNoticeThread = new RemoteCallProcessNoticeThread();
                mRemoteCallProcessNoticeThread.start();
            }
            else Log.v(TAG, "[startRemoteCallProcessNotice] mRemoteCallProcessNoticeThread is not null!!!");
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] startRemoteCallProcessNotice()");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        }
    }

    private void stopRemoteCallProcessNotice() {
        try {
            Log.v(TAG, "[stopRemoteCallProcessNotice] bRemoteCallProcessNoticeRun [" + bRemoteCallProcessNoticeRun + "]");
            if (mRemoteCallProcessNoticeThread != null || bRemoteCallProcessNoticeRun) {
                lRemoteConnectionPeriod = -999;
                bRemoteCallProcessNoticeRun = false;
                mRemoteCallProcessNoticeThread = null;
            }
            else Log.v(TAG, "[stopRemoteCallProcessNotice] mRemoteCallProcessNoticeThread is null!!!");
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] stopRemoteCallProcessNotice()");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        }
    }

    public void showRemoteCallNoticeText(boolean bRun) {
        try {
            Log.i(TAG, "[showRemoteCallNoticeText] bRun [" + bRun + "]");
            if (bRun) {
                TopRemoteCallNotice.setText("모바일 통화중");
                TopRemoteCallNotice.setVisibility(View.VISIBLE);
                startRemoteCallProcessNotice();
            }
            else {
                TopRemoteCallNotice.setText("");
                TopRemoteCallNotice.setVisibility(View.INVISIBLE);
                stopRemoteCallProcessNotice();
            }
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] showRemoteCallNoticeText(boolean bRun)");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        }
    }

    private RemoteCallProcessNoticeThread mRemoteCallProcessNoticeThread;

    private class RemoteCallProcessNoticeThread extends Thread {

        public RemoteCallProcessNoticeThread() {
            Log.i(TAG, "============ [RemoteCallProcessNoticeThread()] ============");
        }

        public void run() {
            try {
                Log.v(TAG, "[RemoteCallProcessNoticeThread().run()] bRemoteCallProcessNoticeRun [" + bRemoteCallProcessNoticeRun + "]");
                lRemoteConnectionPeriod = System.currentTimeMillis() + REMOTECALL_CONNECT_TIMEOUT;
                while ((System.currentTimeMillis() < lRemoteConnectionPeriod) && bRemoteCallProcessNoticeRun) {
                    try {
                        if (bRemoteCallProcessNoticeRun) Thread.sleep(500);   // 500ms에 한번씩 색 반전
                    } catch (InterruptedException e) {
                        Log.e(TAG, "[RemoteCallProcessNoticeThread] Thread.sleep(500)");
                        //e.printStackTrace();
                        LogUtil.errorLogInfo("", TAG, e);
                    }
                    if (nNoticeTextColor == nNoticeTextColor_Orange) {
//                        Log.i(TAG, "[StrangerProcessNoticeThread().run().while()] ===== white =====");
                        nNoticeTextColor = nNoticeTextColor_White;
                    }
                    else {
//                        Log.i(TAG, "[RemoteCallProcessNoticeThread().run().while()] ===== orange =====");
                        nNoticeTextColor = nNoticeTextColor_Orange;
                    }
                    sendHandlerMsg(HANDLERMSG.CHANGE_REMOTECALL_NOTICE_COLOR, 0, 0);
                }
                bRemoteCallProcessNoticeRun = false;
                Log.i(TAG, "[RemoteCallProcessNoticeThread().run()] ===== while end =====");
            } catch (RuntimeException re) {
                LogUtil.errorLogInfo("", TAG, re);
            } catch (Exception e) {
                Log.e(TAG, "[Exception] RemoteCallProcessNoticeThread.run()");
                //e.printStackTrace();
                LogUtil.errorLogInfo("", TAG, e);
            }
        }
    }


    /* ================================================================================================
     * 히든 메뉴 -> 통화시험모드 진입
     ================================================================================================ */
    private void startHideMenu() {
        try {
            TopBackground.setImageResource(0);
            TopBackground.setBackgroundColor(Color.RED);

            mSound.Play(SND.call.CALLSTART);
            super.setFinishTimerDestroy();

            Log.i(TAG, "================================");
            Log.i(TAG, "[startHideMenu] START !!!!!");
            Log.i(TAG, "================================");

            mCallController.set1stCallTimer(CALLTYPE.FRONT, 99999);

            if (SampleModeTitle == null) {
                SampleModeTitle = new WpadTextView(mContext, false, 200, 72, Gravity.CENTER, Color.DKGRAY, Common.fontsize._26_DEFAULT, true, 0);
                ViewRegistration(TopLayout, SampleModeTitle, 316, 17);
            }
            SampleModeTitle.setText("[통화시험모드]");
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] startHideMenu()");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        }
    }


    /* ================================================================================================
     * 원격지 영상
     ================================================================================================ */
    public void initRemoteVideoSurfaceLayout() {
        try {
            LOG_INFO("[initRemoteVideoSurfaceLayout] RemoteVideoLayout = " + RemoteVideoLayout);
            if (RemoteVideoLayout != null) {
                RemoteVideoSurface.getHolder().removeCallback(RemoteVideoCallback);
                RemoteVideoLayout.removeAllViews();
                RemoteVideoLayout = null;
            }

            RemoteVideoLayout = new RelativeLayout(mContext);
            WpadUtil.LayoutRegistration(SurfaceLayout, RemoteVideoLayout, screenWidth, screenHeight - topHeight, 0, 0, ID.MAINACTIVITY.LAYOUT.REMOTEVIDEO);
            RemoteVideoSurface = new SurfaceView(mContext);
//            RemoteVideoHolder = RemoteVideoSurface.getHolder();

            WpadRelativeLayoutParams RemoteVideoParams;
            if (bFFMPEGEnable) {
                RemoteVideoParams = new WpadRelativeLayoutParams(708, 540);
//                RemoteVideoParams.setMargins(107, 112, 0, 0);
                RemoteVideoParams.setMargins(1300, 112, 0, 0); // 안보이게
            }
            else {
                RemoteVideoParams = new WpadRelativeLayoutParams(1000, 800);
                RemoteVideoParams.setMargins(95, 112, 0, 0);
            }

            RemoteVideoLayout.addView(RemoteVideoSurface, RemoteVideoParams);
            RemoteVideoSurface.getHolder().addCallback(RemoteVideoCallback);
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] initRemoteVideoSurfaceLayout()");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        }
    }

    public void showRemoteVideo(boolean bShow, boolean bResidenceCall) {
        try {
            LOG_INFO("[showRemoteVideo] bShow [" + bShow + "], bResidenceCall [" + bResidenceCall + "]");

            if (RemoteVideoSurface == null) {
                LOG_WARN("[showRemoteVideo] RemoteVideoSurface is null!!!");
                return;
            }

            WpadRelativeLayoutParams RemoteVideoParams;

            if (bFFMPEGEnable) {
                if (bShow) {
                    if (bResidenceCall) {
                        RemoteVideoParams = new WpadRelativeLayoutParams(720, 540);
                        RemoteVideoParams.setMargins(144, 112, 0, 0);
                    }
                    else {
                        RemoteVideoParams = new WpadRelativeLayoutParams(708, 540);
                        RemoteVideoParams.setMargins(107, 112, 0, 0);
                    }
                }
                else {
                    RemoteVideoParams = new WpadRelativeLayoutParams(708, 540);
                    RemoteVideoParams.setMargins(1300, 112, 0, 0); // 안보이게
                }
            }
            else {
                if (bShow) {
                    RemoteVideoParams = new WpadRelativeLayoutParams(720, 540);
                    RemoteVideoParams.setMargins(144, 112, 0, 0);
                }
                else {
                    RemoteVideoParams = new WpadRelativeLayoutParams(720, 540);
                    RemoteVideoParams.setMargins(1300, 112, 0, 0); // 안보이게
                }
            }

            RemoteVideoSurface.setLayoutParams(RemoteVideoParams);
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] showRemoteVideo(boolean bShow)");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        }
    }

    public void removeRemoteVideoSurfaceLayout() {
        try {
//            LOG_INFO("[removeRemoteVideoSurfaceLayout] RemoteVideoSurface = " + RemoteVideoSurface + ", RemoteVideoLayout = " + RemoteVideoLayout);
            if (RemoteVideoLayout != null) {
                RemoteVideoSurface.getHolder().removeCallback(RemoteVideoCallback);
                RemoteVideoLayout.removeAllViews();
                RemoteVideoLayout = null;
            }
            else Log.d(TAG, "[removeRemoteVideoSurfaceLayout] RemoteVideoLayout is null!");

//            if (RemoteVideoSurface != null) {
//                RemoteVideoSurface.setVisibility(View.GONE);
//                RemoteVideoSurface.getHolder().removeCallback(RemoteVideoCallback);
//                RemoteVideoSurface = null;
//            }
//
//            if (RemoteVideoLayout != null) {
//                RemoteVideoLayout.setVisibility(View.GONE);
//                RemoteVideoLayout.removeAllViews();
//                RemoteVideoLayout = null;
//            }
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] removeRemoteVideoSurfaceLayout()");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        }
    }

    private Callback RemoteVideoCallback = new Callback() {

        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            LOG_INFO("[RemoteVideoCallback] surfaceCreated!!");

            if (bFFMPEGEnable) {
                mCallController.mVideoJNI.setRemoteSurfaceview(holder.getSurface(), 708, 540);
            }
        }

        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
            LOG_INFO("[RemoteVideoCallback] surfaceChanged!!");
        }

        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
            LOG_INFO("[RemoteVideoCallback] surfaceDestroyed!!");
            if (RemoteVideoSurface != null) {
                LOG_INFO("[RemoteVideoCallback] RemoteVideoSurface is not null!!");
                RemoteVideoSurface.getHolder().removeCallback(RemoteVideoCallback);
            }
        }
    };

    public void displayRemoteID(String strRemoteID) {
        try {
            LOG("[displayRemoteID] strRemoteID = " + strRemoteID);
            if (strRemoteID != null) {
                // strRemoteID에 따른 좌표 적용 (2017.11.22 SEULKI)
                String strBlank = "              ";
                if (strRemoteID.contains("로비")) {
                    LOG_INFO("[displayRemoteID] LOBBY");
                } else if (strRemoteID.contains("동") && (strRemoteID.contains("호"))) {
                    LOG_INFO("[displayRemoteID] NEIGHBOR");
                    strRemoteID = strRemoteID.replace(strRemoteID, strBlank + strRemoteID);
                } else if (strRemoteID.contains("경비")) {
                    LOG_INFO("[displayRemoteID] GUARD");
                }
                TXT_REMOTE_ID.setText(strRemoteID);
                TXT_REMOTE_ID.setVisibility(View.VISIBLE);
            } else {
                TXT_REMOTE_ID.setText("");
                TXT_REMOTE_ID.setVisibility(View.INVISIBLE);
            }
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] displayRemoteID(strRemoteID)");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        }
    }

    public void displayRemoteID(CALLTYPE eCallType, CALLSTATUS eCallStatus) {
        try {
            LOG("[displayRemoteID] eCallType [" + eCallType + "], eCallStatus[" + eCallStatus + "]");
            String strTarget = "";
            String strInfoMent = "";
            String strCalled = " 호출입니다.";
            String strCalling = " 호출중입니다.";
            String strTalking = " 통화중입니다.";

            if (eCallStatus == CALLSTATUS.CALLED) strInfoMent = strCalled;
            else if (eCallStatus == CALLSTATUS.TRYING_CALL || eCallStatus == CALLSTATUS.CALLING) strInfoMent = strCalling;
            else if (eCallStatus == CALLSTATUS.TALKING) strInfoMent = strTalking;

            if (eCallType == CALLTYPE.LOBBY) strTarget = "공동현관";
            else if (eCallType == CALLTYPE.GUARD) strTarget = "경비실";

            if ((!strTarget.equals("")) && (!strInfoMent.equals(""))) {
                TXT_REMOTE_ID.setText(strTarget.concat(strInfoMent));
                TXT_REMOTE_ID.setVisibility(View.VISIBLE);
            } else {
                TXT_REMOTE_ID.setText("");
                TXT_REMOTE_ID.setVisibility(View.INVISIBLE);
            }
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
            Log.e(TAG, "[Exception] displayRemoteID(CALLTYPE eCallType, CALLSTATUS eCallStatus)");
        }
    }


    /* ================================================================================================
     * 내 영상
     ================================================================================================ */
    public Camera mMyCamera;

    public void initMyVideoSurfaceLayout() {
        try {
//            LOG_INFO("[initMyVideoSurfaceLayout] MyVideoLayout = " + MyVideoLayout);
            if (MyVideoLayout != null) {
                MyVideoSurface.getHolder().removeCallback(MyVideoCallback);
                MyVideoLayout.removeAllViews();
                MyVideoLayout = null;
            }

            MyVideoLayout = new RelativeLayout(mContext);
            WpadUtil.LayoutRegistration(SurfaceLayout, MyVideoLayout, screenWidth, screenHeight - topHeight, 0, 0, ID.MAINACTIVITY.LAYOUT.MYVIDEO);
            MyVideoSurface = new SurfaceView(mContext);
//            MyVideoHolder = MyVideoSurface.getHolder();

            WpadRelativeLayoutParams MyVideoParams = new WpadRelativeLayoutParams(280, 210);
            MyVideoParams.setMargins(1300, 112, 0, 0); // 안보이게
            MyVideoLayout.addView(MyVideoSurface, MyVideoParams);
            MyVideoSurface.getHolder().addCallback(MyVideoCallback);
            MyVideoSurface.setZOrderOnTop(true);
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] initMyVideoSurfaceLayout()");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        }
    }

    public void removeMyVideoSurfaceLayout() {
        try {
            LOG_INFO("[removeMyVideoSurfaceLayout] MyVideoSurface = " + MyVideoSurface + ", MyVideoLayout = " + MyVideoLayout);
            if (MyVideoLayout != null) {
//                MyVideoSurface.getHolder().removeCallback(MyVideoCallback);
                MyVideoLayout.removeAllViews();
                MyVideoLayout = null;
            }

//            if (MyVideoSurface != null) {
//                MyVideoSurface.setVisibility(View.GONE);
//                MyVideoSurface.getHolder().removeCallback(MyVideoCallback);
//                MyVideoSurface = null;
//            }
//
//            if (MyVideoLayout != null) {
//                MyVideoLayout.setVisibility(View.GONE);
//                MyVideoLayout.removeAllViews();
//                MyVideoLayout = null;
//            }
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] removeRemoteVideoSurfaceLayout()");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        }
    }

    public void showMyVideo(boolean bShow, boolean bMobile) {
        try {
            LOG_INFO("[showMyVideo] bShow [" + bShow + "], bMobile [" + bMobile + "]");

            if (MyVideoSurface == null) {
                LOG_WARN("[showMyVideo] MyVideoSurface is null!!!");
                return;
            }

            WpadRelativeLayoutParams MyVideoParams;
            if (bShow) {
                if (bMobile) { // 방문객원격통화 홈뷰어일 경우
                    MyVideoParams = new WpadRelativeLayoutParams(720, 540);
                } else {
                    MyVideoParams = new WpadRelativeLayoutParams(280, 210);
                }
                MyVideoParams.setMargins(144, 112, 0, 0);
                MyVideoSurface.setLayoutParams(MyVideoParams);
            }
            else {
                MyVideoParams = new WpadRelativeLayoutParams(280, 210);
                MyVideoParams.setMargins(1300, 112, 0, 0); // 안보이게
                MyVideoSurface.setLayoutParams(MyVideoParams);
            }

            if (mCallController.mSIPInterface != null)
                mCallController.mSIPInterface.showMyVideo(bShow);
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] showMyVideo(boolean bShow)");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        }
    }

    public void finishMyVideo() {
        try {
            LOG_INFO("[finishMyVideo]");
            if (mCallController.mSIPInterface != null)
                mCallController.mSIPInterface.videoSet(false, false, false);
//            mCallController.mVideoJNI.setComposite(false);
            showMyVideo(false, false);
            removeMyVideoSurfaceLayout();
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] finishMyVideo()");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        }
    }

    private Callback MyVideoCallback = new Callback() {

        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            try {
                LOG_INFO("[MyVideoCallback] surfaceCreated!!");
                if (ConfigValues.DEVICE_BOARDTYPE == BOARD_TYPE.V40 || ConfigValues.DEVICE_BOARDTYPE == BOARD_TYPE.V40_NOUGAT
                        || ConfigValues.DEVICE_BOARDTYPE == BOARD_TYPE.V40_IGW300_NOUGAT) {
                    mIOInterface.ctrlWallPadCamPower(true);

                    boolean bAOS7 = false;   // 한국생산(다담, AOS 6.0.1)과 중국생산(사니코, 7.1.1) 구분 (true: 중국생산, false: 한국생산)
                    if (Build.VERSION.SDK_INT > 23) bAOS7 = true;
                    if (ConfigValues.DEVICE_MODELTYPE == MODEL_TYPE.IHN_D101) {
                        if (bAOS7) {
                            // AOS 7.1.1
                            mMyCamera = Camera.open(Camera.CameraInfo.CAMERA_FACING_FRONT);    // 확인완료 (JEFF, 2020.09.02)
                        }
                        else {
                            // AOS 6.0.1
                            mMyCamera = Camera.open(Camera.CameraInfo.CAMERA_FACING_FRONT);
                        }
                    }
                    else {
                        if (bAOS7) {
                            /**
                             * 확인완료 (JEFF, 2020.09.02)
                             * IHN-1020B-I, IHN-D101-I, IHN-1010-I
                             * IHN-HS101-I (SEULKI, 2021.05.11)
                             */
                            // AOS 7.1.1
                            if (ConfigValues.DEVICE_MODELTYPE == MODEL_TYPE.IHN_1020B_I && !Global.getCompareBSPVersion("2020.09.08")) mMyCamera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);
                            else if (ConfigValues.DEVICE_MODELTYPE == MODEL_TYPE.IHN_HS101_I && !Global.getCompareBSPVersion("2020.06.11")) mFrontCamera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);
                            else mMyCamera = Camera.open(Camera.CameraInfo.CAMERA_FACING_FRONT);
                        }
                        else {
                            /**
                             * 확인완료 (JEFF, 2020.09.02)
                             * IHN-1010, IHN-HS101
                             */
                            // AOS 6.0.1
                            mMyCamera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);   // 확인완료 (JEFF, 2020.09.02)
                        }
                    }

                    Camera.Parameters params = mMyCamera.getParameters();
                    params.setPictureSize(320, 240);
                    mMyCamera.setParameters(params);
                    mMyCamera.setPreviewDisplay(holder);
                }
                else {
                    LOG_WARN("[MyVideoCallback] surfaceCreated!! -> NOT Supported ConfigValues.DEVICE_BOARDTYPE [" + ConfigValues.DEVICE_BOARDTYPE + "]");
                }
            } catch (RuntimeException re) {
                LogUtil.errorLogInfo("", TAG, re);
            } catch (Exception e) {
                Log.e(TAG, "[Exception] MyVideoCallback -> surfaceCreated(SurfaceHolder holder)");
                //e.printStackTrace();
                LogUtil.errorLogInfo("", TAG, e);
            }
        }

        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
            try {
                LOG_INFO("[MyVideoCallback] surfaceChanged!!");
                if (ConfigValues.DEVICE_BOARDTYPE == BOARD_TYPE.V40 || ConfigValues.DEVICE_BOARDTYPE == BOARD_TYPE.V40_NOUGAT
                        || ConfigValues.DEVICE_BOARDTYPE == BOARD_TYPE.V40_IGW300_NOUGAT) {
                    mMyCamera.startPreview();
                    if (!bFFMPEGEnable && Common.OPTION_TAB_ANMI_ENABLE) {
                        Animation Anmi = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.screen_on);
                        MyVideoLayout.startAnimation(Anmi);
                    }
                } else {
                    LOG_WARN("[MyVideoCallback] surfaceChanged!! -> NOT Supported ConfigValues.DEVICE_BOARDTYPE [" + ConfigValues.DEVICE_BOARDTYPE + "]");
                }
            } catch (RuntimeException re) {
                LogUtil.errorLogInfo("", TAG, re);
            } catch (Exception e) {
                Log.e(TAG, "[Exception] MyVideoCallback -> surfaceChanged(SurfaceHolder holder, int format, int width, int height)");
                //e.printStackTrace();
                LogUtil.errorLogInfo("", TAG, e);
            }
        }

        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
            try {
                LOG_INFO("[MyVideoCallback] surfaceDestroyed!!");
                if (ConfigValues.DEVICE_BOARDTYPE == BOARD_TYPE.V40 || ConfigValues.DEVICE_BOARDTYPE == BOARD_TYPE.V40_NOUGAT
                        || ConfigValues.DEVICE_BOARDTYPE == BOARD_TYPE.V40_IGW300_NOUGAT) {
                    mIOInterface.ctrlWallPadCamPower(false);
                    if (mMyCamera != null) {
                        mMyCamera.stopPreview();
                        mMyCamera.release();
                        mMyCamera = null;
                    }
                } else {
                    LOG_WARN("[MyVideoCallback] surfaceDestroyed!! -> NOT Supported ConfigValues.DEVICE_BOARDTYPE [" + ConfigValues.DEVICE_BOARDTYPE + "]");
                }
            } catch (RuntimeException re) {
                LogUtil.errorLogInfo("", TAG, re);
            } catch (Exception e) {
                Log.e(TAG, "[Exception] MyVideoCallback -> surfaceDestroyed(SurfaceHolder holder)");
                //e.printStackTrace();
                LogUtil.errorLogInfo("", TAG, e);
            }
        }
    };

    /* ================================================================================================
     * 현관카메라 영상
     ================================================================================================ */
    public Camera mFrontCamera;

    public boolean initFrontVideoLayout() {
        try {
            Log.d(TAG, "[initFrontVideoLayout] front camera");
            FrontVideoLayout = new RelativeLayout(mContext);
            WpadUtil.LayoutRegistration(SurfaceLayout, FrontVideoLayout, screenWidth, screenHeight - topHeight, 0, 0, ID.MAINACTIVITY.LAYOUT.FRONTVIDEO);
            FrontVideoSurface = new SurfaceView(mContext);
            FrontVideoHolder = FrontVideoSurface.getHolder();

            WpadRelativeLayoutParams FrontVideoParams;
            FrontVideoParams = new WpadRelativeLayoutParams(720, 540);
            FrontVideoParams.setMargins(1300, 112, 0, 0);
            FrontVideoLayout.addView(FrontVideoSurface, FrontVideoParams);

            showFrontVideo(false);
            FrontVideoSurface.getHolder().addCallback(FrontVideoCallback);
            FrontVideoSurface.setZOrderOnTop(true);
            return true;
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
            return false;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] initFrontVideoLayout()");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
            return false;
        }
    }

    public boolean removeFrontVideoLayout() {
        try {
//            LOG_INFO("[removeFrontVideoLayout] FrontVideoSurface = " + FrontVideoSurface + ", FrontVideoLayout = " + FrontVideoLayout);
            if (FrontVideoSurface != null) {
                FrontVideoSurface.setVisibility(View.GONE);
                FrontVideoSurface.getHolder().removeCallback(FrontVideoCallback);
                FrontVideoSurface = null;
            }

            if (FrontVideoLayout != null) {
                FrontVideoLayout.setVisibility(View.GONE);
                FrontVideoLayout.removeAllViews();
                FrontVideoLayout = null;
            }

            return true;
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
            return false;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] removeFrontVideoLayout()");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
            return false;
        }
    }

    public void initFrontVideo() {
        try {
            LOG("[initFrontVideo]");
            FrontVideoLayout = new RelativeLayout(mContext);
            WpadUtil.LayoutRegistration(SurfaceLayout, FrontVideoLayout, screenWidth, screenHeight - topHeight, 0, 0, ID.MAINACTIVITY.LAYOUT.FRONTVIDEO);
            FrontVideoSurface = new SurfaceView(mContext);
            FrontVideoHolder = FrontVideoSurface.getHolder();

            WpadRelativeLayoutParams FrontVideoParams;
            FrontVideoParams = new WpadRelativeLayoutParams(720, 540);
            FrontVideoParams.setMargins(95, 112, 0, 0);
            FrontVideoLayout.addView(FrontVideoSurface, FrontVideoParams);
            FrontVideoLayout.setVisibility(View.INVISIBLE);
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] initFrontVideo()");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        }
    }

    private Callback FrontVideoCallback = new Callback() {

        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            try {
                LOG_INFO("[FrontVideoCallback] front camera surfaceCreated!!");

                boolean bAOS7 = false;   // 한국생산(다담, AOS 6.0.1)과 중국생산(사니코, 7.1.1) 구분 (true: 중국생산, false: 한국생산)
                if (Build.VERSION.SDK_INT > 23) bAOS7 = true;
                Log.d(TAG, "[FrontVideoCallback] ConfigValues.DEVICE_MODELTYPE [" + ConfigValues.DEVICE_MODELTYPE + "], ConfigValues.eFrontCameraType [" + ConfigValues.eFrontCameraType + "], bAOS7 [" + bAOS7 + "]");

                if (ConfigValues.DEVICE_MODELTYPE == MODEL_TYPE.IHN_D101) {
                    if (bAOS7) {
                        // AOS 7.1.1
                        mFrontCamera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);   // 확인완료 (JEFF, 2020.09.02)
                    }
                    else {
                        // AOS 6.0.1
                        if (ConfigValues.eFrontCameraType == FRONTCAMERATYPE.SMARTIOT || ConfigValues.eFrontCameraType == FRONTCAMERATYPE.HD) mFrontCamera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);
                        else mFrontCamera = Camera.open();
                    }
                }
                else {
                    if (bAOS7) {
                        /**
                         * 확인완료 (JEFF, 2020.09.02)
                         * IHN-1020B-I, IHN-D101-I, IHN-1010 (중국)
                         * IHN-HS101-I (SEULKI, 2021.05.11)
                         */
                        // AOS 7.1.1
                        if (ConfigValues.DEVICE_MODELTYPE == MODEL_TYPE.IHN_1020B_I && !Global.getCompareBSPVersion("2020.09.08")) mFrontCamera = Camera.open(Camera.CameraInfo.CAMERA_FACING_FRONT);
                        else if (ConfigValues.DEVICE_MODELTYPE == MODEL_TYPE.IHN_HS101_I && !Global.getCompareBSPVersion("2020.06.11")) mFrontCamera = Camera.open(Camera.CameraInfo.CAMERA_FACING_FRONT);
                        else mFrontCamera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);
                    }
                    else {
                        /**
                         * 확인완료 (JEFF, 2020.09.02)
                         * IHN-1010, IHN-HS101
                         */
                        // AOS 6.0.1
                        mFrontCamera = Camera.open(Camera.CameraInfo.CAMERA_FACING_FRONT);   // 확인완료 (JEFF, 2020.09.02)
                    }
                }

                if (ConfigValues.eFrontCameraType == FRONTCAMERATYPE.SMARTIOT || ConfigValues.eFrontCameraType == FRONTCAMERATYPE.HD) {
                    Camera.Parameters params = mFrontCamera.getParameters();
                    params.setPictureSize(1280, 720);
                    mFrontCamera.setParameters(params);
                }
                else {
                    Camera.Parameters params = mFrontCamera.getParameters();
                    params.setPictureSize(640, 480);
                    mFrontCamera.setParameters(params);
                }

                mFrontCamera.setPreviewDisplay(holder);
                mFrontCamera.setErrorCallback(FrontVideoErrorCallback);
            } catch (RuntimeException re) {
                LogUtil.errorLogInfo("", TAG, re);
            } catch (Exception e) {
                Log.e(TAG, "[Exception] FrontVideoCallback -> surfaceCreated(SurfaceHolder holder)");
                //e.printStackTrace();
                LogUtil.errorLogInfo("", TAG, e);
            }
        }

        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
            try {
                LOG_INFO("[FrontVideoCallback] surfaceChanged!!");
                if (mFrontCamera != null) {
                    mFrontCamera.startPreview();
                }
                //add KSJ
                if(mCurrentScreenId != ID.SCREEN.SCREEN_TALKFRONT_SUBWALLPAD) {
                    Handler mHandler = new Handler();
                    mHandler.postDelayed(new Runnable()  {
                        public void run() {
                            // 시간 지난 후 실행할 코딩
                            showFrontVideo(true);
                        }
                    }, 500); // 0.5초후
                }
                if (Common.OPTION_TAB_ANMI_ENABLE) {
                    Animation Anmi = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.screen_on);
                    FrontVideoLayout.startAnimation(Anmi);
                }
            } catch (RuntimeException re) {
                LogUtil.errorLogInfo("", TAG, re);
            } catch (Exception e) {
                Log.e(TAG, "[Exception] FrontVideoCallback -> surfaceChanged(SurfaceHolder holder)");
                //e.printStackTrace();
                LogUtil.errorLogInfo("", TAG, e);
            }
        }

        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
            try {
                LOG_INFO("[FrontVideoCallback] surfaceDestroyed!!");
                if (mFrontCamera != null) {
                    mFrontCamera.stopPreview();
                    mFrontCamera.release();
                    mFrontCamera = null;
                }
            } catch (RuntimeException re) {
                LogUtil.errorLogInfo("", TAG, re);
            } catch (Exception e) {
                Log.e(TAG, "[Exception] FrontVideoCallback -> surfaceDestroyed(SurfaceHolder holder)");
                //e.printStackTrace();
                LogUtil.errorLogInfo("", TAG, e);
            }
        }
    };

    private ErrorCallback FrontVideoErrorCallback = new ErrorCallback() {
        @Override
        public void onError(int error, Camera camera) {
            switch (error) {
                case Camera.CAMERA_ERROR_SERVER_DIED:
                    Log.e(TAG, "[FrontVideoErrorCallback] CAMERA_ERROR_SERVER_DIED");
                    camera.stopPreview();
                    camera.setPreviewCallback(null);
                    camera.release();
                    camera = null;
                    break;

                case Camera.CAMERA_ERROR_UNKNOWN:
                    Log.e(TAG, "[FrontVideoErrorCallback] CAMERA_ERROR_UNKNOWN");
                    break;
            }
        }
    };

    public void showFrontVideo(boolean bShow) {
        try {
            LOG_INFO("[showFrontVideo] bShow [" + bShow + "]");
            if (FrontVideoSurface == null) {
                LOG_WARN("[showFrontVideo] FrontVideoSurface is null!!!");
                return;
            }

            WpadRelativeLayoutParams FrontVideoParams;
            FrontVideoParams = new WpadRelativeLayoutParams(720, 540);
            if (bShow) FrontVideoParams.setMargins(95, 112, 0, 0);
            else FrontVideoParams.setMargins(1300, 112, 0, 0); // 안보이게
            FrontVideoSurface.setLayoutParams(FrontVideoParams);
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] showFrontVideo(boolean bShow)");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        }
    }

    /** 사진 암호화 관련 */
    public static final String ALGORITHM = "AES";
    public static final String TRANSFORMATION = ALGORITHM + "/ECB/PKCS5Padding";
    public static final String VISITOR_PICTURE_ENCRYPT_KEY = "VISITOR_PICTURE_ENCRYPT_KEY";

    private Cipher initCryptConfig(int mode) {
        Cipher cipher = null;
        try {
            byte[] hKey = getAESKey();
            if (hKey != null) {
                cipher = Cipher.getInstance(TRANSFORMATION);
                SecretKeySpec key = new SecretKeySpec(hKey, ALGORITHM);
                cipher.init(mode, key);
            }
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] initCryptConfig(int mode)");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        }
        return cipher;
    }

    private byte[] getAESKey() {
        byte[] hKeyData = null;
        try {
            String strKey = VISITOR_PICTURE_ENCRYPT_KEY.substring(0, 16);
            hKeyData = new byte[16];
            byte[] b = strKey.getBytes("UTF-8");
            int len = b.length;
            if (len > hKeyData.length) {
                len = hKeyData.length;
            }
            System.arraycopy(b, 0, hKeyData, 0, len);
            return hKeyData;
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] getAESKey()");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        }
        return hKeyData;
    }

    public void encryptPictureFile(File sourceFile) {
        InputStream input = null;
        OutputStream output = null;
        try {
//            LOG("[encryptPictureFile] sourceFile [" + sourceFile.getPath() + "]");
            Cipher cipher = initCryptConfig(Cipher.ENCRYPT_MODE);
            if (cipher != null) {
                input = new BufferedInputStream(new FileInputStream(sourceFile));
                LOG("[encryptPictureFile] input.available [" + input.available() + "]");
                output = new BufferedOutputStream(new FileOutputStream(define.VISITOR_PICTURE_LOCATION + "/ENCRYPTED_" + sourceFile.getName()));
                byte[] buffer = new byte[1024];
                int read = -1;
                while((read = input.read(buffer)) != -1) {
                    output.write(cipher.update(buffer, 0, read));
                }
                output.write(cipher.doFinal());
                sourceFile.delete(); // 암호화하기 이전 파일은 삭제
            } else {
                LOG_WARN("[encryptPictureFile] cipher is null!");
            }
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] encryptPictureFile(Fie sourceFile)");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        } finally {
            if (output != null) {
                try { output.close(); } catch (IOException ie) { Log.e(TAG, "[Exception] encryptPictureFile.output.close"); }
            }
            if (input != null) {
                try { input.close(); } catch (IOException ie) { Log.e(TAG, "[Exception] encryptPictureFile.input.close"); }
            }
        }
    }

    /**
     * 방문자사진 복호화 기능 수행
     * @param sourceFile 암호화된 파일 (/sdcrad/Bestin/VisitorPicture/ 폴더에 저장)
     * @param destFile 복호화 파일 (/sdcrad/Bestin/VisitorPicture/Decrypt/ 폴더에 저장)
     * @return destFile (사진을 복호화하여 파일 리턴)
     */
    public File decryptPictureFile(File sourceFile, File destFile) {
        InputStream input = null;
        OutputStream output = null;
        try {
            if (sourceFile.exists()) {
                Cipher cipher = initCryptConfig(Cipher.DECRYPT_MODE);
                if (cipher != null) {
                    input = new BufferedInputStream(new FileInputStream(sourceFile));
                    LOG("[decryptPictureFile] input.available [" + input.available() + "]");
                    output = new BufferedOutputStream(new FileOutputStream(destFile.getPath()));
                    byte[] buffer = new byte[1024];
                    int read = -1;
                    while ((read = input.read(buffer)) != -1) {
                        output.write(cipher.update(buffer, 0, read));
                    }
                    output.write(cipher.doFinal());
                    return destFile;
                } else {
                    LOG_WARN("[decryptPictureFile] cipher is null!");
                }
            } else {
//                LOG("[decryptPictureFile] Do not need to decrypt File!! [" + destFile.getPath() + "]");
                return new File(define.VISITOR_PICTURE_LOCATION + "/" + destFile.getName()); // 기존에 암호화 안되어 저장했던 사진은 복호화 하면 안됨
            }
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] decryptPictureFile(File sourceFile, File destFile)");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        } finally {
            if (output != null) {
                try { output.close(); } catch (IOException ie) { Log.e(TAG, "[Exception] decryptPictureFile.output.close"); }
            }
            if (input != null) {
                try { input.close(); } catch (IOException ie) { Log.e(TAG, "[Exception] decryptPictureFile.input.close"); }
            }
        }
        return null;
    }

    int camOpenCheckCnt1 = 0, camOpenCheckCnt2 = 0, camOpenCheckCnt3 = 0, camOpenCheckCnt4 = 0;
    int handlerMaxCnt = 100;

    /**
     * 현관카메라 OPEN CHECK Handler!!!
     */
    public Handler mFrontCamOpenCheckHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            LOG("[mFrontCamOpenCheckHandler] msg.what = " + msg.what);
            if (msg.what == 0) {
                camOpenCheckCnt1++;
                if (camOpenCheckCnt1 > handlerMaxCnt) {
                    Log.w(TAG, "[mFrontCamOpenCheckHandler] camOpenCheckCnt1 is over!! [" + camOpenCheckCnt1 + "]");
                    mFrontCamOpenCheckHandler.removeMessages(0);
                    mFrontCamOpenCheckHandler.removeMessages(1);
                } else {
                    if (mFrontCamera != null)
                        mFrontCamOpenCheckHandler.sendEmptyMessageDelayed(1, 100);
                    else mFrontCamOpenCheckHandler.sendEmptyMessageDelayed(0, 100);
                }
            } else if (msg.what == 1) {
                // ************ 카메라 밝기 조절!! ************
                Log.d(TAG, "[mFrontCamOpenCheckHandler] [CAMERA OPEN] ctrlCameraBrightness");
                Global.ctrlCameraBrightness(nBrightness);
            } else if (msg.what == 2) {
                camOpenCheckCnt2++;
                if (camOpenCheckCnt2 > handlerMaxCnt) {
                    Log.w(TAG, "[mFrontCamOpenCheckHandler] camOpenCheckCnt2 is over!! [" + camOpenCheckCnt2 + "]");
                    mFrontCamOpenCheckHandler.removeMessages(2);
                    mFrontCamOpenCheckHandler.removeMessages(3);
                } else {
                    if (mFrontCamera != null) mFrontCamOpenCheckHandler.sendEmptyMessageDelayed(3, 100);
                    else mFrontCamOpenCheckHandler.sendEmptyMessageDelayed(2, 100);
                }
            } else if (msg.what == 3) {
                // ************ 스마트현관카메라 영상 녹화 시작!! ************
            } else if (msg.what == 4) {
                camOpenCheckCnt3++;
                if (camOpenCheckCnt3 > handlerMaxCnt) {
                    Log.w(TAG, "[mFrontCamOpenCheckHandler] camOpenCheckCnt3 is over!! [" + camOpenCheckCnt3 + "]");
                    mFrontCamOpenCheckHandler.removeMessages(4);
                    mFrontCamOpenCheckHandler.removeMessages(5);
                } else {
                    if (mFrontCamera != null) mFrontCamOpenCheckHandler.sendEmptyMessageDelayed(5, 100);
                    else mFrontCamOpenCheckHandler.sendEmptyMessageDelayed(4, 100);
                }
            } else if (msg.what == 5) {
                // ************ 서브폰 현관 TV Out 시작!! (IHN-D101 PR2000K / 대외향월패드 기본 현관카메라 호출시) ************
                Log.d(TAG, "[mFrontCamOpenCheckHandler] [CAMERA OPEN] SubPhone TV OUT");
                sendHandlerMsg(HANDLERMSG.SHOW_FRONTCAM_SUBPHONE, 0, 0);
                if (ConfigValues.bRemoteCall) {
                    ((MainActivity) mContext).mFrontCamOpenCheckHandler.sendEmptyMessageDelayed(6, 100); // camera open check, Subphone TVout 이후 encoderStartOperation 시작 (방문객 원격통화 사용할 경우)
                }
            } else if (msg.what == 6) {
                camOpenCheckCnt4++;
                if (camOpenCheckCnt4 > handlerMaxCnt) {
                    Log.w(TAG, "[mFrontCamOpenCheckHandler] camOpenCheckCnt4 is over!! [" + camOpenCheckCnt4 + "]");
                    mFrontCamOpenCheckHandler.removeMessages(6);
                    mFrontCamOpenCheckHandler.removeMessages(7);
                } else {
                    if (mFrontCamera != null) mFrontCamOpenCheckHandler.sendEmptyMessageDelayed(7, 100);
                    else mFrontCamOpenCheckHandler.sendEmptyMessageDelayed(6, 100);
                }
            } else if (msg.what == 7) {
                // ************방문객 원격통화 인코딩 시작!! ************
                Log.d(TAG, "[mFrontCamOpenCheckHandler] [CAMERA OPEN] encoderStart");
                startVideoEncoding(true, true, true); // 모바일로 현관 영상 전송 (방문객 원격통화)
            }
        }
    };

    // ============================== 영상 ==============================
    public void startVideoEncoding(boolean bSet, boolean bEncoding, boolean bDecoding) {
        try {
            Log.d(TAG, "[startVideoEncoding] bSet [" + bSet + "], bEncoding [" + bEncoding + "], bDecoding [" + bDecoding + "]");
            if (mVideoController == null) Log.w(TAG, "[startVideoEncoding] mVideoController is null!");

            if (mVideoController != null) {
                mVideoController.startVideoEncoding(bSet, bEncoding, bDecoding);
            }
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] startVideoEncoding(boolean bSet, boolean bEncoding, boolean bDecoding)");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        }
    }

    int apiCheckCnt1 = 0, apiCheckCnt2 = 0, apiCheckCnt3 = 0;
    protected Handler mWallPadApiCheckHandler = new Handler() {
        public void handleMessage(Message msg) {
            if (msg.what == 0) {
                apiCheckCnt1++;
                if (apiCheckCnt1 > (handlerMaxCnt * 10)) {
                    Log.w(TAG, "[mFrontCamOpenCheckHandler] apiCheckCnt1 is over!! [" + apiCheckCnt1 + "]");
                    mWallPadApiCheckHandler.removeMessages(0);
                    mWallPadApiCheckHandler.removeMessages(1);
                } else {
                    if (mWallPadAPI != null) {
                        if (mWallPadAPI.Check_Connect()) mWallPadApiCheckHandler.sendEmptyMessageDelayed(1, 10);
                        else mWallPadApiCheckHandler.sendEmptyMessageDelayed(0, 10);
                    }
                    else {
                        Log.w(TAG, "[mFrontCamOpenCheckHandler] mWallPadAPI is null!!!");
                    }
                }
            } else if (msg.what == 1) {
                // 스마트현관카메라 API 로딩
                Log.d(TAG, "[mWallPadApiCheckHandler.handleMessage] Handler finish!! mTempCurrentScreenId [" + mTempCurrentScreenId + "]");
                if (ConfigValues.eFrontCameraType == FRONTCAMERATYPE.SMARTIOT || ConfigValues.eFrontCameraType == FRONTCAMERATYPE.SMARTKEY_EXTERNAL || ConfigValues.eFrontCameraType == FRONTCAMERATYPE.SMART_HS || ConfigValues.eFrontCameraType == FRONTCAMERATYPE.SMART_DW) {
                    smartKeyRfDoorAPI = mWallPadAPI.Get_SmartKeyRfDoorController();
                }
                boolean result = setChangeScreen(mTempCurrentScreenId, false);
                if (!result) {
                    int nScreenID = API_Menu.SubMenuCall.Guard;
                    if (!bGuardCallUse) {
                        if (bFrontCallUse) nScreenID = API_Menu.SubMenuCall.Door;
                        else if (bResiCallUse) nScreenID = API_Menu.SubMenuCall.Neighbor;
                        else if (bPSTNCallUse) nScreenID = API_Menu.SubMenuCall.PSTN;
                        else if (bCallHistoryUse) nScreenID = API_Menu.SubMenuCall.CallList;
                        else if (bVisitorPicUse) nScreenID = API_Menu.SubMenuCall.Visitor;
                    }
                    setChangeScreen(nScreenID, false);
                }
            } else if (msg.what == 2) {
                apiCheckCnt2++;
                if (apiCheckCnt2 > (handlerMaxCnt * 10)) {
                    Log.w(TAG, "[mFrontCamOpenCheckHandler] apiCheckCnt2 is over!! [" + apiCheckCnt2 + "]");
                    mWallPadApiCheckHandler.removeMessages(2);
                    mWallPadApiCheckHandler.removeMessages(3);
                } else {
                    if (mWallPadAPI != null) {
                        if (mWallPadAPI.Check_Connect())
                            mWallPadApiCheckHandler.sendEmptyMessageDelayed(3, 10);
                        else mWallPadApiCheckHandler.sendEmptyMessageDelayed(2, 10);
                    }
                }
            } else if (msg.what == 3) {
                // 거실조명 API 로딩
                sdbLivingRoomLightAPI = mWallPadAPI.Get_Sdb_LivingRoomLightAPI();
                Log.d(TAG, "[mWallPadApiCheckHandler.handleMessage] ---------- sdbLivingRoomLightAPI is connected!!! ----------");
            } else if (msg.what == 4) {
                apiCheckCnt3++;
                if (apiCheckCnt3 > (handlerMaxCnt * 10)) {
                    Log.w(TAG, "[mFrontCamOpenCheckHandler] apiCheckCnt3 is over!! [" + apiCheckCnt3 + "]");
                    mWallPadApiCheckHandler.removeMessages(4);
                    mWallPadApiCheckHandler.removeMessages(5);
                } else {
                    if (mWallPadAPI != null) {
                        if (mWallPadAPI.Check_Connect())
                            mWallPadApiCheckHandler.sendEmptyMessageDelayed(5, 10);
                        else mWallPadApiCheckHandler.sendEmptyMessageDelayed(4, 10);
                    }
                }
            } else if (msg.what == 5) {
                // 지문인식 API 로딩
                fpDlockAPI = mWallPadAPI.Get_FP_DLockController();
                Log.d(TAG, "[mWallPadApiCheckHandler.handleMessage] ---------- fpDlockAPI is connected!!! ----------");
            }
        }
    };

    int pathCheckCnt1 = 0, pathCheckCnt2 = 0;
    public Handler mCallPathCheckHandler = new Handler() {
        public void handleMessage(Message msg) {
            try {
                if (ConfigValues.DEVICE_BOARDTYPE == BOARD_TYPE.V40 || ConfigValues.DEVICE_BOARDTYPE == BOARD_TYPE.V40_NOUGAT) {
                    if (msg.what == 0) {
                        pathCheckCnt1++;
                        if (pathCheckCnt1 > 200) {
                            Log.w(TAG, "[mCallPathCheckHandler] pathCheckCnt1 is over!! [" + pathCheckCnt1 + "]");
                            sendHandlerMsg(HANDLERMSG.RECOVER_SYSTEM_VOLUME, 0, 0);
                            mCallPathCheckHandler.removeMessages(0);
                            mCallPathCheckHandler.removeMessages(1);
                        } else {
                            if (mCallController.getTalkPath() == CALLPATH.DOORMUSIC)
                                mCallPathCheckHandler.sendEmptyMessageDelayed(1, 50);
                            else mCallPathCheckHandler.sendEmptyMessageDelayed(0, 50);
                        }
                    } else if (msg.what == 1) {
                        Log.d(TAG, "[mCallPathCheckHandler.handleMessage] Handler finish!! CALLPATH [" + mCallController.getTalkPath() + "]");
                        mIOInterface.ctrlSetTalkPathDoor();
                        sendHandlerMsg(HANDLERMSG.PLAY_DINGDONG, 0, 0); // [띵똥시나리오] 1. 현관카메라 띵똥~
                    } else if (msg.what == 2) {
                        pathCheckCnt2++;
                        if (pathCheckCnt2 > 200) {
                            Log.w(TAG, "[mCallPathCheckHandler] pathCheckCnt2 is over!! [" + pathCheckCnt2 + "]");
                            sendHandlerMsg(HANDLERMSG.RECOVER_SYSTEM_VOLUME, 0, 0);
                            mCallPathCheckHandler.removeMessages(2);
                            mCallPathCheckHandler.removeMessages(3);
                        } else {
                            if (mCallController.getTalkPath() == CALLPATH.NORMAL)
                                mCallPathCheckHandler.sendEmptyMessageDelayed(3, 50);
                            else mCallPathCheckHandler.sendEmptyMessageDelayed(2, 50);
                        }
                    } else if (msg.what == 3) {
                        Log.d(TAG, "[mCallPathCheckHandler.handleMessage] Handler finish!! CALLPATH [" + mCallController.getTalkPath() + "]");
                        CALLSTATUS eCallStatus = mCallController.mCallInfo.getFRONT();
                        Log.d(TAG, "[mCallPathCheckHandler.handleMessage] eCallStatus [" + eCallStatus + "]");
                        if (eCallStatus == CALLSTATUS.CALLED) {
                            sendHandlerMsg(HANDLERMSG.RECOVER_SYSTEM_VOLUME, 0, 0);
                            sendHandlerMsgDelayed(HANDLERMSG.PLAY_FRONT_BELL, 0, 0, 200); // [띵똥시나리오] 3. W/P에서 현관호출음
                            sendHandlerMsgDelayed(HANDLERMSG.SET_TALK_BTN_ENABLE, 0, 0, 1000);
                        }
                    }
                }
            } catch (RuntimeException re) {
                LogUtil.errorLogInfo("", TAG, re);
            } catch (Exception e) {
                Log.e(TAG, "[Exception] mCallPathCheckHandler.handleMessage()");
                //e.printStackTrace();
                LogUtil.errorLogInfo("", TAG, e);
                sendHandlerMsg(HANDLERMSG.RECOVER_SYSTEM_VOLUME, 0, 0);
            }
        }
    };

    public boolean saveFrontPicture() {
        try {
            LOG_INFO("[saveFrontPicture]");
            if (mFrontCamera != null) {
                if (ConfigValues.DEVICE_MODELTYPE == MODEL_TYPE.IHN_D101 || ConfigValues.DEVICE_MODELTYPE == MODEL_TYPE.IHN_D101_I || ConfigValues.DEVICE_MODELTYPE == MODEL_TYPE.IHN_D101_I_LX2
                        || ConfigValues.DEVICE_MODELTYPE == MODEL_TYPE.IHN_D101K || ConfigValues.DEVICE_MODELTYPE == MODEL_TYPE.IHN_D101K_I
                        || ConfigValues.DEVICE_MODELTYPE == MODEL_TYPE.IHN_D101_I_OCF) {
                    mFrontCamera.takePicture(null, null, mPicture_IHND101);
                }
                else {
                    mFrontCamera.takePicture(null, null, mPicture);
                }
                return true;
            } else {
                Log.w(TAG, "[saveFrontPicture] mFrontCamera is null!");
                return false;
            }
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
            return false;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] saveFrontPicture()");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
            return false;
        }
    }

    Camera.PictureCallback mPicture = new Camera.PictureCallback() {
        @Override
        public void onPictureTaken(byte[] data, Camera camera) {
            // JPEG 이미지가 byte[] 형태로 들어옵니다.
            try {
                if (mCallController.strVisitorPicturePath != null) {
                    File mFile = new File(mCallController.strVisitorPicturePath);
                    Bitmap mBitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
                    if (mBitmap != null) {
                        mBitmap = getResizedBitmap(mBitmap, 325, 245);
                        mBitmap = cropBitmap(mBitmap);
//                        LOG("[onPictureTaken] After Resize!! mBitmap.Width [" + mBitmap.getWidth() + "], mBitmap.Height [" + mBitmap.getHeight() + "]");
                        FileOutputStream mFileOutputStream = new FileOutputStream(mFile);
                        if (!Version.getGatewayUsage() || ConfigValues.DEVICE_MODELTYPE == MODEL_TYPE.IHN_1010GL_I
                                || ConfigValues.DEVICE_MODELTYPE == MODEL_TYPE.IHN_1010GL_I_2443 || ConfigValues.DEVICE_MODELTYPE == MODEL_TYPE.IHN_1010GL_I_6410) {
                            if (Build.VERSION.SDK_INT > 23) { // 대외향 모델 중 AOS 7.1인 모델에 적용
                                LOG("[onPictureTaken] apply YUV");
                                byte [] yuv = getNV21(mBitmap.getWidth(), mBitmap.getHeight(), mBitmap);
                                int[] anRGB8888 = decodeYUV420SP(yuv, mBitmap.getWidth(), mBitmap.getHeight());
                                mBitmap = Bitmap.createBitmap(anRGB8888, mBitmap.getWidth(), mBitmap.getHeight(), Bitmap.Config.ARGB_8888);
                                mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, mFileOutputStream);
                            }
                        }
                        else {
                            mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, mFileOutputStream);
                        }
                        mFileOutputStream.flush();
                        mFileOutputStream.close();

                        // 검은화면(카메라 고장 또는 영상 출력빠짐)일 경우 이미지 교체
                        long fileSize = mFile.length();
                        if (fileSize < 2000) {
                            LOG_WARN("[onPictureTaken] fileSize is less than 2000 KB [" + fileSize + "]");
                            mFile.delete();

                            InputStream input = getResources().openRawResource(R.drawable.box_no_image);
                            mFileOutputStream = new FileOutputStream(mFile);
                            byte[] hData = new byte[1024];
                            int length = 0;
                            while ((length = input.read(hData)) > 0) {
//                                Log.d(TAG, "[onPictureTaken] length [" + length + "]");
                                mFileOutputStream.write(hData, 0, length);
                            }
                            mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, mFileOutputStream);
                            mFileOutputStream.flush();
                            mFileOutputStream.close();
                            input.close();
                        }

//                        encryptPictureFile(mFile); // TODO 추후 적용!!! 홈넷 AAA등급 인증을 위한 사진 암호화

                        if (mFrontCamera != null) mFrontCamera.startPreview();
                    } else {
                        Log.w(TAG, "[onPictureTaken] mBitmap is null!");
                    }
                } else {
                    Log.w(TAG, "[onPictureTaken] strVisitorPicturePath is null!");
                }
            } catch (FileNotFoundException e) {
                Log.e(TAG, "[FileNotFoundException] File not found: " + e.getMessage());
                //e.printStackTrace();
                LogUtil.errorLogInfo("", TAG, e);
                mCallController.strVisitorPicturePath = null;
            } catch (IOException e) {
                Log.e(TAG, "[IOException] Error accessing file: " + e.getMessage());
                //e.printStackTrace();
                LogUtil.errorLogInfo("", TAG, e);
                mCallController.strVisitorPicturePath = null;
            } catch (Exception e) {
                Log.e(TAG, "[Exception] onPictureTaken(byte[] data, Camera camera)");
                //e.printStackTrace();
                LogUtil.errorLogInfo("", TAG, e);
                mCallController.strVisitorPicturePath = null;
            }
        }
    };

    Camera.PictureCallback mPicture_IHND101 = new Camera.PictureCallback() {
        @Override
        public void onPictureTaken(byte[] data, Camera camera) {
            // JPEG 이미지가 byte[] 형태로 들어옵니다.
            try {
                if (mCallController.strVisitorPicturePath != null) {
                    File mFile = new File(mCallController.strVisitorPicturePath);
                    Bitmap mBitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
                    if (mBitmap != null) {
                        FileOutputStream mFileOutputStream = new FileOutputStream(mFile);
                        mBitmap = postprocTakenIMG(mBitmap);
                        mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, mFileOutputStream);
                        Log.i(TAG, "[mPicture_IHND101.onPictureTaken] Width [" + mBitmap.getWidth() + "], Height [" + mBitmap.getHeight() + "]");
                        mFileOutputStream.flush();
                        mFileOutputStream.close();

                        // 검은화면(카메라 고장 또는 영상 출력빠짐)일 경우 이미지 교체
                        long fileSize = mFile.length();
                        if (fileSize < 2000) {
                            LOG_WARN("[mPicture_IHND101] fileSize is less than 2000 KB [" + fileSize + "]");
                            mFile.delete();

                            InputStream input = getResources().openRawResource(R.drawable.box_no_image);
                            mFileOutputStream = new FileOutputStream(mFile);
                            byte[] hData = new byte[1024];
                            int length = 0;
                            while ((length = input.read(hData)) > 0) {
                                mFileOutputStream.write(hData, 0, length);
                            }
                            mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, mFileOutputStream);
                            mFileOutputStream.flush();
                            mFileOutputStream.close();
                            input.close();
                        }
//                        encryptPictureFile(mFile); // TODO 추후 적용!!! 홈넷 AAA등급 인증을 위한 사진 암호화

                        if (mFrontCamera != null) mFrontCamera.startPreview();
                    }
                    else {
                        Log.w(TAG, "[mPicture_IHND101] mBitmap is null!");
                    }
                }
                else {
                    Log.w(TAG, "[mPicture_IHND101] strVisitorPicturePath is null!");
                }
            } catch (FileNotFoundException e) {
                Log.e(TAG, "[FileNotFoundException] File not found: " + e.getMessage());
                //e.printStackTrace();
                LogUtil.errorLogInfo("", TAG, e);
                mCallController.strVisitorPicturePath = null;
            } catch (IOException e) {
                Log.e(TAG, "[IOException] Error accessing file: " + e.getMessage());
                //e.printStackTrace();
                LogUtil.errorLogInfo("", TAG, e);
                mCallController.strVisitorPicturePath = null;
            } catch (Exception e) {
                Log.e(TAG, "[Exception] mPicture_IHND101.onPictureTaken(byte[] data, Camera camera)");
                //e.printStackTrace();
                LogUtil.errorLogInfo("", TAG, e);
                mCallController.strVisitorPicturePath = null;
            }
        }
    };

    public Bitmap reverseIMGColor(Bitmap bitmap) {
        try {
            int [] argb = new int[bitmap.getWidth() * bitmap.getHeight()];
            byte [] yuv = getNV21(bitmap.getWidth(), bitmap.getHeight(), bitmap);
            int[] anRGB8888 = decodeYUV420SP(yuv, bitmap.getWidth(), bitmap.getHeight());
            return Bitmap.createBitmap(anRGB8888, bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
            return null;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] reverseIMGColor(Bitmap bitmap)");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
            return null;
        }
    }

    public Bitmap flipTakenIMG(Bitmap bitmap) {
        try {
            Matrix matrix = new Matrix();
            if (ConfigValues.bSmartIOTCamFlip) matrix.setScale(-1, 1);
            else matrix.setScale(1, 1);
            return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, false);
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
            return null;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] flipTakenIMG(Bitmap bitmap)");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
            return null;
        }
    }

    public Bitmap cropBitmap(Bitmap Original) {
        try {
            Bitmap Result;
            Log.w(TAG, "[cropBitmap] ConfigValues.eFrontCameraType [" + ConfigValues.eFrontCameraType + "]");
            if (Build.VERSION.SDK_INT > 23) {
                // AOS 7.1.1 (메이드인랩 BSP)
                if (ConfigValues.eFrontCameraType == FRONTCAMERATYPE.SMARTIOT) {
                    Matrix matrix = new Matrix();
                    if (ConfigValues.bSmartIOTCamFlip) matrix.setScale(-1, 1);
                    else matrix.setScale(1, 1);
                    Result = Bitmap.createBitmap(Original, 5, 5, 320, 240, matrix, true);
                }
                else {
                    Result = Bitmap.createBitmap(Original, 5, 5, 320, 240);
                }
            }
            else {
                // AOS 6.0.1 (다담 BSP)
                Log.i(TAG, "[cropBitmap] Width [" + Original.getWidth() + "], Height [" + Original.getHeight() + "]");
                Result = Bitmap.createBitmap(Original, 5, 5, 320, 240);
            }

            if (Result != Original) Original.recycle();
            return Result;
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
            return null;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] cropBitmap(Bitmap Original)");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
            return null;
        }
    }

    boolean bOriginalSize = false;   // true: 원래 사이즈로 저장, false: 수정된 사이즈(320, 240)로 저장
    int nFixedIMGSize_Width = 320;
    int nFixedIMGSize_Height = 240;
    public Bitmap postprocTakenIMG(Bitmap Original) {
        try {
            Bitmap Result;
            if (Build.VERSION.SDK_INT > 23) {
                // AOS 7.1.1 (메이드인랩 BSP)
                if (bOriginalSize) {
                    Result = Bitmap.createScaledBitmap(Original, Original.getWidth() + 5, Original.getHeight() + 5, false);
                    Result = Bitmap.createBitmap(Result, 5, 5, Original.getWidth(), Original.getHeight());

                    if (ConfigValues.eFrontCameraType == FRONTCAMERATYPE.SMARTIOT || ConfigValues.eFrontCameraType == FRONTCAMERATYPE.HD) {
                        // 스마트IoT현관카메라의 경우 사진 색반전 코드 적용 (JEFF, 2020.08.11)
                        Result = reverseIMGColor(Result);
                    }
                }
                else {
                    Result = getResizedBitmap(Original, nFixedIMGSize_Width + 5, nFixedIMGSize_Height + 5);
                    Result = Bitmap.createBitmap(Result, 5, 5, nFixedIMGSize_Width, nFixedIMGSize_Height);
                    Result = reverseIMGColor(Result);
                    if (ConfigValues.eFrontCameraType == FRONTCAMERATYPE.SMARTIOT || ConfigValues.eFrontCameraType == FRONTCAMERATYPE.HD) {
                        // 스마트IoT현관카메라의 경우 사진 색반전 코드 적용 (JEFF, 2020.08.11)
                        Result = flipTakenIMG(Result);
                    }
                }
            }
            else {
                // AOS 6.0.1 (다담 BSP)
                if (bOriginalSize) {
                    Result = Bitmap.createScaledBitmap(Original, Original.getWidth() + 5, Original.getHeight() + 5, false);
                    Result = Bitmap.createBitmap(Result, 5, 5, Original.getWidth(), Original.getHeight());
                }
                else {
                    Result = getResizedBitmap(Original, nFixedIMGSize_Width + 5, nFixedIMGSize_Height + 5);
                    Result = Bitmap.createBitmap(Result, 5, 5, nFixedIMGSize_Width, nFixedIMGSize_Height);
                }
            }

            if (Result != Original) Original.recycle();
            return Result;
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
            return null;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] postprocTakenIMG(Bitmap Original)");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
            return null;
        }
    }

    public Bitmap getResizedBitmap(Bitmap bitmap, int nNewWidth, int nNewHeight) {
        try {
            int nWidth = bitmap.getWidth();
            int nHeight = bitmap.getHeight();
            float scaleWidth = ((float) nNewWidth) / nWidth;
            float scaleHeight = ((float) nNewHeight) / nHeight;

            Matrix mMatrix = new Matrix();
            mMatrix.postScale(scaleWidth, scaleHeight);
            return Bitmap.createBitmap(bitmap, 0, 0, nWidth, nHeight, mMatrix, false);
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
            return null;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] getResizedBitmap(Bitmap bitmap, int nNewWidth, int nNewHeight)");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
            return null;
        }
    }

    public int[] decodeYUV420SP(byte[] yuv420sp,int width,int height) {
        try {
            final int frameSize = width * height;
            int[] anPixels = new int[frameSize];
            for (int j =0, yp =0; j < height; j++) {
                int uvp = frameSize + (j >>1) * width, u =0, v =0;
                for (int i =0; i < width; i++, yp++) {
                    int y = (0xff & ((int) yuv420sp[yp])) -16;
                    if (y <0) y =0;
                    if ((i &1) ==0) {
                        v = (0xff & yuv420sp[uvp++]) -128;
                        u = (0xff & yuv420sp[uvp++]) -128;
                    }

                    int y1192 =1192 * y;
                    int r = (y1192 +1634 * v);
                    int g = (y1192 -833 * v -400 * u);
                    int b = (y1192 +2066 * u);

                    if (r <0) r =0;else if (r >262143) r =262143;
                    if (g <0) g =0;else if (g >262143) g =262143;
                    if (b <0) b =0;else if (b >262143) b =262143;

                    anPixels[yp] =0xff000000 | ((r <<6) &0xff0000) | ((g >>2) &0xff00) | ((b >>10) &0xff);
                }
            }
            return anPixels;
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
            return null;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] decodeYUV420SP(byte[] yuv420sp,int width,int height)");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
            return null;
        }
    }

    byte [] getNV21(int inputWidth, int inputHeight, Bitmap scaled) {
        try {
            int [] argb = new int[inputWidth * inputHeight];

            scaled.getPixels(argb, 0, inputWidth, 0, 0, inputWidth, inputHeight);

            byte [] yuv = new byte[inputWidth*inputHeight*3/2];
            yuv = encodeYUV420SP(argb, inputWidth, inputHeight);

            scaled.recycle();

            return yuv;
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
            return null;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] getNV21(int inputWidth, int inputHeight, Bitmap scaled)");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
            return null;
        }
    }

    byte [] encodeYUV420SP(int[] argb, int width, int height) {
        try {
            final int frameSize = width * height;
            byte [] yuv = new byte[width*height*3/2];
            int yIndex = 0;
            int uvIndex = frameSize;

            int a, R, G, B, Y, U, V;
            int index = 0;
            for (int j = 0; j < height; j++) {
                for (int i = 0; i < width; i++) {

                    a = (argb[index] & 0xff000000) >> 24; // a is not used obviously
                    R = (argb[index] & 0xff0000) >> 16;
                    G = (argb[index] & 0xff00) >> 8;
                    B = (argb[index] & 0xff) >> 0;

                    // well known RGB to YUV algorithm
                    Y = ( (  66 * R + 129 * G +  25 * B + 128) >> 8) +  16;
                    //U = ( ( -38 * R - 74 * G + 112 * B + 128) >> 8) + 128;
                    //V = ( ( 112 * R - 94 * G - 18 * B + 128) >> 8) + 128;

                    V = ( ( -38 * R -  74 * G + 112 * B + 128) >> 8) + 128;
                    U = ( ( 112 * R -  94 * G -  18 * B + 128) >> 8) + 128;

                    // NV21 has a plane of Y and interleaved planes of VU each sampled by a factor of 2
                    // meaning for every 4 Y pixels there are 1 V and 1 U. Note the sampling is every other
                    // pixel AND every other scanline.
                    yuv[yIndex++] = (byte) ((Y < 0) ? 0 : ((Y > 255) ? 255 : Y));
                    if (j % 2 == 0 && index % 2 == 0) {
                        yuv[uvIndex++] = (byte)((V<0) ? 0 : ((V > 255) ? 255 : V));
                        yuv[uvIndex++] = (byte)((U<0) ? 0 : ((U > 255) ? 255 : U));
                    }
                    index ++;
                }
            }
            return yuv;
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
            return null;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] encodeYUV420SP(int[] argb, int width, int height)");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
            return null;
        }
    }

    public boolean getStrangerRecordingManagerSetting() {
        boolean bResult = false;
        WallpadDeviceSet mWallpadDeviceSet = new WallpadDeviceSet(getApplicationContext());
        try {
            int[] nFrontCam = mWallpadDeviceSet.Get_RFDoorCAM_Info();
            boolean bRecord = mWallpadDeviceSet.Get_Stranger_RecordUse();
            mWallpadDeviceSet.closeDB();

            if (nFrontCam[0] == 1) {
                if (nFrontCam[1] == WallpadDeviceSet.DOORTYPE_IOT_SMART || nFrontCam[1] == WallpadDeviceSet.DOORTYPE_HYOSUNG_SMART || nFrontCam[1] == WallpadDeviceSet.DOORTYPE_DAEWOO_SMART) {
                    if (bRecord) bResult = true;
                    else bResult = false;
                }
                else bResult = false;
            }
            else bResult = false;

        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
            mWallpadDeviceSet.closeDB();
        }
        catch (Exception e) {
            mWallpadDeviceSet.closeDB();
            Log.e(TAG, "[Exception] getStrangerRecordingManagerSetting()");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        }
        Log.d(TAG, "[getStrangerRecordingManagerSetting] bResult [" + bResult + "]");
        return bResult;
    }

    public void ctrlSmartIOTCamStatusMode(byte mode) {
        try {
            if (ConfigValues.eFrontCameraType == FRONTCAMERATYPE.SMARTIOT
                    || ConfigValues.eFrontCameraType == FRONTCAMERATYPE.SMARTKEY_EXTERNAL
                    || ConfigValues.eFrontCameraType == FRONTCAMERATYPE.SMART_HS
                    || ConfigValues.eFrontCameraType == FRONTCAMERATYPE.SMART_DW) {
                LOG("[ctrlSmartIOTCamStatusMode] mode [" + Global.HextoString(mode) + "]");
                if (smartKeyRfDoorAPI != null) smartKeyRfDoorAPI.SetCAMERAmode(mode);
                else Log.w(TAG, "[ctrlSmartIOTCamStatusMode] smartKeyRfDoorAPI is null!!");
            } else {
                Log.w(TAG, "[ctrlSmartIOTCamStatusMode] Not Supported FRONTCAMERA!!");
            }
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] ctrlSmartIOTCamStatusMode(byte mode)");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        }
    }

    public void ctrlSmartIOTCamLEDMode(byte mode) {
        try {
            if (ConfigValues.eFrontCameraType == FRONTCAMERATYPE.SMARTIOT
                    || ConfigValues.eFrontCameraType == FRONTCAMERATYPE.SMARTKEY_EXTERNAL
                    || ConfigValues.eFrontCameraType == FRONTCAMERATYPE.SMART_HS
                    || ConfigValues.eFrontCameraType == FRONTCAMERATYPE.SMART_DW) {
                LOG("[ctrlSmartIOTCamLEDMode] mode [" + Global.HextoString(mode) + "]");
                if (smartKeyRfDoorAPI != null) smartKeyRfDoorAPI.SetLEDmode(mode);
                else Log.w(TAG, "[ctrlSmartIOTCCamLEDMode] smartKeyRfDoorAPI is null!!");
            } else {
                Log.w(TAG, "[ctrlSmartIOTCamLEDMode] Not Supported FRONTCAMERA!!");
            }
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] ctrlSmartIOTCamLEDMode(byte mode)");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        }
    }

    /**
     * 스마트현관카메라 녹화 여부 판별
     */
    private boolean getStrangerRecording() {
        try {
            WallpadStatusData DBMGR = new WallpadStatusData(getContext());
            boolean bResult = DBMGR.GetStrangerRecordingOnOff();
            DBMGR.closeDB();
            Log.d(TAG, "[getStrangerRecording] bResult [" + bResult + "]");

            return bResult;
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
            return false;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] getStrangerRecording()");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
            return false;
        }
    }

    // Surface manager
    public void initVideoSurfaceLayout() {
        try {
            Log.d(TAG, "[initVideoSurfaceLayout] bFFMPEGEnable = " + bFFMPEGEnable);
            if (ConfigValues.DEVICE_BOARDTYPE == BOARD_TYPE.V40_IGW300) {
                mCallController.mVideoJNI.setDecoderInfo_V40(76, 85, 576, 405);
                initFrontVideo();
            }
            else if (ConfigValues.DEVICE_BOARDTYPE == BOARD_TYPE.V40) {
                mCallController.mVideoJNI.setDecoderInfo_V40(76, 85, 576, 405);
                initFrontVideo();
            }
            else if (ConfigValues.DEVICE_BOARDTYPE == BOARD_TYPE.V40_IGW300_NOUGAT) {
                mCallController.mVideoJNI.setDecoderInfo_V40(76, 85, 576, 405);
                initFrontVideo();
            }
            else if (ConfigValues.DEVICE_BOARDTYPE == BOARD_TYPE.V40_NOUGAT) {
                mCallController.mVideoJNI.setDecoderInfo_V40(76, 85, 576, 405);
                if (bFFMPEGEnable) initRemoteVideoSurfaceLayout();
                initFrontVideo();
            }
            else {
                LOG_WARN("[initVideoSurfaceLayout] NOT Supported BOARDTYPE [" + ConfigValues.DEVICE_BOARDTYPE + "]");
            }
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] initVideoSurfaceLayout()");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        }
    }

    public void removeVideoSurfaceLayout() {
        try {
            Log.i(TAG, "[removeVideoSurfaceLayout] start!!");
            if (bFFMPEGEnable) {
                mCallController.mVideoJNI.SWDecoderClose(2);
                mCallController.mVideoJNI.decoderStopOperation();
            }
            removeRemoteVideoSurfaceLayout();
            removeMyVideoSurfaceLayout();
            removeFrontVideoLayout();
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] removeVideoSurfaceLayout()");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        }
    }

    private void getCallTimeoutEnable() {
        try {
            WallpadDeviceSet mWallpadDeviceSet = new WallpadDeviceSet(mContext);
            boolean bResult = mWallpadDeviceSet.Get_CallAppCallTimeout();
            mWallpadDeviceSet.closeDB();

            Log.d(TAG, "[getCallTimeoutEnable] bResult [" + bResult + "]");
            if (bResult) {
                Log.i(TAG, "[getCallTimeoutEnable] Call timeout : Normal mode");
                mCallController.mCTT.setTalkNormalMode();
            } else {
                Log.i(TAG, "[getCallTimeoutEnable] Call timeout : Test mode");
                mCallController.mCTT.setTalkTestMode();
                SampleModeTitle = new WpadTextView(this, false, 200, 72, Gravity.CENTER, Color.DKGRAY, Common.fontsize._26_DEFAULT, true, 0);
                ViewRegistration(TopLayout, SampleModeTitle, 316, 17);
                SampleModeTitle.setText("[통화시험모드]");
            }
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] getCallTimeoutEnable()");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        }
    }

    public enum MAINEVENT {
        BTN_HOME,
        BTN_HOME_MOBILE
    }

    public interface MainEventListener {
        public void onMainTouchEvent(MAINEVENT eEvent);
    }

    MainEventListener mMainEventListener;

    public void setMainEventListener(MainEventListener MEL) {
        mMainEventListener = MEL;
    }

    public void releaseMainEventListener() {
        mMainEventListener = null;
    }

    // MainActivity Handler
    public final class HANDLERMSG {
        public final static int RELEASE_TOPMENUBTN_BLOCK = 10;
        public final static int CHECK_RECEIVINGCALL = 100;
        public final static int REMOVE_VIDEO_COVER = 110;
        public final static int SHOW_VIDEO_COVER = 120;
        public final static int CLEAR_ALL_CALL = 130;
        public final static int TAKE_PICTURE_FRONT = 140;
        public final static int CHANGESCREEN = 260;
        public final static int CHANGESCREEN_FRONT = 261;
        public final static int CHANGESCREEN_LOBBY = 262;
        public final static int CHANGESCREEN_GUARD = 263;
        public final static int CHANGESCREEN_RESIDENCE = 264;
        public final static int CHANGESCREEN_PSTN = 265;
        public final static int INIT_FRONTVIDEO = 310;
        public final static int REMOVE_FRONTVIDEO = 311;
        public final static int SHOW_FRONTVIDEO = 312;
        public final static int CTRL_FRONTVIDEO_BRIGHTNESS = 313;
        public final static int SET_TEMPSYSTEM_VOLUME = 400;
        public final static int RECOVER_SYSTEM_VOLUME = 410;
        public final static int SET_DTMF_VOLUME = 420;
        public final static int SET_RELIEFCALL_VOLUME = 430;
        public final static int SET_DINGDONG_VOLUME = 440;
        public final static int SETTALKPATH_DOORMUSIC = 450;
        public final static int SHOW_FRONTCAM_SUBPHONE = 500;
        public final static int CHANGE_STRANGER_NOTICE_COLOR = 600;
        public final static int CHANGE_REMOTECALL_NOTICE_COLOR = 650;
        public final static int SEND_REQUEST_PSTN_STATUS = 700;
        public final static int SEND_HOOK_ON = 710;
        public final static int SEND_PSTN_ARS_MODE = 720;
        public final static int PLAY_DINGDONG = 800;
        public final static int STOP_DINGDONG = 810;
        public final static int PLAY_FRONT_BELL = 820;
        public final static int SET_TALK_BTN_ENABLE = 830;
        public final static int CHECK_WALLPAD_CAMERA = 840;
        public final static int SEND_SUBWALLPAD_MOIP_FINISH = 850;
        public final static int RELEASE_BLOCK_FRONTCALL = 996;
        public final static int REFRESH_HOMEICON = 997;
        public final static int FINISH_WALLPADCALL = 998;
        public final static int FINISH_ACTIVITY = 999;
    }

    int nBrightness = 0;
    public Handler MainHandler = new Handler(Looper.getMainLooper()) {
        public void handleMessage(Message msg) {
            LOG("[MainHandler] MainHandler : what [" + msg.what + "], arg1 [" + msg.arg1 + "], arg2 [" + msg.arg2 + "]");
            switch (msg.what) {
                case HANDLERMSG.RELEASE_TOPMENUBTN_BLOCK:
                    bBlockTopMenuBTN = false;
                    break;

                case HANDLERMSG.CHECK_RECEIVINGCALL:
                    generateCallEvent();
                    break;

                case HANDLERMSG.REMOVE_VIDEO_COVER:
                    break;

                case HANDLERMSG.SHOW_VIDEO_COVER:
                    break;

                case HANDLERMSG.CLEAR_ALL_CALL:
//                    mCallController.mCallInfo.resetAllCallInfo();
//                    finishActivity();
//                    mCallController.mCallInfo.resetAllCallInfo();
                    setFinishTimerCreate(Common.FINISH_TIME_ALL_CALL_CLEAR);
                    break;

                case HANDLERMSG.RELEASE_BLOCK_FRONTCALL:
                    bBlockFrontCall = false;
                    break;

                case HANDLERMSG.TAKE_PICTURE_FRONT:
                    break;

                case HANDLERMSG.CHANGESCREEN:
                    if (msg.arg1 == HANDLERMSG.CHANGESCREEN_FRONT) {
                        changeMenuNScreen(ID.MENU.MENU_TALKFRONT);
                    }
                    else if (msg.arg1 == HANDLERMSG.CHANGESCREEN_LOBBY) {
                        changeMenuNScreen(ID.MENU.MENU_TALKLOBBY);
                    }
                    else if (msg.arg1 == HANDLERMSG.CHANGESCREEN_GUARD) {
                        changeMenuNScreen(ID.MENU.MENU_TALKGUARD);
                    }
                    else if (msg.arg1 == HANDLERMSG.CHANGESCREEN_RESIDENCE) {
                        changeMenuNScreen(ID.MENU.MENU_TALKRESIDENCE);
                    }
                    else if (msg.arg1 == HANDLERMSG.CHANGESCREEN_PSTN) {
                        changeMenuNScreen(ID.MENU.MENU_TALKPSTN);
                    }
                    else {
                        LOG("[MainHandler] Invalid Screen Info!!");
                    }
                    break;

                case HANDLERMSG.INIT_FRONTVIDEO:
                    initFrontVideoLayout();
                    break;

                case HANDLERMSG.REMOVE_FRONTVIDEO:
                    removeFrontVideoLayout();
                    break;

                case HANDLERMSG.SHOW_FRONTVIDEO:
                    showFrontVideo(true);
                    break;

                case HANDLERMSG.CTRL_FRONTVIDEO_BRIGHTNESS:
                    nBrightness = msg.arg1;
                    Log.d(TAG, "[CTRL_FRONTVIDEO_BRIGHTNESS] nBrightness: " + nBrightness);
                    if (mFrontCamOpenCheckHandler != null) mFrontCamOpenCheckHandler.sendEmptyMessage(0); // camera open check를 위한 핸들러 구현 (seulki)
                    else Log.w(TAG, "[MainHandler] mFrontCamOpenCheckHandler is null!! -> HANDLERMSG.CTRL_FRONTVIDEO_BRIGHTNESS");
                    break;

                case HANDLERMSG.SET_TEMPSYSTEM_VOLUME:
                    if (mAudioManager != null) {
                        mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, nTempSysVolume, 0);
                        Log.d(TAG, "[MainHandler SET_TEMP_SYSTEM_VOLUME] Volume: " + mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC));
                    }
                    else Log.w(TAG, "[MainHandler] mAudioManager is null!! -> HANDLERMSG.SET_TEMPSYSTEM_VOLUME");
                    break;

                case HANDLERMSG.RECOVER_SYSTEM_VOLUME:
                    // 통화 종료 후 시스템 볼륨 원복 seulki
                    if (nSysVolume > 0) {
                        if (mAudioManager != null) {
                            mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, nSysVolume, 0);
                            Log.d(TAG, "[MainHandler RECOVER_SYSTEM_VOLUME] Volume: " + mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC));
                        }
                        else Log.w(TAG, "[MainHandler] mAudioManager is null!! -> HANDLERMSG.RECOVER_SYSTEM_VOLUME");
                    }
                    break;

                case HANDLERMSG.SET_DTMF_VOLUME:
                    // IHN-1010 에서는 DTMF 발신시 볼륨 11로 셋팅
                    if (mAudioManager != null) {
                        mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, nTempDTMFVolume, 0);
                        Log.d(TAG, "[MainHandler SET_DTMF_SYSTEM_VOLUME] Volume: " + mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC));
                    }
                    else Log.w(TAG, "[MainHandler] mAudioManager is null!! -> HANDLERMSG.SET_DTMF_VOLUME");
                    break;

                case HANDLERMSG.SET_RELIEFCALL_VOLUME:
                    // 안심통화시(오디오모드 19) 볼륨 11로 셋팅
                    if (mAudioManager != null) {
                        mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, nTempReliefVolume, 0);
                        Log.d(TAG, "[MainHandler SET_RELIEFCALL_VOLUME] Volume: " + mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC));
                    }
                    else Log.w(TAG, "[MainHandler] mAudioManager is null!! -> HANDLERMSG.SET_RELIEFCALL_VOLUME");
                    break;

                case HANDLERMSG.SET_DINGDONG_VOLUME:
                    // 현관띵똥시 볼륨 12로 셋팅 / 효성카메라(IDC-HS100)일 경우 10
                    int nVolume = nTempDingDongVolume;
                    if (ConfigValues.DEVICE_MODELTYPE == MODEL_TYPE.IHN_HS101 || ConfigValues.DEVICE_MODELTYPE == MODEL_TYPE.IHN_HS101_I) {
                        if (ConfigValues.eFrontCameraType == FRONTCAMERATYPE.BASIC) {
                            nVolume = nTempDingDongVolume_IDCHS100;
                        }
                    }
                    if (mAudioManager != null) {
                        mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, nVolume, 0);
                        Log.d(TAG, "[MainHandler SET_DINGDONG_VOLUME] Volume: " + mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC));
                    }
                    else Log.w(TAG, "[MainHandler] mAudioManager is null!! -> HANDLERMSG.SET_DINGDONG_VOLUME");
                    break;

                case HANDLERMSG.SETTALKPATH_DOORMUSIC:
                    Log.d(TAG, "[MainHandler] SETTALKPATH_DOORMUSIC");
                    if (mCallController != null) mCallController.setTalkPath(CALLPATH.DOORMUSIC);
                    break;

                case HANDLERMSG.SHOW_FRONTCAM_SUBPHONE:
                    if (mCallController != null) mCallController.selectVideoSourceToSubPhone(CALLTYPE.FRONT, false);
                    else Log.w(TAG, "[MainHandler] mCallController is null!! -> HANDLERMSG.SHOW_FRONTCAM_SUBPHONE");
                    break;

                case HANDLERMSG.CHANGE_STRANGER_NOTICE_COLOR:
                    if (TopStrangerRecodingNotice != null) TopStrangerRecodingNotice.setTextColor(nNoticeTextColor);
                    else Log.w(TAG, "[MainHandler] TopStrangerRecodingNotice is null!! -> HANDLERMSG.CHANGE_STRANGER_NOTICE_COLOR");
                    break;

                case HANDLERMSG.CHANGE_REMOTECALL_NOTICE_COLOR:
                    if (TopRemoteCallNotice != null) TopRemoteCallNotice.setTextColor(nNoticeTextColor);
                    else Log.w(TAG, "[MainHandler] TopRemoteCallNotice is null!! -> HANDLERMSG.CHANGE_REMOTECALL_NOTICE_COLOR");
                    break;

                case HANDLERMSG.SEND_REQUEST_PSTN_STATUS:
                    if (mPSTNController != null) mPSTNController.sendGetPSTNPath();
                    else Log.w(TAG, "[MainHandler] mPSTNController is null!! -> HANDLERMSG.SEND_REQUEST_PSTN_STATUS");
                    break;

                case HANDLERMSG.SEND_HOOK_ON:
                    if (mPSTNController != null) mPSTNController.sendHookOn();
                    else Log.w(TAG, "[MainHandler] mPSTNController is null!! -> HANDLERMSG.SEND_HOOK_ON");
                    break;

                case HANDLERMSG.SEND_PSTN_ARS_MODE:
                    if (mCallController != null) mCallController.onPSTNEvent(CALLEVENTTYPE.PSTN_RING, null, null);
                    else Log.w(TAG, "[MainHandler] mCallController is null!! -> HANDLERMSG.SEND_PSTN_ARS_MODE");
                    break;

                case HANDLERMSG.PLAY_DINGDONG:
                    Log.d(TAG, "[MainHandler] PLAY_DINGDONG");
                    int time = 0;
                    if (mSound != null) time = mSound.PlayMent(SND.call.DINGDONG);
                    LOG("[MainHandler] time [" + time + "]");
                    if (time < 0) time = 2088;
                    sendHandlerMsgDelayed(HANDLERMSG.STOP_DINGDONG, 0, 0, time + 500); // [띵똥시나리오] 2. 띵똥 stop / 패스 변경
                    break;

                case HANDLERMSG.STOP_DINGDONG:
                    Log.d(TAG, "[MainHandler] STOP_DINGDONG");
                    if (mIOInterface != null) mIOInterface.ctrlSetTalkPathNormal();
                    if (mAudioManager != null) mAudioManager.setMode(AudioManager.MODE_NORMAL);
                    else Log.w(TAG, "[MainHandler] mAudioManager is null!! -> HANDLERMSG.STOP_DINGDONG");
                    if (mCallPathCheckHandler != null) mCallPathCheckHandler.sendEmptyMessage(2);
                    else Log.w(TAG, "[MainHandler] mCallPathCheckHandler is null!! -> HANDLERMSG.STOP_DINGDONG");
                    break;

                case HANDLERMSG.PLAY_FRONT_BELL:
                    LOG("[MainHandler] PLAY_FRONT_BELL");
                    Global.playMelodyRepeat(CALLTYPE.FRONT);
                    break;

                case HANDLERMSG.SET_TALK_BTN_ENABLE:
                    Log.d(TAG, "[MainHandler] SET_TALK_BTN_ENABLE");
//                    if (TalkFront.BTN_TALK != null) TalkFront.BTN_TALK.setButtonEventOffDisable();
//                    else Log.w(TAG, "[MainHandler] TalkFront.BTN_TALK is null!! -> HANDLERMSG.SET_TALK_BTN_ENABLE");
                    break;

                case HANDLERMSG.REFRESH_HOMEICON:
                    bBlockHomeBTN = false;
                    break;

                case HANDLERMSG.FINISH_WALLPADCALL:
                    finishWallPadCall();
                    break;

                case HANDLERMSG.FINISH_ACTIVITY:
                    finishActivity();
                    break;

                case IGW300CMD.AUDIO_OFF:
                    Log.d(TAG, "[MainHandler] AUDIO_OFF ms.arg1 [" + msg.arg1 + "]");
                    if (mIOInterface != null) mIOInterface.IGW300_CallPathCtrl(IGW300API.TEL_PATH.OFF);
                    else Log.d(TAG, "[MainHandler] mIOInterface is null!! -> IGW300CMD.AUDIO_OFF");
                    break;

                case IGW300CMD.AUDIO_PSTN_WALLPAD:
                    Log.d(TAG, "[MainHandler] AUDIO_PSTN_WALLPAD");
                    Log.d(TAG, "[MainHandler] ConfigValues.DEVICE_MODELTYPE [" + ConfigValues.DEVICE_MODELTYPE + "]");
                    if (ConfigValues.DEVICE_MODELTYPE == MODEL_TYPE.IHN_D101 || ConfigValues.DEVICE_MODELTYPE == MODEL_TYPE.IHN_D101_I || ConfigValues.DEVICE_MODELTYPE == MODEL_TYPE.IHN_D101_I_LX2
                            || ConfigValues.DEVICE_MODELTYPE == MODEL_TYPE.IHN_D101K || ConfigValues.DEVICE_MODELTYPE == MODEL_TYPE.IHN_D101K_I
                            || ConfigValues.DEVICE_MODELTYPE == MODEL_TYPE.IHN_D101_I_OCF)
                    {
                        sendPSTNRingEndBR();
                    }
                    else {
                        Log.d(TAG, "[MainHandler] ConfigValues.DEVICE_MODELTYPE [" + ConfigValues.DEVICE_MODELTYPE + "]");
                    }

                    if (mIOInterface != null) mIOInterface.IGW300_CallPathCtrl(IGW300API.TEL_PATH.WPAD_TEL);
                    else Log.d(TAG, "[MainHandler] mIOInterface is null!! -> IGW300CMD.AUDIO_PSTN_WALLPAD");
                    break;

                case IGW300CMD.AUDIO_PSTN_SUBPHONE:
                    Log.d(TAG, "[MainHandler] AUDIO_PSTN_SUBPHONE");
                    if (mIOInterface != null) mIOInterface.IGW300_CallPathCtrl(IGW300API.TEL_PATH.SUB_TEL);
                    else Log.d(TAG, "[MainHandler] mIOInterface is null!! -> IGW300CMD.AUDIO_PSTN_SUBPHONE");
                    break;

                case IGW300CMD.AUDIO_FRONT_WALLPAD:
                    Log.d(TAG, "[MainHandler] AUDIO_FRONT_WALLPAD");
                    if (mIOInterface != null) mIOInterface.IGW300_CallPathCtrl(IGW300API.TEL_PATH.WPAD_DOOR);
                    else Log.d(TAG, "[MainHandler] mIOInterface is null!! -> IGW300CMD.AUDIO_FRONT_WALLPAD");
                    break;

                case IGW300CMD.AUDIO_FRONT_SUBPHONE:
                    Log.d(TAG, "[MainHandler] AUDIO_FRONT_SUBPHONE");
                    if (mIOInterface != null) mIOInterface.IGW300_CallPathCtrl(IGW300API.TEL_PATH.SUB_DOOR);
                    else Log.d(TAG, "[MainHandler] mIOInterface is null!! -> IGW300CMD.AUDIO_FRONT_SUBPHONE");
                    break;

                case IGW300CMD.AUDIO_MOIP_SUBPHONE:
                    Log.d(TAG, "[MainHandler] AUDIO_MOIP_SUBPHONE");
                    if (mIOInterface != null) mIOInterface.IGW300_CallPathCtrl(IGW300API.TEL_PATH.MOIP_SUB);
                    break;

                case IGW300CMD.AUDIO_PSTN_REJECT:
                    Log.d(TAG, "[MainHandler] AUDIO_PSTN_REJECT");
                    if (ConfigValues.DEVICE_MODELTYPE == MODEL_TYPE.IHN_D101 || ConfigValues.DEVICE_MODELTYPE == MODEL_TYPE.IHN_D101_I || ConfigValues.DEVICE_MODELTYPE == MODEL_TYPE.IHN_D101_I_LX2
                            || ConfigValues.DEVICE_MODELTYPE == MODEL_TYPE.IHN_D101K || ConfigValues.DEVICE_MODELTYPE == MODEL_TYPE.IHN_D101K_I
                            || ConfigValues.DEVICE_MODELTYPE == MODEL_TYPE.IHN_D101_I_OCF) {
                        sendPSTNRingEndBR();
                    }

                    if (mIOInterface != null) mIOInterface.IGW300_CallPathCtrl(IGW300API.TEL_PATH.WPAD_TEL);
                    else Log.d(TAG, "[MainHandler] mIOInterface is null!! -> IGW300API.TEL_PATH.WPAD_TEL");
                    try { Thread.sleep(500); }
                    catch (InterruptedException e) {
                        //e.printStackTrace();
                        LogUtil.errorLogInfo("", TAG, e);
                    }
                    if (mIOInterface != null) mIOInterface.IGW300_CallPathCtrl(IGW300API.TEL_PATH.OFF);
                    else Log.d(TAG, "[MainHandler] mIOInterface is null!! -> IGW300API.TEL_PATH.OFF");
                    break;

                case HANDLERMSG.SEND_SUBWALLPAD_MOIP_FINISH:
                    Intent mIntent = new Intent();
                    mIntent.setAction(Declare.BR.APP_FINISH);
                    mContext.sendBroadcast(mIntent);
                    break;

                default:
                    LOG("MainHandler : " + msg.what);
                    break;
            }
        }
    };

    public void sendHandlerMsg(int what, int arg1, int arg2) {
        try {
            LOG("[sendHandlerMsg] what [" + what + "], arg1 [" + arg1 + "], arg2 [" + arg2 + "]");
            Message HandleMsg = MainHandler.obtainMessage();
            HandleMsg.what = what;
            HandleMsg.arg1 = arg1;
            HandleMsg.arg2 = arg2;
            MainHandler.sendMessage(HandleMsg);
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] sendHandlerMsg(msg)");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        }
    }

    public void sendHandlerMsgDelayed(int what, int arg1, int arg2, long delay) {
        try {
            LOG("[sendHandlerMsgDelayed] what [" + what + "], arg1 [" + arg1 + "], arg2 [" + arg2 + "], delay [" + delay + "]");
            Message HandleMsg = MainHandler.obtainMessage();
            HandleMsg.what = what;
            HandleMsg.arg1 = arg1;
            HandleMsg.arg2 = arg2;
            MainHandler.sendMessageDelayed(HandleMsg, delay);
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] sendHandlerMsgDelayed(msg)");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        }
    }

    /**
     * JEFF, 2020.01.04
     * IGW-300연동시에는 국선 호출의 시작과 끝만 알려준다.
     * 또한, 월패드에서 통화를 수신한 경우에는 국선 호출의 끝을 알려주지 않으므로
     * 월패드에서 hookon하는 순간 국선 호출에 대한 링을 강제로 발생시키는 쓰레드를 종료하기위해 아래의 BR 메시지를 보낸다
     * 수신지는 iMapServer의 mWallPadNotifyBR -> kr.co.icontrols.wallpad.BR_MAIN_NOTI -> Common.BR_MAIN_NOTI.NOTICE_PSTN_RING_END
     */
    int NOTICE_PSTN_RING_END = 1025;
    public void sendPSTNRingEndBR() {
        try {
            Log.i(TAG, "[sendPSTNRingEndBR] ===== START =====");
            Intent mIntent = new Intent();
            mIntent.setAction(ACNAME_MAIN_NOTI);
            mIntent.putExtra("KIND", NOTICE_PSTN_RING_END);
            mContext.sendBroadcast(mIntent);
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] sendPSTNRingEndBR()");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        }
    }

    public void setBlockFrontCall() {
        try {
            bBlockFrontCall = true;
            MainHandler.removeMessages(HANDLERMSG.RELEASE_BLOCK_FRONTCALL);
            ((MainActivity) mContext).sendHandlerMsgDelayed(HANDLERMSG.RELEASE_BLOCK_FRONTCALL, 0, 0, 3000);
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] setBlockFrontCall()");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        }
    }

    private String KIND = "KIND";

    private boolean getBusinessSampleMode() {
        try {
            // 영업샘플모드인 경우, LCD를 항상 ON 시켜 놓는다.
            WallpadSalesSampleData mWallpadSalesSampleData = new WallpadSalesSampleData(mContext);
            int nMode = mWallpadSalesSampleData.getSalesSampleData(WallpadSalesSampleData.SALES_SAMPLE_MODE_SLEEP);
            mWallpadSalesSampleData.closeDB();
            if (nMode == 0) return true;
            else return false;
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
            return false;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] getBusinessSampleMode()");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
            return false;
        }
    }

    private void getLCDReverse() {
        try {
            if (mIOInterface.getBoardRevision() != 0) bLCDReverse = true;
            else bLCDReverse = false;
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
            bLCDReverse = false;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] getLCDReverse()");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
            bLCDReverse = false;
        }
    }

    private void notifyAppFinish() {
        try {
            WallpadStatusData SetData = new WallpadStatusData(getApplicationContext());
            int nAlarmStatus = SetData.GetAlarmStatus();
            SetData.closeDB();
            LOG("[notifyAppFinish] nAlarmStatus [" + nAlarmStatus + "]");

            Intent intent = new Intent(ACNAME_MAIN_NOTI, null);
            intent.putExtra(KIND, Declare.BR.APK_EXIT_MAIN_CHECK);
            getContext().sendBroadcast(intent);
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] notifyAppFinish()");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        }
    }

    private void notifyCallAppFinish() {
        try {
            WallpadStatusData SetData = new WallpadStatusData(getApplicationContext());
            int nAlarmStatus = SetData.GetAlarmStatus();
            SetData.closeDB();
            LOG("[notifyCallAppFinish] nAlarmStatus [" + nAlarmStatus + "]");

            Intent intent = new Intent(ACNAME_MAIN_NOTI, null);
            intent.putExtra(KIND, Declare.BR.NOTI_CALLAPP_FINISHING);
            getContext().sendBroadcast(intent);
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] notifyCallAppFinish()");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        }
    }

    boolean bBlockFrontCall = false;   // 현관통화가 종료되고 통화앱이 종료되기까지 시간이 걸리므로 플래그를 세워 일정시간 현관콜을 막는다.
    BroadcastReceiver mMainExtraEventReceiver = new BroadcastReceiver() {
        String TAG = "MainExtraEventReceiver";

        @Override
        public void onReceive(Context context, Intent intent) {
            try {
                String strAction = intent.getAction();
                Log.d(this.TAG, "[onReceive] strAction [" + strAction + "]");
                if (strAction.equals(Declare.BR.APP_FINISH)) {
                    mIOInterface.ctrlPopupGUI(true);
                    mCallController.setTalkPath(CALLPATH.NORMAL); // Finish BR 수신시 통화패스 Normal로 변경
                    if (mMainEventListener != null) {
                        String strCallOwner = intent.getStringExtra(CALLTRIGGER.CALLOWNER);
                        Log.d(this.TAG, "[onReceive] strCallOwner [" + strCallOwner + "]");
                        if (strCallOwner!= null) {
                            if (strCallOwner.equals("MOBILE")) mMainEventListener.onMainTouchEvent(MAINEVENT.BTN_HOME_MOBILE);
                        } else {
                            mMainEventListener.onMainTouchEvent(MAINEVENT.BTN_HOME);
                        }
                    }
                    else {
                        finishWallPadCall();
                    }
                }
                else if (strAction.equals(Declare.BR.WALLPAD_ALERT)) {
                    Log.d(this.TAG, "[onReceive] strAction [" + strAction + "]");
                    int nKind = intent.getIntExtra(define.NOTIBR_KIND, 0);
                    if (nKind == Declare.BR.NOTIFY_ALARM_FIRED) finishWallPadCall();
                }
                else if (strAction.equals(Declare.BR.EVENT_DEVICE_CONTROL)) {
                    KeyEvent mKeyEvent = intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
                    Log.i(this.TAG, "[onReceive] mKeyEvent : " + mKeyEvent + ", mKeyEvent.getKeyCode() : " + mKeyEvent.getKeyCode());
                    if (mKeyEvent.getKeyCode() == Declare.BTN.TALK || mKeyEvent.getKeyCode() == Declare.BTN.TALK_V40) {
//                        if (mCallController.mCallInfo.getFRONT() == CALLSTATUS.IDLE && !bBlockFrontCall) {
//                            setBlockFrontCall();
//                            mCallController.onFrontEvent(CALLEVENTTYPE.RECEIVE_CALL, CALLTYPE.FRONT);
//                        }
//                        else Log.w(this.TAG, "[onReceive] Front call ignored!!! [" + mCallController.mCallInfo.getFRONT() + "], bBlockFrontCall [" + bBlockFrontCall + "]");
                    }
                    else if (mKeyEvent.getKeyCode() == Declare.BTN.FRONT || mKeyEvent.getKeyCode() == Declare.BTN.FRONT_V40) {
                        Log.i(this.TAG, "[onReceive] mKeyEvent.getKeyCode() : " + mKeyEvent.getKeyCode());
                        if (!bBlockFrontCall) {
                            if (ConfigValues.DEVICE_BOARDTYPE == BOARD_TYPE.V40 || ConfigValues.DEVICE_BOARDTYPE == BOARD_TYPE.V40_NOUGAT) {
                                if (mCallController.mCallInfo.getIDLECnt() == mCallController.mCallInfo.IDLECNT_MAX) {
                                    sendHandlerMsg(HANDLERMSG.SET_DINGDONG_VOLUME, 0, 0); // 현관띵똥 볼륨 고정(시스템 볼륨 따라가지 않도록)
                                    sendHandlerMsg(HANDLERMSG.SETTALKPATH_DOORMUSIC, 0, 0);
                                    mCallPathCheckHandler.sendEmptyMessage(0); // 통화앱이 실행되어 있으나 통화상태가 아닌 경우에도 띵똥 소리 나야함 (메인앱에서 현관 호출 BR 수신이 불가하므로 통화앱에서 처리)
                                }
                            }

                            if (mCallController.mCallInfo.getFRONT() == CALLSTATUS.IDLE) {
                                setBlockFrontCall();
                                mCallController.onFrontEvent(CALLEVENTTYPE.RECEIVE_CALL, CALLTYPE.FRONT);
                            }
                            else {
                                Log.w(this.TAG, "[onReceive] Front call ignored!!! getFRONT() [" + mCallController.mCallInfo.getFRONT() + "]");
                            }
                        }
                        else {
                            Log.w(this.TAG, "[onReceive] Front call ignored!!! bBlockFrontCall [" + bBlockFrontCall + "]");
                        }
                    }
                    else if (mKeyEvent.getKeyCode() == Declare.BTN.IGW300_PSTN_RING_START) {
                        /**
                         * JEFF, 2020.01.04
                         * IHN-D101 국선전화 링시작시 링이벤트를 주기적으로 발생시키는 쓰레드
                         * IGW-300은 국선전화 링의 시작과 끝만 알려주므로, 통화시나리오를 처리하기에 어려움이 있다.
                         *  - 통화앱이 종료되는 시점에 링이 발생하는 경우, 국선전화 벨 안울릴 가능성 있음
                         *  - 국선전화 링 시작 신호를 놓치는 경우, 벨 안울림
                         */
                        if (mPSTNController != null) mPSTNController.sendMsgToLocalService(PSTNHANDLERMSG.RECEIVE_RING, null);

//                        if (ConfigValues.DEVICE_MODELTYPE == MODEL_TYPE.IHN_D101) {
//                            if (mPSTNController != null) mPSTNController.sendMsgToLocalService(PSTNHANDLERMSG.RECEIVE_RING, null);
//                        }
                    }
                    else if (mKeyEvent.getKeyCode() == Declare.BTN.IGW300_PSTN_RING_END) {
                        if (mPSTNController != null) mPSTNController.sendMsgToLocalService(PSTNHANDLERMSG.RECEIVE_RING_END, null);
                    }
                    else if (mKeyEvent.getKeyCode() == Declare.BTN.PSTN_RING_V40) {
                        if (ConfigValues.DEVICE_BOARDTYPE == BOARD_TYPE.V40 || ConfigValues.DEVICE_BOARDTYPE == BOARD_TYPE.V40_NOUGAT) {
                            if (mPSTNController != null) mPSTNController.sendMsgToLocalService(PSTNHANDLERMSG.RECEIVE_RING, null);
                        }
                    }
                }
                else if (strAction.equals(define.NOTIFY_ACNAME)) {
                    int kind = intent.getIntExtra(define.NOTIBR_KIND,0);
                    if (kind == define.NOTIFY_FINISH_FRONT_DINGDONG) {
                        // 메인 App으로 부터 띵똥 종료 BR 수신 받을 경우 현관 호출음 재생
                        sendHandlerMsgDelayed(HANDLERMSG.PLAY_FRONT_BELL, 0, 0, 200);
                        sendHandlerMsgDelayed(HANDLERMSG.SET_TALK_BTN_ENABLE, 0, 0, 200);
                    }
                }
                else if (strAction.equals(Declare.BR.BR_SHOW_REMOTEVIEW_TRUE)) {
                    mCallController.onShowRemoteVideo(true);
                }
                else if (strAction.equals(Declare.BR.BR_SHOW_REMOTEVIEW_FALSE)) {
                    mCallController.onShowRemoteVideo(false);
                }
            } catch (RuntimeException re) {
                LogUtil.errorLogInfo("", TAG, re);
            } catch (Exception e) {
                Log.e(this.TAG, "[Exception] onReceive(Context context, Intent intent)");
                //e.printStackTrace();
                LogUtil.errorLogInfo("", TAG, e);
            }
        }
    };

    private void registerBRReceiver() {
        try {
            LOG_INFO("[registerBRReceiver] ========== START ==========");
            IntentFilter mIntentFilter = new IntentFilter();
            mIntentFilter.addAction(Declare.BR.APP_FINISH);
            mIntentFilter.addAction(Declare.BR.WALLPAD_ALERT);
            mIntentFilter.addAction(Declare.BR.EVENT_DEVICE_CONTROL);
            mIntentFilter.addAction(define.NOTIFY_ACNAME);
            mIntentFilter.addAction(Declare.BR.VISITOR_REMOTE_CALL);
            mIntentFilter.addAction(Declare.BR.BR_SHOW_REMOTEVIEW_TRUE);
            mIntentFilter.addAction(Declare.BR.BR_SHOW_REMOTEVIEW_FALSE);
            registerReceiver(mMainExtraEventReceiver, mIntentFilter, null, null);

            mIntentFilter = new IntentFilter();
            mIntentFilter.addAction("MENU_EVENT");
            registerReceiver(mWallPadAlertBR, mIntentFilter);

            mIntentFilter = new IntentFilter();
            mIntentFilter.addAction(define.NOTIFY_DAIL);
            mIntentFilter.addAction("WALLPAD_DIAL_GLOBALSCREEN_TOUCH");
            registerReceiver(mWallPadJogBR, mIntentFilter);

        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] registerBRReceiver()");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        }
    }

    private void unregisterBRReceiver() {
        try {
            LOG_INFO("[unregisterBRReceiver] ========== START ==========");
            unregisterReceiver(mMainExtraEventReceiver);
            unregisterReceiver(mWallPadAlertBR);
            unregisterReceiver(mWallPadJogBR);
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] unregisterBRReceiver()");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        }
    }

    private void registerWallPadCallLiveBRReceiver() {
        try {
            LOG_INFO("[registerWallPadCallLiveBRReceiver] ========== START ==========");
            IntentFilter mIntentFilter = new IntentFilter();
            mIntentFilter.addAction(Declare.BR.BR_REQUEST_WALLPADCALL_LIVE);
            registerReceiver(WallPadCallLiveBRCheck, mIntentFilter);

        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] registerWallPadCallLiveBRReceiver()");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        }
    }

    private void unregisterWallPadCallLiveBRReceiver() {
        try {
            LOG_INFO("[unregisterBRReceiver] ========== START ==========");
            unregisterReceiver(WallPadCallLiveBRCheck);
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] unregisterWallPadCallLiveBRReceiver()");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        }
    }

    /**
     * 부재중 방문자 사진을 단지서버에 전송할때
     * 해당 BR을 전송하여 메인App에서 방문자 사진의 전송을 처리한다.
     * 통화 App이 종료되는 시간 안에 전송을 완료하기 어려움
     */
    public void sendBRMissedVisitorPicture(String strDong, String strHo, String[] strMissedCallPicURI) {
        try {
            Log.i(TAG, "[sendBRMissedVisitorPicture] strDong [" + strDong + "], strHo [" + strHo + "], strMissedCallPicURI.length [" + strMissedCallPicURI.length + "]");

            Intent mIntent = new Intent();
            mIntent.setAction(ACNAME_MAIN_NOTI);
            mIntent.putExtra(KIND, Declare.BR.REQ_UPLOAD_MISSEDVISITORPIC);
            mIntent.putExtra("DONG", strDong);
            mIntent.putExtra("HO", strHo);
            mIntent.putExtra("CNT", strMissedCallPicURI.length);
            for (int i = 0; i < strMissedCallPicURI.length; i++) {
                Log.i(TAG, "[sendBRMissedVisitorPicture] strMissedCallPicURI[" + i + "] = [" + strMissedCallPicURI[i] + "]");
                mIntent.putExtra("URI_" + i, strMissedCallPicURI[i]);
            }
            getContext().sendBroadcast(mIntent);
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] sendBRMissedVisitorPicture(String strDong, String strHo, String[] strMissedCallPicURI)");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        }
    }

    boolean bFinishing = false;

    public void finishWallPadCall() {
        try {
            LOG("[finishWallPadCall] bFinishing [" + bFinishing + "]");
            if (bFinishing) {
                return;
            }
            bFinishing = true;

            sendBlockSIPCallBR();

            notifyCallAppFinish();

            if (sdbLivingRoomLightAPI != null) {
                Log.d(TAG, "[finishWallPadCall] sdbLivingRoomLightAPI.SetWifiModuleOnOff [TRUE]");
                sdbLivingRoomLightAPI.SetWifiModuleOnOff(true);
                sdbLivingRoomLightAPI = null;
            }

            Global.stopMelodyRepeat();
            Global.ctrlLCDOnOff(false);

            if (ConfigValues.eWallPadType == WALLPADTYPE.MAIN) {
                /**
                 * 아래와 같은 증상으로 인해 주석처리 함 (JEFF, 2020.04.02)
                 * 1. 국선 호출수신/통화중 홈버튼 눌러서 종료되는 경우 hook on, hook off가 반복되는 증상
                 *    - 내선 전화 사용시 플래시 효과가 되어 버림
                 * 2. 국선 통화중 홈버튼 눌러서 종료시 PSTN 릴레이 딸각하는 소리가 두번 들림
                 */
//                if (ConfigValues.bPSTNEnable) {
//                    mPSTNController.sendReject();
//                    mPSTNController.sendHookOffDelay();
//                }
            }
            else {
                if (ConfigValues.eSubWallPadPSTNType == SUBWALLPAD_PSTNTYPE.DIRECT) {
                    mPSTNController.sendReject();
                    mPSTNController.sendHookOffDelay();
                }
            }

            ctrlSmartIOTCamStatusMode(SmartRFCamStatusMode.STATUS_OFF);
            ctrlSmartIOTCamLEDMode(SmartRFCamLEDMode.LED_OFF);

//            if (mIOInterface != null) {
//                mIOInterface.releaseIOInterface();
//                mIOInterface = null;
//            }

            sendHandlerMsgDelayed(HANDLERMSG.FINISH_ACTIVITY, 0, 0, 500);
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] finishWallPadCall()");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        }
    }

    public void finishActivity() {
        try {
            LOG_INFO("[finishActivity]");
            super.finish();
//            setCallAppRunning(false);
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] finishActivity()");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        }
    }

    /**
     * 통화 앱 실행 여부 판별 임시 코드
     */
    public void setCallAppRunning(boolean bRunning) {
        try {
            WallpadStatusData DBMGR = new WallpadStatusData(getApplicationContext());
            DBMGR.SetCallAPKStatus(bRunning);
            DBMGR.closeDB();
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] setCallAppRunning(boolean bRunning)");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        }
    }

    public boolean getCallAppRunning() {
        boolean bRunning = false;
        try {
            WallpadStatusData DBMGR = new WallpadStatusData(getApplicationContext());
            bRunning = DBMGR.GetCallAPKStatusRunning();
            DBMGR.closeDB();
            Log.i(TAG, "[getCallAppRunning] bRunning [" + bRunning + "]");
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] getCallAppRunning()");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        }
        return bRunning;
    }

    /**
     * 통화 앱 꼬임시 임시 보완 코드
     */
    public void killCallProcess() {
        try {
            LOG_INFO("[killCallProcess]");
            finishWallPadCall();

            int pid = android.os.Process.myPid();
            android.os.Process.killProcess(pid);
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] killCallProcess()");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        }
    }

    /** 메모리 체크 코드 **/
    public void checkMemoryUsage() {
        try {
            Runtime.getRuntime().gc();
            long totalMem = Runtime.getRuntime().totalMemory();
            long freeMem = Runtime.getRuntime().freeMemory();
            long usedMem = totalMem - freeMem;

            Log.e(TAG, "**************** [checkMemoryUsage] *************");
            Log.e(TAG, "************ TOTAL MEM : " + totalMem + " bytes ***********");
            Log.e(TAG, "************ FREE MEM : " + freeMem + " bytes ***********");
            Log.e(TAG, "************ USED MEM : " + usedMem + " bytes ***********");
            Log.e(TAG, "*************************************************");
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] checkMemoryUsage()");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        }
    }

    private void sendWallPadCallLiveBR_ACK() {
        try {
//            Log.i(TAG, "[sendWallPadCallLiveBR_ACK] ===== START =====");
            Intent mIntent = new Intent();
            mIntent.setAction(Declare.BR.BR_ACK_WALLPADCALL_LIVE);
            mIntent.putExtra("WALLPADCALL_VIEW", mCurrentScreenId);
            getApplicationContext().sendBroadcast(mIntent);
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] sendWallPadCallLiveBR_ACK()");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        }
    }

    BroadcastReceiver WallPadCallLiveBRCheck = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            try {
                String strActionName = intent.getAction();
//                Log.d(TAG,"[WallPadCallLiveBRCheck] strActionName [" + strActionName + "]");

                if (strActionName.equals(Declare.BR.BR_REQUEST_WALLPADCALL_LIVE)) {
//                    Log.e(TAG,"[WallPadCallLiveBRCheck] Common.BR_ACK_WALLPADCALL_LIVE");
                    sendWallPadCallLiveBR_ACK();
                }
                else {
                    Log.w(TAG,"[WallPadCallLiveBRCheck] Not supported strActionName [" + strActionName + "]");
                }
            } catch (RuntimeException re) {
                LogUtil.errorLogInfo("", TAG, re);
            } catch (Exception e) {
                Log.e(TAG, "[Exception] BroadcastReceiver -> WallPadCallLiveBRCheck");
                //e.printStackTrace();
                LogUtil.errorLogInfo("", TAG, e);
            }
        }
    };

    private void sendBlockSIPCallBR() {
        try {
            Log.i(TAG, "[sendBlockSIPCallBR] ===== START =====");
            Intent mIntent = new Intent();
            mIntent.setAction(Declare.BR.BR_BLOCK_SIPCALL);
            getApplicationContext().sendBroadcast(mIntent);
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] sendBlockSIPCallBR()");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        }
    }













    /**
     * Sound PlayMent 시험용 코드 (JEFF, 2020.03.09)
     */
    private static MediaPlayer mMentMediaPlayer =  null;
    private static final String SOUND_PATH_ROOT = "/system/media/audio/wallpad/";
    @SuppressLint("HandlerLeak")
    public static int PlayMent_JeffTest(int SND_index) {
        FileInputStream fileInputStream = null;
        try {
            StopMent();

            String filepath = getFilePath(SND_index);
            if (filepath == null) {
                Log.e(TAG, "[PlayMent_JeffTest] - SND_index  Not Found FilePath !!! (" +  SND_index + ")");
                return -1;
            }
            Log.i(TAG, "[PlayMent_JeffTest] - filepath [" +  filepath + "]");

            mMentMediaPlayer = new MediaPlayer();
            fileInputStream = null;
            try {
                fileInputStream = new FileInputStream(filepath);
                FileDescriptor fileDescriptor = fileInputStream.getFD();
                mMentMediaPlayer.setDataSource(fileDescriptor);
//			mMentMediaPlayer.setDataSource(filepath);
            } catch (RuntimeException re) {
                LogUtil.errorLogInfo("", TAG,re);
                return -2;
            } catch (Exception e) {
                Log.e(TAG, "[ExceptionError] - PlayMent_JeffTest->setDataSource : " + e);
                return -2;
            }
            finally {
                if(fileInputStream!=null)
                    fileInputStream.close();
                fileInputStream = null;
            }

            try {
                mMentMediaPlayer.prepare();
            } catch (RuntimeException re) {
                LogUtil.errorLogInfo("", TAG, re);
                return -3;
            } catch (Exception e) {
                Log.e(TAG, "[ExceptionError] - PlayMent_JeffTest->prepare : " + e);
                return -3;
            }

            float PlayVolume = getPlayVolume(AudioManager.STREAM_MUSIC);
            if(PlayVolume < 0) PlayVolume = 1;

            mMentMediaPlayer.setVolume(PlayVolume, PlayVolume);
            mMentMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);

            try {
                mMentMediaPlayer.start();
            } catch (RuntimeException re) {
                LogUtil.errorLogInfo("", TAG, re);
                return -4;
            } catch (Exception e) {
                Log.e(TAG, "[ExceptionError] - PlayMent_JeffTest->start : " + e);
                return -4;
            }

            return mMentMediaPlayer.getDuration();
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
            return -5;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] PlayMent_JeffTest(int SND_index, int volume_kind)");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
            return -5;
        }
    }

    public static int PlayMent_JeffTest2(int SND_index) {
        try {
            StopMent();

            String filepath = getFilePath(SND_index);
            if (filepath == null) {
                Log.e(TAG, "[PlayMent_JeffTest] - SND_index  Not Found FilePath !!! (" +  SND_index + ")");
                return -1;
            }
            Log.i(TAG, "[PlayMent_JeffTest] - filepath [" +  filepath + "]");

            mMentMediaPlayer = new MediaPlayer();
            mMentMediaPlayer.setDataSource(filepath);
            mMentMediaPlayer.prepare();
            mMentMediaPlayer.start();



//            mMentMediaPlayer = new MediaPlayer();
//            FileInputStream fileInputStream = null;
//            try {
//                fileInputStream = new FileInputStream(filepath);
//                FileDescriptor fileDescriptor = fileInputStream.getFD();
//                mMentMediaPlayer.setDataSource(fileDescriptor);
//                fileInputStream.close();
//
////			mMentMediaPlayer.setDataSource(filepath);
//            } catch (Exception e) {
//                Log.e(TAG, "[ExceptionError] - PlayMent_JeffTest->setDataSource : " + e);
//                return -2;
//            }
//
//            try {
//                mMentMediaPlayer.prepare();
//            } catch (Exception e) {
//                Log.e(TAG, "[ExceptionError] - PlayMent_JeffTest->prepare : " + e);
//                return -3;
//            }
//
//            float PlayVolume = getPlayVolume(AudioManager.STREAM_MUSIC);
//            if(PlayVolume < 0) PlayVolume = 1;
//
//            mMentMediaPlayer.setVolume(PlayVolume, PlayVolume);
//            mMentMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);

//            try {
//                mMentMediaPlayer.start();
//            } catch (RuntimeException re) {
//		          LogUtil.errorLogInfo("", TAG, re);
//	          } catch (Exception e) {
//                Log.e(TAG, "[ExceptionError] - PlayMent_JeffTest->start : " + e);
//                return -4;
//            }

            return mMentMediaPlayer.getDuration();
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
            return -5;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] PlayMent_JeffTest(int SND_index, int volume_kind)");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
            return -5;
        }
    }

    public static boolean StopMent() {
        if (mMentMediaPlayer == null) return false;
        mMentMediaPlayer.stop();
        mMentMediaPlayer.release();
        mMentMediaPlayer = null;
        return true;
    }

    /**
     * 사운드파일 상수(SND)로 하여 실제 사운드파일 Path 를 리턴한다.<br>
     * 내부메소드<br>
     *
     * @param index - 사운드 INDEX ({@link SND})
     * @return null 일경우 잘못된 index , null 이 아닐경우 FilePath
     */
    private static String getFilePath(int index) {
        String FileName = null;
        switch (index) {
            // [number]
            case SND.number.NUM0:				FileName = "number/0.wav"; break;
            case SND.number.NUM1:				FileName = "number/1.wav"; break;
            case SND.number.NUM2:				FileName = "number/2.wav"; break;
            case SND.number.NUM3:				FileName = "number/3.wav"; break;
            case SND.number.NUM4:				FileName = "number/4.wav"; break;
            case SND.number.NUM5:				FileName = "number/5.wav"; break;
            case SND.number.NUM6:				FileName = "number/6.wav"; break;
            case SND.number.NUM7:				FileName = "number/7.wav"; break;
            case SND.number.NUM8:				FileName = "number/8.wav"; break;
            case SND.number.NUM9:				FileName = "number/9.wav"; break;

            // [effect]
            case SND.effect.BUTTON: 			FileName = "effect/button.wav"; break;
            case SND.effect.TOUCH_LATCHED: 		FileName = "effect/touch-latched.wav"; break;
            case SND.effect.TOUCH_UNLATCHED: 	FileName = "effect/touch-unlatched.wav"; break;
            case SND.effect.EFFECT1: 			FileName = "effect/effect1.wav"; break;
            case SND.effect.END_2_MONO: 		FileName = "effect/end_2_mono.wav"; break;
            case SND.effect.WARNING005: 		FileName = "effect/Warning005.wav"; break;

            // [setting]
            case SND.setting.DONG:				FileName = "setting/dong.wav"; break;
            case SND.setting.HO:				FileName = "setting/ho.wav"; break;
            case SND.setting.HOUR:				FileName = "setting/Hour.wav"; break;
            case SND.setting.MINUTE:			FileName = "setting/Minute.wav"; break;
            case SND.setting.SETTING:			FileName = "setting/Setting.wav"; break;
            case SND.setting.RETRY_ACTION:		FileName = "setting/RetryAction.wav"; break;
            case SND.setting.RETRY_INPUT:		FileName = "setting/RetryInput.wav"; break;

            // [bell]
            case SND.bell.FRONT:				FileName = "bell/Bell_Front.wav"; break;
            case SND.bell.GUARDROOM:			FileName = "bell/Bell_GuardRoom.wav"; break;
            case SND.bell.LOBBY:				FileName = "bell/Bell_Lobby.wav"; break;
            case SND.bell.NEIGHBOOR:			FileName = "bell/Bell_Neighboor.wav"; break;
            case SND.bell.PSTN:					FileName = "bell/Bell_Pstn.wav"; break;
            case SND.bell.ALRAM:				FileName = "bell/Alram.wav"; break;
            case SND.bell.MONINGCALL_01:		FileName = "bell/MoningCall01.wav"; break;
            case SND.bell.MONINGCALL_02:		FileName = "bell/MoningCall02.wav"; break;
            case SND.bell.MONINGCALL_03:		FileName = "bell/MoningCall03.wav"; break;

            // [call]
            case SND.call.CALL_VOIP:			FileName = "call/callVOIP.wav"; break;
            case SND.call.CALLSTART:			FileName = "call/CallStart.wav"; break;
            case SND.call.DINGDONG:				FileName = "call/DingDong.wav"; break;
            case SND.call.FRONTCALL:			FileName = "call/FrontCallSound.wav"; break;
            case SND.call.RING_BUSY:			FileName = "call/RingBusy.wav"; break;
            case SND.call.CONNECT_SUBPHONE:		FileName = "call/ConnectSubPhone.wav"; break;
            case SND.call.RECEIVE_CALL:			FileName = "call/MoipCallReceiveSound.wav"; break;
            case SND.call.SEND_CALL:			FileName = "call/MoipCallSendSound.wav"; break;
            case SND.call.BUSY_TRY_LATER:       FileName = "call/BusyTryLater.wav"; break;

            // [elevator]
            case SND.elevator.CALL:				FileName = "elevator/CallElevator.wav"; break;
            case SND.elevator.DN_ARRIVED:		FileName = "elevator/ElevatorArrived.wav"; break;
            case SND.elevator.UP_ARRIVED:		FileName = "elevator/MoveUp.wav"; break;
            case SND.elevator.ORG_ARRIVED:		FileName = "elevator/ORG_ElevatorArrived.wav"; break;

            // [emergency]
            case SND.emergency.DEFAULT:			FileName = "emergency/Emergency.wav"; break;
            case SND.emergency.ALARM:			FileName = "emergency/EmergencyAram.wav"; break;
            case SND.emergency.INVASION:		FileName = "emergency/EmergencyInvasion.wav"; break;
            case SND.emergency.RELEASE_COMEBACK:FileName = "emergency/EmergencyRelease_Comeback.wav"; break;
            case SND.emergency.COMEBACK:		FileName = "emergency/Comeback_Emergency.wav"; break;
            case SND.emergency.SIRLEN1:			FileName = "emergency/sirlen1.wav"; break;
            case SND.emergency.STOP_SIREN:		FileName = "emergency/StopSiren.wav"; break;
            case SND.emergency.SILENT:			FileName = "emergency/silent.wav"; break;

            // [mode]
            case SND.mode.NORMALMODE_COMEBACK:	FileName = "mode/NormalModeComeback.wav"; break;
            case SND.mode.HOME_DEVICE_CHECK:	FileName = "mode/HomeDeviceCheck.wav"; break;
            case SND.mode.INMODE_SETTING:		FileName = "mode/InModeSetting.wav"; break;
            case SND.mode.OUTMODE_SETTING:		FileName = "mode/OutModeSetting.wav"; break;
            case SND.mode.OUTMODE_SETTING_LOW:	FileName = "mode/OutModeSetting_low.wav"; break;
            case SND.mode.SENSOR_INVASION:		FileName = "mode/SensorInvasion.wav"; break;
            case SND.mode.SENSORMOTION_RELEASE:	FileName = "mode/SensorMotion_Release.wav"; break;
            case SND.mode.START_2_MONO:			FileName = "mode/start_2_mono.wav"; break;
            case SND.mode.VISITOR_OUTMODERUN:	FileName = "mode/Visitor_OutModeRun.wav"; break;
            case SND.mode.CAR_ARRIVED:			FileName = "mode/ArrivedCar.wav"; break;
            case SND.mode.BOX_ARRIVED:			FileName = "mode/BoxArrived.wav"; break;
            case SND.mode.OPENDOOR:				FileName = "mode/OpenDoor.wav"; break;

            // [ars_ment]
            case SND.ars_ment.ARS1_1:			FileName = "ars_ment/ARS1_1.wav"; break;
            case SND.ars_ment.ARS1_2:			FileName = "ars_ment/ARS1_2.wav"; break;
            case SND.ars_ment.ARS1_3:			FileName = "ars_ment/ARS1_3.wav"; break;
            case SND.ars_ment.ARS1_4:			FileName = "ars_ment/ARS1_4.wav"; break;
            case SND.ars_ment.ARS2_3:			FileName = "ars_ment/ARS2_3.wav"; break;
            case SND.ars_ment.ARS2_3_NOLIGHT:	FileName = "ars_ment/ARS2_3_NoLight.wav"; break;
            case SND.ars_ment.ARS3_3:			FileName = "ars_ment/ARS3_3.wav"; break;
            case SND.ars_ment.ARS3_4:			FileName = "ars_ment/ARS3_4.wav"; break;
            case SND.ars_ment.ARS3_6:			FileName = "ars_ment/ARS3_6.wav"; break;
            case SND.ars_ment.ARS4_1:			FileName = "ars_ment/ARS4_1.wav"; break;
            case SND.ars_ment.ARS4_3:			FileName = "ars_ment/ARS4_3.wav"; break;
            case SND.ars_ment.ARS4_4:			FileName = "ars_ment/ARS4_4.wav"; break;
            case SND.ars_ment.ARS5_1:			FileName = "ars_ment/ARS5_1.wav"; break;
            case SND.ars_ment.ARS5_2:			FileName = "ars_ment/ARS5_2.wav"; break;
            case SND.ars_ment.ARS6_1:			FileName = "ars_ment/ARS6_1.wav"; break;
            case SND.ars_ment.ARS7_1:			FileName = "ars_ment/ARS7_1.wav"; break;
            case SND.ars_ment.ARS8_1:			FileName = "ars_ment/ARS8_1.wav"; break;
            case SND.ars_ment.ARS9_1:			FileName = "ars_ment/ARS9_1.wav"; break;
            case SND.ars_ment.ARS9_2:			FileName = "ars_ment/ARS9_2.wav"; break;

            // [lobby]
            case SND.lobby.BELL_01:             FileName = "lobby/bell_01.ogg"; break;
            case SND.lobby.BELL_02:             FileName = "lobby/bell_02.ogg"; break;
            case SND.lobby.BELL_03:             FileName = "lobby/bell_03.ogg"; break;
            case SND.lobby.BELL_04:             FileName = "lobby/bell_04.ogg"; break;
            case SND.lobby.BELL_05:             FileName = "lobby/bell_05.ogg"; break;
            case SND.lobby.BELL_06:             FileName = "lobby/bell_06.ogg"; break;
            case SND.lobby.BOOTING:             FileName = "lobby/booting.ogg"; break;
            case SND.lobby.BUSYTRYLATER:        FileName = "lobby/busytrylater.ogg"; break;
            case SND.lobby.BUTTON:              FileName = "lobby/button.ogg"; break;
            case SND.lobby.CALLED:              FileName = "lobby/callend.ogg"; break;
            case SND.lobby.CALLSTART:           FileName = "lobby/callstart.ogg"; break;
            case SND.lobby.CONFIRMSETTING:      FileName = "lobby/confirmsetting.ogg"; break;
            case SND.lobby.DOOROPEN:            FileName = "lobby/dooropen.ogg"; break;
            case SND.lobby.INPUTFAIL:           FileName = "lobby/inputfail.ogg"; break;
            case SND.lobby.PACKAGEARRIVED:      FileName = "lobby/packagearrived.ogg"; break;
            case SND.lobby.RESULTOK:            FileName = "lobby/resultok.ogg"; break;
            case SND.lobby.RETRYINPUT:          FileName = "lobby/retryinput.ogg"; break;
            case SND.lobby.SETTING:             FileName = "lobby/setting.ogg"; break;
            case SND.lobby.TRYLATER:            FileName = "lobby/trylater.ogg"; break;

            // [guard]
            case SND.guard.BELL_01:             FileName = "guard/bell_01.ogg"; break;
            case SND.guard.BELL_02:             FileName = "guard/bell_02.ogg"; break;
            case SND.guard.BELL_03:             FileName = "guard/bell_03.ogg"; break;
            case SND.guard.BELL_04:             FileName = "guard/bell_04.ogg"; break;
            case SND.guard.BELL_05:             FileName = "guard/bell_05.ogg"; break;
            case SND.guard.BELL_06:             FileName = "guard/bell_06.ogg"; break;
            case SND.guard.BOOTING:             FileName = "guard/booting.ogg"; break;
            case SND.guard.BREAK:               FileName = "guard/break.ogg"; break;
            case SND.guard.BUSYTRYLATER:        FileName = "guard/busytrylater.ogg"; break;
            case SND.guard.BUTTON:              FileName = "guard/button.ogg"; break;
            case SND.guard.CALLEND:             FileName = "guard/callend.ogg"; break;
            case SND.guard.CALLRECEIVED:        FileName = "guard/callreceived.ogg"; break;
            case SND.guard.CALLSTART:           FileName = "guard/callstart.ogg"; break;
            case SND.guard.CONFIRMSETTING:      FileName = "guard/confirmsetting.ogg"; break;
            case SND.guard.DOOROPEN:            FileName = "guard/dooropen.ogg"; break;
            case SND.guard.EMER_COM:            FileName = "guard/emer_com.ogg"; break;
            case SND.guard.EMERGENCY:           FileName = "guard/emergency.ogg"; break;
            case SND.guard.FIRE:                FileName = "guard/fire.ogg"; break;
            case SND.guard.GAS:                 FileName = "guard/gas.ogg"; break;
            case SND.guard.INPUTFAIL:           FileName = "guard/inputfail.ogg"; break;
            case SND.guard.PACKAGEARRIVED:      FileName = "guard/packagearrived.ogg"; break;
            case SND.guard.RELEASE:             FileName = "guard/release.ogg"; break;
            case SND.guard.RESULTOK:            FileName = "guard/resultok.ogg"; break;
            case SND.guard.RETRYINPUT:          FileName = "guard/retryinput.ogg"; break;
            case SND.guard.SETTING:             FileName = "guard/setting.ogg"; break;
            case SND.guard.TRYLATER:            FileName = "guard/trylater.ogg"; break;
            case SND.guard.NOSOUND:             FileName = "guard/no_sound.ogg"; break;

            default:
                Log.e(TAG, "[Error] getFileName - Index Not Found!!! (" + index + ")");
                break;
        }

        if (FileName == null) return null;
        Log.e(TAG, "[getFileName] Filepath (" + SOUND_PATH_ROOT + FileName + ")");
        return (String)(SOUND_PATH_ROOT + FileName);
    }

    /**
     * 사운드 출력할 볼륨 레벨을 정의한다.
     */
    public static final class VOLUME_KIND {
        /**
         * 안드로이드에서 제공하는 기본 볼륨 음량 테이블을 정의한다.
         */
        public static final class stream {
            /**
             * 알람 음량
             */
            public final static int  ALARM			= AudioManager.STREAM_ALARM;
            /**
             * DTMP 출력시 음량
             */
            public final static int  DTMF			= AudioManager.STREAM_DTMF;
            /**
             * 음악, 동영상, 게임 및 기타 미디어 재생 음량
             */
            public final static int  MUSIC			= AudioManager.STREAM_MUSIC;
            /**
             * 알림 음량
             */
            public final static int  NOTIFICATION	= AudioManager.STREAM_NOTIFICATION;
            /**
             * 벨소리 음량
             */
            public final static int  RING			= AudioManager.STREAM_RING;
            /**
             * 시스템 음량
             */
            public final static int  SYSTEM			= AudioManager.STREAM_SYSTEM;
            /**
             * 통화 대기음 음량
             */
            public final static int  VOICE_CALL		= AudioManager.STREAM_VOICE_CALL;
        }

        /**
         * 고정된 볼륨을 정의한다. ( MUTE포함 총 15단계)
         */
        public static final class fixed {
            /**
             * BASE 상수 (※ 사용하지 않는다.  MUTE와 동일)
             */
            public final static int  BASE     = 100;

            /**
             * MUTE
             */
            public final static int  MUTE     = BASE + 0;

            public final static int  LEV0     = BASE + 0;
            public final static int  LEV1     = BASE + 1;
            public final static int  LEV2     = BASE + 2;
            public final static int  LEV3     = BASE + 3;
            public final static int  LEV4     = BASE + 4;
            public final static int  LEV5     = BASE + 5;
            public final static int  LEV6     = BASE + 6;
            public final static int  LEV7     = BASE + 7;
            public final static int  LEV8     = BASE + 8;
            public final static int  LEV9     = BASE + 9;
            public final static int  LEV10    = BASE + 10;
            public final static int  LEV11    = BASE + 11;
            public final static int  LEV12    = BASE + 12;
            public final static int  LEV13    = BASE + 13;
            public final static int  LEV14    = BASE + 14;
            public final static int  LEV15    = BASE + 15;

            /**
             * MAX
             */
            public final static int  MAX      = LEV15;
        }
    }

    /**
     * VOLUME_KIND 값에서 Play 시 사용할 Volume 값을 가져온다. <br>
     *
     * @param volume_kind - 재생시킬 볼륨 ({@link VOLUME_KIND} 참조)
     *
     * @return -1 : volume_kind Out of range ,  0f ~ 1f : Play 용 볼륨값
     */
    private static float getPlayVolume(int volume_kind) {
        if (mAudioManager == null) return -1;

        // 1. 범위체크
        int streamNfixed = -1;		// 1 : stream , 2 : fixed
        switch (volume_kind) {
            case VOLUME_KIND.stream.ALARM:
            case VOLUME_KIND.stream.DTMF:
            case VOLUME_KIND.stream.MUSIC:
            case VOLUME_KIND.stream.NOTIFICATION:
            case VOLUME_KIND.stream.RING:
            case VOLUME_KIND.stream.SYSTEM:
            case VOLUME_KIND.stream.VOICE_CALL:
                streamNfixed = 1;
                break;
            default:
                if ((volume_kind >= VOLUME_KIND.fixed.LEV0) && (volume_kind <= VOLUME_KIND.fixed.LEV15)) {
                    streamNfixed = 2;
                }
                break;
        }

        if (streamNfixed == -1) {
            Log.e(TAG, "[getVolume] Parameters - volume_kind Out of range !!! (" + volume_kind + ")");
            return -1;
        }

        // 2. 볼륨값 계산
        float calcVolume = -1;
        if (streamNfixed == 1) {
            float nowVolume = (float)mAudioManager.getStreamVolume(volume_kind);
            float maxVolume = (float)mAudioManager.getStreamMaxVolume(volume_kind);
            calcVolume = nowVolume / maxVolume;

            //Log.d(TAG, "[getVolume] kind=stream(" + volume_kind + ")" + "   nowVolume : " + nowVolume + " / maxVolume : " + maxVolume + " / calcVolume : " + calcVolume);
        }
        else if (streamNfixed == 2) {
            float fixedVolume = (float) volume_kind - VOLUME_KIND.fixed.BASE;
            float maxVolume = (float) VOLUME_KIND.fixed.MAX - VOLUME_KIND.fixed.BASE;
            calcVolume = fixedVolume / maxVolume;

            //Log.d(TAG, "[getVolume] kind=fixed(" + volume_kind + ")" + "   fixedVolume : " + fixedVolume + " / maxVolume : " + maxVolume + " / calcVolume : " + calcVolume);
        }

        return calcVolume;
    }

    public void sendSoundPlayRequestBR(int nSoundID) {
        try {
            Intent intent = new Intent();
            intent.setAction(define.NOTIFY_ACNAME);
            intent.putExtra(define.NOTIBR_KIND, define.NOTIFY_PLAYMENT);
            intent.putExtra(define.NOTIBR_CONTENT, nSoundID);
            getContext().sendBroadcast(intent);
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] sendSoundPlayRequestBR(int nSoundID)");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        }
    }

    public void setEncodingStopError() {
        try {
            LOG("[setEncodingStopError]");
            WallpadStatusData data = new WallpadStatusData(mContext);
            data.SetCameraEncodingError(true);
            data.closeDB();
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] setEncodingStopError()");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        }
    }

    public void checkEncodingStopError() {
        try {
            WallpadStatusData DBMGR = new WallpadStatusData(getContext());
            boolean bError = DBMGR.GetCameraEncodingError();
            LOG("[checkEncodingStopError] bError [" + bError + "]");
            if (bError) {
                if (mCallController.mVideoJNI != null) {
                    LOG_WARN("[checkEncodingStopError] mCallController.mVideoJNI.encoderStopOperation()");
                    mCallController.mVideoJNI.encoderStopOperation();
                }
                DBMGR.SetCameraEncodingError(false);
                LOG("[checkEncodingStopError] GetCameraEncodingError [" + DBMGR.GetCameraEncodingError() + "]");
            }
            DBMGR.closeDB();
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] checkEncodingStopError()");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        }
    }

    public static int nResidentSafetyCheckSetting = WallpadDeviceSet.RESIDENT_SAFETY_CHECK_DISABLE;
    private void getResidentSafetyCheckSetting() {
        try {
            WallpadDeviceSet mWallpadDeviceSet = new WallpadDeviceSet(getApplicationContext());
            nResidentSafetyCheckSetting = mWallpadDeviceSet.getResidentSafetyCheck();
            mWallpadDeviceSet.closeDB();

            Log.e(TAG, "[getResidentSafetyCheckSetting] nResidentSafetyCheckSetting: " + nResidentSafetyCheckSetting);

            if (nResidentSafetyCheckSetting == WallpadDeviceSet.RESIDENT_SAFETY_CHECK_ENABLE) Version.setResidentSafety();
            else Version.unsetResidentSafety();
        } catch (RuntimeException re) {
            LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] getResidentSafetyCheckSetting()");
            //e.printStackTrace();
            LogUtil.errorLogInfo("", TAG, e);
        }
    }

}