diff options
author | Wei Hua <whua@google.com> | 2012-08-28 13:46:31 -0700 |
---|---|---|
committer | Wei Hua <whua@google.com> | 2012-08-29 15:23:10 -0700 |
commit | 9c3a7dc466e2f8de02e15030b2b7f4096ba97e5a (patch) | |
tree | 6dc99b2f5c5897637948952d358ccbe0e0017ba9 | |
parent | 83954e853dc1e1a28b2c3efbe1585f188266df02 (diff) | |
download | ml-9c3a7dc466e2f8de02e15030b2b7f4096ba97e5a.tar.gz |
Added Fake location support.
Change-Id: I894a135bf15f6d776f06b5e1c6b59db64ae745c1
5 files changed, 193 insertions, 76 deletions
diff --git a/bordeaux/service/src/android/bordeaux/services/AggregatorManager.java b/bordeaux/service/src/android/bordeaux/services/AggregatorManager.java index 42ccf9f22..c314ee7c0 100644 --- a/bordeaux/service/src/android/bordeaux/services/AggregatorManager.java +++ b/bordeaux/service/src/android/bordeaux/services/AggregatorManager.java @@ -20,15 +20,21 @@ package android.bordeaux.services; import android.bordeaux.services.StringString; import android.content.Context; import android.util.Log; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; -import java.util.ArrayList; class AggregatorManager extends IAggregatorManager.Stub { private final String TAG = "AggregatorMnager"; - private static HashMap<String, Aggregator> sFeatureMap; + // this maps from the aggregator name to the registered aggregator instance + private static HashMap<String, Aggregator> mAggregators = new HashMap<String, Aggregator>(); + // this maps from the feature names to the aggregator that generates the feature + private static HashMap<String, Aggregator> sFeatureMap = new HashMap<String, Aggregator>(); private static AggregatorManager mManager = null; + private String mFakeLocation = null; + private AggregatorManager() { sFeatureMap = new HashMap<String, Aggregator>(); } @@ -50,16 +56,49 @@ class AggregatorManager extends IAggregatorManager.Stub { } public void registerAggregator(Aggregator agg, AggregatorManager m) { + if (mAggregators.get(agg.getClass().getName()) != null) { + // only one instance + throw new RuntimeException("Can't register more than one instance"); + } + mAggregators.put(agg.getClass().getName(), agg); agg.setManager(m); String[] fl = agg.getListOfFeatures(); for ( int i = 0; i< fl.length; i ++) sFeatureMap.put(fl[i], agg); } - + // Start of IAggregatorManager interface public ArrayList<StringString> getData(String dataName) { return getList(getDataMap(dataName)); } + public List<String> getLocationClusters() { + LocationStatsAggregator agg = (LocationStatsAggregator) + mAggregators.get(LocationStatsAggregator.class.getName()); + if (agg == null) return new ArrayList<String> (); + ArrayList<String> clusters = new ArrayList<String>(); + return agg.getClusterNames(); + } + + // Set an empty string "" to disable the fake location + public boolean setFakeLocation(String location) { + LocationStatsAggregator agg = (LocationStatsAggregator) + mAggregators.get(LocationStatsAggregator.class.getName()); + if (agg == null) return false; + agg.setFakeLocation(location); + mFakeLocation = location; + return true; + } + + // Get the current mode, if fake mode return true + public boolean getFakeMode() { + boolean fakeMode = false; + // checking any features that are in the fake mode + if (mFakeLocation != null && mFakeLocation.length() != 0) + fakeMode = true; + return fakeMode; + } + // End of IAggregatorManger interface + public Map<String, String> getDataMap(String dataName) { if (sFeatureMap.get(dataName) != null) return sFeatureMap.get(dataName).getFeatureValue(dataName); diff --git a/bordeaux/service/src/android/bordeaux/services/BordeauxAggregatorManager.java b/bordeaux/service/src/android/bordeaux/services/BordeauxAggregatorManager.java index 7e2346f2d..659e84799 100644 --- a/bordeaux/service/src/android/bordeaux/services/BordeauxAggregatorManager.java +++ b/bordeaux/service/src/android/bordeaux/services/BordeauxAggregatorManager.java @@ -61,6 +61,39 @@ public class BordeauxAggregatorManager { } } + public List<String> getLocationClusters() { + if (!retrieveAggregatorManager()) + throw new RuntimeException(AggregatorManager_NOTAVAILABLE); + try { + return mAggregatorManager.getLocationClusters(); + } catch (RemoteException e) { + Log.e(TAG,"Error getting location clusters"); + throw new RuntimeException(AggregatorManager_NOTAVAILABLE); + } + } + + public boolean setFakeLocation(final String name) { + if (!retrieveAggregatorManager()) + throw new RuntimeException(AggregatorManager_NOTAVAILABLE); + try { + return mAggregatorManager.setFakeLocation(name); + } catch (RemoteException e) { + Log.e(TAG,"Error setting fake location:" + name); + throw new RuntimeException(AggregatorManager_NOTAVAILABLE); + } + } + + public boolean getFakeMode() { + if (!retrieveAggregatorManager()) + throw new RuntimeException(AggregatorManager_NOTAVAILABLE); + try { + return mAggregatorManager.getFakeMode(); + } catch (RemoteException e) { + Log.e(TAG,"Error getting fake mode"); + throw new RuntimeException(AggregatorManager_NOTAVAILABLE); + } + } + private Map<String, String> getMap(final List<StringString> sample) { HashMap<String, String> map = new HashMap<String, String>(); for (int i =0; i < sample.size(); i++) { diff --git a/bordeaux/service/src/android/bordeaux/services/ClusterManager.java b/bordeaux/service/src/android/bordeaux/services/ClusterManager.java index f6217e328..b5d0b1a20 100644 --- a/bordeaux/service/src/android/bordeaux/services/ClusterManager.java +++ b/bordeaux/service/src/android/bordeaux/services/ClusterManager.java @@ -191,27 +191,29 @@ public class ClusterManager { List<Map<String, String> > allData = mStorage.getAllData(); HashMap<String, Long> histogram = new HashMap<String, Long>(); - mSemanticClusters.clear(); - for (Map<String, String> map : allData) { - String semanticId = map.get(SEMANTIC_ID); - double longitude = Double.valueOf(map.get(SEMANTIC_LONGITUDE)); - double latitude = Double.valueOf(map.get(SEMANTIC_LATITUDE)); - SemanticCluster cluster = new SemanticCluster( - semanticId, longitude, latitude, CONSOLIDATE_INTERVAL); - - histogram.clear(); - for (int i = mFeatureValueStart; i <= mFeatureValueEnd; i++) { - String featureValue = SEMANTIC_COLUMNS[i]; - if (map.containsKey(featureValue)) { - histogram.put(featureValue, Long.valueOf(map.get(featureValue))); + synchronized (mSemanticClusters) { + mSemanticClusters.clear(); + for (Map<String, String> map : allData) { + String semanticId = map.get(SEMANTIC_ID); + double longitude = Double.valueOf(map.get(SEMANTIC_LONGITUDE)); + double latitude = Double.valueOf(map.get(SEMANTIC_LATITUDE)); + SemanticCluster cluster = new SemanticCluster( + semanticId, longitude, latitude, CONSOLIDATE_INTERVAL); + + histogram.clear(); + for (int i = mFeatureValueStart; i <= mFeatureValueEnd; i++) { + String featureValue = SEMANTIC_COLUMNS[i]; + if (map.containsKey(featureValue)) { + histogram.put(featureValue, Long.valueOf(map.get(featureValue))); + } } + cluster.setHistogram(histogram); + + mSemanticClusters.add(cluster); } - cluster.setHistogram(histogram); - mSemanticClusters.add(cluster); + mSemanticClusterCount = mSemanticClusters.size(); } - - mSemanticClusterCount = mSemanticClusters.size(); Log.e(TAG, "load " + mSemanticClusterCount + " semantic clusters."); } @@ -219,76 +221,80 @@ public class ClusterManager { HashMap<String, String> rowFeatures = new HashMap<String, String>(); Log.e(TAG, "save " + mSemanticClusters.size() + " semantic clusters."); - mStorage.removeAllData(); - for (SemanticCluster cluster : mSemanticClusters) { - rowFeatures.clear(); - rowFeatures.put(SEMANTIC_ID, cluster.getSemanticId()); + synchronized (mSemanticClusters) { + mStorage.removeAllData(); + for (SemanticCluster cluster : mSemanticClusters) { + rowFeatures.clear(); + rowFeatures.put(SEMANTIC_ID, cluster.getSemanticId()); - rowFeatures.put(SEMANTIC_LONGITUDE, - String.valueOf(cluster.getCenterLongitude())); - rowFeatures.put(SEMANTIC_LATITUDE, - String.valueOf(cluster.getCenterLatitude())); + rowFeatures.put(SEMANTIC_LONGITUDE, + String.valueOf(cluster.getCenterLongitude())); + rowFeatures.put(SEMANTIC_LATITUDE, + String.valueOf(cluster.getCenterLatitude())); - HashMap<String, Long> histogram = cluster.getHistogram(); - for (Map.Entry<String, Long> entry : histogram.entrySet()) { - rowFeatures.put(entry.getKey(), String.valueOf(entry.getValue())); + HashMap<String, Long> histogram = cluster.getHistogram(); + for (Map.Entry<String, Long> entry : histogram.entrySet()) { + rowFeatures.put(entry.getKey(), String.valueOf(entry.getValue())); + } + mStorage.addData(rowFeatures); } - mStorage.addData(rowFeatures); } } private void updateSemanticClusters() { HashMap<String, ArrayList<BaseCluster> > semanticMap = new HashMap<String, ArrayList<BaseCluster> >(); - for (SemanticCluster cluster : mSemanticClusters) { - String semanticId = cluster.getSemanticId(); - semanticMap.put(cluster.getSemanticId(), new ArrayList<BaseCluster>()); - semanticMap.get(semanticId).add(cluster); - } - - // select candidate location clusters - ArrayList<LocationCluster> candidates = new ArrayList<LocationCluster>(); - for (LocationCluster cluster : mLocClusters) { - if (cluster.passThreshold(SEMANTIC_CLUSTER_THRESHOLD)) { - candidates.add(cluster); + synchronized (mSemanticClusters) { + for (SemanticCluster cluster : mSemanticClusters) { + String semanticId = cluster.getSemanticId(); + semanticMap.put(cluster.getSemanticId(), new ArrayList<BaseCluster>()); + semanticMap.get(semanticId).add(cluster); } - } - // assign each candidate to a semantic cluster - for (LocationCluster candidate : candidates) { - if (candidate.hasSemanticId()) { - // candidate has been assigned to a semantic cluster - continue; + // select candidate location clusters + ArrayList<LocationCluster> candidates = new ArrayList<LocationCluster>(); + for (LocationCluster cluster : mLocClusters) { + if (cluster.passThreshold(SEMANTIC_CLUSTER_THRESHOLD)) { + candidates.add(cluster); + } } - // find the closest semantic cluster - float bestClusterDistance = Float.MAX_VALUE; - SemanticCluster bestCluster = null; - for (SemanticCluster cluster : mSemanticClusters) { - float distance = cluster.distanceToCluster(candidate); - Log.e(TAG, "distance to semantic cluster: " + cluster.getSemanticId()); + // assign each candidate to a semantic cluster + for (LocationCluster candidate : candidates) { + if (candidate.hasSemanticId()) { + // candidate has been assigned to a semantic cluster + continue; + } - if (distance < bestClusterDistance) { - bestClusterDistance = distance; - bestCluster = cluster; + // find the closest semantic cluster + float bestClusterDistance = Float.MAX_VALUE; + SemanticCluster bestCluster = null; + for (SemanticCluster cluster : mSemanticClusters) { + float distance = cluster.distanceToCluster(candidate); + Log.e(TAG, "distance to semantic cluster: " + cluster.getSemanticId()); + + if (distance < bestClusterDistance) { + bestClusterDistance = distance; + bestCluster = cluster; + } } - } - // add the location to the selected cluster - SemanticCluster semanticCluster; - if (bestClusterDistance > SEMANTIC_CLUSTER_RADIUS) { - // if it is far away from all existing clusters, create a new cluster. - bestCluster = new SemanticCluster(candidate, CONSOLIDATE_INTERVAL, - mSemanticClusterCount++); - String id = bestCluster.getSemanticId(); - semanticMap.put(id, new ArrayList<BaseCluster>()); - semanticMap.get(id).add(bestCluster); + // add the location to the selected cluster + SemanticCluster semanticCluster; + if (bestClusterDistance > SEMANTIC_CLUSTER_RADIUS) { + // if it is far away from all existing clusters, create a new cluster. + bestCluster = new SemanticCluster(candidate, CONSOLIDATE_INTERVAL, + mSemanticClusterCount++); + String id = bestCluster.getSemanticId(); + semanticMap.put(id, new ArrayList<BaseCluster>()); + semanticMap.get(id).add(bestCluster); + } + String semanticId = bestCluster.getSemanticId(); + candidate.setSemanticId(semanticId); + semanticMap.get(semanticId).add(candidate); } - String semanticId = bestCluster.getSemanticId(); - candidate.setSemanticId(semanticId); - semanticMap.get(semanticId).add(candidate); + candidates.clear(); } - candidates.clear(); Log.e(TAG, "number of semantic clusters: " + semanticMap.size()); // use candidates semantic cluster @@ -316,12 +322,24 @@ public class ClusterManager { // instead of using the last location, try acquiring the latest location. if (mLastLocation != null) { // TODO: use fast neatest neighbor search speed up location search - for (SemanticCluster cluster: mSemanticClusters) { - if (cluster.distanceToCenter(mLastLocation) < SEMANTIC_CLUSTER_RADIUS) { - return cluster.getSemanticId(); + synchronized (mSemanticClusters) { + for (SemanticCluster cluster: mSemanticClusters) { + if (cluster.distanceToCenter(mLastLocation) < SEMANTIC_CLUSTER_RADIUS) { + return cluster.getSemanticId(); + } } } } return label; } + + public List<String> getClusterNames() { + ArrayList<String> clusters = new ArrayList<String>(); + synchronized (mSemanticClusters) { + for (SemanticCluster cluster: mSemanticClusters) { + clusters.add(cluster.getSemanticId()); + } + } + return clusters; + } } diff --git a/bordeaux/service/src/android/bordeaux/services/IAggregatorManager.aidl b/bordeaux/service/src/android/bordeaux/services/IAggregatorManager.aidl index 65028be41..1b2f06797 100644 --- a/bordeaux/service/src/android/bordeaux/services/IAggregatorManager.aidl +++ b/bordeaux/service/src/android/bordeaux/services/IAggregatorManager.aidl @@ -20,4 +20,11 @@ import android.bordeaux.services.StringString; interface IAggregatorManager { List<StringString> getData(in String dataName); + + // TODO: remove the following interfaces in production + // they are only used for demo purpose + List<String> getLocationClusters(); + // use "" to disable the fake location + boolean setFakeLocation(in String cluster); + boolean getFakeMode(); } diff --git a/bordeaux/service/src/android/bordeaux/services/LocationStatsAggregator.java b/bordeaux/service/src/android/bordeaux/services/LocationStatsAggregator.java index 0c4dddbb5..0c05157c2 100644 --- a/bordeaux/service/src/android/bordeaux/services/LocationStatsAggregator.java +++ b/bordeaux/service/src/android/bordeaux/services/LocationStatsAggregator.java @@ -29,6 +29,7 @@ import android.os.Message; import android.os.Process; import android.util.Log; import java.util.HashMap; +import java.util.List; import java.util.Map; // TODO: add functionality to detect speed (use GPS) when needed @@ -57,6 +58,9 @@ public class LocationStatsAggregator extends Aggregator { private LocationManager mLocationManager; private ClusterManager mClusterManager; + // Fake location, used for testing. + private String mFakeLocation = null; + public LocationStatsAggregator(final Context context) { mLocationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); @@ -82,12 +86,28 @@ public class LocationStatsAggregator extends Aggregator { String location = mClusterManager.getSemanticLocation(); if (!location.equals(UNKNOWN_LOCATION)) { - feature.put(CURRENT_LOCATION, location); + if (mFakeLocation != null) { + feature.put(CURRENT_LOCATION, mFakeLocation); + } else { + feature.put(CURRENT_LOCATION, location); + } } } return (Map) feature; } + public List<String> getClusterNames() { + return mClusterManager.getClusterNames(); + } + + // set a fake location using cluster name. + // Set an empty string "" to disable the fake location + public void setFakeLocation(String name) { + if (name != null && name.length() != 0) + mFakeLocation = name; + else mFakeLocation = null; + } + private void setClusteringThread(Context context) { mClusterManager = new ClusterManager(context); |