package com.sensetime.demo.ui;


import android.Manifest;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.SurfaceTexture;
import android.graphics.Typeface;
import android.hardware.usb.UsbDevice;
import android.media.MediaPlayer;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.SystemClock;
import android.text.TextUtils;
import android.util.Base64;
import android.util.Log;
import android.view.KeyEvent;
import android.view.TextureView;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.RadioGroup;
import android.widget.Switch;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.appcompat.widget.AppCompatSpinner;

import com.afollestad.materialdialogs.DialogAction;
import com.afollestad.materialdialogs.MaterialDialog;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import com.orhanobut.logger.Logger;

import com.sensetime.demo.SenseTimeMtc;
import com.sensetime.demo.bean.FaceStatus;
import com.sensetime.demo.bean.TrackingResult;
import com.sensetime.demo.bean.VerifyResult;
import com.sensetime.demo.util.FileUtils;
import com.sensetime.demo.util.MaterialDialogUtils;
import com.sensetime.demo.util.Util;
import com.sensetime.demo.view.UVCCameraSurfaceView;
import com.sensetime.demo.view.UVCCameraTextureView;
import com.sensetime.mtc.AiConfig;
import com.sensetime.mtc.IReceiveCallback;
import com.sensetime.mtc.MClient;
import com.sensetime.mtc.MtcCallback;
import com.sensetime.mtc.MtcCode;
import com.serenegiant.usb.DeviceFilter;
import com.serenegiant.usb.IFrameCallback;
import com.serenegiant.usb.USBMonitor;
import com.serenegiant.usb.UVCCamera;

import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.ref.WeakReference;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;

import io.reactivex.Observable;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
import kr.co.icontrols.ilp300_700.R;

import static com.sensetime.demo.bean.FaceStatus.AI_STATUS_ALREADY;
import static com.sensetime.demo.bean.FaceStatus.AI_STATUS_NONLIVENESS;
import static com.sensetime.demo.bean.FaceStatus.AI_STATUS_STRANGER;
import static com.sensetime.demo.bean.FaceStatus.AI_STATUS_UNKNOWN;
import static com.sensetime.demo.bean.FaceStatus.AI_STATUS_USER;

/**
 * MainActivity功能: M10 数据预览, 接受M10识别结果并显示
 * <p>
 * ------------------------使用-----------------------------
 * 步骤1: 在布局内添加UVCCameraTextureView
 * <com.sensetime.demo.view.UVCCameraTextureView
 * android:id="@+id/camera_surface_view"
 * android:layout_width="match_parent"
 * android:layout_height="match_parent"
 * android:layout_centerInParent="true" />
 * <p>
 * 步骤2: 在 onCreate 中进行初始化
 * a.注册USB监听
 * mUVCCameraView.registerUSBMonitor(this);
 * b.注册人脸识别结果回调
 * mUVCCameraView.setOnFaceCallback(faceList -> {
 * drawFaces(faceList);
 * });`
 * c.设置显示比例<一般固定></>
 * mUVCCameraView.setAspectRatio(16, 9);
 * d.设置预览的方向<需要根据Andorid上位机来调配: 0.0f or 90.0f></>
 * mUVCCameraView.setRotation(0.0f);
 * <p>
 * 步骤3: 在 onDestroy 中释放资源
 * mUVCCameraView.unRegisterUSBMonitor();
 * <p>
 * 步骤4: 绘制部分, 一共分为2层,
 * 底层UVCCameraTextureView做实时预览展示
 * 上层SurfaceView做人脸识别结果的绘制<List<UVCFaces.Face> faceList></>, 具体参考Android API Canvas绘制
 * <p>
 * data class Face(
 *
 * @SerializedName("rect") var rect: Rect = Rect(), //人脸坐标框, 基于预览帧数据的坐标系, 一般正向情况下, 左上角坐标为原点(0, 0)
 * @SerializedName("status") var status: Int = 0,  //0: UNKNOWN; 1: nonLiveness; 2.User; 3: Stranger
 * @SerializedName("uid") var uid: String = ""  //识别成功后的用户id
 * )
 */
public final class MainActivity extends BaseActivity {
    private final Object mSyncUVCCamera = new Object();
    private final Object mSyncUSBMonitor = new Object();
    // for accessing USB and USB camera
    private USBMonitor mUSBMonitor;
    private UVCCamera mUVCCamera;

    private Matrix mScaleMatrix = new Matrix();
    private Paint mTextPaint, mTextAreaPaint, mTextPaintResult;
    private UVCCameraTextureView mUVCCameraView;
    private UVCCameraSurfaceView mTrackView;
    //private FrameLayout mResultView;
    private TextView mResultText;

    private TextView takeOffTipsTv;

    private static final int mDelayCleanCanva = 1000; //Customizable.
    private long lastTime = System.currentTimeMillis(); // ms
    private SenseTimeMtc senseTimeMtc = SenseTimeMtc.getInstance();
    private Button btnDisregard;
    private View controlContentView;
    private ImageView hdcImageView;
    private ImageView hdcResultView;
    private Switch switchUvc;
    private Handler myHandler = new Handler();

    private MClient mClient = MClient.getInstance();
    private static Gson mGson = new Gson();

    //add KSJ
    boolean m_isSwitchState = false;
    boolean m_isSwitchState_check = false;
    boolean m_isResultView = false;
    boolean m_isResult = false;
    boolean m_isResultActivity = false;
    boolean m_isResultActivity_check = false;
    String m_strRecognitionId="";
    private boolean m_bLauncherStart = false;
    private int DETECTLEN = 150;
    private int m_iDetectLen = 150;
    private int m_iDetectLen_1 = 10;
    private float m_fThreshValue = 9.0f;

    MediaPlayer mMediaPlayer;// = MediaPlayer.create(this, R.raw.opendoor);
    //~add KSJ
    /**
     * RGB 摄像头是否打开
     */
    private boolean isSwitchRGBCamera = true;

    /**
     * 判断是MainActivity运行状态
     */
    private boolean isRunning = false;

    /**
     * 判断是否与模组连接上
     */
    private boolean isConnect = false;

    /**
     * 上一次拿到数据回调的时间
     */
    private volatile long lastUpdatePreviewDataMillis;

    /**
     * 是否有带口罩或安全帽，会影响识别，得提示用户摘下来
     */
    private volatile boolean isHaveMaskOrHat = false;

    private volatile long lastTakeOffMaskTime;

    private CheckCameraStatusRunnable mCheckCameraStatusRunnable = new CheckCameraStatusRunnable(this);

    private static class CheckCameraStatusRunnable implements Runnable {
        private WeakReference<MainActivity> activityWeakReference;

        public CheckCameraStatusRunnable(MainActivity mainActivity) {
            activityWeakReference = new WeakReference<>(mainActivity);
        }

        @Override
        public void run() {
            MainActivity mainActivity = activityWeakReference.get();
            if (mainActivity == null) {
                return;
            }
            Logger.d("CheckCameraStatusRunnable");
            mainActivity.checkCameraStatus();
        }
    }

    private ClearCanvasRunable clearCanvasRunable = new ClearCanvasRunable(this);

