16b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua/*
26b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua * Copyright (C) 2012 The Android Open Source Project
36b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua *
46b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua * Licensed under the Apache License, Version 2.0 (the "License");
56b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua * you may not use this file except in compliance with the License.
66b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua * You may obtain a copy of the License at
76b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua *
86b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua *      http://www.apache.org/licenses/LICENSE-2.0
96b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua *
106b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua * Unless required by applicable law or agreed to in writing, software
116b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua * distributed under the License is distributed on an "AS IS" BASIS,
126b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua * See the License for the specific language governing permissions and
146b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua * limitations under the License.
156b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua */
166b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua
176b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Huapackage android.bordeaux.services;
186b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua
196b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Huaimport android.app.Activity;
206b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Huaimport android.app.Notification;
216b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Huaimport android.app.NotificationManager;
226b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Huaimport android.app.PendingIntent;
236b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Huaimport android.app.Service;
246b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Huaimport android.content.ComponentName;
256b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Huaimport android.content.Context;
266b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Huaimport android.content.Intent;
271dd8ef56681617db46caec7776c9bf416f01d8ddWei Huaimport android.content.pm.PackageManager;
286b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Huaimport android.content.ServiceConnection;
296b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Huaimport android.os.Bundle;
306b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Huaimport android.os.Handler;
316b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Huaimport android.os.IBinder;
326b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Huaimport android.os.Message;
336b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Huaimport android.os.Process;
346b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Huaimport android.os.RemoteCallbackList;
351dd8ef56681617db46caec7776c9bf416f01d8ddWei Huaimport android.os.RemoteException;
366b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Huaimport android.view.View;
376b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Huaimport android.view.View.OnClickListener;
386b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Huaimport android.widget.Button;
396b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Huaimport android.widget.TextView;
406b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Huaimport android.widget.Toast;
411dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua
42984e52f31d596840cfa51b1238e1c43d2e1918f8saberian//import android.bordeaux.R;
436b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Huaimport android.util.Log;
446b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua
451dd8ef56681617db46caec7776c9bf416f01d8ddWei Huaimport java.io.*;
466b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua
476b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua/**
486b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua * Machine Learning service that runs in a remote process.
496b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua * The application doesn't use this class directly.
506b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua *
516b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua */
526b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Huapublic class BordeauxService extends Service {
536b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua    private final String TAG = "BordeauxService";
546b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua    /**
556b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua     * This is a list of callbacks that have been registered with the
566b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua     * service.
576b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua     * It's a place holder for future communications with all registered
586b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua     * clients.
596b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua     */
606b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua    final RemoteCallbackList<IBordeauxServiceCallback> mCallbacks =
616b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua            new RemoteCallbackList<IBordeauxServiceCallback>();
626b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua
636b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua    int mValue = 0;
646b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua    NotificationManager mNotificationManager;
656b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua
661dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua    BordeauxSessionManager mSessionManager;
67984e52f31d596840cfa51b1238e1c43d2e1918f8saberian    AggregatorManager mAggregatorManager;
68984e52f31d596840cfa51b1238e1c43d2e1918f8saberian    TimeStatsAggregator mTimeStatsAggregator;
69984e52f31d596840cfa51b1238e1c43d2e1918f8saberian    LocationStatsAggregator mLocationStatsAggregator;
70984e52f31d596840cfa51b1238e1c43d2e1918f8saberian    MotionStatsAggregator mMotionStatsAggregator;
716b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua
726b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua    @Override
736b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua    public void onCreate() {
741dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua        Log.i(TAG, "Bordeaux service created.");
75984e52f31d596840cfa51b1238e1c43d2e1918f8saberian        //mNotificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
761dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua        mSessionManager = new BordeauxSessionManager(this);
77984e52f31d596840cfa51b1238e1c43d2e1918f8saberian        mMotionStatsAggregator = new MotionStatsAggregator();
78984e52f31d596840cfa51b1238e1c43d2e1918f8saberian        mLocationStatsAggregator = new LocationStatsAggregator();
79984e52f31d596840cfa51b1238e1c43d2e1918f8saberian        mTimeStatsAggregator = new TimeStatsAggregator();
80984e52f31d596840cfa51b1238e1c43d2e1918f8saberian        mAggregatorManager = AggregatorManager.getInstance();
81984e52f31d596840cfa51b1238e1c43d2e1918f8saberian        mAggregatorManager.registerAggregator(mMotionStatsAggregator, mAggregatorManager);
82984e52f31d596840cfa51b1238e1c43d2e1918f8saberian        mAggregatorManager.registerAggregator(mLocationStatsAggregator, mAggregatorManager);
83984e52f31d596840cfa51b1238e1c43d2e1918f8saberian        mAggregatorManager.registerAggregator(mTimeStatsAggregator, mAggregatorManager);
84984e52f31d596840cfa51b1238e1c43d2e1918f8saberian        //Log.i(TAG, "Bordeaux aggregators were registered");
856b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua
866b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua        // Display a notification about us starting.
876b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua        // TODO: don't display the notification after the service is
886b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua        // automatically started by the system, currently it's useful for
896b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua        // debugging.
906b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua        showNotification();
916b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua    }
926b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua
936b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua    @Override
946b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua    public void onDestroy() {
951dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua        // Save the sessions
961dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua        mSessionManager.saveSessions();
971dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua
986b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua        // Cancel the persistent notification.
99984e52f31d596840cfa51b1238e1c43d2e1918f8saberian        //mNotificationManager.cancel(R.string.remote_service_started);
1006b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua
1016b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua        // Tell the user we stopped.
102984e52f31d596840cfa51b1238e1c43d2e1918f8saberian        //Toast.makeText(this, R.string.remote_service_stopped, Toast.LENGTH_SHORT).show();
1036b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua
1046b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua        // Unregister all callbacks.
1056b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua        mCallbacks.kill();
1061dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua
1071dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua        Log.i(TAG, "Bordeaux service stopped.");
1086b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua    }
1096b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua
1106b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua    @Override
1116b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua    public IBinder onBind(Intent intent) {
1126b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua        // Return the requested interface.
1136b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua        if (IBordeauxService.class.getName().equals(intent.getAction())) {
1146b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua            return mBinder;
1156b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua        }
1166b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua        return null;
1176b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua    }
1186b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua
1191dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua
1206b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua    // The main interface implemented by the service.
1216b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua    private final IBordeauxService.Stub mBinder = new IBordeauxService.Stub() {
1221dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua        private IBinder getLearningSession(Class learnerClass, String name) {
1236b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua            PackageManager pm = getPackageManager();
1246b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua            String uidname = pm.getNameForUid(getCallingUid());
1256b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua            Log.i(TAG,"Name for uid: " + uidname);
1261dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua            BordeauxSessionManager.SessionKey key =
1271dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua                    mSessionManager.getSessionKey(uidname, learnerClass, name);
1281dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua            Log.i(TAG, "request learning session: " + key.value);
1291dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua            try {
1301dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua                IBinder iLearner = mSessionManager.getSessionBinder(learnerClass, key);
1311dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua                return iLearner;
1321dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua            } catch (RuntimeException e) {
1331dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua                Log.e(TAG, "Error getting learning interface" + e);
1341dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua                return null;
1356b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua            }
1361dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua        }
1371dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua
1381dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua        public IBinder getClassifier(String name) {
1391dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua            return getLearningSession(Learning_MulticlassPA.class, name);
1406b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua        }
1416b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua
1426b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua        public IBinder getRanker(String name) {
1431dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua            return getLearningSession(Learning_StochasticLinearRanker.class, name);
1446b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua        }
1456b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua
146984e52f31d596840cfa51b1238e1c43d2e1918f8saberian        public IBinder getPredictor(String name) {
147984e52f31d596840cfa51b1238e1c43d2e1918f8saberian            return getLearningSession(Predictor.class, name);
148984e52f31d596840cfa51b1238e1c43d2e1918f8saberian        }
149984e52f31d596840cfa51b1238e1c43d2e1918f8saberian
150984e52f31d596840cfa51b1238e1c43d2e1918f8saberian        public IBinder getAggregatorManager() {
151984e52f31d596840cfa51b1238e1c43d2e1918f8saberian            return (IBinder) mAggregatorManager;
152984e52f31d596840cfa51b1238e1c43d2e1918f8saberian        }
153984e52f31d596840cfa51b1238e1c43d2e1918f8saberian
1546b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua        public void registerCallback(IBordeauxServiceCallback cb) {
1556b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua            if (cb != null) mCallbacks.register(cb);
1566b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua        }
1576b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua
1586b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua        public void unregisterCallback(IBordeauxServiceCallback cb) {
1596b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua            if (cb != null) mCallbacks.unregister(cb);
1606b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua        }
1616b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua    };
1626b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua
1636b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua    @Override
1646b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua    public void onTaskRemoved(Intent rootIntent) {
1656b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua        Toast.makeText(this, "Task removed: " + rootIntent, Toast.LENGTH_LONG).show();
1666b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua    }
1676b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua
1686b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua    /**
1696b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua     * Show a notification while this service is running.
1706b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua     * TODO: remove the code after production (when service is loaded
1716b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua     * automatically by the system).
1726b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua     */
1736b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua    private void showNotification() {
174984e52f31d596840cfa51b1238e1c43d2e1918f8saberian        /*// In this sample, we'll use the same text for the ticker and the expanded notification
1756b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua        CharSequence text = getText(R.string.remote_service_started);
1766b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua
1776b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua        // The PendingIntent to launch our activity if the user selects this notification
1786b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua        PendingIntent contentIntent =
1796b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua                PendingIntent.getActivity(this, 0,
1806b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua                                          new Intent("android.bordeaux.DEBUG_CONTROLLER"), 0);
1816b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua
1826b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua       // // Set the info for the views that show in the notification panel.
1836b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua
1846b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua        Notification.Builder builder = new Notification.Builder(this);
1856b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua        builder.setSmallIcon(R.drawable.ic_bordeaux);
1866b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua        builder.setWhen(System.currentTimeMillis());
1876b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua        builder.setTicker(text);
1886b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua        builder.setContentTitle(text);
1896b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua        builder.setContentIntent(contentIntent);
1906b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua        Notification notification = builder.getNotification();
1916b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua        // Send the notification.
1926b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua        // We use a string id because it is a unique number.  We use it later to cancel.
193984e52f31d596840cfa51b1238e1c43d2e1918f8saberian        mNotificationManager.notify(R.string.remote_service_started, notification); */
1946b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua    }
1956b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua
1966b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua}
197