xuxiuxi
2017-07-26 e465984927353ef5922b5c1fe9f7dd1cf29e9094
VisitFace/DemoForBsk/app/src/main/java/cn/com/basic/face/base/MainActivity.java
@@ -1,37 +1,97 @@
package cn.com.basic.face.base;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.drawable.ColorDrawable;
import android.hardware.Camera;
import android.hardware.Camera.PreviewCallback;
import android.hardware.Camera.Size;
import android.os.Bundle;
import android.os.Handler;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.view.WindowManager;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.awsle.aibatis.client.SqlMapClientBuilder;
import com.bsk.zhangbo.demoforbsk.R;
import cn.com.basic.face.fragment.SurveillanceFragment;
import cn.com.basic.face.util.TabNameUtil;
import com.luxand.FSDK;
import com.luxand.FSDK.HTracker;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import cn.com.basic.face.dialog.AttenderRegisterSelectPhotoDialog;
import cn.com.basic.face.dialog.AttenderRegisterUploadPhotoDialog;
import cn.com.basic.face.dialog.VisitorRegisterSelectPhotoDialog;
import cn.com.basic.face.dialog.VisitorRegisterUploadPhotoDialog;
import cn.com.basic.face.discern.common.CommonVariables;
import cn.com.basic.face.discern.query.item.SurveillanceQueryItem;
import cn.com.basic.face.fragment.AttendanceFragment;
import cn.com.basic.face.fragment.CheckInFragment;
import cn.com.basic.face.fragment.DeviceFragment;
import cn.com.basic.face.fragment.PhoneCallFragment;
import cn.com.basic.face.fragment.RegisterFragment;
import cn.com.basic.face.fragment.SurveillanceFragment;
import cn.com.basic.face.fragment.VisitFragment;
import cn.com.basic.face.fragment.VisitorRegisterFragment;
import cn.com.basic.face.service.DeviceMng;
import cn.com.basic.face.service.InternetAccessThread;
import cn.com.basic.face.service.SurveillanceMng;
import cn.com.basic.face.service.sqlite.SurveillanceDao;
import cn.com.basic.face.service.sqlite.TestDao;
import cn.com.basic.face.service.sync.up.BaseSync;
import cn.com.basic.face.util.FileUtil;
import cn.com.basic.face.util.NativeImg;
import cn.com.basic.face.util.TabNameUtil;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class MainActivity extends BaseActivity {
public class MainActivity extends BaseActivity implements View.OnClickListener{
    private static MainActivity instance;
    private static TabLayout mTabLayout;
    private static ViewPager mViewPager;
    public static ViewPager mViewPager;
    public SQLiteDatabase db;
    private int internetAccessible = CommonVariables.InternetAccess.INTERNET_NOT_INITIALIZE;
    public int getInternetAccessible() {
        return internetAccessible;
    }
    public void setInternetAccessible(int internetAccessible) {
        this.internetAccessible = internetAccessible;
    }
    public static void selectPage(int pageNum) {
        mTabLayout.getTabAt(pageNum).select();
@@ -48,31 +108,42 @@
        mViewPager = (ViewPager) findViewById(R.id.viewpager);
        mTabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
        instance = this;
        internetAccessThread.start();
    }
    public MyFragmentPagerAdapter myFragmentPagerAdapter;
    @Override
    public void initData() {
        List<String> tabNamesList = Arrays.asList(TabNameUtil.tabNames);
        int[] tabIcons = TabNameUtil.tabIcons;
        MyFragmentPagerAdapter myFragmentPagerAdapter = new MyFragmentPagerAdapter(getSupportFragmentManager(),MainActivity.this);
        myFragmentPagerAdapter = new MyFragmentPagerAdapter(getSupportFragmentManager(),MainActivity.this);
        myFragmentPagerAdapter.addFragment(SurveillanceFragment.getInstance(), tabNamesList.get(0),tabIcons[0]);
        myFragmentPagerAdapter.addFragment(RegisterFragment.getInstance(), tabNamesList.get(1),tabIcons[1]);
        myFragmentPagerAdapter.addFragment(VisitorRegisterFragment.getInstance(), tabNamesList.get(1),tabIcons[1]);
//        myFragmentPagerAdapter.addFragment(AttenderRegisterFragment.getInstance(), tabNamesList.get(1),tabIcons[1]);
//        myFragmentPagerAdapter.addFragment(RegisterFragment.getInstance(), tabNamesList.get(1),tabIcons[1]);
        myFragmentPagerAdapter.addFragment(CheckInFragment.getInstance(), tabNamesList.get(2),tabIcons[2]);
        myFragmentPagerAdapter.addFragment(PhoneCallFragment.getInstance(), tabNamesList.get(3),tabIcons[3]);
        myFragmentPagerAdapter.addFragment(VisitFragment.getInstance(), tabNamesList.get(4),tabIcons[4]);
        myFragmentPagerAdapter.addFragment(AttendanceFragment.newInstance(), tabNamesList.get(5),tabIcons[5]);
        myFragmentPagerAdapter.addFragment(DeviceFragment.newInstance(), tabNamesList.get(6),tabIcons[6]);
        myFragmentPagerAdapter.addFragment(AttendanceFragment.getInstance(), tabNamesList.get(5),tabIcons[5]);
        myFragmentPagerAdapter.addFragment(DeviceFragment.getInstance(), tabNamesList.get(6),tabIcons[6]);
        mViewPager.setAdapter(myFragmentPagerAdapter);
        mViewPager.setOffscreenPageLimit(6);//viewpager缓存个数
        mTabLayout.setupWithViewPager(mViewPager);
        mTabLayout.setTabMode(TabLayout.MODE_FIXED);
        for (int i = 0; i < mTabLayout.getTabCount(); i++) {
            TabLayout.Tab tab = mTabLayout.getTabAt(i);
            tab.setCustomView(myFragmentPagerAdapter.getTabView(i));
            LinearLayout view = (LinearLayout)myFragmentPagerAdapter.getTabView(i);
            tab.setCustomView(view);
            if (i == 0) {
                tab.getCustomView().setSelected(true);
            }
        }
        if (CommonVariables.ID_CARD) {
            myThread = new MyThread();
            myThread.start();
        }
//        initSqlMap();
    }
    public static MainActivity getInstance() {
@@ -94,6 +165,12 @@
            mFragments.add(fragment);
            mFragmentTitles.add(title);
            mFragmentIcons.add(drawable);
        }
        public void setFragment(int index, Fragment fragment) {
            mFragments.remove(index);
            mFragments.add(index, fragment);
            notifyDataSetChanged();
        }
        @Override
@@ -122,4 +199,839 @@
    }
    boolean doubleBackToExitPressedOnce = false;
    @Override
    public void onBackPressed() {
        if (doubleBackToExitPressedOnce) {
            super.onBackPressed();
            return;
        }
        this.doubleBackToExitPressedOnce = true;
        Toast.makeText(this, "请再次按返回键退出", Toast.LENGTH_SHORT).show();
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                doubleBackToExitPressedOnce=false;
            }
        }, 2000);
    }
    private MyThread myThread;
    class MyThread extends Thread{
        @Override
        public void run() {
            try {
                setBmpDecodeEnv();
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    /**
     * 将raw下的文件复制到sdCard
     */
    public boolean setBmpDecodeEnv() {
        String path=getFilesDir().getAbsolutePath();
        String filename = "base.dat";
        try{
            String databaseFilename = path + "/" + filename;
            File dir = new File(path);
            if (!dir.exists())
                dir.mkdir();
            if (!(new File(databaseFilename)).exists()){
                InputStream is = getResources().openRawResource(R.raw.base);
                FileOutputStream fos = new FileOutputStream(databaseFilename);
                byte[] buffer = new byte[8192];
                int count = 0;
                while ((count = is.read(buffer)) > 0)
                {
                    fos.write(buffer, 0, count);
                }
                fos.close();
                is.close();
            }
        }
        catch (Exception e){
            System.out.println(e.getMessage());
            return false;
        }
        String filename1 = "license.lic";
        try{
            String databaseFilename = path + "/" + filename1;
            File dir = new File(path);
            if (!dir.exists())
                dir.mkdir();
            if (!(new File(databaseFilename)).exists()){
                InputStream is = getResources().openRawResource(R.raw.license);
                FileOutputStream fos = new FileOutputStream(databaseFilename);
                byte[] buffer = new byte[8192];
                int count = 0;
                while ((count = is.read(buffer)) > 0)
                {
                    fos.write(buffer, 0, count);
                }
                fos.close();
                is.close();
            }
        }
        catch (Exception e){
            System.out.println(e.getMessage());
            return false;
        }
        return true;
    }
/////////////////////////////
    /**
     * 初始化sqlMap
     */
    private void initSqlMap() {
        Config.sqlMap = SqlMapClientBuilder.buildSqlMapClient(this.getClass().getResourceAsStream("/assets/config/SqlMapConfig.xml")).init(this);
    }
    /**
     * 初始化数据
     */
    private void initDb() {
        InputStream dbIn = getClass().getResourceAsStream(Config.DB);
        FileOutputStream out = null;
        File z = null;
        try {
            byte[] bytes = new byte[1024];
            z = new File(Config.APPDBPATH);
            if(!z.exists()){
                z.mkdirs();
            }
            //判断数据库是否存在
            z = new File(Config.APPDB);
            if (!z.exists()) {
                out = new FileOutputStream(z);
                int len = 0;
                while((len = dbIn.read(bytes))!= -1){
                    out.write(bytes,0,len);
                }
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (out != null)
                    out.close();
                if (dbIn != null)
                    dbIn.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        try {
            //对数据库文件权限
            Runtime.getRuntime().exec("chmod 7755 " + z.toString());
        } catch (IOException e) {
            e.printStackTrace();
        }
        //Log.d(Config.APPTAG, "初始化数据完成!");
    }
    ////////////////////////////////////////////////////////
    private boolean mIsFailed = false;
    public Preview mPreview;
    public ProcessImageAndDrawResults mDraw;
    private final String database = "Memory50.dat";
    private final String help_text = "help";
    public static float sDensity = 1.0f;
    InternetAccessThread internetAccessThread = new InternetAccessThread();
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initDb();
        db=openOrCreateDatabase("/data/data/com.bsk.zhangbo.demoforbsk/databases/aibatis_test_db", Context.MODE_PRIVATE, null);
        TestDao.getInstance().test();
        DeviceMng.getInstance().findDevice();
        if (CommonVariables.FACE_SERVER) {
            sDensity = getResources().getDisplayMetrics().scaledDensity;
            String s = FileUtil.getStringFromFile("/system/a");
            int res = FSDK.ActivateLibrary(s);
            if (res != FSDK.FSDKE_OK) {
                mIsFailed = true;
                showErrorAndClose("failed", res);
            } else {
                FSDK.Initialize();
                // Hide the window title (it is done in manifest too)
                getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
                //requestWindowFeature(Window.FEATURE_NO_TITLE);
                // Lock orientation
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
                // Camera layer and drawing layer
                mDraw = new ProcessImageAndDrawResults(this);
                mPreview = new Preview(this, mDraw);
                mDraw.mTracker = new HTracker();
                String templatePath = this.getApplicationInfo().dataDir + "/" + database;
                if (FSDK.FSDKE_OK != FSDK.LoadTrackerMemoryFromFile(mDraw.mTracker, templatePath)) {
                    res = FSDK.CreateTracker(mDraw.mTracker);
                    if (FSDK.FSDKE_OK != res) {
                        showErrorAndClose("Error creating tracker", res);
                    }
                }
                resetTrackerParameters();
                this.getWindow().setBackgroundDrawable(new ColorDrawable()); //black background
                //setContentView(mPreview); //creates MainActivity contents
                //addContentView(mDraw, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
                // Menu
//                LayoutInflater inflater = (LayoutInflater)this.getSystemService( Context.LAYOUT_INFLATER_SERVICE );
//                View buttons = inflater.inflate(R.layout.bottom_menu, null );
//                buttons.findViewById(R.id.helpButton).setOnClickListener(this);
//                buttons.findViewById(R.id.clearButton).setOnClickListener(this);
//                addContentView(buttons, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
//                FSDK.Initialize();
//                getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
//                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
//                mDraw = new ProcessImageAndDrawResults(this);
//                mPreview = new Preview(this, mDraw);
//                mDraw.mTracker = new FSDK.HTracker();
//                String templatePath = this.getApplicationInfo().dataDir + "/" + database;
//                if (FSDK.FSDKE_OK != FSDK.LoadTrackerMemoryFromFile(mDraw.mTracker, templatePath)) {
//                    res = FSDK.CreateTracker(mDraw.mTracker);
//                    if (FSDK.FSDKE_OK != res) {
//                        showErrorAndClose("Error creating tracker", res);
//                    }
//                }
//                resetTrackerParameters();
//
//                setContentView(mPreview); //creates MainActivity contents
//                addContentView(mDraw, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
                // Menu
//                LayoutInflater inflater = (LayoutInflater)this.getSystemService( Context.LAYOUT_INFLATER_SERVICE );
//                View buttons = inflater.inflate(R.layout.bottom_menu, null );
//                buttons.findViewById(R.id.helpButton).setOnClickListener(this);
//                buttons.findViewById(R.id.clearButton).setOnClickListener(this);
//                addContentView(buttons, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
            }
        }
    }
    @Override
    public void onClick(View view) {
        if(CommonVariables.FACE_SERVER) {
            if (view.getId() == R.id.helpButton) {
                showMessage(help_text);
            } else if (view.getId() == R.id.clearButton) {
                AlertDialog.Builder builder = new AlertDialog.Builder(this);
                builder.setMessage("Are you sure to clear the memory?" )
                        .setPositiveButton("Ok", new DialogInterface.OnClickListener() {
                            @Override public void onClick(DialogInterface dialogInterface, int j) {
                                pauseProcessingFrames();
                                FSDK.ClearTracker(mDraw.mTracker);
                                resetTrackerParameters();
                                resumeProcessingFrames();
                            }
                        })
                        .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                            @Override public void onClick(DialogInterface dialogInterface, int j) {
                            }
                        })
                        .setCancelable(false)
                        .show();
            }
        }
    }
    @Override
    protected void onPause() {
        super.onPause();
        if(CommonVariables.FACE_SERVER) {
            pauseProcessingFrames();
            String templatePath = this.getApplicationInfo().dataDir + "/" + database;
            FSDK.SaveTrackerMemoryToFile(mDraw.mTracker, templatePath);
        }
        VisitorRegisterUploadPhotoDialog.getInstance().hide();
        VisitorRegisterSelectPhotoDialog.getInstance().hide();
        AttenderRegisterSelectPhotoDialog.getInstance().hide();
        AttenderRegisterUploadPhotoDialog.getInstance().hide();
    }
    @Override
    protected void onResume() {
        super.onResume();
        if(CommonVariables.FACE_SERVER) {
            if (mIsFailed)
                return;
            resumeProcessingFrames();
        }
    }
    public void showErrorAndClose(String error, int code) {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setMessage(error + ": " + code)
                .setPositiveButton("Ok", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        android.os.Process.killProcess(android.os.Process.myPid());
                    }
                })
                .show();
    }
    public void showMessage(String message) {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setMessage(message)
                .setPositiveButton("Ok", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                    }
                })
                .setCancelable(false)
                .show();
    }
    private void resetTrackerParameters() {
        int errpos[] = new int[1];
        FSDK.SetTrackerMultipleParameters(mDraw.mTracker, "ContinuousVideoFeed=true;FacialFeatureJitterSuppression=0;RecognitionPrecision=0;Threshold=0.996;Threshold2=0.9995;ThresholdFeed=0.97;MemoryLimit=1000;HandleArbitraryRotations=false;DetermineFaceRotationAngle=false;InternalResizeWidth=70;FaceDetectionThreshold=5;", errpos);
        if (errpos[0] != 0) {
            showErrorAndClose("Error setting tracker parameters, position", errpos[0]);
        }
    }
    private void pauseProcessingFrames() {
        mDraw.mStopping = 1;
        for (int i=0; i<100; ++i) {
            if (mDraw.mStopped != 0) break;
            try { Thread.sleep(10); }
            catch (Exception ex) {}
        }
    }
    private void resumeProcessingFrames() {
        mDraw.mStopped = 0;
        mDraw.mStopping = 0;
    }
    @Override
    protected void onStop() {
        super.onStop();
        VisitorRegisterUploadPhotoDialog.getInstance().hide();
        VisitorRegisterSelectPhotoDialog.getInstance().hide();
        AttenderRegisterSelectPhotoDialog.getInstance().hide();
        AttenderRegisterUploadPhotoDialog.getInstance().hide();
        //Config.sqlMap.getDb().close();
//        db.close();
    }
}
class FaceRectangle {
    public int x1, y1, x2, y2;
}
// Draw graphics on top of the video
class ProcessImageAndDrawResults extends View {
    public HTracker mTracker;
    final int MAX_FACES = 5;
    final FaceRectangle[] mFacePositions = new FaceRectangle[MAX_FACES];
    final long[] mIDs = new long[MAX_FACES];
    final Lock faceLock = new ReentrantLock();
    int mTouchedIndex;
    long mTouchedID;
    int mStopping;
    int mStopped;
    Context mContext;
    Paint mPaintGreen, mPaintBlue, mPaintBlueTransparent;
    byte[] mYUVData;
    byte[] mRGBData;
    int mImageWidth, mImageHeight;
    boolean first_frame_saved;
    boolean rotated;
    int GetFaceFrame(FSDK.FSDK_Features Features, FaceRectangle fr)
    {
        if (Features == null || fr == null)
            return FSDK.FSDKE_INVALID_ARGUMENT;
        float u1 = Features.features[0].x;
        float v1 = Features.features[0].y;
        float u2 = Features.features[1].x;
        float v2 = Features.features[1].y;
        float xc = (u1 + u2) / 2;
        float yc = (v1 + v2) / 2;
        int w = (int)Math.pow((u2 - u1) * (u2 - u1) + (v2 - v1) * (v2 - v1), 0.5);
        fr.x1 = (int)(xc - w * 1.6 * 0.9);
        fr.y1 = (int)(yc - w * 1.1 * 0.9);
        fr.x2 = (int)(xc + w * 1.6 * 0.9);
        fr.y2 = (int)(yc + w * 2.1 * 0.9);
        if (fr.x2 - fr.x1 > fr.y2 - fr.y1) {
            fr.x2 = fr.x1 + fr.y2 - fr.y1;
        } else {
            fr.y2 = fr.y1 + fr.x2 - fr.x1;
        }
        return 0;
    }
    public ProcessImageAndDrawResults(Context context) {
        super(context);
        mTouchedIndex = -1;
        mStopping = 0;
        mStopped = 0;
        rotated = false;
        mContext = context;
        mPaintGreen = new Paint();
        mPaintGreen.setStyle(Paint.Style.FILL);
        mPaintGreen.setColor(Color.GREEN);
        mPaintGreen.setTextSize(18 * MainActivity.sDensity);
        mPaintGreen.setTextAlign(Align.CENTER);
        mPaintBlue = new Paint();
        mPaintBlue.setStyle(Paint.Style.FILL);
        mPaintBlue.setColor(Color.BLUE);
        mPaintBlue.setTextSize(18 * MainActivity.sDensity);
        mPaintBlue.setTextAlign(Align.CENTER);
        mPaintBlueTransparent = new Paint();
        mPaintBlueTransparent.setStyle(Paint.Style.STROKE);
        mPaintBlueTransparent.setStrokeWidth(2);
        mPaintBlueTransparent.setColor(Color.BLUE);
        mPaintBlueTransparent.setTextSize(25);
        //mBitmap = null;
        mYUVData = null;
        mRGBData = null;
        first_frame_saved = false;
    }
    @Override
    protected void onDraw(Canvas canvas) {
        if (mStopping == 1) {
            mStopped = 1;
            super.onDraw(canvas);
            return;
        }
        if (mYUVData == null || mTouchedIndex != -1) {
            super.onDraw(canvas);
            return;
        }
        int canvasWidth = canvas.getWidth();
        decodeYUV420SP(mRGBData, mYUVData, mImageWidth, mImageHeight);
        FSDK.HImage Image = new FSDK.HImage();
        FSDK.FSDK_IMAGEMODE imagemode = new FSDK.FSDK_IMAGEMODE();
        imagemode.mode = FSDK.FSDK_IMAGEMODE.FSDK_IMAGE_COLOR_24BIT;
        FSDK.LoadImageFromBuffer(Image, mRGBData, mImageWidth, mImageHeight, mImageWidth*3, imagemode);
        FSDK.MirrorImage(Image, false);
        FSDK.HImage RotatedImage = new FSDK.HImage();
        FSDK.CreateEmptyImage(RotatedImage);
        int ImageWidth = mImageWidth;
        if (rotated) {
            ImageWidth = mImageHeight;
            FSDK.RotateImage90(Image, -1, RotatedImage);
        } else {
            FSDK.CopyImage(Image, RotatedImage);
        }
//        FSDK.TFacePosition fp11 = new FSDK.TFacePosition();
//        FSDK.DetectFace(RotatedImage, fp11);
        FSDK.FSDK_FaceTemplate face = new FSDK.FSDK_FaceTemplate();
        int result = FSDK.GetFaceTemplate(RotatedImage, face);
        if (result == FSDK.FSDKE_OK) {
        }
        String surveillancePhotoName11 = "/storage/sdcard1/"+System.currentTimeMillis()+".jpg";
        FSDK.SaveImageToFile(Image, surveillancePhotoName11);
        FSDK.FreeImage(Image);
        long IDs[] = new long[MAX_FACES];
        long face_count[] = new long[1];
        FSDK.FeedFrame(mTracker, 0, RotatedImage, face_count, IDs);
        System.out.println("face_count="+face_count[0]+", mImageWidth="+mImageWidth+", mImageHeight="+mImageHeight);
        faceLock.lock();
        for (int i=0; i<MAX_FACES; ++i) {
            mFacePositions[i] = new FaceRectangle();
            mFacePositions[i].x1 = 0;
            mFacePositions[i].y1 = 0;
            mFacePositions[i].x2 = 0;
            mFacePositions[i].y2 = 0;
            mIDs[i] = IDs[i];
        }
        float ratio = (canvasWidth * 1.0f) / ImageWidth;
        for (int i = 0; i < (int)face_count[0]; ++i) {
            FSDK.FSDK_Features Eyes = new FSDK.FSDK_Features();
            FSDK.GetTrackerEyes(mTracker, 0, mIDs[i], Eyes);
            GetFaceFrame(Eyes, mFacePositions[i]);
            mFacePositions[i].x1 *= ratio;
            mFacePositions[i].y1 *= ratio;
            mFacePositions[i].x2 *= ratio;
            mFacePositions[i].y2 *= ratio;
        }
        if ((int)face_count[0] > 0) {
            FSDK.HImage img2 = new FSDK.HImage();
            FSDK.CreateEmptyImage(img2);
            FSDK.TFacePosition fp = new FSDK.TFacePosition();
            FSDK.DetectFace(RotatedImage, fp);
            int x1 = (int)(fp.xc - 1.2*fp.w/2);
            int y1 = (int)(fp.yc - 1.4*fp.w/2);
            int x2 = (int)(fp.xc + 1.2*fp.w/2);
            int y2 = (int)(fp.yc + 1.4*fp.w/2);
            FSDK.CopyRect(RotatedImage, x1, y1, x2, y2, img2);
            int maxWidth = 337;
            int maxHeight = 450;
            FSDK.ResizeImage(img2, Math.max((maxWidth+0.4)/(x2-x1+1), (maxHeight+0.4)/(y2-y1+1)), RotatedImage);
            System.out.println("face_count="+face_count[0]);
            String surveillancePhotoName = MainActivity.getInstance().getFilesDir().getAbsolutePath()+System.currentTimeMillis()+".jpg";
            FSDK.SaveImageToFile(img2, surveillancePhotoName);
            List bitmapList = new ArrayList();
            for (int i = 0; i < 1; i++) {
                NativeImg nativeImg = new NativeImg();
                nativeImg.image = FileUtil.readFile(new File(surveillancePhotoName));
                nativeImg.size = nativeImg.image.length;
                SurveillanceQueryItem surveillanceQueryItem = new SurveillanceQueryItem();
                surveillanceQueryItem.setNativeImg(nativeImg);
                nativeImg.st_track_id = 1;
                surveillanceQueryItem.setStTrackId(nativeImg.st_track_id);
                BitmapFactory.Options options = new BitmapFactory.Options();
                options.inMutable = true;
                Bitmap bmp = BitmapFactory.decodeByteArray(nativeImg.image, 0, nativeImg.image.length, options);
                Canvas canvas1 = new Canvas(bmp);
                surveillanceQueryItem.setBitmap(bmp);
                surveillanceQueryItem.setWidth("100");
                surveillanceQueryItem.setHeight("100");
                surveillanceQueryItem.setRegisterOrCheckIn(CommonVariables.Surveillance.OFFLINE_SURVEILLANCE_ITEM_TYPE);
                surveillanceQueryItem.setCreateTime(new Date());
                bitmapList.add(surveillanceQueryItem);
                if (BaseApplication.getInstance().networkAvailable()) {
                    SurveillanceMng.getInstance().addBitmap(bitmapList, nativeImg.image, 0, CommonVariables.Camera.IN+"", nativeImg.image);
                } else {
                    SurveillanceMng.getInstance().addOfflineBitmap(bitmapList, nativeImg.image, CommonVariables.Camera.IN+"");
                }
            }
        }
        FSDK.FreeImage(RotatedImage);
        faceLock.unlock();
        int shift = (int)(22 * MainActivity.sDensity);
        for (int i=0; i<face_count[0]; ++i) {
            canvas.drawRect(mFacePositions[i].x1, mFacePositions[i].y1, mFacePositions[i].x2, mFacePositions[i].y2, mPaintBlueTransparent);
            boolean named = false;
            if (IDs[i] != -1) {
                String names[] = new String[1];
                FSDK.GetAllNames(mTracker, IDs[i], names, 1024);
                if (names[0] != null && names[0].length() > 0) {
                    canvas.drawText(names[0], (mFacePositions[i].x1+mFacePositions[i].x2)/2, mFacePositions[i].y2+shift, mPaintBlue);
                    named = true;
                }
            }
            if (!named) {
                canvas.drawText("Tap to name", (mFacePositions[i].x1+mFacePositions[i].x2)/2, mFacePositions[i].y2+shift, mPaintGreen);
            }
        }
        super.onDraw(canvas);
    } // end onDraw method
    @Override
    public boolean onTouchEvent(MotionEvent event) { //NOTE: the method can be implemented in Preview class
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                int x = (int)event.getX();
                int y = (int)event.getY();
                faceLock.lock();
                FaceRectangle rects[] = new FaceRectangle[MAX_FACES];
                long IDs[] = new long[MAX_FACES];
                for (int i=0; i<MAX_FACES; ++i) {
                    rects[i] = new FaceRectangle();
                    if(rects[i] == null) {
                        faceLock.unlock();
                        return true;
                    }
                    rects[i].x1 = mFacePositions[i].x1;
                    rects[i].y1 = mFacePositions[i].y1;
                    rects[i].x2 = mFacePositions[i].x2;
                    rects[i].y2 = mFacePositions[i].y2;
                    IDs[i] = mIDs[i];
                }
                faceLock.unlock();
                for (int i=0; i<MAX_FACES; ++i) {
                    if (rects[i] != null && rects[i].x1 <= x && x <= rects[i].x2 && rects[i].y1 <= y && y <= rects[i].y2 + 30) {
                        mTouchedID = IDs[i];
                        mTouchedIndex = i;
                        // requesting name on tapping the face
                        final EditText input = new EditText(mContext);
                        AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
                        builder.setMessage("Enter person's name" )
                                .setView(input)
                                .setPositiveButton("Ok", new DialogInterface.OnClickListener() {
                                    @Override public void onClick(DialogInterface dialogInterface, int j) {
                                        FSDK.LockID(mTracker, mTouchedID);
                                        FSDK.SetName(mTracker, mTouchedID, input.getText().toString());
                                        FSDK.UnlockID(mTracker, mTouchedID);
                                        mTouchedIndex = -1;
                                    }
                                })
                                .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                                    @Override public void onClick(DialogInterface dialogInterface, int j) {
                                        mTouchedIndex = -1;
                                    }
                                })
                                .setCancelable(false) // cancel with button only
                                .show();
                        break;
                    }
                }
        }
        return true;
    }
    static public void decodeYUV420SP(byte[] rgb, byte[] yuv420sp, int width, int height) {
        final int frameSize = width * height;
        int yp = 0;
        for (int j = 0; j < height; j++) {
            int uvp = frameSize + (j >> 1) * width, u = 0, v = 0;
            for (int i = 0; i < width; i++) {
                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;
                rgb[3*yp] = (byte) ((r >> 10) & 0xff);
                rgb[3*yp+1] = (byte) ((g >> 10) & 0xff);
                rgb[3*yp+2] = (byte) ((b >> 10) & 0xff);
                ++yp;
            }
        }
    }
} // end of ProcessImageAndDrawResults class
// Show video from camera and pass frames to ProcessImageAndDraw class
class Preview extends SurfaceView implements SurfaceHolder.Callback {
    Context mContext;
    SurfaceHolder mHolder;
    Camera mCamera;
    ProcessImageAndDrawResults mDraw;
    boolean mFinished;
    Preview(Context context, ProcessImageAndDrawResults draw) {
        super(context);
        mContext = context;
        mDraw = draw;
        //Install a SurfaceHolder.Callback so we get notified when the underlying surface is created and destroyed.
        mHolder = getHolder();
        mHolder.addCallback(this);
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }
    //SurfaceView callback
    public void surfaceCreated(SurfaceHolder holder) {
        mFinished = false;
        // Find the ID of the camera
        int cameraId = 0;
        boolean frontCameraFound = false;
        Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
        for (int i = 0; i < Camera.getNumberOfCameras(); i++) {
            Camera.getCameraInfo(i, cameraInfo);
            //if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK)
            if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
                cameraId = i;
                frontCameraFound = true;
            }
        }
        if (frontCameraFound) {
            mCamera = Camera.open(cameraId);
        } else {
            mCamera = Camera.open();
        }
        try {
            mCamera.setPreviewDisplay(holder);
            // Preview callback used whenever new viewfinder frame is available
            mCamera.setPreviewCallback(new PreviewCallback() {
                public void onPreviewFrame(byte[] data, Camera camera) {
                    if ( (mDraw == null) || mFinished )
                        return;
                    if (mDraw.mYUVData == null) {
                        // Initialize the draw-on-top companion
                        Camera.Parameters params = camera.getParameters();
                        mDraw.mImageWidth = params.getPreviewSize().width;
                        mDraw.mImageHeight = params.getPreviewSize().height;
                        mDraw.mRGBData = new byte[3 * mDraw.mImageWidth * mDraw.mImageHeight];
                        mDraw.mYUVData = new byte[data.length];
                    }
                    // Pass YUV data to draw-on-top companion
                    System.arraycopy(data, 0, mDraw.mYUVData, 0, data.length);
                    mDraw.invalidate();
                }
            });
        }
        catch (Exception exception) {
            AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
            builder.setMessage("Cannot open camera" )
                    .setPositiveButton("Ok", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialogInterface, int i) {
                            android.os.Process.killProcess(android.os.Process.myPid());
                        }
                    })
                    .show();
            if (mCamera != null) {
                mCamera.release();
                mCamera = null;
            }
        }
    }
    //SurfaceView callback
    public void surfaceDestroyed(SurfaceHolder holder) {
        // Surface will be destroyed when we return, so stop the preview.
        // Because the CameraDevice object is not a shared resource, it's very
        // important to release it when the activity is paused.
        mFinished = true;
        if (mCamera != null) {
            mCamera.setPreviewCallback(null);
            mCamera.stopPreview();
            mCamera.release();
            mCamera = null;
        }
    }
    //SurfaceView callback, configuring camera
    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
        if (mCamera == null) return;
        // Now that the size is known, set up the camera parameters and begin
        // the preview.
        Camera.Parameters parameters = mCamera.getParameters();
        //Keep uncommented to work correctly on phones:
        //This is an undocumented although widely known feature
      /**/
        if (this.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE) {
            parameters.set("orientation", "portrait");
            mCamera.setDisplayOrientation(90); // For Android 2.2 and above
            mDraw.rotated = true;
        } else {
            parameters.set("orientation", "landscape");
            mCamera.setDisplayOrientation(0); // For Android 2.2 and above
        }
      /**/
        // choose preview size closer to 640x480 for optimal performance
        List<Size> supportedSizes = parameters.getSupportedPreviewSizes();
        int width = 0;
        int height = 0;
        for (Size s: supportedSizes) {
            if ((width - 640)*(width - 640) + (height - 480)*(height - 480) >
                    (s.width - 640)*(s.width - 640) + (s.height - 480)*(s.height - 480)) {
                width = s.width;
                height = s.height;
            }
        }
        //try to set preferred parameters
        try {
            if (width*height > 0) {
                parameters.setPreviewSize(width, height);
            }
            //parameters.setPreviewFrameRate(10);
            parameters.setSceneMode(Camera.Parameters.SCENE_MODE_PORTRAIT);
            parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
            mCamera.setParameters(parameters);
        } catch (Exception ex) {
        }
        mCamera.startPreview();
        parameters = mCamera.getParameters();
        Camera.Size previewSize = parameters.getPreviewSize();
        makeResizeForCameraAspect(1.0f / ((1.0f * previewSize.width) / previewSize.height));
    }
    private void makeResizeForCameraAspect(float cameraAspectRatio){
        LayoutParams layoutParams = this.getLayoutParams();
        int matchParentWidth = this.getWidth();
        int newHeight = (int)(matchParentWidth/cameraAspectRatio);
        if (newHeight != layoutParams.height) {
            layoutParams.height = newHeight;
            layoutParams.width = matchParentWidth;
            this.setLayoutParams(layoutParams);
            this.invalidate();
        }
    }
} // end of Preview class