    private static class ClearCanvasRunable implements Runnable {

        private final WeakReference<MainActivity> mActivity;

        public ClearCanvasRunable(MainActivity mActivity) {
            this.mActivity = new WeakReference<MainActivity>(mActivity);
        }

        @Override
        public void run() {
            MainActivity activity = mActivity.get();
            if (activity != null) {
                if (System.currentTimeMillis() - activity.lastTime > mDelayCleanCanva)
                    activity.clearCanvas();
            }
        }
    }

    private MyIReceiveCallback myIReceiveCallback = new MyIReceiveCallback(this);

    private static class MyIReceiveCallback implements IReceiveCallback {

        private final WeakReference<MainActivity> mActivity;

        public MyIReceiveCallback(MainActivity mainActivity) {
            this.mActivity = new WeakReference<>(mainActivity);
        }

        @Override
        public void onTracking(String data) {
//            Logger.d("data: " + data); // only for DEBUG, it is easy to cause memory leak
            MainActivity mainActivity = mActivity.get();
            if (data != null && mainActivity != null && mainActivity.m_bLauncherStart) {
                mainActivity.drawFaces(data);
            }
        }

        @Override
        public void onVerify(String data) {
//            Logger.e("onVerify(String data):" + data); // only for DEBUG, it is easy to cause memory leak
            MainActivity mainActivity = mActivity.get();

            if (data != null && mainActivity != null) {
                mainActivity.verifyResult(data);
            }
        }

        @Override
        public void onPhotoData(int trackId, String recognizeId, ByteBuffer rgbHeadpose, ByteBuffer rgbBackground, ByteBuffer irBackgroud) {
            long ts = System.currentTimeMillis();
            Logger.d(recognizeId + "_headpose_" + ts + ".jpg");
            if (rgbHeadpose != null) {
                byte[] data = new byte[rgbHeadpose.capacity()];
                rgbHeadpose.get(data);
                FileUtils.writeDataToDisk(data, "/sdcard/Pictures/" + recognizeId + "_headpose_" + ts + ".jpg");
//                Logger.d("rgb headpose size: " + rgbHeadpose.capacity() + ",ts:" + ts);  // only for DEBUG, it is easy to cause memory leak
                rgbHeadpose.clear();
                rgbHeadpose = null;
                data = null;
            }
            if (rgbBackground != null) {
//                Logger.d("rgb bg size: " + rgbBackground.capacity()); //only for DEBUG, it is easy to cause memory leak
                rgbBackground.clear();
                rgbBackground = null;
            }
            if (irBackgroud != null) {
                byte[] data = new byte[irBackgroud.capacity()];
                irBackgroud.get(data);
                FileUtils.writeDataToDisk(data, "/sdcard/Pictures/" + recognizeId + "_ir_" + ts + ".jpg");
//                Logger.d("ir size: " + irBackgroud.capacity() + ",ts:" + ts);  only for DEBUG, it is easy to cause memory leak
                irBackgroud.clear();
                irBackgroud = null;
                data = null;
            }
            System.gc();
        }

        @Override
        public void onFeatureData(String traceId, ByteBuffer feature) {
//            Logger.d("traceId length: " + traceId.length() + " ,id: " + traceId);  //only for DEBUG, it is easy to cause memory leak
//            Logger.d("feature length:" + feature.capacity());  //only for DEBUG, it is easy to cause memory leak
            if (feature != null) {
                byte[] data = new byte[feature.capacity()];
                feature.get(data);
                String fileName = traceId + "_feature_" + System.currentTimeMillis() + ".txt";
                FileUtils.writeDataToDisk(data, "/sdcard/Pictures/" + fileName);
                feature.clear();
                feature = null;
            }
            System.gc();
        }

        @Override
        public void onDisconnect(ByteBuffer notUseNow) {
            if (notUseNow != null) {
                //cb data Not Use Now
            }
            MainActivity mainActivity = mActivity.get();
            if (mainActivity == null) {
                return;
            }
//            mainActivity.mClient.mtcDestroy(); // if you have used checkConnectThread, then you don't need to call mtcDestroy().
            Logger.d("disconnect,destroy mtc!!!!!");
        }
    }

    private MyDeviceConnectListener myDeviceConnectListener = new MyDeviceConnectListener(this);

    private static class MyDeviceConnectListener implements USBMonitor.OnDeviceConnectListener {

        private final WeakReference<MainActivity> activityWeakReference;

        public MyDeviceConnectListener(MainActivity mainActivity) {
            this.activityWeakReference = new WeakReference<>(mainActivity);
        }

        @Override
        public void onAttach(final UsbDevice device) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                Logger.d("OnDeviceConnectListener onAttach:" + device.getProductName());
            } else {
                Logger.d("OnDeviceConnectListener onAttach:" + device.getDeviceName());
            }

            MainActivity mainActivity = activityWeakReference.get();
            if (mainActivity != null && DEVICE_PRODUCT_VIP == device.getVendorId() && DEVICE_PRODUCT_PID == device.getProductId()) {
                mainActivity.checkCameraStatus();
            }
        }

        @Override
        @SuppressLint("CheckResult")
        public void onConnect(final UsbDevice device, final USBMonitor.UsbControlBlock ctrlBlock, final boolean createNew) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                Logger.v("OnDeviceConnectListener onConnect:" + device.getProductName());
            }
            Logger.d("onConnect ctrlBlock: " + ctrlBlock);
            MainActivity mainActivity = activityWeakReference.get();
            if (mainActivity != null) {
                mainActivity.initCamera(ctrlBlock);
            }
        }

        @Override
        public void onDisconnect(final UsbDevice device, final USBMonitor.UsbControlBlock ctrlBlock) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                Logger.v("OnDeviceConnectListener onDisconnect:" + device.getProductName());
            }
            Logger.d("onDisconnect device: " + device);
            MainActivity mainActivity = activityWeakReference.get();
            if (mainActivity != null) {
                Logger.e("onDisconnect");
                mainActivity.isConnect = false;
                mainActivity.releaseAndRequestCamera(null);
                mainActivity.checkCameraStatus();
            }
        }

        @Override
        public void onDettach(final UsbDevice device) {

        }

        @Override
        public void onCancel(final UsbDevice device) {
        }
    }

    private MyIFrameCallback myIFrameCallback = new MyIFrameCallback(this);

    private static class MyIFrameCallback implements IFrameCallback {

        private WeakReference<MainActivity> activityWeakReference;

        public MyIFrameCallback(MainActivity mainActivity) {
            activityWeakReference = new WeakReference<>(mainActivity);
        }

        @Override
        public void onVerifyFrame(ByteBuffer frame, ByteBuffer verifyResultBuffer) {
            MainActivity mainActivity = activityWeakReference.get();
            if (mainActivity == null) {
                return;
            }
            mainActivity.verifyFrame(frame, verifyResultBuffer);
        }
    }

    private void checkCameraStatus() {

        long timeInterval = SystemClock.elapsedRealtime() - lastUpdatePreviewDataMillis;
        Logger.d("isRunning:" + isRunning + ",  isConnect:" + isConnect + ",  timeInterval:" + timeInterval);
        if (!isRunning || isConnect || timeInterval < 10000) {
            // 这个activity不在顶层运行或者已经连接上了，就不执行了,或者上次请求时间小于10秒
            //RGB摄像头未打卡或者从未来过数据的话，不执行。
            return;
        }
        Logger.e("preview stop, prepare restart");
        lastUpdatePreviewDataMillis = SystemClock.elapsedRealtime();
        requestPermissionDevice();
        myHandler.postDelayed(mCheckCameraStatusRunnable, 10000);
    }

    //private static final int DEVICE_PRODUCT_VIP = 4817;
    //private static final int DEVICE_PRODUCT_PID = 17185;
