diff options
author | saberian <saberian@google.com> | 2012-06-05 18:23:53 -0700 |
---|---|---|
committer | saberian <saberian@google.com> | 2012-06-05 18:23:53 -0700 |
commit | 984e52f31d596840cfa51b1238e1c43d2e1918f8 (patch) | |
tree | eac927df7c58672aefab78595f7860431d3f7682 | |
parent | cb4a1963f47f607164b7cfa5591c1223c19a3dec (diff) | |
download | ml-jb-mr1-dev-plus-aosp.tar.gz |
Adding Aggregators and predcitor to the serviceandroid-sdk-support_r11android-cts-4.2_r2android-cts-4.2_r1android-4.2_r1android-4.2.2_r1.2android-4.2.2_r1.1android-4.2.2_r1android-4.2.1_r1.2android-4.2.1_r1.1android-4.2.1_r1tools_r22jb-mr1.1-releasejb-mr1.1-dev-plus-aospjb-mr1.1-devjb-mr1-releasejb-mr1-dev-plus-aospjb-mr1-dev
Android.mk is modified to build a static java for whole service
Change-Id: I25b0f55ce9693efb3c59b209d4f0cf5c07c47fe1
23 files changed, 1008 insertions, 19 deletions
diff --git a/bordeaux/learning/Android.mk b/bordeaux/learning/Android.mk index 86e4209a9..f61259a8d 100644 --- a/bordeaux/learning/Android.mk +++ b/bordeaux/learning/Android.mk @@ -43,7 +43,8 @@ include $(CLEAR_VARS) LOCAL_MODULE_TAGS := samples tests -LOCAL_SRC_FILES :=$(call all-java-files-under, multiclass_pa stochastic_linear_ranker) +LOCAL_SRC_FILES := $(call all-java-files-under, multiclass_pa stochastic_linear_ranker ) \ + $(call all-java-files-under, predictor_histogram) LOCAL_MODULE := bordeaux_learners diff --git a/bordeaux/learning/predictor_histogram/Android.mk b/bordeaux/learning/predictor_histogram/Android.mk new file mode 100644 index 000000000..1c352f1cb --- /dev/null +++ b/bordeaux/learning/predictor_histogram/Android.mk @@ -0,0 +1,16 @@ +# Copyright (C) 2011 The Android Open Source Project +# +# 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. +# + +LOCAL_PATH := $(call my-dir) diff --git a/bordeaux/learning/predictor_histogram/java/android/bordeaux/learning/predictorHist.java b/bordeaux/learning/predictor_histogram/java/android/bordeaux/learning/predictorHist.java new file mode 100644 index 000000000..7924424eb --- /dev/null +++ b/bordeaux/learning/predictor_histogram/java/android/bordeaux/learning/predictorHist.java @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * 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 android.bordeaux.learning; + +import java.util.HashMap; +import java.util.Map; +import android.util.Log; + +/** + * A simple impelentation of histograms with sparse enteries using HashMap. + * User can push examples or extract probabilites from this histogram. + */ +public class predictorHist { + private HashMap<String, Integer> mCountHist; + private int mSampleCount; + String TAG = "PredicrtHist"; + + public predictorHist() { + mCountHist = new HashMap<String, Integer>(); + mSampleCount = 0; + } + + // reset histogram + public void ResetPredictorHist() { + mCountHist.clear(); + mSampleCount = 0; + } + + // getters + public final HashMap<String, Integer> getHist() { + return mCountHist; + } + + public int getHistCounts() { + return mSampleCount; + } + + //setter + public void set(HashMap<String, Integer> hist) { + ResetPredictorHist(); + for (Map.Entry<String, Integer> x : hist.entrySet()) { + mCountHist.put(x.getKey(), x.getValue()); + mSampleCount = mSampleCount + x.getValue(); + } + } + + /** + * pushes a new example to the histogram + */ + public void pushSample( String fs) { + int histValue = 1; + if (mCountHist.get(fs) != null ) + histValue = histValue + mCountHist.get(fs); + mCountHist.put(fs,histValue); + mSampleCount++; + } + + /** + * return probabilty of an exmple using the histogram + */ + public float getProbability(String fs) { + float res = 0; + if (mCountHist.get(fs) != null ) + res = ((float) mCountHist.get(fs)) / ((float)mSampleCount); + return res; + } +} diff --git a/bordeaux/service/Android.mk b/bordeaux/service/Android.mk index c49a6d6de..f71bc8583 100644 --- a/bordeaux/service/Android.mk +++ b/bordeaux/service/Android.mk @@ -1,21 +1,24 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) -LOCAL_MODULE_TAGS := samples tests +LOCAL_MODULE_TAGS := optional # Only compile source java files in this apk. LOCAL_SRC_FILES := $(call all-java-files-under, src) LOCAL_SRC_FILES += \ src/android/bordeaux/services/IBordeauxServiceCallback.aidl \ + src/android/bordeaux/services/IAggregatorManager.aidl \ src/android/bordeaux/services/ILearning_MulticlassPA.aidl \ + src/android/bordeaux/services/IPredictor.aidl \ src/android/bordeaux/services/ILearning_StochasticLinearRanker.aidl \ - src/android/bordeaux/services/IBordeauxService.aidl + src/android/bordeaux/services/IBordeauxService.aidl \ LOCAL_STATIC_JAVA_LIBRARIES := bordeaux_learners +LOCAL_JNI_SHARED_LIBRARIES := libbordeaux +LOCAL_REQUIRED_MODULES := libbordeaux LOCAL_PACKAGE_NAME := bordeaux -LOCAL_SDK_VERSION := current include $(BUILD_PACKAGE) @@ -29,13 +32,15 @@ LOCAL_MODULE_TAGS := optional LOCAL_SRC_FILES += \ src/android/bordeaux/services/IntFloat.java \ src/android/bordeaux/services/StringFloat.java \ + src/android/bordeaux/services/StringString.java \ src/android/bordeaux/services/BordeauxClassifier.java \ src/android/bordeaux/services/BordeauxRanker.java \ + src/android/bordeaux/services/BordeauxPredictor.java \ + src/android/bordeaux/services/BordeauxAggregatorManager.java \ src/android/bordeaux/services/BordeauxManagerService.java \ - src/android/bordeaux/services/IBordeauxLearner.java \ - src/android/bordeaux/services/Learning_StochasticLinearRanker.java \ - src/android/bordeaux/services/StochasticLinearRankerWithPrior.java \ src/android/bordeaux/services/IBordeauxServiceCallback.aidl \ + src/android/bordeaux/services/IAggregatorManager.aidl \ + src/android/bordeaux/services/IPredictor.aidl \ src/android/bordeaux/services/ILearning_MulticlassPA.aidl \ src/android/bordeaux/services/ILearning_StochasticLinearRanker.aidl \ src/android/bordeaux/services/IBordeauxService.aidl \ @@ -47,5 +52,29 @@ LOCAL_PROGUARD_ENABLED := disabled include $(BUILD_STATIC_JAVA_LIBRARY) +## Building the whole Bordeaux service +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := optional + +# Only compile source java files in this apk. +LOCAL_SRC_FILES := $(call all-java-files-under, src) +LOCAL_SRC_FILES += \ + src/android/bordeaux/services/IBordeauxServiceCallback.aidl \ + src/android/bordeaux/services/IAggregatorManager.aidl \ + src/android/bordeaux/services/ILearning_MulticlassPA.aidl \ + src/android/bordeaux/services/IPredictor.aidl \ + src/android/bordeaux/services/ILearning_StochasticLinearRanker.aidl \ + src/android/bordeaux/services/IBordeauxService.aidl \ + +LOCAL_STATIC_JAVA_LIBRARIES := bordeaux_learners +LOCAL_JNI_SHARED_LIBRARIES := libbordeaux + +LOCAL_JAVA_RESOURCE_DIRS := res +LOCAL_MODULE := bordeaux_whole_service +LOCAL_PROGUARD_ENABLED := disabled + +include $(BUILD_STATIC_JAVA_LIBRARY) + # Use the folloing include to make our test apk. include $(call all-makefiles-under,$(LOCAL_PATH)) diff --git a/bordeaux/service/src/android/bordeaux/services/Aggregator.java b/bordeaux/service/src/android/bordeaux/services/Aggregator.java new file mode 100644 index 000000000..a5aced04a --- /dev/null +++ b/bordeaux/service/src/android/bordeaux/services/Aggregator.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * 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 android.bordeaux.services; + +import java.util.Map; + +abstract class Aggregator { + protected AggregatorManager mAggregatorManager; + public void setManager(AggregatorManager m) { + mAggregatorManager = m; + } + abstract public String[] getListOfFeatures(); + abstract public Map<String,String> getFeatureValue(String featureName); +} diff --git a/bordeaux/service/src/android/bordeaux/services/AggregatorManager.java b/bordeaux/service/src/android/bordeaux/services/AggregatorManager.java new file mode 100644 index 000000000..42ccf9f22 --- /dev/null +++ b/bordeaux/service/src/android/bordeaux/services/AggregatorManager.java @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * 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 android.bordeaux.services; + + +import android.bordeaux.services.StringString; +import android.content.Context; +import android.util.Log; +import java.util.HashMap; +import java.util.Map; +import java.util.ArrayList; + +class AggregatorManager extends IAggregatorManager.Stub { + private final String TAG = "AggregatorMnager"; + private static HashMap<String, Aggregator> sFeatureMap; + private static AggregatorManager mManager = null; + + private AggregatorManager() { + sFeatureMap = new HashMap<String, Aggregator>(); + } + + public static AggregatorManager getInstance() { + if (mManager == null ) + mManager = new AggregatorManager(); + return mManager; + } + + public String[] getListOfFeatures() { + String[] s = new String[sFeatureMap.size()]; + int i = 0; + for (Map.Entry<String, Aggregator> x : sFeatureMap.entrySet()) { + s[i] = x.getKey(); + i++; + } + return s; + } + + public void registerAggregator(Aggregator agg, AggregatorManager m) { + agg.setManager(m); + String[] fl = agg.getListOfFeatures(); + for ( int i = 0; i< fl.length; i ++) + sFeatureMap.put(fl[i], agg); + } + + public ArrayList<StringString> getData(String dataName) { + return getList(getDataMap(dataName)); + } + + public Map<String, String> getDataMap(String dataName) { + if (sFeatureMap.get(dataName) != null) + return sFeatureMap.get(dataName).getFeatureValue(dataName); + else + Log.e(TAG, "There is no feature called " + dataName); + return null; + } + + private ArrayList<StringString> getList(final Map<String, String> sample) { + ArrayList<StringString> StringString_sample = new ArrayList<StringString>(); + for (Map.Entry<String, String> x : sample.entrySet()) { + StringString v = new StringString(); + v.key = x.getKey(); + v.value = x.getValue(); + StringString_sample.add(v); + } + return StringString_sample; + } +} diff --git a/bordeaux/service/src/android/bordeaux/services/BordeauxAggregatorManager.java b/bordeaux/service/src/android/bordeaux/services/BordeauxAggregatorManager.java new file mode 100644 index 000000000..a26e9cdc6 --- /dev/null +++ b/bordeaux/service/src/android/bordeaux/services/BordeauxAggregatorManager.java @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * 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 android.bordeaux.services; + +import android.bordeaux.services.IAggregatorManager; +import android.bordeaux.services.StringString; +import android.content.Context; +import android.os.RemoteException; +import android.util.Log; +import java.util.List; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +/** AggregatorManger for Learning framework. + */ +public class BordeauxAggregatorManager { + static final String TAG = "BordeauxAggregatorManager"; + static final String AggregatorManager_NOTAVAILABLE = "AggregatorManager not Available"; + private Context mContext; + private IAggregatorManager mAggregatorManager; + + public boolean retrieveAggregatorManager() { + if (mAggregatorManager == null) + mAggregatorManager = BordeauxManagerService.getAggregatorManager(mContext); + if (mAggregatorManager == null) { + Log.e(TAG, AggregatorManager_NOTAVAILABLE); + return false; + } + return true; + } + + public BordeauxAggregatorManager (Context context) { + mContext = context; + mAggregatorManager = BordeauxManagerService.getAggregatorManager(mContext); + } + + public Map<String, String> GetData(final String dataName) { + if (!retrieveAggregatorManager()) + throw new RuntimeException(AggregatorManager_NOTAVAILABLE); + try { + return getMap(mAggregatorManager.getData(dataName)); + } catch (RemoteException e) { + Log.e(TAG,"Exception in Getting " + dataName); + throw new RuntimeException(AggregatorManager_NOTAVAILABLE); + } + } + + private Map<String, String> getMap(final List<StringString> sample) { + HashMap<String, String> m = new HashMap<String, String>(); + for (int i =0; i < sample.size(); i++) + m.put(sample.get(i).key, sample.get(i).value); + return (Map) m; + } +} diff --git a/bordeaux/service/src/android/bordeaux/services/BordeauxManagerService.java b/bordeaux/service/src/android/bordeaux/services/BordeauxManagerService.java index e136ca60a..65ffdda80 100644 --- a/bordeaux/service/src/android/bordeaux/services/BordeauxManagerService.java +++ b/bordeaux/service/src/android/bordeaux/services/BordeauxManagerService.java @@ -44,6 +44,8 @@ public class BordeauxManagerService { static private final String TAG = "BordeauxMangerService"; static private IBordeauxService mService = null; static private ILearning_StochasticLinearRanker mRanker = null; + static private IAggregatorManager mAggregatorManager = null; + static private IPredictor mPredictor = null; static private ILearning_MulticlassPA mClassifier = null; static private boolean mStarted = false; @@ -72,6 +74,33 @@ public class BordeauxManagerService { return mService; } + static public synchronized IAggregatorManager getAggregatorManager(Context context) { + if (mService == null) { + bindServices(context); + return null; + } + try { + mAggregatorManager = IAggregatorManager.Stub.asInterface( + mService.getAggregatorManager()); + } catch (RemoteException e) { + mAggregatorManager = null; + } + return mAggregatorManager; + } + + static public synchronized IPredictor getPredictor(Context context, String name) { + if (mService == null) { + bindServices(context); + return null; + } + try { + mPredictor = IPredictor.Stub.asInterface(mService.getPredictor(name)); + } catch (RemoteException e) { + mPredictor = null; + } + return mPredictor; + } + static public synchronized ILearning_StochasticLinearRanker getRanker(Context context, String name) { if (mService == null) { diff --git a/bordeaux/service/src/android/bordeaux/services/BordeauxPredictor.java b/bordeaux/service/src/android/bordeaux/services/BordeauxPredictor.java new file mode 100644 index 000000000..cd0e57eaf --- /dev/null +++ b/bordeaux/service/src/android/bordeaux/services/BordeauxPredictor.java @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * 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 android.bordeaux.services; + +import android.bordeaux.services.IPredictor; +import android.content.Context; +import android.os.RemoteException; +import android.util.Log; + +import java.util.ArrayList; +import java.util.List; +import java.util.HashMap; +import java.util.Map; + +/** Predictor for the Learning framework. + */ +public class BordeauxPredictor { + static final String TAG = "BordeauxPredictor"; + static final String PREDICTOR_NOTAVAILABLE = "Predictor is not available."; + private Context mContext; + private String mName; + private IPredictor mPredictor; + + public boolean retrievePredictor() { + if (mPredictor == null) + mPredictor = BordeauxManagerService.getPredictor(mContext, mName); + if (mPredictor == null) { + Log.e(TAG, PREDICTOR_NOTAVAILABLE); + return false; + } + return true; + } + + public BordeauxPredictor(Context context) { + mContext = context; + mName = "defaultPredictor"; + mPredictor = BordeauxManagerService.getPredictor(context, mName); + } + + public BordeauxPredictor(Context context, String name) { + mContext = context; + mName = name; + mPredictor = BordeauxManagerService.getPredictor(context, mName); + } + + public boolean reset() { + if (!retrievePredictor()){ + Log.e(TAG, PREDICTOR_NOTAVAILABLE); + return false; + } + try { + mPredictor.ResetPredictor(); + return true; + } catch (RemoteException e) { + } + return false; + } + + public void pushSample(String s) { + if (!retrievePredictor()) + throw new RuntimeException(PREDICTOR_NOTAVAILABLE); + try { + mPredictor.pushNewSample(s); + } catch (RemoteException e) { + Log.e(TAG,"Exception: pushing a new example"); + throw new RuntimeException(PREDICTOR_NOTAVAILABLE); + } + } + + public float getProbability(String s) { + if (!retrievePredictor()) + throw new RuntimeException(PREDICTOR_NOTAVAILABLE); + try { + return mPredictor.getSampleProbability(s); + } catch (RemoteException e) { + Log.e(TAG,"Exception: getting sample probability"); + throw new RuntimeException(PREDICTOR_NOTAVAILABLE); + } + } + + public boolean setParameter(String key, String value) { + if (!retrievePredictor()) + throw new RuntimeException(PREDICTOR_NOTAVAILABLE); + try { + return mPredictor.setPredictorParameter(key, value); + } catch (RemoteException e) { + Log.e(TAG,"Exception: setting predictor parameter"); + throw new RuntimeException(PREDICTOR_NOTAVAILABLE); + } + } +} diff --git a/bordeaux/service/src/android/bordeaux/services/BordeauxRanker.java b/bordeaux/service/src/android/bordeaux/services/BordeauxRanker.java index 1977ce1f9..1ae5fcb62 100644 --- a/bordeaux/service/src/android/bordeaux/services/BordeauxRanker.java +++ b/bordeaux/service/src/android/bordeaux/services/BordeauxRanker.java @@ -132,7 +132,7 @@ public class BordeauxRanker { try { return mRanker.SetModelParameter(key, value); } catch (RemoteException e) { - Log.e(TAG,"Exception: scoring the sample with prior."); + Log.e(TAG,"Exception: Setting Parameter"); throw new RuntimeException(RANKER_NOTAVAILABLE); } } diff --git a/bordeaux/service/src/android/bordeaux/services/BordeauxService.java b/bordeaux/service/src/android/bordeaux/services/BordeauxService.java index 84a6df070..16bb78f2d 100644 --- a/bordeaux/service/src/android/bordeaux/services/BordeauxService.java +++ b/bordeaux/service/src/android/bordeaux/services/BordeauxService.java @@ -39,7 +39,7 @@ import android.widget.Button; import android.widget.TextView; import android.widget.Toast; -import android.bordeaux.R; +//import android.bordeaux.R; import android.util.Log; import java.io.*; @@ -64,12 +64,24 @@ public class BordeauxService extends Service { NotificationManager mNotificationManager; BordeauxSessionManager mSessionManager; + AggregatorManager mAggregatorManager; + TimeStatsAggregator mTimeStatsAggregator; + LocationStatsAggregator mLocationStatsAggregator; + MotionStatsAggregator mMotionStatsAggregator; @Override public void onCreate() { Log.i(TAG, "Bordeaux service created."); - mNotificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE); + //mNotificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE); mSessionManager = new BordeauxSessionManager(this); + mMotionStatsAggregator = new MotionStatsAggregator(); + mLocationStatsAggregator = new LocationStatsAggregator(); + mTimeStatsAggregator = new TimeStatsAggregator(); + mAggregatorManager = AggregatorManager.getInstance(); + mAggregatorManager.registerAggregator(mMotionStatsAggregator, mAggregatorManager); + mAggregatorManager.registerAggregator(mLocationStatsAggregator, mAggregatorManager); + mAggregatorManager.registerAggregator(mTimeStatsAggregator, mAggregatorManager); + //Log.i(TAG, "Bordeaux aggregators were registered"); // Display a notification about us starting. // TODO: don't display the notification after the service is @@ -84,10 +96,10 @@ public class BordeauxService extends Service { mSessionManager.saveSessions(); // Cancel the persistent notification. - mNotificationManager.cancel(R.string.remote_service_started); + //mNotificationManager.cancel(R.string.remote_service_started); // Tell the user we stopped. - Toast.makeText(this, R.string.remote_service_stopped, Toast.LENGTH_SHORT).show(); + //Toast.makeText(this, R.string.remote_service_stopped, Toast.LENGTH_SHORT).show(); // Unregister all callbacks. mCallbacks.kill(); @@ -131,6 +143,14 @@ public class BordeauxService extends Service { return getLearningSession(Learning_StochasticLinearRanker.class, name); } + public IBinder getPredictor(String name) { + return getLearningSession(Predictor.class, name); + } + + public IBinder getAggregatorManager() { + return (IBinder) mAggregatorManager; + } + public void registerCallback(IBordeauxServiceCallback cb) { if (cb != null) mCallbacks.register(cb); } @@ -151,7 +171,7 @@ public class BordeauxService extends Service { * automatically by the system). */ private void showNotification() { - // In this sample, we'll use the same text for the ticker and the expanded notification + /*// In this sample, we'll use the same text for the ticker and the expanded notification CharSequence text = getText(R.string.remote_service_started); // The PendingIntent to launch our activity if the user selects this notification @@ -170,7 +190,7 @@ public class BordeauxService extends Service { Notification notification = builder.getNotification(); // Send the notification. // We use a string id because it is a unique number. We use it later to cancel. - mNotificationManager.notify(R.string.remote_service_started, notification); + mNotificationManager.notify(R.string.remote_service_started, notification); */ } } diff --git a/bordeaux/service/src/android/bordeaux/services/BordeauxSessionStorage.java b/bordeaux/service/src/android/bordeaux/services/BordeauxSessionStorage.java index 89aa370a1..9979d84de 100644 --- a/bordeaux/service/src/android/bordeaux/services/BordeauxSessionStorage.java +++ b/bordeaux/service/src/android/bordeaux/services/BordeauxSessionStorage.java @@ -116,13 +116,18 @@ class BordeauxSessionStorage { Cursor cursor = mDbSessions.query(true, SESSION_TABLE, new String[]{COLUMN_KEY, COLUMN_CLASS, COLUMN_MODEL, COLUMN_TIME}, COLUMN_KEY + "=\"" + key + "\"", null, null, null, null, null); - if (cursor == null) return null; - if (cursor.getCount() == 0) return null; + if ((cursor == null) | (cursor.getCount() == 0)) { + cursor.close(); + return null; + } if (cursor.getCount() > 1) { + cursor.close(); throw new RuntimeException("Unexpected duplication in session table for key:" + key); } cursor.moveToFirst(); - return getSessionFromCursor(cursor); + BordeauxSessionManager.Session s = getSessionFromCursor(cursor); + cursor.close(); + return s; } void getAllSessions(ConcurrentHashMap<String, BordeauxSessionManager.Session> sessions) { diff --git a/bordeaux/service/src/android/bordeaux/services/FeatureAssembly.java b/bordeaux/service/src/android/bordeaux/services/FeatureAssembly.java new file mode 100644 index 000000000..8dae57c65 --- /dev/null +++ b/bordeaux/service/src/android/bordeaux/services/FeatureAssembly.java @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * 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 android.bordeaux.services; + +import android.os.IBinder; +import android.util.Log; +import java.util.HashMap; +import java.util.Map; +import java.util.List; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; +import java.util.Iterator; +import android.bordeaux.services.AggregatorManager; +import android.bordeaux.services.Aggregator; +import java.io.Serializable; + +public class FeatureAssembly { + private static final String TAG = "FeatureAssembly"; + private List<String> mPossibleFeatures; + private HashSet<String> mUseFeatures; + private AggregatorManager mAggregatorManager; + + public FeatureAssembly() { + mAggregatorManager = AggregatorManager.getInstance(); + mPossibleFeatures = Arrays.asList(mAggregatorManager.getListOfFeatures()); + mUseFeatures = new HashSet<String>(); + } + + public boolean registerFeature(String s) { + boolean res = mPossibleFeatures.contains(s); + if (res){ + if (!mUseFeatures.contains(s)) + mUseFeatures.add(s); + } + return res; + } + + public Set<String> getUsedFeatures() { + return (Set) mUseFeatures; + } + + public String augmentFeatureInputString(String s) { + String fs = s; + Iterator itr = mUseFeatures.iterator(); + while(itr.hasNext()) { + String f = (String) itr.next(); + fs = fs + "+" + mAggregatorManager.getDataMap(f).get(f); + } + return fs; + } +} diff --git a/bordeaux/service/src/android/bordeaux/services/IAggregatorManager.aidl b/bordeaux/service/src/android/bordeaux/services/IAggregatorManager.aidl new file mode 100644 index 000000000..65028be41 --- /dev/null +++ b/bordeaux/service/src/android/bordeaux/services/IAggregatorManager.aidl @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * 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 android.bordeaux.services; + +import android.bordeaux.services.StringString; + +interface IAggregatorManager { + List<StringString> getData(in String dataName); +} diff --git a/bordeaux/service/src/android/bordeaux/services/IBordeauxService.aidl b/bordeaux/service/src/android/bordeaux/services/IBordeauxService.aidl index 059d62e66..4aa4f08de 100644 --- a/bordeaux/service/src/android/bordeaux/services/IBordeauxService.aidl +++ b/bordeaux/service/src/android/bordeaux/services/IBordeauxService.aidl @@ -31,6 +31,12 @@ interface IBordeauxService { */ IBinder getClassifier(String name); + /* Request to access AggregatorManager + */ + IBinder getAggregatorManager(); + /* Request a Predictor + */ + IBinder getPredictor(String name); /** * Often you want to allow a service to call back to its clients. * This shows how to do so, by registering a callback interface with diff --git a/bordeaux/service/src/android/bordeaux/services/IPredictor.aidl b/bordeaux/service/src/android/bordeaux/services/IPredictor.aidl new file mode 100644 index 000000000..d2f6036f0 --- /dev/null +++ b/bordeaux/service/src/android/bordeaux/services/IPredictor.aidl @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * 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 android.bordeaux.services; + +interface IPredictor { + boolean setPredictorParameter( in String s, in String f ); + void pushNewSample(in String s); + void ResetPredictor(); + float getSampleProbability(in String s); +} diff --git a/bordeaux/service/src/android/bordeaux/services/Learning_StochasticLinearRanker.java b/bordeaux/service/src/android/bordeaux/services/Learning_StochasticLinearRanker.java index ab51f9464..c648bd2d1 100644 --- a/bordeaux/service/src/android/bordeaux/services/Learning_StochasticLinearRanker.java +++ b/bordeaux/service/src/android/bordeaux/services/Learning_StochasticLinearRanker.java @@ -112,7 +112,6 @@ public class Learning_StochasticLinearRanker extends ILearning_StochasticLinearR objStream.writeObject(model); //return byteStream.toByteArray(); byte[] bytes = byteStream.toByteArray(); - Log.i(TAG, "getModel: " + bytes); return bytes; } catch (IOException e) { throw new RuntimeException("Can't get model"); @@ -128,7 +127,6 @@ public class Learning_StochasticLinearRanker extends ILearning_StochasticLinearR if (mLearningSlRanker == null) mLearningSlRanker = new StochasticLinearRankerWithPrior(); boolean res = mLearningSlRanker.loadModel(model); - Log.i(TAG, "LoadModel: " + modelData); return res; } catch (IOException e) { throw new RuntimeException("Can't load model"); diff --git a/bordeaux/service/src/android/bordeaux/services/LocationStatsAggregator.java b/bordeaux/service/src/android/bordeaux/services/LocationStatsAggregator.java new file mode 100644 index 000000000..6294df8e1 --- /dev/null +++ b/bordeaux/service/src/android/bordeaux/services/LocationStatsAggregator.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * 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 android.bordeaux.services; + +import android.util.Log; +import java.util.HashMap; +import java.util.Map; + +class LocationStatsAggregator extends Aggregator { + final String TAG = "LocationStatsAggregator"; + public static final String CURRENT_LOCATION = "Current Location"; + public String[] getListOfFeatures(){ + String [] list = new String[1]; + list[0] = CURRENT_LOCATION; + return list; + } + public Map<String,String> getFeatureValue(String featureName) { + HashMap<String,String> m = new HashMap<String,String>(); + if (featureName.equals(CURRENT_LOCATION)) + m.put(CURRENT_LOCATION, "Here"); //TODO put location resutls here + else + Log.e(TAG, "There is no Location feature called " + featureName); + return (Map) m; + } +} diff --git a/bordeaux/service/src/android/bordeaux/services/MotionStatsAggregator.java b/bordeaux/service/src/android/bordeaux/services/MotionStatsAggregator.java new file mode 100644 index 000000000..c9344fda8 --- /dev/null +++ b/bordeaux/service/src/android/bordeaux/services/MotionStatsAggregator.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * 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 android.bordeaux.services; + +import android.util.Log; +import java.util.HashMap; +import java.util.Map; + +class MotionStatsAggregator extends Aggregator { + final String TAG = "MotionStatsAggregator"; + public static final String CURRENT_MOTION = "Current Motion"; + public String[] getListOfFeatures(){ + String [] list = new String[1]; + list[0] = CURRENT_MOTION; + return list; + } + public Map<String,String> getFeatureValue(String featureName) { + HashMap<String,String> m = new HashMap<String,String>(); + if (featureName.equals(CURRENT_MOTION)) + m.put(CURRENT_MOTION,"Running"); //TODO maybe use clustering for user motion + else + Log.e(TAG, "There is no motion feature called " + featureName); + return (Map) m; + } +} diff --git a/bordeaux/service/src/android/bordeaux/services/Predictor.java b/bordeaux/service/src/android/bordeaux/services/Predictor.java new file mode 100644 index 000000000..8bfd82e78 --- /dev/null +++ b/bordeaux/service/src/android/bordeaux/services/Predictor.java @@ -0,0 +1,218 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * 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 android.bordeaux.services; + +import android.os.IBinder; +import android.util.Log; +import java.util.HashMap; +import java.util.ArrayList; +import java.util.Map; +import java.util.HashSet; +import java.util.Iterator; +import java.io.Serializable; +import java.io.*; +import java.lang.Boolean; +import android.bordeaux.services.FeatureAssembly; +import android.bordeaux.learning.predictorHist; + +/** + * This is interface to implement Prediction based on histogram that + * uses predictor_histogram from learnerning section + */ +public class Predictor extends IPredictor.Stub + implements IBordeauxLearner { + private ModelChangeCallback modelChangeCallback = null; + private final String TAG = "Predictor"; + private final String SET_EXPIRE_TIME = "SetExpireTime"; + private final String USE_HISTORY = "Use History"; + private final String SET_FEATURE = "Set Feature"; + private long mExpireTime = 3 * 60; + private long mLastSampleTime = 0; + private boolean mUseHistoryFlag = false; + private final String NEW_START = "New Start"; + + static public class Model implements Serializable { + public HashMap<String, Integer> countHistogram = new HashMap<String, Integer>(); + public HashSet<String> usedFeatures = new HashSet<String>(); + public int sampleCounts; + public boolean useHistoryFlag; + public long expireTime; + public long lastSampleTime; + } + + private predictorHist mPredictorHist = new predictorHist(); + private String mLastSample = NEW_START; + public FeatureAssembly mFeatureAssembly = new FeatureAssembly(); + + /** + * Reset the Predictor + */ + public void ResetPredictor(){ + printModel(getPredictionModel()); + mPredictorHist.ResetPredictorHist(); + mUseHistoryFlag = false; + mLastSampleTime = 0; + mLastSample = NEW_START; + mFeatureAssembly = new FeatureAssembly(); + printModel(getPredictionModel()); + if (modelChangeCallback != null) { + modelChangeCallback.modelChanged(this); + } + } + + /** + * Augment input string with buildin features such as time, location + */ + private String buildDataPoint(String sampleName) { + String fs = mFeatureAssembly.augmentFeatureInputString(sampleName); + if (mUseHistoryFlag) { + if (((System.currentTimeMillis()- mLastSampleTime)/1000) > mExpireTime) { + mLastSample = NEW_START; + } + fs = fs + "+" + mLastSample; + } + return fs; + } + + /** + * Input is a sampleName e.g.action name. This input is then augmented with requested build-in + * features such as time and location to create sampleFeatures. The sampleFeatures is then + * pushed to the histogram + */ + public void pushNewSample(String sampleName) { + String sampleFeatures = buildDataPoint(sampleName); + mLastSample = sampleName; + mLastSampleTime = System.currentTimeMillis(); + mPredictorHist.pushSample(sampleFeatures); + if (modelChangeCallback != null) { + modelChangeCallback.modelChanged(this); + } + //printModel(getPredictionModel()); + } + + /** + * return probabilty of an exmple using the histogram + */ + public float getSampleProbability(String sampleName) { + String sampleFeatures = buildDataPoint(sampleName); + return mPredictorHist.getProbability(sampleFeatures); + } + + /** + * Set parameters for 1) using History in probability estimations e.g. consider the last event + * and 2) featureAssembly e.g. time and location. + */ + public boolean setPredictorParameter(String s, String f) { + boolean res = false; + if (s.equals(USE_HISTORY)) { + if (f.equals("true")){ + mUseHistoryFlag = true; + res = true; + } + else if (f.equals("false")) { + mUseHistoryFlag = false; + res = true; + } + } else if (s.equals(SET_EXPIRE_TIME)) { + mExpireTime = Long.valueOf(f); + res = true; + } else if (s.equals(SET_FEATURE)) { + res = mFeatureAssembly.registerFeature(f); + } + if (!res) + Log.e(TAG,"Setting parameter " + s + " with " + f + " is not valid"); + return res; + } + + public Model getPredictionModel() { + Model m = new Model(); + m.countHistogram.putAll(mPredictorHist.getHist()); + m.sampleCounts = mPredictorHist.getHistCounts(); + m.expireTime = mExpireTime; + m.usedFeatures = (HashSet) mFeatureAssembly.getUsedFeatures(); + m.useHistoryFlag = mUseHistoryFlag; + m.lastSampleTime = mLastSampleTime; + return m; + } + + public boolean loadModel(Model m) { + //Log.i(TAG,"on loadModel"); + //printModel(m); + mPredictorHist = new predictorHist(); + mPredictorHist.set(m.countHistogram); + mExpireTime = m.expireTime; + mUseHistoryFlag = m.useHistoryFlag; + mLastSampleTime = m.lastSampleTime; + mFeatureAssembly = new FeatureAssembly(); + boolean res = false; + Iterator itr = m.usedFeatures.iterator(); + while(itr.hasNext()) { + res = res & mFeatureAssembly.registerFeature((String) itr.next()); + } + return res; + } + + public void printModel(Model m) { + Log.i(TAG,"histogram is : " + m.countHistogram.toString()); + Log.i(TAG,"number of counts in histogram is : " + m.sampleCounts); + Log.i(TAG,"ExpireTime time is : " + m.expireTime); + Log.i(TAG,"useHistoryFlag is : " + m.useHistoryFlag); + Log.i(TAG,"used features are : " + m.usedFeatures.toString()); + } + + // Beginning of the IBordeauxLearner Interface implementation + public byte [] getModel() { + Model model = getPredictionModel(); + //Log.i(TAG,"on getModel"); + printModel(model); + try { + ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); + ObjectOutputStream objStream = new ObjectOutputStream(byteStream); + objStream.writeObject(model); + byte[] bytes = byteStream.toByteArray(); + //Log.i(TAG, "getModel: " + bytes); + return bytes; + } catch (IOException e) { + throw new RuntimeException("Can't get model"); + } + } + + public boolean setModel(final byte [] modelData) { + //Log.i(TAG,"on setModel"); + try { + ByteArrayInputStream input = new ByteArrayInputStream(modelData); + ObjectInputStream objStream = new ObjectInputStream(input); + Model model = (Model) objStream.readObject(); + boolean res = loadModel(model); + //Log.i(TAG, "LoadModel: " + modelData); + return res; + } catch (IOException e) { + throw new RuntimeException("Can't load model"); + } catch (ClassNotFoundException e) { + throw new RuntimeException("Learning class not found"); + } + } + + public IBinder getBinder() { + return this; + } + + public void setModelChangeCallback(ModelChangeCallback callback) { + modelChangeCallback = callback; + } + // End of IBordeauxLearner Interface implemenation +} diff --git a/bordeaux/service/src/android/bordeaux/services/StringString.aidl b/bordeaux/service/src/android/bordeaux/services/StringString.aidl new file mode 100644 index 000000000..3cb89b9cf --- /dev/null +++ b/bordeaux/service/src/android/bordeaux/services/StringString.aidl @@ -0,0 +1,3 @@ +package android.bordeaux.services; + +parcelable StringString; diff --git a/bordeaux/service/src/android/bordeaux/services/StringString.java b/bordeaux/service/src/android/bordeaux/services/StringString.java new file mode 100644 index 000000000..109462e9f --- /dev/null +++ b/bordeaux/service/src/android/bordeaux/services/StringString.java @@ -0,0 +1,41 @@ +package android.bordeaux.services; + +import android.os.Parcel; +import android.os.Parcelable; + +public final class StringString implements Parcelable { + public String key; + public String value; + + public static final Parcelable.Creator<StringString> + CREATOR = new Parcelable.Creator<StringString>() { + public StringString createFromParcel(Parcel in) { + return new StringString(in); + } + + public StringString[] newArray(int size) { + return new StringString[size]; + } + }; + + public StringString() { + } + + private StringString(Parcel in) { + readFromParcel(in); + } + + public int describeContents() { + return 0; + } + + public void writeToParcel(Parcel out, int flags) { + out.writeString(key); + out.writeString(value); + } + + public void readFromParcel(Parcel in) { + key = in.readString(); + value = in.readString(); + } +} diff --git a/bordeaux/service/src/android/bordeaux/services/TimeStatsAggregator.java b/bordeaux/service/src/android/bordeaux/services/TimeStatsAggregator.java new file mode 100644 index 000000000..86261890a --- /dev/null +++ b/bordeaux/service/src/android/bordeaux/services/TimeStatsAggregator.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * 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 android.bordeaux.services; + +import java.util.Date; +import android.util.Log; +import java.util.HashMap; +import java.util.Map; + +class TimeStatsAggregator extends Aggregator { + final String TAG = "TimeStatsAggregator"; + public static final String CURRENT_TIME = "Current Time"; + final String EARLY_MORNING = "EarlyMorning"; + final String MORNING = "Morning"; + final String NOON = "Noon"; + final String AFTERNOON = "AfterNoon"; + final String NIGHT = "Night"; + final String LATE_NIGHT = "LateNight"; + + public String[] getListOfFeatures(){ + String [] list = new String[1]; + list[0] = CURRENT_TIME; + return list; + } + + public Map<String,String> getFeatureValue(String featureName) { + HashMap<String,String> m = new HashMap<String,String>(); + if (featureName.equals(CURRENT_TIME)) + m.put(CURRENT_TIME, getCurrentTimeLabel()); + else + Log.e(TAG, "There is no Time feature called " + featureName); + return (Map) m; + } + + private String getCurrentTimeLabel(){ + Date d = new Date(System.currentTimeMillis()); + String t = ""; //TODO maybe learn thresholds + int h = d.getHours(); + if ((h > 5) & (h <= 7) ) + t = EARLY_MORNING; + else if ((h > 7) & (h <= 11) ) + t = MORNING; + else if ((h > 11) & (h <= 15)) + t = NOON; + else if ((h > 15) & (h <= 20)) + t = AFTERNOON; + else if ((h > 20) & (h <= 24)) + t = NIGHT; + else if ((h > 0) & (h <= 5)) + t = LATE_NIGHT; + return t; + } +} |