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