//12d1:4321
    private static final int DEVICE_PRODUCT_VIP = 4817;
    private static final int DEVICE_PRODUCT_PID = 17185;
    private void requestPermissionDevice() {
        final List<DeviceFilter> filter = DeviceFilter.getDeviceFilters(this, com.serenegiant.uvccamera.R.xml.device_filter);
        if (filter.size() > 0 && mUSBMonitor != null) {
            List<UsbDevice> usbDeviceList = mUSBMonitor.getDeviceList(filter.get(0));
            for (UsbDevice device : usbDeviceList) {
                if (DEVICE_PRODUCT_VIP == device.getVendorId() && DEVICE_PRODUCT_PID == device.getProductId()) {
                    Logger.d("requestPermission");
                    releaseAndRequestCamera(device);
                }
            }
        }
    }

    private void initCamera(final USBMonitor.UsbControlBlock ctrlBlock) {

        if (!mUVCCameraView.isAvailable()) {
            //return;
        }
        final UVCCamera camera = new UVCCamera();
        try {
            camera.open(ctrlBlock);
        } catch (UnsupportedOperationException e) {
            Logger.e(e.toString());
            return;
        }
        Logger.i("supportedSize:" + camera.getSupportedSize());
        SenseTimeMtc senseTimeMtc = SenseTimeMtc.getInstance();

        int PREVIEW_W, PREVIEW_H;
        if (senseTimeMtc.getmM10_L_P() == SenseTimeMtc.LANDSCAPE_0 || senseTimeMtc.getmM10_L_P() == SenseTimeMtc.LANDSCAPE_180) {
            PREVIEW_W = senseTimeMtc.getmPreviewWidth();
            PREVIEW_H = senseTimeMtc.getmPreviewHeight();
        } else {//竖屏状态
            PREVIEW_W = senseTimeMtc.getmPreviewHeight();
            PREVIEW_H = senseTimeMtc.getmPreviewWidth();
        }
        try {
            camera.setPreviewSize(PREVIEW_W, PREVIEW_H, UVCCamera.FRAME_FORMAT_MJPEG); //可以指定帧格式
            Logger.d("PREVIEW_W:" + PREVIEW_W + ",  PREVIEW_H:" + PREVIEW_H);
        } catch (final IllegalArgumentException e) {
            // fallback to YUV mode
            try {
                camera.setPreviewSize(PREVIEW_W, PREVIEW_H, UVCCamera.DEFAULT_PREVIEW_MODE);
            } catch (final IllegalArgumentException e1) {
                camera.destroy();
                return;
            }
        }
        final SurfaceTexture st = mUVCCameraView.getSurfaceTexture();
        if (st != null) {
            camera.setPreviewTexture(st);
            camera.setFrameCallback(myIFrameCallback, UVCCamera.PIXEL_FORMAT_NV21, false);
            camera.startPreview();
        }
        synchronized (mSyncUVCCamera) {
            mUVCCamera = camera;
        }



        myHandler.postDelayed(() -> {
            m_bLauncherStart = true;
        }, 2000);
        if (senseTimeMtc.getmPreviewHeight() == 360) {
            myHandler.postDelayed(() -> {
                mClient.mtcDeviceScreenSizeSet(0x01, (mtcCode, result) -> {
                    Logger.d(" 360p mtcCode:" + mtcCode);
                    if (mtcCode != MtcCode.SUCCESS) {
                        showToast(MainActivity.this.getMtcErrorMsg(mtcCode));
                        isConnect = false;
                    } else {
                        isConnect = true;
                    }
                });//360p
            }, 200);
        } else {
            myHandler.postDelayed(() -> {
                mClient.mtcDeviceScreenSizeSet(0x00, (mtcCode, result) -> {
                    Logger.d("720p mtcCode:" + mtcCode);
                    if (mtcCode != MtcCode.SUCCESS) {
                        showToast(MainActivity.this.getMtcErrorMsg(mtcCode));
                        isConnect = false;
                    } else {
                        isConnect = true;
                    }
                });//720p
            }, 200);
        }
    }

    @Override
    protected void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
        if (Build.VERSION.SDK_INT >= 19) {
            //for new api versions.
            View decorView = getWindow().getDecorView();
            decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                    | View.SYSTEM_UI_FLAG_FULLSCREEN
                    | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
        }
        m_iDetectLen = DETECTLEN;

        //getmDeviceInfo
        //mClient.mtcSystemVersionInfoGet((mtcCode, result) ->
                //showBasicDialogNoCancel(R.string.setting_btn_device_info, "" + result));
        //add KSJ
        //if (senseTimeMtc.getmPreviewHeight() != 360) {
            senseTimeMtc.setmPreviewWidth(640);
            senseTimeMtc.setmPreviewHeight(360);
        //}
        //senseTimeMtc.setmM10_L_P(SenseTimeMtc.PORTRAIT_90);
        //senseTimeMtc.setmPreviewWidth(1280);
        //senseTimeMtc.setmPreviewHeight(720);
        //Logger.d("onCreate " + senseTimeMtc.getmPreviewHeight());
        //Log.d("KSJ", "devices : " + senseTimeMtc.getmDeviceInfo());

