import com.enqualcomm.support.LocationClient;
import com.enqualcomm.support.R;
import com.enqualcomm.support.bean.Runtime;
+import com.enqualcomm.support.bean.StringMessage;
import com.enqualcomm.support.service.base.AbstractInvokeHandlerService;
import com.enqualcomm.support.utils.AlarmHelper;
import com.enqualcomm.support.utils.Connection;
import com.enqualcomm.support.utils.ICLogger;
import com.enqualcomm.support.utils.Util;
import com.enqualcomm.support.utils.VibrateUtil;
+import com.ic.protocols.protocolAPIHelper;
import java.lang.ref.WeakReference;
import static java.lang.Thread.sleep;
-public class AntiMonitorService extends AbstractInvokeHandlerService {
+public class AntiMonitorService extends AbstractInvokeHandlerService implements InputEventReader.InputEventReceiver {
private static final String TAG = "AntiMonitorService";
Runtime mRuntime;
Connection mConnection;
-
+ private InputEventReader m_inputEventReader=null;
private SensorManager mSensorManager;
//current_anti_status == 2 表示表带 锁定 , ==12 表示表带非法解锁
//current_anti_status == 0 表示佩戴 ==10 表示脱腕
private Handler mHandler = null;
PowerManager.WakeLock mWakeLock = null;
+ @Override
+ public void onInputEventRecevied(int type, int event) {
+ if(type== InputEventReader.EVENT_TYPE_CUT && event == InputEventReader.EVENT_FALLOFF){
+ send_fall_off_event();
+ }
+ }
+
+ private void send_fall_off_event(){
+ mRuntime.setAlarmType(Runtime.AlarmType.ALARM_FALL);
+ StringMessage alarmmsg=protocolAPIHelper.getWarningMSG(mRuntime);
+ Deliver.sendLocationMSG(alarmmsg);
+ ICLogger.i(" send fall off event !");
+ }
private static class InnerHandler extends Handler {
// mWakeLock = mPowerManager.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, AntiMonitorService.class.getSimpleName());
mWakeLock = mPowerManager.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, AntiMonitorService.class.getSimpleName());
}
+
+ m_inputEventReader=new InputEventReader(this);
}
private void play_notify() {
--- /dev/null
+package com.enqualcomm.support.service;
+
+import com.enqualcomm.support.utils.ICLogger;
+import com.enqualcomm.support.utils.ThreadPool;
+import com.enqualcomm.support.utils.Util;
+
+import java.io.FileInputStream;
+
+public class InputEventReader {
+ public static final int EVENT_TYPE_ANTI=0;
+ public static final int EVENT_TYPE_CUT=0;
+ public static final int EVENT_ANTI_OFF=10;
+ public static final int EVENT_WEARED=1;
+ public static final int EVENT_CUT_OFF=12;
+ public static final int EVENT_LOCKED=2;
+ public static final int EVENT_FALLOFF=3;
+
+
+ /***
+ *循环读取设备的name 匹配对应的设备名,确定是否制定设备
+ * /sys/class/input/input0/name
+ * /sys/class/input/input1/name
+ * ...
+ * /sys/class/input/inputX/name
+ */
+ private static final String SYS_INPUT_BASE="/sys/class/input/input";
+ private static final String EVENT_PATH_BASE="/dev/input/event";
+ /***
+ * 读取/sys/class/input/inputX/name 对应的名称 符合 antiDevNames 即是 佩戴检测事件节点
+ * 检测对应 /dev/input/eventX 节点可以获取佩戴事件
+ */
+ private static final String antiDevNames= Util.getSystemProperties("persist.sys.AntiInputName","");
+ /***
+ * 读取/sys/class/input/inputX/name 对应的名称 符合 cutDevNames 即是 剪断检测事件节点
+ * 检测对应 /dev/input/eventX 节点可以获取剪断事件
+ */
+ private static final String cutDevNames= Util.getSystemProperties("persist.sys.ic.falldev","");
+
+
+ private String getInputDevNameByID(int id){
+ byte buffer[]=new byte[255];
+ String ret="";
+ String input=SYS_INPUT_BASE+id+"/name";
+ try {
+ FileInputStream fis=new FileInputStream(input);
+ int len=fis.read(buffer);
+ if (len > 0){
+ ret=new String(buffer,0,len);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ ICLogger.i("getInputDevNameByID "+input+ " "+ret);
+ return ret.trim();
+ }
+
+ private int get_DevID_By_Name(String name){
+ int devid=-1;
+ for ( int i=0;i< 10;i++){
+ if(getInputDevNameByID(i).startsWith(name.trim())) {
+ devid = i;
+ break;
+ }
+ }
+ return devid;
+ }
+
+
+
+ public int getEventFromData(boolean isAntiEvent,byte[] eventMsgs){
+ /***
+ * 4d3bfc5fd1ab0a0001008e00010000004d3bfc5fd1ab0a0001008e00000000004d3bfc5fd1ab0a000000000000000000
+ *
+ * 4d3bfc5fd1ab0a00 timestamp 8bytes
+ * 0100 eventtype 2bytes
+ * 8e00 eventcode 2bytes
+ * 01000000 value 4bytes
+ * 4d3bfc5fd1ab0a00 timestamp
+ * 0100 eventtype
+ * 8e00 eventcode
+ * 00000000 value
+ * 4d3bfc5fd1ab0a00 timestamp
+ * 0000 eventtype
+ * 0000 eventcode
+ * 00000000 value
+ *
+ * 0001 008e 00000001
+ * 0001 008e 00000000
+ * 0000 0000 00000000
+ */
+ int ret=0;
+ byte int_bytes[]=new byte[4];
+ boolean msg_printted=false;
+ if(eventMsgs.length%16==0){
+ int eventtype,eventvalue;
+ long eventcode;
+ for(int i=0;i<eventMsgs.length/16;i++)
+ {
+ StringBuilder sb=new StringBuilder("Received EventType ");
+ int_bytes[0]=int_bytes[1]=int_bytes[2]=int_bytes[3]=0;
+ int_bytes[3]=eventMsgs[8+i*16];
+ int_bytes[2]=eventMsgs[9+i*16];
+ eventtype=Util.byteArray4ToInt(int_bytes);
+ sb.append(Util.byte2hex(int_bytes));
+ int_bytes[3]=eventMsgs[10+i*16];
+ int_bytes[2]=eventMsgs[11+i*16];
+ eventcode=Util.byteArray4ToInt(int_bytes);
+ sb.append(" EventCode ").append(Util.byte2hex(int_bytes));
+ int_bytes[3]=eventMsgs[12+i*16];
+ int_bytes[2]=eventMsgs[13+i*16];
+ int_bytes[1]=eventMsgs[14+i*16];
+ int_bytes[0]=eventMsgs[15+i*16];
+ eventvalue=Util.byteArray4ToInt(int_bytes);
+ sb.append(" Value ").append(Util.byte2hex(int_bytes));
+ if( eventcode == 0x28 )
+ {
+ if (!msg_printted)
+ {
+ ICLogger.i("read cut Event " + eventMsgs.length+ " "+ Util.bytesToHexString(eventMsgs));
+ }
+ ICLogger.i("Received EventType " + eventtype + " EventCode " + eventcode + " Value " + eventvalue);
+ }
+ if(eventcode==0x28 && eventvalue==1){
+
+ ICLogger.i("Received EventType FALL OFF " );
+ ret=EVENT_FALLOFF;
+ }
+ if(eventtype==1 && eventvalue==1){
+ /***
+ * case 0x8e: //KeyCode AntiOff 脱腕
+ * if(value==1){
+ * #ifdef GPIO_CUTOFF
+ * value= 12;
+ * #else
+ * value= 10;
+ *
+ * #endif
+ * case 0x8d: //KeyCode Wear 佩戴
+ * if(value==1){
+ * #ifdef GPIO_CUTOFF
+ * value=2;
+ * #else
+ * value=0;
+ * #endif
+ */
+ int f=Math.abs((int)eventcode);
+// ICLogger.i(" eventcode "+eventcode+" "+f+" 0x8e "+0x8e+" 0x8d "+0x8d);
+ switch(f){
+ case 0x8e: //KeyCode AntiOff 脱腕
+ if(isAntiEvent){
+ ret=EVENT_ANTI_OFF;
+ }else{
+ ret=EVENT_CUT_OFF;
+ }
+ break;
+ case 0x8d://KeyCode Wear 佩戴
+ if(isAntiEvent){
+ ret=EVENT_WEARED;
+ }else{
+ ret=EVENT_LOCKED;
+ }
+ break;
+ }
+ sb.append(" ret ").append(ret);
+
+ }
+ if( eventcode == 0x28 )
+ {
+ ICLogger.i(sb.toString());
+ }
+ }
+
+ }else{
+ ICLogger.e("Error Input Event Format!");
+ }
+ return ret;
+ }
+ /***
+ * 佩戴检测事件读取线程
+ */
+ private Runnable antiEventThread=new Runnable() {
+ @Override
+ public void run() {
+ ICLogger.i("Enter antiEventThread "+Thread.currentThread().getName()+" "+ antiDevNames);
+ int devid=get_DevID_By_Name(antiDevNames);
+ if (devid>-1){
+
+ try{
+ String antipath=EVENT_PATH_BASE+devid;
+ ICLogger.i("open AntiEventPATH "+antipath);
+ FileInputStream br=new FileInputStream(antipath);
+ byte buf[]=new byte[50];
+ int len=0;
+ while(true){
+ len=br.read(buf);
+ if(len>0) {
+ byte t[]=new byte[len];
+ for(int i=0;i<len;i++)
+ t[i]=buf[i];
+ ICLogger.i("read anti Event " + len+ " "+ Util.bytesToHexString(t));
+ int event=getEventFromData(true,t);
+ if(callback!=null){
+ callback.onInputEventRecevied(EVENT_TYPE_ANTI,event);
+ }
+ }
+ }
+ }catch (Exception e){
+ ICLogger.e(e.getMessage(),e);
+ }
+
+ }else{
+ ICLogger.e("no AntiDev antiEventThread exit! ");
+ }
+ }
+ } ;
+ /***
+ * 剪断检测事件读取线程
+ */
+ private Runnable cutEventThread=new Runnable() {
+ @Override
+ public void run() {
+ ICLogger.i("Enter cutEventThread "+Thread.currentThread().getName() +" "+cutDevNames);
+ int devid=get_DevID_By_Name(cutDevNames);
+ if (devid>-1){
+
+ try{
+ String cutpath=EVENT_PATH_BASE+devid;
+ ICLogger.i("open CutEventPATH "+cutpath);
+ FileInputStream br=new FileInputStream(cutpath);
+ byte buf[]=new byte[50];
+ int len=0;
+ while(true){
+ len=br.read(buf);
+ if(len>0) {
+ byte t[]=new byte[len];
+ for(int i=0;i<len;i++)
+ t[i]=buf[i];
+ // ICLogger.i("read cut Event " + len+ " "+ Util.bytesToHexString(t));
+ int event=getEventFromData(false,t);
+ if(callback!=null){
+ callback.onInputEventRecevied(EVENT_TYPE_CUT,event);
+ }
+ }
+ }
+ }catch (Exception e){
+ ICLogger.e(e.getMessage(),e);
+ }
+
+ }else{
+ ICLogger.e("no CutDev cutEventThread exit! ");
+ }
+ }
+ } ;
+
+ private InputEventReceiver callback=null;
+
+ public InputEventReader(InputEventReceiver ier){
+ callback=ier;
+ // ThreadPool.getInstance().submitThreadPool(antiEventThread);
+ ThreadPool.getInstance().submitThreadPool(cutEventThread);
+
+ }
+
+ public interface InputEventReceiver{
+ void onInputEventRecevied(int type,int event);
+ }
+}
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Enumeration;
private static byte charToByte(char c) {
return (byte) "0123456789ABCDEF".indexOf(c);
}
+
+ public static int byteArray4ToInt(byte[] b) {
+ return b[3] & 0xFF |
+ (b[2] & 0xFF) << 8 |
+ (b[1] & 0xFF) << 16 |
+ (b[0] & 0xFF) << 24;
+ }
+ public static byte[] intToByteArray4(int a) {
+ return new byte[] {
+ (byte) ((a >> 24) & 0xFF),
+ (byte) ((a >> 16) & 0xFF),
+ (byte) ((a >> 8) & 0xFF),
+ (byte) (a & 0xFF)
+ };
+ }
+
+ /**
+ * 将字节数组转为long<br>
+ * 如果input为null,或offset指定的剩余数组长度不足8字节则抛出异常
+ * @param input
+ * @param offset 起始偏移量
+ * @param littleEndian 输入数组是否小端模式
+ * @return
+ */
+ public static long longFrom8Bytes(byte[] input, int offset, boolean littleEndian){
+ if(offset <0 || offset+8>input.length)
+ throw new IllegalArgumentException(String.format("less than 8 bytes from index %d is insufficient for long",offset));
+ long value=0;
+ for(int count=0;count<8;++count){
+ int shift=(littleEndian?count:(7-count))<<3;
+ value |=((long)0xff<< shift) & ((long)input[offset+count] << shift);
+ }
+ return value;
+ }
+
+ /**
+ * 利用 {@link java.nio.ByteBuffer}实现byte[]转long
+ * @param input
+ * @param offset
+ * @param littleEndian 输入数组是否小端模式
+ * @return
+ */
+ public static long bytesToLong(byte[] input, int offset, boolean littleEndian) {
+ if(offset <0 || offset+8>input.length)
+ throw new IllegalArgumentException(String.format("less than 8 bytes from index %d is insufficient for long",offset));
+ ByteBuffer buffer = ByteBuffer.wrap(input,offset,8);
+ if(littleEndian){
+ // ByteBuffer.order(ByteOrder) 方法指定字节序,即大小端模式(BIG_ENDIAN/LITTLE_ENDIAN)
+ // ByteBuffer 默认为大端(BIG_ENDIAN)模式
+ buffer.order(ByteOrder.LITTLE_ENDIAN);
+ }
+ return buffer.getLong();
+ }
}