/*
* Copyright 2012 The Stanford MobiSocial Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package mobisocial.musubi.nearby.broadcast;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
import mobisocial.musubi.App;
import mobisocial.musubi.model.DbContactAttributes;
import mobisocial.musubi.ui.SettingsActivity;
import mobisocial.musubi.util.Util;
import mobisocial.socialkit.musubi.Musubi;
import mobisocial.socialkit.obj.MemObj;
import org.json.JSONException;
import org.json.JSONObject;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiManager;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
/**
* A persistent service for managing Musubi's long-lived tasks such
* as network connectivity.
*/
public class WifiFingerprintService extends Service {
public static final String TAG = "DungBeetleService";
private Timer updateFingerprintTimer;
private final long UPDATE_INTERVAL = 1000 * 60; // every minute
private Musubi mMusubi;
@Override
public void onCreate() {
mMusubi = App.getMusubi(this);
updateFingerprintTimer = new Timer();
updateFingerprintTimer.scheduleAtFixedRate(new UpdateFingerprint(), 0, UPDATE_INTERVAL);
}
private class UpdateFingerprint extends TimerTask {
public void run() {
SharedPreferences p = getSharedPreferences(SettingsActivity.PREFS_NAME, 0);
boolean wifi_fingerprinting = p.getBoolean(SettingsActivity.PREF_WIFI_FINGERPRINTING, SettingsActivity.PREF_WIFI_FINGERPRINTING_DEFAULT);
if(wifi_fingerprinting) {
//did the fingerprint change enough?
String oldFingerprintString = DbContactAttributes.getDeviceAttribute(
WifiFingerprintService.this,
DbContactAttributes.ATTR_WIFI_FINGERPRINT);
if(oldFingerprintString == null) {
oldFingerprintString = "";
}
Set<String> oldFingerprint = new HashSet<String>(Arrays.asList(oldFingerprintString.split(":")));
WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
List<ScanResult> results = wifi.getScanResults();
Set<String> newFingerprint = new HashSet<String>();
if (results == null) {
return;
}
for (ScanResult result : results) {
newFingerprint.add(Util.MD5(result.SSID));
}
int initialSize = oldFingerprint.size();
//compute intersection of old and new fingerprint
oldFingerprint.retainAll(newFingerprint);
int overlapSize = oldFingerprint.size();
//only update if less than 50% of the old fingerprint is still valid
if(initialSize > 0 && (double)overlapSize / (double)initialSize < .5) {
String fingerprint = Util.computeWifiFingerprint(wifi.getScanResults());
JSONObject loc = new JSONObject();
try {
loc.put(DbContactAttributes.ATTR_WIFI_FINGERPRINT, fingerprint);
} catch (JSONException e) {
// Impossible json exception
}
// XXX killed for now
//mMusubi.getAppFeed().postObj(new MemObj("locUpdate", loc));
//Log.w(TAG, "sending fingerprint");
}
}
}
}
@Override
public void onDestroy() {
// Toast.makeText(this, R.string.stopping, Toast.LENGTH_SHORT).show();
updateFingerprintTimer.cancel();
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
// This is the object that receives interactions from clients. See
// RemoteService for a more complete example.
private final IBinder mBinder = new Binder(){
WifiFingerprintService getService(){
return WifiFingerprintService.this;
}
};
}