/*
        mClient.mtcAiClearAllImage((mtcCode, result) -> {
            if (mtcCode == MtcCode.SUCCESS) {
                showToast(R.string.notice_success);
            } else {
                showToast(getMtcErrorMsg(mtcCode));
            }
        });
*/
        mMediaPlayer = MediaPlayer.create(this, R.raw.opendoor);
    }

    @Override
    public boolean onKeyUp(int keyCode, KeyEvent event) {
        Log.d("KSJ", "onKeyUp");
        //Intent intent1 = getPackageManager().getLaunchIntentForPackage("kr.co.icontrols.ilp300_700");
        //intent1.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
        //startActivity(intent1);




        if (KeyEvent.KEYCODE_1 <= keyCode && keyCode <= KeyEvent.KEYCODE_9) {
            Intent intent1 = getPackageManager().getLaunchIntentForPackage("kr.co.icontrols.ilp300_700");
            intent1.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
            startActivity(intent1);
            //this.finish();
        }

        if(KeyEvent.KEYCODE_B == keyCode)
        {
            Intent intent1 = getPackageManager().getLaunchIntentForPackage("kr.co.icontrols.ilp300_700");
            intent1.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
            startActivity(intent1);
            //this.finish();
        }

        if(KeyEvent.KEYCODE_C == keyCode)
        {
            Intent intent1 = getPackageManager().getLaunchIntentForPackage("kr.co.icontrols.ilp300_700");
            intent1.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
            startActivity(intent1);
            //this.finish();
        }


        return super.onKeyUp(keyCode, event);
        /*
        switch (keyCode) {
            case KeyEvent.KEYCODE_1:

                mClient.mtcAiClearAllImage((mtcCode, result) -> {
                    if (mtcCode == MtcCode.SUCCESS) {
                        showToast("등록된 유저 정보를 삭제 하였습니다.");
                    } else {
                        showToast_rotate("X");
                    }
                });
                return true;
            case KeyEvent.KEYCODE_2:
                m_iDetectLen = DETECTLEN;
                m_iDetectLen_1 = 20;
                //showToast("150");
                showToast("감지 거리를 150으로 설정하였습니다.");
                return true;
            case KeyEvent.KEYCODE_3:
                m_iDetectLen = 0;
                m_iDetectLen_1 = 0;
                //showToast("0");
                showToast("감지 거리를 0 설정하였습니다.");
                return true;
            case KeyEvent.KEYCODE_4:
                irRGBSwitch(0x00);
                return true;
            case KeyEvent.KEYCODE_5:
                setCaptureAdd();
                return true;
            case KeyEvent.KEYCODE_6:
                irRGBSwitch(0x01);
                return true;
            case KeyEvent.KEYCODE_7:
                setAiConfig(0);
                return true;
            case KeyEvent.KEYCODE_8:
                setAiConfig(2);
                return true;
            case KeyEvent.KEYCODE_9:
                setAiConfig(1);
                return true;
            default:
                return super.onKeyUp(keyCode, event);
        }

         */
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        Log.d("KSJ", "onKeyDown");
        if (KeyEvent.KEYCODE_1 <= keyCode && keyCode <= KeyEvent.KEYCODE_9) {
            Intent intent = new Intent();
            intent.setAction("UPDATE_KEYDATA");
            intent.putExtra("data", keyCode);
            sendBroadcast(intent);
        }

        if(KeyEvent.KEYCODE_B == keyCode)
        {
            Intent intent = new Intent();
            intent.setAction("UPDATE_KEYDATA");
            intent.putExtra("data", keyCode);
            sendBroadcast(intent);
        }

        if(KeyEvent.KEYCODE_C == keyCode)
        {
            Intent intent = new Intent();
            intent.setAction("UPDATE_KEYDATA");
            intent.putExtra("data", keyCode);
            sendBroadcast(intent);
        }
        return super.onKeyDown(keyCode, event);
    }



    public void setCaptureAdd()
    {
        String id = "default_test";
        int mode = 0x02;
        MaterialDialog progressDialog = MaterialDialogUtils.showIndeterminateProgressDialog(MainActivity.this, "", false).show();
        MClient.getInstance().mtcAiAddImageByCamera(mode, id, (mtcCode, result) -> {

            if (progressDialog != null) {
                progressDialog.dismiss();
            }

            Logger.d("mtcCode:" + mtcCode);
            if (mode == 0x02 && mtcCode != MtcCode.ERR_TIME_OUT && !TextUtils.isEmpty(result)) {
                if (mtcCode == MtcCode.SUCCESS) {
                    MainActivity.this.showToast(R.string.notice_success);
                } else {
                    showToast(getMtcErrorMsg(mtcCode));
                }
                byte[] data = Base64.decode(result, Base64.DEFAULT);
                long ts = System.currentTimeMillis();
                FileUtils.writeDataToDisk(data, "/sdcard/pictures_add_user/" + id + "_" + ts + ".jpg");
            } else if (mode == 0x01 && mtcCode == MtcCode.SUCCESS) {
                showToast(R.string.notice_success);
            } else {
                showToast(MainActivity.this.getMtcErrorMsg(mtcCode));
            }
        });
    }

    public void setAiConfig(int iCmd) {
        /*
        MaterialDialog setAiConfigDialog = MaterialDialogUtils.showCustomDialog(this, getString(R.string.set_ai_config), R.layout.ai_config_dialog)
                .onPositive((@NonNull MaterialDialog dialog, @NonNull DialogAction which) -> {
                    EditText configEt = dialog.getCustomView().findViewById(R.id.config_et);

                    try {
                        Gson gson = new Gson();
                        AiConfig aiConfigNew = gson.fromJson(configEt.getText().toString(), AiConfig.class);
                        if (aiConfigNew == null || !aiConfigNew.isValueValid()) {
                            showToast(R.string.check_ai_config);
                        } else {
                            mClient.mtcAiConfigSet(gson.toJson(aiConfigNew), (mtcCode, result) -> {
                                if (mtcCode == MtcCode.SUCCESS) {
                                    showToast(R.string.notice_success);
                                    AiConfig.setInstance(aiConfigNew);
                                } else {
                                    showToast(getMtcErrorMsg(mtcCode));
                                }
                            });
                        }
                    } catch (JsonSyntaxException e) {
                        e.printStackTrace();
                        showToast(R.string.check_ai_config);
                    }
                }).build();
*/
        AiConfig aiConfig = AiConfig.getInstance();
        m_fThreshValue = aiConfig.getRecognitionThresh();
        Log.d("KSJ", "m_fThreshValue : " + m_fThreshValue);
        float fThresh = 0.0f;
        if(iCmd == 0)
            fThresh = m_fThreshValue - 0.01f;
        else if(iCmd == 1)
            fThresh = m_fThreshValue + 0.01f;
        else if(iCmd == 2)
            fThresh = 0.9f;

        m_fThreshValue = fThresh;
        Log.d("KSJ", "fThresh : " + fThresh);
        aiConfig.setRecognitionThresh(fThresh);
        Gson gson = new Gson();
        String aiConfigString = gson.toJson(aiConfig);
        //EditText configEt = (EditText) setAiConfigDialog.getCustomView().findViewById(R.id.config_et);
        //configEt.setText(Util.stringToJSON(aiConfigString));

        AiConfig aiConfigNew = gson.fromJson(Util.stringToJSON(aiConfigString), AiConfig.class);

        if (aiConfigNew == null || !aiConfigNew.isValueValid()) {
            showToast(R.string.check_ai_config);
        } else {
            mClient.mtcAiConfigSet(gson.toJson(aiConfigNew), (mtcCode, result) -> {
                if (mtcCode == MtcCode.SUCCESS) {
                    showToast("set thresh : " + m_fThreshValue);
                    AiConfig.setInstance(aiConfigNew);
                } else {
                    showToast(getMtcErrorMsg(mtcCode));
                }
            });
        }
        //Log.d("KSJ", Util.stringToJSON(aiConfigString));
        //setAiConfigDialog.show();
    }

    @Override
    protected void onStart() {
        super.onStart();
        Logger.d("onStart");

        if(!m_bLauncherStart)
        {
            if (senseTimeMtc.getmDeviceModule() == SenseTimeMtc.M10) {
                if (senseTimeMtc.getmM10_L_P() == SenseTimeMtc.PORTRAIT_90 || senseTimeMtc.getmM10_L_P() == SenseTimeMtc.PORTRAIT_270) {
                    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); //force portrait if you wish.
                } else {
                    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
                }
            } else { //M20
                //setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
            }

            String[] permissions = new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE};
            permissionGranted(permissions, 0);
            synchronized (mSyncUSBMonitor) {
                mUSBMonitor.register();
            }
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        Logger.d("onResume,  mUVCCameraView.isAvailable():" + mUVCCameraView.isAvailable() + ",   isRunning:" + isRunning);
        //MClient.getInstance().setReceiveCallback(myIReceiveCallback);



        if (!isRunning) {
            new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
                @Override
                public void run() {
                    // Todo
                    //m_bLauncherStart = true;

                }
            }, 100);
            isRunning = true;
            MClient.getInstance().setReceiveCallback(myIReceiveCallback);
            requestPermissionDevice();

            if (senseTimeMtc.isPauseAI()) {//用户手动去暂停了AI识别算法
                mClient.mtcAiPause((mtcCode, result) -> {
                    Logger.d("mtcAiPause's result:" + getMtcErrorMsg(mtcCode));
                });
            } else {//用户手动去恢复了AI识别算法，默认模式
                mClient.mtcAiResume((mtcCode, result) -> {
                    Logger.d("mtcAiResume's result:" + getMtcErrorMsg(mtcCode));
                });
            }
            if (senseTimeMtc.getIsIRRGBMode() == SenseTimeMtc.IR_RGB_NONE && SenseTimeMtc.M20 == senseTimeMtc.getmDeviceModule()) {
                //不知道是IR还是RGB模式下，默认换成RGB模式
                irRGBSwitch(0);
            }
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        m_bLauncherStart = false;
        m_isResultView = false;
        m_isSwitchState = false;
        Logger.d("onPause");
    }

    @Override
    protected void onStop() {
        Logger.d("onStop");

        MClient.getInstance().setReceiveCallback(null);
        super.onStop();

        Logger.d("onStop2");
        clearCanvas();
        isRunning = false;
        releaseAndRequestCamera(null);
        lastUpdatePreviewDataMillis = 0;
        //m_bLauncherStart = false;


            //Note 为了防止摄像头过烫，和节省能源，在onStop里自动关闭camera，在onResume里自动打开camera。
       /* // 关闭RGB摄像头，节省能量，防止模组过热
        mClient.mtcDeviceCameraStatusSet(0x01, 0x00, (mtcCode, result) -> {
            if (mtcCode != MtcCode.SUCCESS) {
                Logger.e("error message of close RGB camera:" + getMtcErrorMsg(mtcCode));
            }
        });

        // 关闭IR摄像头，节省能量，防止模组过热
        mClient.mtcDeviceCameraStatusSet(0x01, 0x01, (mtcCode, result) -> {
            if (mtcCode != MtcCode.SUCCESS) {
                Logger.e("error message of close IR camera:" + getMtcErrorMsg(mtcCode));
            }
        });*/

            //离开视频页面时，最好关闭人脸识别功能，因为人脸识别的数据有可能包含图片数据，
            // 同时做其他动作比如升级固件、添加底库就容易导致串口通信承载不了那么大数据
        /*mClient.mtcAiPause((mtcCode, result) -> {
            if (mtcCode != MtcCode.SUCCESS) {
                Logger.e("mtcAiPause error message:" + getMtcErrorMsg(mtcCode));
            }
        });*/



    }

    @Override
    protected void onDestroy() {
        Logger.d("onDestroy");
        super.onDestroy();
        synchronized (mSyncUSBMonitor) {
            if (mUSBMonitor != null) {
                mUSBMonitor.unregister();
                mUSBMonitor.destroy();
                mUSBMonitor = null;
            }
        }
    }

    protected void initView() {
        Logger.d("initView");
        setContentView(R.layout.activity_u_s_b_camera2);

        mTrackView = (UVCCameraSurfaceView) findViewById(R.id.camera_face_sv);

        mTrackView.setZOrderOnTop(true);
        mTrackView.getHolder().setFormat(PixelFormat.TRANSLUCENT);
        //mTrackView.wid
        //mTrackView.setAspectRatio(22, 17);
        mTrackView.setAspectRatio(30, 17);
        //mTrackView.setScaleX(2f); //NOTE mirror image
        //mTrackView.setScaleY(-1f); // only for debug
        mUVCCameraView = (UVCCameraTextureView) findViewById(R.id.camera_texture_view);



        //mUVCCameraView.setRotation(90);
        //mTrackView.setRotation(90);
        mUVCCameraView.setSurfaceTextureListener(mSurfaceTextureListener);
        //mUVCCameraView.setAspectRatio(8, 17);
        mUVCCameraView.setAspectRatio(9, 16);
        mUVCCameraView.setScaleX(-3f); //-2.2 NOTE mirror image
        mUVCCameraView.setScaleY(2.2f); // 2.2 only for debug
        //mUVCCameraView.set


        Logger.d("mUVCCameraView's width:" + mUVCCameraView.getWidth() + ",  mUVCCameraView's height:" + mUVCCameraView.getHeight());

        initTextPaint();
        mTrackView.setOnClickListener(view ->
        {
            /*
            if (controlContentView.getVisibility() == View.VISIBLE) {
                controlContentView.setVisibility(View.GONE);
            } else {
                controlContentView.setVisibility(View.VISIBLE);
            }*/
            controlContentView.setVisibility(View.GONE);
        });
        mTrackView.setKeepScreenOn(true);

    }

    @Override
    protected void initData() {
        mUSBMonitor = new USBMonitor(this, myDeviceConnectListener);
    }


    private void irRGBSwitch(int command) {
        mClient.mtcDeviceCameraSwitch(command, (mtcCode, result) -> {
            if (mtcCode == MtcCode.SUCCESS) {
                if (command == 0) {
                    senseTimeMtc.setIsIRRGBMode(SenseTimeMtc.RGB);
                } else {
                    senseTimeMtc.setIsIRRGBMode(SenseTimeMtc.IR);
                }
                if (senseTimeMtc.getmPreviewHeight() == 360) {
                    // 如果360p 需要再发一次
                    mClient.mtcDeviceScreenSizeSet(0x01, (mtcCode1, result1) -> {
                        if (mtcCode1 != MtcCode.SUCCESS) {
                            showToast("mtcCode1:" + mtcCode1);
                        }
                    });//360p
                }
            } else {
                showToast("mtcCode:" + mtcCode);
            }
        });
    }


    private void initTextPaint() {
        mTextPaint = new Paint();
        mTextPaint.setColor(Color.WHITE);
        mTextPaint.setStyle(Paint.Style.FILL);
        mTextPaint.setTypeface(Typeface.DEFAULT_BOLD);
        mTextPaint.setTextSize(30);

        mTextPaintResult = new Paint();
        mTextPaintResult.setColor(Color.WHITE);
        mTextPaintResult.setStyle(Paint.Style.FILL);
        mTextPaintResult.setTextSize(50);
        //绘制字符串所占区域
        mTextAreaPaint = new Paint();
        mTextAreaPaint.setColor(Color.BLACK);
        mTextAreaPaint.setStyle(Paint.Style.FILL);
    }

    private void verifyFrame(ByteBuffer frame, ByteBuffer verifyResultBuffer) {
        if (!isRunning) {
            return;
        }
        int len = verifyResultBuffer.capacity();
        if (len <= 0) {
            drawFaces(null);

            return;
        }
        byte[] verifyResultBytes = new byte[len];
        verifyResultBuffer.get(verifyResultBytes);
        String facesJson = new String(verifyResultBytes);
        Logger.d("facesJson:" + facesJson); // only for DEBUG, it is easy to cause memory leak

        if (!TextUtils.isEmpty(facesJson)) {
            TrackingResult trackingResult = mGson.fromJson(facesJson, TrackingResult.class);
            List<TrackingResult.Tracking> trackingList = trackingResult.getTrack_infos();
            TrackingResult.Tracking tracking = trackingList.get(0);
            if (tracking.getRecognizeScore() > 0 && senseTimeMtc.getAutoUploadAiInfoMode() == SenseTimeMtc.TURN_OFF_AUTO_UPLOAD_AI_INFO) { //关闭了主动上报，才走这里
                int maskSign = tracking.getMaskSign();
                int safetyHat = tracking.getSafetyHat();
                StringBuilder takeOffTips = new StringBuilder();
                if (maskSign == 1 || maskSign == 2) { //戴口罩的，有可能产生误识，这个数据可丢弃。提示用户摘下口罩。
                    takeOffTips.append(getString(R.string.take_off_mask) + "\n");
                }

                if (safetyHat == 1 || safetyHat == 2) { //戴了帽子，有可能产生误识，这数据可丢弃，提示用户摘下帽子再做识别。
                    takeOffTips.append(getString(R.string.take_off_hat));
                }

                //runOnUiThread(() -> takeOffTipsTv.setText(takeOffTips.toString()));

                if (!TextUtils.isEmpty(takeOffTips.toString())) {
                    lastTakeOffMaskTime = System.currentTimeMillis();
                    isHaveMaskOrHat = true;
                    myHandler.postDelayed(() -> {
                        if ((System.currentTimeMillis() - lastTakeOffMaskTime) > 5 * 1000) {
                            isHaveMaskOrHat = false;
                            //takeOffTipsTv.setText("");
                        }
                    }, 5 * 1000);
                } else {
                    isHaveMaskOrHat = false;
                }

            }

            try {
                drawFaces(facesJson);   // 45ms

            } catch (JsonSyntaxException ex) {
                ex.printStackTrace();

                drawFaces(null);
            }
        }
    }

    private void verifyResult(String verifyData) {
        if (!TextUtils.isEmpty(verifyData)) {
            VerifyResult verifyResult = mGson.fromJson(verifyData, VerifyResult.class);
            int maskSign = verifyResult.getMaskSign();
            int safetyHat = verifyResult.getSafetyHat();
            StringBuilder takeOffTips = new StringBuilder();
            if (maskSign == 1 || maskSign == 2) { //戴口罩的，有可能产生误识，这个数据可丢弃。提示用户摘下口罩。
                takeOffTips.append(getString(R.string.take_off_mask) + "\n");
            }

            if (safetyHat == 1 || safetyHat == 2) { //戴了帽子，有可能产生误识，这数据可丢弃，提示用户摘下帽子再做识别。
                takeOffTips.append(getString(R.string.take_off_hat));
            }
            //runOnUiThread(() -> takeOffTipsTv.setText(takeOffTips.toString()));

            if (!TextUtils.isEmpty(takeOffTips.toString())) {

                lastTakeOffMaskTime = System.currentTimeMillis();
                isHaveMaskOrHat = true;
                myHandler.postDelayed(() -> {

                    if ((System.currentTimeMillis() - lastTakeOffMaskTime) > 5 * 1000) {
                        isHaveMaskOrHat = false;
                        //takeOffTipsTv.setText("");

                    }
                }, 5 * 1000);
            } else {

                isHaveMaskOrHat = false;
            }

            drawFaces(verifyData);
        }
    }

    private void drawFaces(String trackingData) {
        if(!m_bLauncherStart) {
            //Log.d("KSJ", "m_bLauncherStart " + m_bLauncherStart);
            return;
        }
        synchronized (mTrackView.getmSyncSurface()) {

            TrackingResult trackingResult = mGson.fromJson(trackingData, TrackingResult.class);
            if (trackingResult == null) {
                //Log.d("KSJ2","drawFaces6");
                if (System.currentTimeMillis() - lastTime > mDelayCleanCanva) {
                    //Log.d("KSJ2","drawFaces1");
                    m_isSwitchState = false;
                    m_isResultView = false;
                    m_isSwitchState_check = false;
                    clearCanvas();
                }


                return;
            }
            Canvas canvas = null;
            try {
                if (!mTrackView.getHolder().getSurface().isValid()) {
                    //Log.d("KSJ2","drawFaces2");
                    return;
                }
                canvas = mTrackView.getHolder().lockCanvas();
                if (canvas == null) {
                    //Log.d("KSJ2","drawFaces3");
                    return;
                }
                canvas.drawColor(0, PorterDuff.Mode.CLEAR);
                canvas.save();

                canvas.setMatrix(mScaleMatrix);

/*
                if (trackingResult.getFaceInfo() != null) {//识别到的人脸
                    FaceInfoItem faceInfoItem = trackingResult.getFaceInfo();
                    faceInfoItem.setShowRect(FaceStatus.calcShowRect(faceInfoItem.getRect()));
                    Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_track_focus);

                    canvas.drawBitmap(bitmap, null, faceInfoItem.getShowRect(), null);//绘制人脸框
                    if (bitmap != null) {
                        //Log.d("KSJ2","drawFaces4");
                        bitmap.recycle();
                        bitmap = null;
                    }
                    String displayStr = trackingResult.getRecognitionId();
                    if (!isHaveMaskOrHat) {// 没有带口罩和安全帽，可以拿取其识别结果
                        drawText(displayStr, faceInfoItem.getShowRect(), canvas);
                    }
                }
                else
                {
                    //Log.d("KSJ2","drawFaces5");
                }
*/
                Rect rect = new Rect();

                int iLeft_old =0;
                int iRight_old = 0;
                int iTop_old = 0;
                int iBottom_old = 0;


                for (int i = 0; i < trackingResult.getTrack_infos().size(); i++) {//跟踪的人脸
                //for (int i = 0; i < 1; i++) {
                    TrackingResult.Tracking tracking = trackingResult.getTrack_infos().get(i);

                    FaceStatus faceStatus = FaceStatus.getByStatus(tracking.getRecognitionStatus());


                    //Log.d("KSJ", "canvas.getWidth(); " +canvas.getWidth() + " canvas.getWidth(); " + canvas.getHeight());
                    if (faceStatus == AI_STATUS_NONLIVENESS
                            || faceStatus == AI_STATUS_USER
                            || faceStatus == AI_STATUS_STRANGER
                            || faceStatus == AI_STATUS_UNKNOWN
                            || faceStatus == AI_STATUS_ALREADY) {



                        tracking.getFaceInfo().setShowRect(FaceStatus.calcShowRect(tracking.getFaceInfo().getRect()));

                        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.image_trigger_1280_red);

                        //int iMargin = 350;
                        int iMargin = 400;
                        //Log.d("KSJ", i + " iTop " + tracking.getFaceInfo().getRect().top + " iLeft " + tracking.getFaceInfo().getRect().left + " iRight " + tracking.getFaceInfo().getRect().right + " iBottom " + tracking.getFaceInfo().getRect().bottom);
                        //int iLeft = tracking.getFaceInfo().getRect().left-60;
                        //int iRight = tracking.getFaceInfo().getRect().right+10;
                        //int iTop = tracking.getFaceInfo().getRect().top+100;
                        //int iBottom = tracking.getFaceInfo().getRect().bottom+130;

                        int iLeft = tracking.getFaceInfo().getRect().left;
                        int iRight = tracking.getFaceInfo().getRect().right;
                        int iTop = tracking.getFaceInfo().getRect().top-iMargin;
                        int iBottom = tracking.getFaceInfo().getRect().bottom-iMargin;

                        //if((((iTop_old < iTop) && (iBottom_old > iTop)) || ((iTop_old < iBottom) && (iBottom_old > iBottom))) &&
                        //        (((iLeft_old < iLeft) && (iRight_old > iLeft)) || ((iLeft_old < iRight) && (iRight_old > iRight))))

                        //{
                        //    Log.d(("KSJ"), "test1");
                        //    continue;
                        //}

                        iLeft_old = iLeft;
                        iRight_old = iRight;
                        iTop_old = iTop;
                        iBottom_old = iBottom;
                        //int iMargin = 250;

                        //Log.d("KSJ", "iTop " + iTop + " iLeft " + iLeft + " iRight " + iRight + " iBottom " + iBottom);
                        //Log.d("KSJ", "x " + tracking.getFaceInfo().getRect().centerX() + " y " + tracking.getFaceInfo().getRect().centerY());
                        //if((((iBottom-iTop) > 150) &&  ((iRight-iLeft) > 150))) {
                        if((((iBottom-iTop) > m_iDetectLen) &&  ((iRight-iLeft) > m_iDetectLen))) {
                            m_isSwitchState = true;
                            m_isSwitchState_check = true;


                            //rect.set(iLeft,iTop,iRight,iBottom);

                            //rect.set(iLeft,iTop,iRight,iBottom);

                            rect.set((int) 760 - (iRight),iTop,(int) 760 - (iLeft),iBottom);
                            //rect.set((int) 1280 - (iBottom)-iMargin, (int)(720 - (iRight)+iMargin), (int) 1280- (iTop)-iMargin, (int)(720 - iLeft+iMargin));

                            tracking.getFaceInfo().getRect().set(rect);

                            //canvas.drawBitmap(bitmap, null, tracking.getFaceInfo().getRect() , null);//绘制人脸框
                            canvas.drawBitmap(bitmap, null, rect , null);//绘制人脸框


                            if (bitmap != null) {
                                bitmap.recycle();
                                bitmap = null;
                            }
                            String displayStr = tracking.getRecognitionId();

                            if (faceStatus != AI_STATUS_UNKNOWN && !isHaveMaskOrHat) { // 没有戴安全帽和口罩，可以拿
                                //drawText(displayStr, tracking.getFaceInfo().getShowRect(), canvas);
                                //if (i == 0)
                                drawText(displayStr, tracking.getFaceInfo().getRect(), canvas);
                            }

                            if (faceStatus == AI_STATUS_USER || faceStatus == AI_STATUS_ALREADY) {
                                //识别返回的数据
                                String recognitionId = tracking.getRecognitionId();
                                if (!TextUtils.isEmpty(recognitionId) && !recognitionId.equals("STRANGER") && !recognitionId.equals("UNKNOWN")
                                        && !recognitionId.equals("NONLIVENESS") && !recognitionId.equals("VERIFY_FAIL")) {
                                    //Log.v(MainActivity.class.getSimpleName(), i + " Identification success" + m_strRecognitionId);
                                    m_isResultView = true;
                                    m_isResult = true;
                                    //if(!m_isResultActivity)
                                    if(!m_strRecognitionId.equals(recognitionId))
                                    {
                                        Log.v(MainActivity.class.getSimpleName(), "Identification success");

                                        //SoundPool sound;
                                        //sound = new SoundPool(2, AudioManager.STREAM_MUSIC, 0);
                                        //int soundId = sound.load(this, R.raw.opendoor, 1);
                                        //sound.play(soundId, 1.0F, 1.0F, 1, 0, 1.0F);
                                        mMediaPlayer.start();
                                        setSystemCall("wpd_interface 0xff95 0");

                                        new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
                                            @Override
                                            public void run() {

                                                //Intent intent = new Intent(MainActivity.this, DetectResult.class);
                                                //intent.putExtra("result_id", recognitionId);
                                                //startActivity(intent);
                                                //finish();
                                                m_strRecognitionId="";
                                            }
                                        }, 5000);

                                    }
                                    m_strRecognitionId = recognitionId;
                                    //m_isResultActivity = true;


/*


                                    mClient.mtcAiPause((mtcCode, result) -> {
                                        Logger.d("mtcAiPause's result:" + getMtcErrorMsg(mtcCode));
                                    });

                                    new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
                                        @Override
                                        public void run() {
                                            mClient.mtcAiResume((mtcCode, result) -> {
                                                Logger.d("mtcAiResume's result:" + getMtcErrorMsg(mtcCode));
                                            });
                                        }
                                    }, 3000);
*/
                                    //Log.v("KSJ", "Identification success");
                                    //hdcResultView.setVisibility(View.VISIBLE);
                                    //showToast("실패되었습니다.", 270);
                                    //showToast("인증되었습니다", 270);

                                    //drawText_result("인증되었습니다.", tracking.getFaceInfo().getRect(), canvas);
                                } else {
                                    m_isResultView = true;
                                    m_isResult = false;
                                    //hdcResultView.setVisibility(View.VISIBLE);
                                    //Log.v("KSJ", "Identification failure");

                                    //showToast("실패되었습니다.", 270);

                                    //drawText_result("인증되었습니다.", tracking.getFaceInfo().getRect(), canvas);
                                    //Log.v(MainActivity.class.getSimpleName(), "Identification failure");
                                }
                            }
                            else
                            {
                                m_isResultView = false;
                                m_isResult = false;
                            }

                        }
                        else if((((iBottom-iTop) > m_iDetectLen-m_iDetectLen_1) &&  ((iRight-iLeft) > m_iDetectLen-m_iDetectLen_1)))
                        {
                            //Log.d("KSJ", "test1");
                        }
                        else
                        {

                            if(!m_isSwitchState_check) {
                                m_isResultView = false;
                                m_isSwitchState = false;

                            }
                            m_isSwitchState_check = false;
                            //return;
                            //Log.d("KSJ2","drawFaces 5");

                        }



                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    if (canvas != null) {
                        canvas.restore();
                    }
                    mTrackView.getHolder().unlockCanvasAndPost(canvas);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                trackingData = null;
                trackingResult = null;
                System.gc();
            }
            lastTime = System.currentTimeMillis();
            myHandler.removeCallbacks(clearCanvasRunable);
            myHandler.postDelayed(clearCanvasRunable, mDelayCleanCanva + 20);
        }
    }

    private void setSystemCall(String strCmd)
    {
        Runtime runtime = Runtime.getRuntime();
        Process process;
        try {
            process = runtime.exec(strCmd);

        }
        catch (Exception exception)
        {
            Log.e("KSJ", "system call error");
        }
        //return "";
    }


    private void clearCanvas() {
        if (mTrackView == null) {
            return;
        }
        Canvas canvas = mTrackView.getHolder().lockCanvas();
        if (canvas != null) {
            try {
                canvas.drawColor(0, PorterDuff.Mode.CLEAR);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    mTrackView.getHolder().unlockCanvasAndPost(canvas);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private void drawText_result(String text, Rect faceRect, Canvas canvas) {
        canvas.drawText(text, 0, 0, mTextPaintResult);
    }

    private void drawText(String text, Rect faceRect, Canvas canvas) {
        if (TextUtils.isEmpty(text)) {
            m_isResultView = false;
            m_isResult = false;
            return;
        }
        mTextPaint.setTextSize(25);
        float width = mTextPaint.measureText(text);//获取字符串所占宽度

        //faceRect.width();
//        if (mUVCCameraView.mIsLandScape) {
        //int baselineX = (int) (faceRect.left + (faceRect.right - faceRect.left) / 2.0f - width / 2.0f);
        //int baselineY = faceRect.top - 20;
        int baselineX = faceRect.left + 20;//(int) (faceRect.right + faceRect.height() / 1.0f - width / 1.0f);
        int baselineY = faceRect.bottom + 40;
//        }

        //获取当前线到baseline线的距离
        Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics();
        float top = fontMetrics.top;
        float bottom = fontMetrics.bottom;
        //获取字符串所占高度
        float height = fontMetrics.bottom - fontMetrics.top;

        //mTextAreaPaint.setColor(Color.WHITE);
        //mTextPaint.setColor(Color.RED);
        //mTextPaint.setTextSize(20);
        //canvas.rotate(90, baselineX, baselineY);
//        if (!mUVCCameraView.mIsLandScape) {
//            canvas.rotate(90, baselineX, baselineY);
//        }
        //绘制背景
        //canvas.drawRect(faceRect.left, faceRect.top, faceRect.right, faceRect.bottom, mTextAreaPaint);
        canvas.drawRect(baselineX - 10, baselineY + top - 5, width + baselineX + 10, bottom + baselineY + 5, mTextAreaPaint);
        //绘制文本
        //Log.d("KSJ1", "left "+ faceRect.left + " top " + faceRect.top + " right " + faceRect.right + " bottom " + faceRect.bottom);
        //Log.d("KSJ1", "baselineX "+ baselineX + " baselineY" + baselineY);
        //canvas.drawText(text, faceRect.left-faceRect.height()+20, faceRect.bottom-20, mTextPaint);

        canvas.drawText(text, baselineX, baselineY, mTextPaint);

//        if (!mUVCCameraView.mIsLandScape) {
//            canvas.rotate(-90, baselineX, baselineY);
//        }
    }


    @SuppressLint("CheckResult")
    private void releaseAndRequestCamera(UsbDevice device) {
        Logger.d("releaseAndRequestCamera");
        Observable.create((ObservableOnSubscribe<String>) emitter -> {
            synchronized (mSyncUVCCamera) {
                Logger.d("mUVCCamera:" + mUVCCamera);
                if (mUVCCamera != null) {
                    try {
                        mUVCCamera.close();
                        mUVCCamera.destroy();
                    } catch (final Exception e) {
                        e.printStackTrace();
                    }
                    mUVCCamera = null;
                }
                isConnect = false;
            }
            emitter.onNext("complete");
//        }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
        }).subscribeOn(Schedulers.single()).observeOn(AndroidSchedulers.mainThread())
                .subscribe(s -> {
                    Logger.d("requestPermission device:" + device + ",  mUSBMonitor:" + mUSBMonitor);
                    if (device != null && mUSBMonitor != null) {
                        mUSBMonitor.requestPermission(device);
                    }
                });
    }


    private final TextureView.SurfaceTextureListener mSurfaceTextureListener = new TextureView.SurfaceTextureListener() {

        @Override
        public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
            float scaleX;
            float scaleY;
            float modulus;
            SenseTimeMtc senseTimeMtc = SenseTimeMtc.getInstance();
            int PREVIEW_W, PREVIEW_H;
            if (senseTimeMtc.getmM10_L_P() == SenseTimeMtc.LANDSCAPE_0 || senseTimeMtc.getmM10_L_P() == SenseTimeMtc.LANDSCAPE_180) {
                PREVIEW_W = senseTimeMtc.getmPreviewWidth();
                PREVIEW_H = senseTimeMtc.getmPreviewHeight();
            } else {//竖屏状态
                PREVIEW_W = senseTimeMtc.getmPreviewHeight();
                PREVIEW_H = senseTimeMtc.getmPreviewWidth();
            }
            if (SenseTimeMtc.M10 == senseTimeMtc.getmDeviceModule() && (senseTimeMtc.getmM10_L_P() == SenseTimeMtc.LANDSCAPE_0
                    || senseTimeMtc.getmM10_L_P() == SenseTimeMtc.LANDSCAPE_180)) {
                modulus = 720.0f / (float) PREVIEW_H;
            } else {
                modulus = 1280.0f / (float) PREVIEW_H;
            }
            //modulus = 720.0f / (float) PREVIEW_H;
            //width = width*2;
            //height = height*2;
            //width = 310;
            //height = 550;

            width = 410;
            height = 750;
            if (width > height) {
                scaleX = width / (float) PREVIEW_W / modulus;
                scaleY = height / (float) PREVIEW_H / modulus;
            } else {
                scaleX = height / (float) PREVIEW_H / modulus;
                scaleY = width / (float) PREVIEW_W / modulus;
            }

            Logger.d("onSurfaceTextureAvailable  modulus:" + modulus + ",  PREVIEW_H:" + PREVIEW_H + ",  PREVIEW_W:" + PREVIEW_W );
            Logger.d("onSurfaceTextureAvailable  width:" + width + ",  height:" + height + ",  scaleX:" + scaleX + ",  scaleY:" + scaleY);
            mScaleMatrix.setScale(scaleX, scaleY);
            //requestPermissionDevice();
        }

        @Override
        public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
            Logger.d("onSurfaceTextureSizeChanged  width:" + width + ",  height:" + height);
        }

        @Override
        public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
            Logger.d("onSurfaceTextureDestroyed   surface:" + surface);
            return false;
        }

        @Override
        public void onSurfaceTextureUpdated(SurfaceTexture surface) {
//			Logger.d("onSurfaceTextureUpdated  surface:"+surface);
        }
    };

}