summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsaberian <saberian@google.com>2012-06-04 11:19:43 -0700
committersaberian <saberian@google.com>2012-06-04 11:19:43 -0700
commit7b5b77b038b846e8e2d3aaf0d94c206723a83ccf (patch)
tree17e80489dc3b1bb1df853b80e553dffca41671a5
parentb019e89cbea221598c482b05ab68b7660b41aa23 (diff)
downloadml-7b5b77b038b846e8e2d3aaf0d94c206723a83ccf.tar.gz
Adding Bordeaux AggregatorManager
and BordeauxPredictor and SmartApplauncherWidget and logging activity data in protobuff Change-Id: Iddf9d97e27595426d4bc73145c894a0eea84667d Signed-off-by: saberian <saberian@google.com>
-rw-r--r--bordeaux/apps/Android.mk18
-rw-r--r--bordeaux/apps/AppLauncherWidget/Android.mk42
-rw-r--r--bordeaux/apps/AppLauncherWidget/AndroidManifest.xml34
-rw-r--r--bordeaux/apps/AppLauncherWidget/res/drawable/background.xml8
-rw-r--r--bordeaux/apps/AppLauncherWidget/res/drawable/ic_launcher.pngbin0 -> 4147 bytes
-rw-r--r--bordeaux/apps/AppLauncherWidget/res/layout/main.xml13
-rw-r--r--bordeaux/apps/AppLauncherWidget/res/layout/widget.xml85
-rw-r--r--bordeaux/apps/AppLauncherWidget/res/values/strings.xml7
-rw-r--r--bordeaux/apps/AppLauncherWidget/res/xml/widget_info.xml7
-rw-r--r--bordeaux/apps/AppLauncherWidget/src/android/bordeaux/applauncherwidget/AppLauncherWidgetActivity.java13
-rw-r--r--bordeaux/apps/AppLauncherWidget/src/android/bordeaux/applauncherwidget/AppLauncherWidgetProvider.java397
-rw-r--r--bordeaux/apps/AppLauncherWidget/src/android/bordeaux/applauncherwidget/proto/activity_record.proto33
-rw-r--r--bordeaux/learning/Android.mk3
-rw-r--r--bordeaux/learning/predictor_histogram/Android.mk16
-rw-r--r--bordeaux/learning/predictor_histogram/java/android/bordeaux/learning/predictorHist.java82
-rw-r--r--bordeaux/service/Android.mk17
-rw-r--r--bordeaux/service/src/android/bordeaux/services/Aggregator.java28
-rw-r--r--bordeaux/service/src/android/bordeaux/services/AggregatorManager.java81
-rw-r--r--bordeaux/service/src/android/bordeaux/services/BordeauxAggregatorManager.java69
-rw-r--r--bordeaux/service/src/android/bordeaux/services/BordeauxManagerService.java29
-rw-r--r--bordeaux/service/src/android/bordeaux/services/BordeauxPredictor.java105
-rw-r--r--bordeaux/service/src/android/bordeaux/services/BordeauxRanker.java2
-rw-r--r--bordeaux/service/src/android/bordeaux/services/BordeauxService.java20
-rw-r--r--bordeaux/service/src/android/bordeaux/services/BordeauxSessionStorage.java11
-rw-r--r--bordeaux/service/src/android/bordeaux/services/FeatureAssembly.java66
-rw-r--r--bordeaux/service/src/android/bordeaux/services/IAggregatorManager.aidl23
-rw-r--r--bordeaux/service/src/android/bordeaux/services/IBordeauxService.aidl6
-rw-r--r--bordeaux/service/src/android/bordeaux/services/IPredictor.aidl24
-rw-r--r--bordeaux/service/src/android/bordeaux/services/Learning_StochasticLinearRanker.java2
-rw-r--r--bordeaux/service/src/android/bordeaux/services/LocationStatsAggregator.java39
-rw-r--r--bordeaux/service/src/android/bordeaux/services/MotionStatsAggregator.java39
-rw-r--r--bordeaux/service/src/android/bordeaux/services/Predictor.java218
-rw-r--r--bordeaux/service/src/android/bordeaux/services/StringString.aidl3
-rw-r--r--bordeaux/service/src/android/bordeaux/services/StringString.java41
-rw-r--r--bordeaux/service/src/android/bordeaux/services/TimeStatsAggregator.java67
35 files changed, 1639 insertions, 9 deletions
diff --git a/bordeaux/apps/Android.mk b/bordeaux/apps/Android.mk
new file mode 100644
index 000000000..0918da517
--- /dev/null
+++ b/bordeaux/apps/Android.mk
@@ -0,0 +1,18 @@
+# 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.
+#
+
+TOP_LOCAL_PATH:= $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/bordeaux/apps/AppLauncherWidget/Android.mk b/bordeaux/apps/AppLauncherWidget/Android.mk
new file mode 100644
index 000000000..b6af305f2
--- /dev/null
+++ b/bordeaux/apps/AppLauncherWidget/Android.mk
@@ -0,0 +1,42 @@
+# Copyright (C) 2009 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.
+#
+
+TOP_LOCAL_PATH:= $(call my-dir)
+
+# Build activity
+
+LOCAL_PATH:= $(TOP_LOCAL_PATH)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-proto-files-under, src) \
+ $(call all-java-files-under, src)
+
+LOCAL_STATIC_JAVA_LIBRARIES := bordeaux_learners bordeaux_service j2meproto google-common
+
+LOCAL_PROTOC_OPTIMIZE_TYPE := micro
+
+LOCAL_PACKAGE_NAME := App_Launcher_Widget
+LOCAL_CERTIFICATE := platform
+
+LOCAL_PROGUARD_ENABLED := disabled
+
+include $(BUILD_PACKAGE)
+
+# ============================================================
+
+# Also build all of the sub-targets under this one: the shared library.
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/bordeaux/apps/AppLauncherWidget/AndroidManifest.xml b/bordeaux/apps/AppLauncherWidget/AndroidManifest.xml
new file mode 100644
index 000000000..d9d4e9d43
--- /dev/null
+++ b/bordeaux/apps/AppLauncherWidget/AndroidManifest.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.bordeaux.applauncherwidget"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="15" />
+ <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+ <activity
+ android:name=".AppLauncherWidgetActivity"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ <receiver android:name=".AppLauncherWidgetProvider"
+ android:label="Smart App Launcher">
+ <intent-filter>
+ <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
+ <action android:name="android.appwidget.action.APPWIDGET_ENABLED" />
+ <action android:name="android.appwidget.action.APPWIDGET_DISABLED" />
+ <action android:name="android.appwidget.action.ACTION_APPWIDGET_DELETED" />
+ </intent-filter>
+ <meta-data android:name="android.appwidget.provider"
+ android:resource="@xml/widget_info" />
+ </receiver>
+ <service android:name=".AppLauncherWidgetProvider$UpdateService" />
+ <service android:name=".AppLauncherWidgetProvider$GetStatService" />
+ </application>
+</manifest>
diff --git a/bordeaux/apps/AppLauncherWidget/res/drawable/background.xml b/bordeaux/apps/AppLauncherWidget/res/drawable/background.xml
new file mode 100644
index 000000000..44ba71f6d
--- /dev/null
+++ b/bordeaux/apps/AppLauncherWidget/res/drawable/background.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/Corners">
+ <gradient android:startColor="#CC111111" android:endColor="#CC7f7f7f" android:angle="45"/>
+ <padding android:left="4dp" android:top="1dp" android:right="4dp" android:bottom="1dp" />
+ <corners android:radius="4dp" />
+ <stroke android:width="2dp" android:color="#FFAfAfAf"/>
+</shape>
diff --git a/bordeaux/apps/AppLauncherWidget/res/drawable/ic_launcher.png b/bordeaux/apps/AppLauncherWidget/res/drawable/ic_launcher.png
new file mode 100644
index 000000000..8074c4c57
--- /dev/null
+++ b/bordeaux/apps/AppLauncherWidget/res/drawable/ic_launcher.png
Binary files differ
diff --git a/bordeaux/apps/AppLauncherWidget/res/layout/main.xml b/bordeaux/apps/AppLauncherWidget/res/layout/main.xml
new file mode 100644
index 000000000..74699ca83
--- /dev/null
+++ b/bordeaux/apps/AppLauncherWidget/res/layout/main.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:orientation="vertical" >
+
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/hello" />
+
+</LinearLayout>
+
diff --git a/bordeaux/apps/AppLauncherWidget/res/layout/widget.xml b/bordeaux/apps/AppLauncherWidget/res/layout/widget.xml
new file mode 100644
index 000000000..29519c3f9
--- /dev/null
+++ b/bordeaux/apps/AppLauncherWidget/res/layout/widget.xml
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:orientation="horizontal"
+ android:background="@drawable/background"
+ android:padding = "8dp">
+ <LinearLayout
+ android:id="@+id/linearLayout0"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:layout_weight="1">
+ <ImageButton
+ android:id="@+id/button_app0"
+ android:layout_width="match_parent"
+ android:layout_height="52dp"
+ android:background="@android:color/transparent"
+ android:scaleType="fitCenter"/>
+ <TextView
+ android:id="@+id/text_app0"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:singleLine="true"/>
+ </LinearLayout>
+ <LinearLayout
+ android:id="@+id/linearLayout1"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:layout_weight= "1">
+ <ImageButton
+ android:id="@+id/button_app1"
+ android:layout_width="match_parent"
+ android:layout_height="52dp"
+ android:background="@android:color/transparent"
+ android:scaleType="fitCenter"/>
+ <TextView
+ android:id="@+id/text_app1"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:singleLine="true"/>
+ </LinearLayout>
+ <LinearLayout
+ android:id="@+id/linearLayout2"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:layout_weight= "1">
+ <ImageButton
+ android:id="@+id/button_app2"
+ android:layout_width="match_parent"
+ android:layout_height="52dp"
+ android:background="@android:color/transparent"
+ android:scaleType="fitCenter"/>
+ <TextView
+ android:id="@+id/text_app2"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:singleLine="true"/>
+ </LinearLayout>
+ <LinearLayout
+ android:id="@+id/linearLayout3"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:layout_weight= "1">
+ <ImageButton
+ android:id="@+id/button_app3"
+ android:layout_width="match_parent"
+ android:layout_height="52dp"
+ android:background="@android:color/transparent"
+ android:scaleType="fitCenter"/>
+ <TextView
+ android:id="@+id/text_app3"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:singleLine="true"/>
+ </LinearLayout>
+</LinearLayout>
diff --git a/bordeaux/apps/AppLauncherWidget/res/values/strings.xml b/bordeaux/apps/AppLauncherWidget/res/values/strings.xml
new file mode 100644
index 000000000..4414116d2
--- /dev/null
+++ b/bordeaux/apps/AppLauncherWidget/res/values/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+ <string name="hello"> Activity for Smart App Launcher</string>
+ <string name="app_name">Smart App Launcher</string>
+
+</resources>
diff --git a/bordeaux/apps/AppLauncherWidget/res/xml/widget_info.xml b/bordeaux/apps/AppLauncherWidget/res/xml/widget_info.xml
new file mode 100644
index 000000000..67d57c3be
--- /dev/null
+++ b/bordeaux/apps/AppLauncherWidget/res/xml/widget_info.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
+ android:minWidth="296dp"
+ android:minHeight="36dp"
+ android:updatePeriodMillis="1000"
+ android:initialLayout="@layout/widget" >
+</appwidget-provider>
diff --git a/bordeaux/apps/AppLauncherWidget/src/android/bordeaux/applauncherwidget/AppLauncherWidgetActivity.java b/bordeaux/apps/AppLauncherWidget/src/android/bordeaux/applauncherwidget/AppLauncherWidgetActivity.java
new file mode 100644
index 000000000..c75dbed41
--- /dev/null
+++ b/bordeaux/apps/AppLauncherWidget/src/android/bordeaux/applauncherwidget/AppLauncherWidgetActivity.java
@@ -0,0 +1,13 @@
+package android.bordeaux.applauncherwidget;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class AppLauncherWidgetActivity extends Activity {
+ /** Called when the activity is first created. */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.main);
+ }
+}
diff --git a/bordeaux/apps/AppLauncherWidget/src/android/bordeaux/applauncherwidget/AppLauncherWidgetProvider.java b/bordeaux/apps/AppLauncherWidget/src/android/bordeaux/applauncherwidget/AppLauncherWidgetProvider.java
new file mode 100644
index 000000000..60ecb2937
--- /dev/null
+++ b/bordeaux/apps/AppLauncherWidget/src/android/bordeaux/applauncherwidget/AppLauncherWidgetProvider.java
@@ -0,0 +1,397 @@
+package android.bordeaux.applauncherwidget;
+
+import java.util.Arrays;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.Comparator;
+import java.util.ArrayList;
+import java.io.*;
+import android.app.PendingIntent;
+import android.app.Service;
+import android.app.AlarmManager;
+import android.appwidget.AppWidgetManager;
+import android.appwidget.AppWidgetProvider;
+import android.util.Log;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.RemoteViews;
+import android.widget.Button;
+import android.widget.TextView;
+import android.content.Intent;
+import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ApplicationInfo;
+import android.content.ComponentName;
+import android.content.BroadcastReceiver;
+import android.graphics.drawable.Drawable;
+import android.content.IntentFilter;
+import android.graphics.Bitmap;
+import android.graphics.drawable.BitmapDrawable;
+import android.os.IBinder;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.DropBoxManager;
+import com.android.internal.os.PkgUsageStats;
+import com.android.internal.app.IUsageStats;
+// libraries for bordeaux service
+import android.bordeaux.services.BordeauxPredictor;
+import android.bordeaux.services.BordeauxAggregatorManager;
+import android.bordeaux.services.BordeauxManagerService;
+// libraries for using protobuffer
+import com.google.common.io.protocol.ProtoBuf;
+import com.google.common.io.protocol.ProtoBufType;
+import com.google.protobuf.micro.*;
+import android.bordeaux.applauncherwidget.proto.ActivityRecordProto;
+import android.bordeaux.applauncherwidget.proto.ActivityRecordProto.ActivityRecordProtoBuff;
+
+public class AppLauncherWidgetProvider extends AppWidgetProvider {
+ String TAG = "AppLauncherWidgetProvider";
+ final static int STAT_SAMPLING_TIME = 3000; // milliseconds
+ final static int WIDGET_UPDATE_TIME = 8000; // milliseconds
+ // These numbers are low for debugging purpose and should be changed for final version
+ final static String PROTO_FILE_NAME = "ActivityLogProto";
+ final static String PREDICTOR_NAME ="SmartAppLauncher";
+ final static String CURRENT_TIME = "Current Time";
+ final static String CURRENT_LOCATION = "Current Location";
+ final static String CURRENT_MOTION = "Current Motion";
+ final static String EXP_TIME_STRING = "120";
+
+ static private PendingIntent sWidgetUpdateService = null;
+ static private PendingIntent sGetStatService = null;
+ static private AlarmManager sAlarmManager;
+ static PkgUsageStats[] sStatsNew;
+ static PkgUsageStats[] sStatsOld;
+ static PackageManager sPackageManager;
+ static IUsageStats sUsageStatsService;
+ static BordeauxPredictor sPredictor;
+ static BordeauxAggregatorManager sAggregatorManager;
+ static volatile boolean sGetPredictor = false;
+ static volatile boolean sSetPredictor = false;
+ static volatile boolean sNewAppLaunched = false;
+ static boolean sWidgetFirstRun;
+ static boolean sWasScreenOn = true;
+
+ public void onEnabled(Context context) {
+ sWidgetFirstRun = true;
+ sPackageManager = context.getPackageManager();
+ sAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
+ sUsageStatsService = IUsageStats.Stub.asInterface(ServiceManager.getService("usagestats"));
+ if (sUsageStatsService == null) {
+ Log.e(TAG, "Failed to retrieve usagestats service");
+ return;
+ }
+ }
+
+ public void onDisabled(Context context) {
+ sAlarmManager.cancel(sWidgetUpdateService);
+ sAlarmManager.cancel(sGetStatService);
+ }
+
+ public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
+ //Log.i(TAG, "onUpdate widget");
+ setServices(context);
+ }
+
+ public static void setServices(Context context) {
+ Intent i = new Intent(context, UpdateService.class);
+ if (sWidgetUpdateService == null)
+ {
+ sWidgetUpdateService = PendingIntent.getService(context, 0, i,
+ PendingIntent.FLAG_CANCEL_CURRENT);
+ }
+ sAlarmManager.set(AlarmManager.RTC, System.currentTimeMillis(), sWidgetUpdateService);
+ i = new Intent(context, GetStatService.class);
+ if (sGetStatService == null)
+ {
+ sGetStatService = PendingIntent.getService(context, 1, i,
+ PendingIntent.FLAG_CANCEL_CURRENT);
+ }
+ sAlarmManager.set(AlarmManager.RTC, System.currentTimeMillis(), sGetStatService);
+ }
+ //broadcast reciever for screen on/off
+ public static class ScreenReceiver extends BroadcastReceiver {
+ String TAG = "ScreenReceiver";
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
+ if (sWasScreenOn) {
+ //Log.i(TAG,"Screen is off");
+ sAlarmManager.cancel(sWidgetUpdateService);
+ sAlarmManager.cancel(sGetStatService);
+ sWasScreenOn = false;
+ }
+ } else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
+ if (!sWasScreenOn) {
+ //Log.i(TAG,"Screen is on");
+ setServices(context);
+ sWasScreenOn = true;
+ }
+ }
+ }
+ }
+ // Service for updating widget icons
+ public static class UpdateService extends Service {
+ String TAG = "updating Service";
+
+ @Override
+ public void onStart(Intent intent, int startId) {
+ Log.i(TAG,"update widget layout ");
+ //if ((mNewAppLaunched)|| (mWidgetFirstRun)) {
+ RemoteViews updateViews = buildUpdate(this);
+ ComponentName thisWidget = new ComponentName(this, AppLauncherWidgetProvider.class);
+ AppWidgetManager manager = AppWidgetManager.getInstance(this);
+ manager.updateAppWidget(thisWidget, updateViews);
+ sNewAppLaunched = false;
+ sWidgetFirstRun = false;
+ //}
+ sAlarmManager.set(AlarmManager.RTC, System.currentTimeMillis() + WIDGET_UPDATE_TIME,
+ sWidgetUpdateService);
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return null;
+ }
+
+ public RemoteViews buildUpdate(Context context) {
+ final int APP_NUM = 4;
+ ApplicationInfo[] appInfo = new ApplicationInfo[APP_NUM];
+ PendingIntent[] pendingIntent = new PendingIntent[APP_NUM];
+ CharSequence[] labels = new CharSequence[APP_NUM];
+ Bitmap[] icons = new Bitmap[APP_NUM];
+ String[] appList = new String [APP_NUM];
+ RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget);
+ // get the app list from the Bordeaux Service
+ if (!sGetPredictor) {
+ sAggregatorManager = new BordeauxAggregatorManager(this);
+ sPredictor = new BordeauxPredictor(this, PREDICTOR_NAME);
+ sGetPredictor = true;
+ }
+
+ if (!sPredictor.retrievePredictor()) {
+ Log.i(TAG,"Predictor is not availible yet");
+ appList[0] = "com.google.android.gm";
+ appList[1] = "com.google.android.talk";
+ appList[2] = "com.google.android.browser";
+ appList[3] = "com.google.android.deskclock";
+ } else {
+ if (!sSetPredictor) {
+ sPredictor.setParameter("Set Feature", CURRENT_TIME);
+ sPredictor.setParameter("Set Feature", CURRENT_LOCATION);
+ sPredictor.setParameter("Set Feature", CURRENT_MOTION);
+ sPredictor.setParameter("SetExpireTime", EXP_TIME_STRING);
+ //sPredictor.setParameter("UseHistory", "true");
+ sSetPredictor = true;
+ }
+ appList = getSortedAppList(sPredictor, APP_NUM);
+ }
+ // Get intent, icon and label for each app
+ for (int j = 0; j < APP_NUM; j++){
+ try {
+ appInfo[j] = sPackageManager.getApplicationInfo(appList[j],
+ sPackageManager.GET_META_DATA);
+ labels[j] = sPackageManager.getApplicationLabel(appInfo[j]);
+ Intent intent = sPackageManager.getLaunchIntentForPackage(appList[j]);
+ pendingIntent[j] = PendingIntent.getActivity(context, 0, intent, 0);
+ icons[j] = ((BitmapDrawable) sPackageManager
+ .getApplicationIcon(appInfo[j])).getBitmap();
+ } catch (NameNotFoundException e ) {
+ Log.e(TAG,"package name is not found");
+ }
+ }
+ // Set Application names
+ views.setTextViewText(R.id.text_app0, labels[0]);
+ views.setTextViewText(R.id.text_app1, labels[1]);
+ views.setTextViewText(R.id.text_app2, labels[2]);
+ views.setTextViewText(R.id.text_app3, labels[3]);
+ // Set Application Icons
+ views.setImageViewBitmap(R.id.button_app0, icons[0]);
+ views.setImageViewBitmap(R.id.button_app1, icons[1]);
+ views.setImageViewBitmap(R.id.button_app2, icons[2]);
+ views.setImageViewBitmap(R.id.button_app3, icons[3]);
+ // Set Application Intents
+ views.setOnClickPendingIntent(R.id.button_app0, pendingIntent[0]);
+ views.setOnClickPendingIntent(R.id.button_app1, pendingIntent[1]);
+ views.setOnClickPendingIntent(R.id.button_app2, pendingIntent[2]);
+ views.setOnClickPendingIntent(R.id.button_app3, pendingIntent[3]);
+ return views;
+ }
+
+ private String[] getSortedAppList(BordeauxPredictor predictor, int n) {
+ class TComp implements Comparator{
+ public int compare(Object o1, Object o2) {
+ float f1 = ((Float)o1).floatValue();
+ float f2 = ((Float)o2).floatValue();
+ if (f1 < f2)
+ return +1;
+ return -1;
+ }
+ }
+ TreeMap<Float, String> tMap = new TreeMap<Float, String>(new TComp());
+ for (PackageInfo info : sPackageManager.getInstalledPackages(0)) {
+ float f = predictor.getProbability(info.packageName);
+ tMap.put( f, info.packageName);
+ }
+ String[] sortedlist = new String[n];
+ ArrayList<String> sortedApps = new ArrayList<String>(tMap.values());
+ int l = sortedApps.size();
+ int j = 0;
+ for (int i = 0; i < n ; i++) {
+ while ((sPackageManager.getLaunchIntentForPackage(sortedApps.get(j))==null)&(j<l)){
+ j++;
+ if (j>= l)
+ break;
+ }
+ if (j>= l)
+ break;
+ sortedlist[i] = sortedApps.get(j);
+ j++;
+ }
+ return sortedlist;
+ }
+ }
+ // Service for getting stats about application usage.
+ public static class GetStatService extends Service {
+ String TAG = "get stat Service";
+ private class appRecord {
+ String pkgName;
+ int launchNum;
+ float duration;
+ public void set(appRecord r){
+ this.pkgName = r.pkgName;
+ this.launchNum = r.launchNum;
+ this.duration = r.duration;
+ }
+ }
+
+ public GetStatService() {
+ super();
+ try {
+ sStatsOld = sUsageStatsService.getAllPkgUsageStats();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to get usage stats of applications");
+ }
+ }
+
+ @Override
+ public void onStart(Intent intent, int startId) {
+ // registering broadcast reciever for screen on/off
+ IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
+ filter.addAction(Intent.ACTION_SCREEN_OFF);
+ BroadcastReceiver receiver = new ScreenReceiver();
+ this.registerReceiver(receiver, filter);
+
+ try {
+ sStatsNew = sUsageStatsService.getAllPkgUsageStats();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to get usage stats of applications");
+ }
+ ArrayList<appRecord> newLaunchedApps = extractLaunchedApps(sStatsNew, sStatsOld);
+ Log.i(TAG, "Serivce got the stats " + newLaunchedApps.size());
+ if (!sGetPredictor) {
+ sAggregatorManager = new BordeauxAggregatorManager(this);
+ sPredictor = new BordeauxPredictor(this, PREDICTOR_NAME);
+ sGetPredictor = true;
+ }
+
+ if ((newLaunchedApps.size() > 0 ) && sPredictor.retrievePredictor()) {
+ sNewAppLaunched = true;
+ if (!sSetPredictor) {
+ sPredictor.setParameter("Set Feature", CURRENT_TIME);
+ sPredictor.setParameter("Set Feature", CURRENT_LOCATION);
+ sPredictor.setParameter("Set Feature", CURRENT_MOTION);
+ sPredictor.setParameter("SetExpireTime", EXP_TIME_STRING);
+ //sPredictor.setParameter("UseHistory", "true");
+ sSetPredictor = true;
+ }
+ for (int i = 0 ; i < newLaunchedApps.size(); i ++ ) {
+ sPredictor.pushSample(newLaunchedApps.get(i).pkgName);
+ }
+ sStatsOld = (PkgUsageStats[]) sStatsNew.clone();
+ //put activity logs in DropBox
+ putLogsInDropBox(this, newLaunchedApps);
+ // TODO Maybe Wait for sometime and then put the logs in DropBox
+ }
+ sAlarmManager.set(AlarmManager.RTC, System.currentTimeMillis() + STAT_SAMPLING_TIME,
+ sGetStatService);
+ }
+
+ private void putLogsInDropBox(Context con, ArrayList<appRecord> activityList) {
+ // write new activities in protobuffer
+ ActivityRecordProtoBuff activityRecordProto = new ActivityRecordProtoBuff();
+ String feaNum = CURRENT_TIME;
+ String currTime = sAggregatorManager.GetData(feaNum).get(feaNum);
+ feaNum = CURRENT_LOCATION;
+ String currLocation = sAggregatorManager.GetData(feaNum).get(feaNum);
+ feaNum = CURRENT_MOTION;
+ String currMotion = sAggregatorManager.GetData(feaNum).get(feaNum);
+ for (int i = 0 ; i < activityList.size(); i ++ ) {
+ ActivityRecordProtoBuff.activityInfo appInfo =
+ new ActivityRecordProtoBuff.activityInfo();
+ appInfo.setPkgName(activityList.get(i).pkgName);
+ appInfo.setTime(currTime);
+ appInfo.setLocation(currLocation);
+ appInfo.setMotion(currMotion);
+ activityRecordProto.addActivityLog(appInfo);
+ }
+ // SEND TO DropBox
+ DropBoxManager db = (DropBoxManager) con.getSystemService(Context.DROPBOX_SERVICE);
+ try {
+ File file = File.createTempFile(PROTO_FILE_NAME, "proto", con.getFilesDir());
+ FileOutputStream fos = new FileOutputStream(file);
+ CodedOutputStreamMicro cos = CodedOutputStreamMicro.newInstance(fos);
+ activityRecordProto.writeTo(cos);
+ cos.flush();
+ fos.close();
+ db.addFile(PROTO_FILE_NAME, file, 0);
+ } catch (IOException e) {
+ Log.e(TAG, "Couldn't write log file.", e);
+ }
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return null;
+ }
+
+ private ArrayList<appRecord> extractLaunchedApps(PkgUsageStats[] statsNew,
+ PkgUsageStats[] statsOld) {
+ ArrayList<appRecord> tmpRecord = new ArrayList<appRecord>();
+ for (int i = 0; i < statsNew.length; i++) {
+ if ( statsNew[i].launchCount > 0 ) {
+ boolean found = false;
+ String tmpName = statsNew[i].packageName;
+ if (sPackageManager.getLaunchIntentForPackage(tmpName) == null )
+ continue;
+ if (statsOld != null) {
+ for (int j =0; j < statsOld.length; j++) {
+ if (tmpName.equals(statsOld[j].packageName)) {
+ if (statsNew[i].launchCount > statsOld[j].launchCount) {
+ appRecord r = new appRecord();
+ r.pkgName = tmpName;
+ r.launchNum = statsNew[i].launchCount - statsOld[j].launchCount;
+ r.duration = statsNew[i].usageTime - statsOld[j].usageTime;
+ tmpRecord.add(r);
+ }
+ found = true;
+ break;
+ }
+ }
+ }
+ if (!found){
+ appRecord r = new appRecord();
+ r.pkgName = tmpName;
+ r.launchNum = statsNew[i].launchCount;
+ r.duration = statsNew[i].usageTime;
+ tmpRecord.add(r);
+ }
+ }
+ }
+ return tmpRecord;
+ }
+ }
+}
diff --git a/bordeaux/apps/AppLauncherWidget/src/android/bordeaux/applauncherwidget/proto/activity_record.proto b/bordeaux/apps/AppLauncherWidget/src/android/bordeaux/applauncherwidget/proto/activity_record.proto
new file mode 100644
index 000000000..fbd759f31
--- /dev/null
+++ b/bordeaux/apps/AppLauncherWidget/src/android/bordeaux/applauncherwidget/proto/activity_record.proto
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+syntax = "proto2";
+
+//option optimize_for = LITE_RUNTIME;
+//option java_package = "android.bordeaux.protobufdemo.proto";
+option java_outer_classname = "ActivityRecordProto";
+
+package android.bordeaux.applauncherwidget.proto;
+
+message ActivityRecordProtoBuff {
+ message activityInfo {
+ required string pkg_name = 1;
+ required string location = 2;
+ required string time = 3;
+ required string motion = 4;
+ };
+ repeated activityInfo activity_log = 1;
+}
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..b6509ef05 100644
--- a/bordeaux/service/Android.mk
+++ b/bordeaux/service/Android.mk
@@ -1,13 +1,15 @@
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
@@ -15,7 +17,6 @@ LOCAL_STATIC_JAVA_LIBRARIES := bordeaux_learners
LOCAL_PACKAGE_NAME := bordeaux
-LOCAL_SDK_VERSION := current
include $(BUILD_PACKAGE)
@@ -29,13 +30,25 @@ 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/AggregatorManager.java \
+ src/android/bordeaux/services/Predictor.java \
+ src/android/bordeaux/services/Aggregator.java \
+ src/android/bordeaux/services/FeatureAssembly.java \
+ src/android/bordeaux/services/LocationStatsAggregator.java \
+ src/android/bordeaux/services/TimeStatsAggregator.java \
+ src/android/bordeaux/services/MotionStatsAggregator.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 \
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..7c85facf7 100644
--- a/bordeaux/service/src/android/bordeaux/services/BordeauxService.java
+++ b/bordeaux/service/src/android/bordeaux/services/BordeauxService.java
@@ -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);
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
@@ -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);
}
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;
+ }
+}