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(); 78f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Lin mLocationStatsAggregator = new LocationStatsAggregator(this); 79984e52f31d596840cfa51b1238e1c43d2e1918f8saberian mTimeStatsAggregator = new TimeStatsAggregator(); 80984e52f31d596840cfa51b1238e1c43d2e1918f8saberian mAggregatorManager = AggregatorManager.getInstance(); 81984e52f31d596840cfa51b1238e1c43d2e1918f8saberian mAggregatorManager.registerAggregator(mMotionStatsAggregator, mAggregatorManager); 82984e52f31d596840cfa51b1238e1c43d2e1918f8saberian mAggregatorManager.registerAggregator(mLocationStatsAggregator, mAggregatorManager); 83984e52f31d596840cfa51b1238e1c43d2e1918f8saberian mAggregatorManager.registerAggregator(mTimeStatsAggregator, mAggregatorManager); 846b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua 856b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua // Display a notification about us starting. 866b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua // TODO: don't display the notification after the service is 876b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua // automatically started by the system, currently it's useful for 886b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua // debugging. 896b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua showNotification(); 906b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua } 916b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua 926b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua @Override 936b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua public void onDestroy() { 941dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua // Save the sessions 951dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua mSessionManager.saveSessions(); 961dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua 976b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua // Cancel the persistent notification. 98984e52f31d596840cfa51b1238e1c43d2e1918f8saberian //mNotificationManager.cancel(R.string.remote_service_started); 996b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua 1006b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua // Tell the user we stopped. 101984e52f31d596840cfa51b1238e1c43d2e1918f8saberian //Toast.makeText(this, R.string.remote_service_stopped, Toast.LENGTH_SHORT).show(); 1026b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua 1036b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua // Unregister all callbacks. 1046b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua mCallbacks.kill(); 1051dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua 10647c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin mLocationStatsAggregator.release(); 10747c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin 1081dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua Log.i(TAG, "Bordeaux service stopped."); 1096b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua } 1106b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua 1116b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua @Override 1126b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua public IBinder onBind(Intent intent) { 1136b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua // Return the requested interface. 1146b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua if (IBordeauxService.class.getName().equals(intent.getAction())) { 1156b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua return mBinder; 1166b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua } 1176b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua return null; 1186b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua } 1196b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua 1201dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua 1216b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua // The main interface implemented by the service. 1226b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua private final IBordeauxService.Stub mBinder = new IBordeauxService.Stub() { 1231dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua private IBinder getLearningSession(Class learnerClass, String name) { 1246b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua PackageManager pm = getPackageManager(); 1256b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua String uidname = pm.getNameForUid(getCallingUid()); 1266b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua Log.i(TAG,"Name for uid: " + uidname); 1271dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua BordeauxSessionManager.SessionKey key = 1281dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua mSessionManager.getSessionKey(uidname, learnerClass, name); 1291dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua Log.i(TAG, "request learning session: " + key.value); 1301dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua try { 1311dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua IBinder iLearner = mSessionManager.getSessionBinder(learnerClass, key); 1321dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua return iLearner; 1331dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua } catch (RuntimeException e) { 1341dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua Log.e(TAG, "Error getting learning interface" + e); 1351dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua return null; 1366b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua } 1371dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua } 1381dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua 1391dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua public IBinder getClassifier(String name) { 1401dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua return getLearningSession(Learning_MulticlassPA.class, name); 1416b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua } 1426b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua 1436b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua public IBinder getRanker(String name) { 1441dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua return getLearningSession(Learning_StochasticLinearRanker.class, name); 1456b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua } 1466b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua 147984e52f31d596840cfa51b1238e1c43d2e1918f8saberian public IBinder getPredictor(String name) { 148984e52f31d596840cfa51b1238e1c43d2e1918f8saberian return getLearningSession(Predictor.class, name); 149984e52f31d596840cfa51b1238e1c43d2e1918f8saberian } 150984e52f31d596840cfa51b1238e1c43d2e1918f8saberian 151984e52f31d596840cfa51b1238e1c43d2e1918f8saberian public IBinder getAggregatorManager() { 152984e52f31d596840cfa51b1238e1c43d2e1918f8saberian return (IBinder) mAggregatorManager; 153984e52f31d596840cfa51b1238e1c43d2e1918f8saberian } 154984e52f31d596840cfa51b1238e1c43d2e1918f8saberian 1556b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua public void registerCallback(IBordeauxServiceCallback cb) { 1566b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua if (cb != null) mCallbacks.register(cb); 1576b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua } 1586b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua 1596b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua public void unregisterCallback(IBordeauxServiceCallback cb) { 1606b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua if (cb != null) mCallbacks.unregister(cb); 1616b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua } 1626b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua }; 1636b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua 1646b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua @Override 1656b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua public void onTaskRemoved(Intent rootIntent) { 1666b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua Toast.makeText(this, "Task removed: " + rootIntent, Toast.LENGTH_LONG).show(); 1676b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua } 1686b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua 1696b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua /** 1706b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua * Show a notification while this service is running. 1716b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua * TODO: remove the code after production (when service is loaded 1726b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua * automatically by the system). 1736b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua */ 1746b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua private void showNotification() { 175984e52f31d596840cfa51b1238e1c43d2e1918f8saberian /*// In this sample, we'll use the same text for the ticker and the expanded notification 1766b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua CharSequence text = getText(R.string.remote_service_started); 1776b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua 1786b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua // The PendingIntent to launch our activity if the user selects this notification 1796b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua PendingIntent contentIntent = 1806b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua PendingIntent.getActivity(this, 0, 1816b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua new Intent("android.bordeaux.DEBUG_CONTROLLER"), 0); 1826b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua 1836b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua // // Set the info for the views that show in the notification panel. 1846b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua 1856b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua Notification.Builder builder = new Notification.Builder(this); 1866b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua builder.setSmallIcon(R.drawable.ic_bordeaux); 1876b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua builder.setWhen(System.currentTimeMillis()); 1886b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua builder.setTicker(text); 1896b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua builder.setContentTitle(text); 1906b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua builder.setContentIntent(contentIntent); 1916b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua Notification notification = builder.getNotification(); 1926b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua // Send the notification. 1936b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua // We use a string id because it is a unique number. We use it later to cancel. 194984e52f31d596840cfa51b1238e1c43d2e1918f8saberian mNotificationManager.notify(R.string.remote_service_started, notification); */ 1956b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua } 1966b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua 1976b4eebc73439cbc3ddfb547444a341d1f9be7996Wei Hua} 198