/* * Copyright (C) 2014 TU Darmstadt, Hessen, Germany. * Department of Computer Science Databases and Distributed Systems * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package de.tudarmstadt.dvs.myhealthassistant.myhealthhub.services.messagehandler; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map.Entry; import java.util.Set; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import android.app.Service; import android.content.BroadcastReceiver; import android.content.ContentValues; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.database.Cursor; import android.os.IBinder; import android.support.v4.content.LocalBroadcastManager; import android.util.Log; import de.tudarmstadt.dvs.myhealthassistant.myhealthhub.commontools.EventUtils; import de.tudarmstadt.dvs.myhealthassistant.myhealthhub.events.AbstractChannel; import de.tudarmstadt.dvs.myhealthassistant.myhealthhub.events.Event; import de.tudarmstadt.dvs.myhealthassistant.myhealthhub.events.localmanagement.EventTransformationRequest; import de.tudarmstadt.dvs.myhealthassistant.myhealthhub.events.localmanagement.EventTransformationResponse; import de.tudarmstadt.dvs.myhealthassistant.myhealthhub.events.management.Advertisement; import de.tudarmstadt.dvs.myhealthassistant.myhealthhub.events.management.Announcement; import de.tudarmstadt.dvs.myhealthassistant.myhealthhub.events.management.JSONDataExchange; import de.tudarmstadt.dvs.myhealthassistant.myhealthhub.events.management.ManagementEvent; import de.tudarmstadt.dvs.myhealthassistant.myhealthhub.events.management.StartProducer; import de.tudarmstadt.dvs.myhealthassistant.myhealthhub.events.management.StopProducer; import de.tudarmstadt.dvs.myhealthassistant.myhealthhub.events.management.Subscription; import de.tudarmstadt.dvs.myhealthassistant.myhealthhub.events.management.Unadvertisement; import de.tudarmstadt.dvs.myhealthassistant.myhealthhub.events.management.Unsubscription; import de.tudarmstadt.dvs.myhealthassistant.myhealthhub.events.notifications.NotificationEvent; import de.tudarmstadt.dvs.myhealthassistant.myhealthhub.events.sensorreadings.SensorReadingEvent; import de.tudarmstadt.dvs.myhealthassistant.myhealthhub.services.transformationmanager.database.LocalTransformationDB; import de.tudarmstadt.dvs.myhealthassistant.myhealthhub.services.transformationmanager.database.LocalTransformationDBMS; public class MessageHandler extends Service { /** For Debugging */ private static final String TAG = "MessageHandler"; private static boolean D = false; private static final String TAG_ANNOUNCEMENT = "Announcement MessageHandler"; private static boolean D_ANNOUNCEMENT = false; private static final String TAG_ROUTING = "MessageHandler Routing"; private static boolean D_ROUTING = true; DBAdapterSubscriptions db; // = new DBAdapterSubscriptions(this); private HashMap<String, List<String>> subscriberChannelHashMap; private HashMap<String, List<ProducerDetails>> advertisementHashMap; private HashMap<String, Integer> sensorConnectivityAnnouncement; private EventUtils evtUtils; private final IntentFilter sensorReadingsChannel = new IntentFilter(AbstractChannel.RECEIVER); private EventReceiver mEventReceiver; private ManagementReceiver mManagementReceiver; private final IntentFilter managementReceiverChannel = new IntentFilter(AbstractChannel.MANAGEMENT); private ResponseReceiver mResponseReceiver; private IntentFilter mResponseReceiverChannel = new IntentFilter(AbstractChannel.LOCAL_MANAGEMENT); private final IntentFilter notificationChannel = new IntentFilter(AbstractChannel.NOTIFICATION); private NotificationReceiver mNotificationReceiver; private class NotificationReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { final NotificationEvent evt = (NotificationEvent) intent .getParcelableExtra(Event.PARCELABLE_EXTRA_EVENT); // Create subject String tempSubject = "myHealthAssistant "; switch (evt.severity) { case NotificationEvent.SEVERITY_INFORMATION: tempSubject += "INFORMATION"; break; case NotificationEvent.SEVERITY_DEBUG: tempSubject += "DEBUG"; break; case NotificationEvent.SEVERITY_CRITICAL: tempSubject += "CRITICAL"; break; case NotificationEvent.SEVERITY_WARNING: tempSubject += "WARNING"; break; } tempSubject += ": " + evt.subject; final String subject = tempSubject; // Create body final String body = "(This is an auto-generated message from myHealthAssistant.)" + "\n\nMessage: " + evt.text+ "\n\nProcuder: "+evt.getProducerID(); // Send e-mail Thread thread = new Thread() { public void run() { try { // GMailSender sender = new GMailSender( // null, // null); // sender.sendMail(subject, body, // null, // null); } catch (Exception e) { Log.e("SendMail", e.getMessage(), e); } } }; thread.start(); } } /** Event Handler */ private class EventReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Event evt = intent.getParcelableExtra(Event.PARCELABLE_EXTRA_EVENT); if(D)Log.d(TAG, "Incoming event of type "+evt.getEventType()); String eventType = intent.getStringExtra(Event.PARCELABLE_EXTRA_EVENT_TYPE); // Discard null values for a String if(eventType==null){ Log.e(TAG, "eventType is null"); return; } // Parse event type into an event tree String[] eventTree = parseEventType(eventType); // Discard invalid events if(eventTree == null) { Log.e(TAG, "Invalid incoming event type: "+eventType); return; } // Skip if tree height is smaller than 2 if(eventTree.length<1) { Log.e(TAG, "Event tree too small. Event is not forwarded. "+eventType); return; } List<String> tempSubscriberForEventTypeList; String eventTypeKey = Event.EVENT_ROOT; //Check for each step in the eventTree if anyone is subscribed for(int i=0;i<eventTree.length;i++){ eventTypeKey=(eventTypeKey+"."+eventTree[i]); tempSubscriberForEventTypeList = subscriberChannelHashMap.get(eventTypeKey); if(tempSubscriberForEventTypeList!=null){ //set implicit intent.setAction(eventTypeKey); //Send to all subscribers for(int j=0;j<tempSubscriberForEventTypeList.size();j++){ String receiverPackage = tempSubscriberForEventTypeList.get(j); /*if(receiverPackage.equals(getPackageName())) { // send locally if(D)Log.i(TAG, "Send locally to package: "+receiverPackage); LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intent); //TODO intent.setPackage(tempSubscriberForEventTypeList.get(j)); getApplicationContext().sendBroadcast(intent); } else {*/ // globally if(D)Log.i(TAG, "Send globally to package: "+receiverPackage); //set explicit intent.setPackage(tempSubscriberForEventTypeList.get(j)); getApplicationContext().sendBroadcast(intent); //} } } } }; } /** Management Receiver */ private class ManagementReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if(intent == null)return; //Log.d(TAG, "Received EventTypeShort: "+getLastStringAfterDot(intent.getStringExtra(Event.PARCELABLE_EXTRA_EVENT_TYPE))); Event evt = intent.getParcelableExtra(Event.PARCELABLE_EXTRA_EVENT); //Checks the ManamgentEvent and notifies the sender about the invalid argument if(!isManagementEventValid(evt))return; // JSONDataExchange if (evt.getEventType().equals(ManagementEvent.JSON_DATA_EXCHANGE)){ Log.d(TAG, "JSON Data Exchange event from: "+ evt.getProducerID()); String eventProducerID = evt.getProducerID(); String eventProducersPackageName = ((JSONDataExchange)evt).getPackageName(); String dataExchangeEventType = ((JSONDataExchange)evt).getDataExchangeEventType(); // ProducerDetails producerDetails = new ProducerDetails(eventProducerID, eventProducersPackageName); String jsonDataString = ((JSONDataExchange)evt).getJSONEncodedData(); try { JSONObject jsonData = new JSONObject(jsonDataString); String json_request = jsonData.optString(JSONDataExchange.JSON_REQUEST, "null"); JSONArray jObjArray = jsonData.optJSONArray(JSONDataExchange.JSON_CONTENT_ARRAY); if (json_request.equalsIgnoreCase(JSONDataExchange.JSON_STORE) && jObjArray != null){ // save contents to db ArrayList<ContentValues> vArray = new ArrayList<ContentValues>(); for (int i = 0; i < jObjArray.length(); i++){ JSONObject jObj = jObjArray.optJSONObject(i); if (jObj != null){ String contents = jObj.toString(); String contentDate = jObj.optString(JSONDataExchange.JSON_DATE, "null"); String contentExtra = jObj.optString(JSONDataExchange.JSON_EXTRA, "null"); ContentValues value = new ContentValues(); value.put(LocalTransformationDB.COUMN_JSON_DATE, contentDate); value.put(LocalTransformationDB.COUMN_JSON_CONTENT, contents); value.put(LocalTransformationDB.COUMN_JSON_EXTRA, contentExtra); vArray.add(value); } } LocalTransformationDBMS transformationDB = new LocalTransformationDBMS(context); transformationDB.open(); transformationDB.storeJsonData(vArray); transformationDB.close(); } else if (json_request.equalsIgnoreCase(JSONDataExchange.JSON_GET)){ // send to eventProducer all data from db LocalTransformationDBMS transformationDB = new LocalTransformationDBMS(context); transformationDB.open(); JSONArray getJArray = transformationDB.getAlljsonData(); transformationDB.close(); JSONObject jEncodedData = new JSONObject(); jEncodedData.putOpt(JSONDataExchange.JSON_REQUEST, JSONDataExchange.JSON_GET); jEncodedData.putOpt(JSONDataExchange.JSON_CONTENT_ARRAY, getJArray); if (evtUtils != null){ JSONDataExchange eData = new JSONDataExchange( evtUtils.getEventID(), evtUtils.getTimestamp(), TAG, eventProducersPackageName, dataExchangeEventType, jEncodedData.toString()); sendToManagementChannel(eData, eventProducersPackageName); Log.e(TAG, "send EncodedData to " + eventProducersPackageName + "; ID:" + eventProducerID ); } else { Log.e(TAG, "cant send back jsonEncodedData to " + eventProducersPackageName + "; ID:" + eventProducerID ); } } else if (json_request.equalsIgnoreCase(JSONDataExchange.JSON_EDIT) && jObjArray != null){ // edit contents in db ArrayList<ContentValues> vArray = new ArrayList<ContentValues>(); int id = -1; for (int i = 0; i < jObjArray.length(); i++){ JSONObject jObj = jObjArray.optJSONObject(i); if (jObj != null){ id = jObj.optInt(JSONDataExchange.JSON_CONTENT_ID, -1); String contents = jObj.toString(); String contentDate = jObj.optString(JSONDataExchange.JSON_DATE, "null"); String contentExtra = jObj.optString(JSONDataExchange.JSON_EXTRA, "null"); ContentValues value = new ContentValues(); value.put(LocalTransformationDB.COUMN_JSON_DATE, contentDate); value.put(LocalTransformationDB.COUMN_JSON_CONTENT, contents); value.put(LocalTransformationDB.COUMN_JSON_EXTRA, contentExtra); vArray.add(value); } } LocalTransformationDBMS transformationDB = new LocalTransformationDBMS(context); transformationDB.open(); transformationDB.editJsonData(id, vArray.get(0)); // assume that only one jObj passed in transformationDB.close(); } else if (json_request.equalsIgnoreCase(JSONDataExchange.JSON_DEL) && jObjArray != null){ // delete contents in db int id = -1; for (int i = 0; i < jObjArray.length(); i++){ JSONObject jObj = jObjArray.optJSONObject(i); if (jObj != null){ id = jObj.optInt(JSONDataExchange.JSON_CONTENT_ID, -1); } } Log.e(TAG, "delet json:" + id); LocalTransformationDBMS transformationDB = new LocalTransformationDBMS(context); transformationDB.open(); transformationDB.deleteJsonData(id); transformationDB.close(); } } catch (JSONException e) { e.printStackTrace(); } } //Advertisement if(evt.getEventType().equals(ManagementEvent.ADVERTISEMENT)) { if(D)Log.d(TAG, "Advertisement event from "+evt.getProducerID()); String eventProducerID = evt.getProducerID(); String eventProducersPackageName = ((Advertisement)evt).getPackageName(); String advertisedEventType = ((Advertisement)evt).getAdvertisedEventType(); ProducerDetails producerDetails = new ProducerDetails(eventProducerID, eventProducersPackageName); //Get producers for the EventType List<ProducerDetails> tempProducerDetailsList = advertisementHashMap.get(advertisedEventType); // Check if anyone is already providing the event if (tempProducerDetailsList!=null) { //Check if producer is already in list for(int i=0;i<tempProducerDetailsList.size();i++){ if(tempProducerDetailsList.get(i).getProducerID().equals(eventProducerID)){ if(D)Log.d(TAG, "Producer already in List: "+eventProducerID); sendAnnouncement(Announcement.ADVERTSIMENT_UNSUCESSFULL_PRODUCER_ALREADY_IN_LIST, advertisedEventType, eventProducersPackageName); return; } } tempProducerDetailsList.add(producerDetails); if(D)Log.d(TAG, "Producer added to advertisementList: "+ eventProducerID); } else { // If no producer exists for EventType create a new entry List<ProducerDetails> producerList = new ArrayList<ProducerDetails>(); producerList.add(producerDetails); advertisementHashMap.put(advertisedEventType,producerList); if(D)Log.d(TAG, "New Entry in Producer HashMap: "+eventProducerID); } // Send a startEvent/StopEvent to the producer and a ManagementEvent to all subscribers List<String> subscribersListForEventType = getSubscribersListForEventType(advertisedEventType); if (subscribersListForEventType != null) { sendStartEvent(eventProducerID, advertisedEventType, eventProducersPackageName); sendAnnouncementToRecieverList(Announcement.ADVERTISMENT_NEW_EVENT_TYPE_AVAILABLE,advertisedEventType,subscribersListForEventType); } else { sendStopEvent(eventProducerID, advertisedEventType,eventProducersPackageName); } sendAnnouncement(Announcement.ADVERTISMENT_SUCCESSFULL, advertisedEventType, eventProducersPackageName); if(D_ROUTING)printAdvertisementsAndSubscriptions(); //Unadvertisement } else if(evt.getEventType().equals(ManagementEvent.UNADVERTISEMENT)) { String eventProducer = evt.getProducerID(); String packageName = ((Unadvertisement)evt).getPackageName(); String unadvertisedEventType = ((Unadvertisement)evt).getUnadvertisedEventType(); ProducerDetails producerDetails = new ProducerDetails(eventProducer, packageName); //Check if there are producers for EventType if(advertisementHashMap.containsKey(unadvertisedEventType)){ List<ProducerDetails> producerDetailsList = advertisementHashMap.get(unadvertisedEventType); for(int i=0;i<producerDetailsList.size();i++){ if(producerDetailsList.get(i).getProducerID().equals(producerDetails.getProducerID())){ producerDetailsList.remove(i); i--; if(D)Log.d(TAG,"Removed ProducerDetails: ProducerID: "+producerDetails.getProducerID() + " PackageNameShort "+getLastStringAfterDot(producerDetails.getProducerPackageName())); } } //If there are no more producer for the EventType remove from EventType advertismentHashMap and notify all subscribers if(producerDetailsList.isEmpty()){ advertisementHashMap.remove(unadvertisedEventType); //Notify all EventType subscribers List<String> receiverPackageNameList = getSubscribersListForEventType(unadvertisedEventType); if(receiverPackageNameList!=null){ sendAnnouncementToRecieverList(Announcement.UNADVERTISMENT_EVENT_TYPE_NOT_LONGER_AVAILABLE, unadvertisedEventType, receiverPackageNameList); } } sendAnnouncement(Announcement.UNADVERTISMENT_SUCCESSFULL, unadvertisedEventType, packageName); } if(D_ROUTING)printAdvertisementsAndSubscriptions(); //Subscription } else if(evt.getEventType().equals(ManagementEvent.SUBSCRIPITON)) { if(D)Log.d(TAG, "Subscription event from "+evt.getProducerID()); String subscribersPackageName = ((Subscription)evt).getPackageName(); String subscriptionSensorReadings = ((Subscription)evt).getSubscriptionSensorReadings(); // Check if an entry for the eventType already exists if (subscriberChannelHashMap.containsKey(subscriptionSensorReadings)) { List<String> tempSubscribersListForEventType = subscriberChannelHashMap.get(subscriptionSensorReadings); if (!tempSubscribersListForEventType.contains(subscribersPackageName)) { //Check all effected producers and send a StartEvent if no one is already subscribed to it subscriptionCheckWithAllAvailableEventsThatMatch(subscriptionSensorReadings); //Important: check before adding! tempSubscribersListForEventType.add(subscribersPackageName); if(D)Log.d(TAG,"Subscriber added to Entry in subscribersHashMap: EventTypeShort: "+getLastStringAfterDot(subscriptionSensorReadings)+", PackageNameShort: "+subscribersPackageName); } else { sendAnnouncement(Announcement.SUBSCRIPTOPN_SUBSCRIBER_ALREADY_IN_LIST, subscriptionSensorReadings, subscribersPackageName); return; } } else { // If no entry exists create a new one and send a StartEvent to the EventType producer List<String> receiverList = new ArrayList<String>(); receiverList.add(subscribersPackageName); //Check all effected producers and send a StartEvent if no one is already subscribed to it subscriptionCheckWithAllAvailableEventsThatMatch(subscriptionSensorReadings); //Important: check before adding! subscriberChannelHashMap.put(subscriptionSensorReadings, receiverList); if(D)Log.d(TAG,"Subscriber Package new Entry in subscribersHashMap: EventTypeShort: "+getLastStringAfterDot(subscriptionSensorReadings)+", PackageNameShort: "+subscribersPackageName); } sendAnnouncement(Announcement.SUBSCRIPTION_SUCCESSFULL,subscriptionSensorReadings, subscribersPackageName); // send sensor connectivity if(sensorConnectivityAnnouncement.containsKey(subscriptionSensorReadings)) sendAnnouncement(sensorConnectivityAnnouncement.get(subscriptionSensorReadings), subscriptionSensorReadings, subscribersPackageName); //Write Subscription into databases db.openWritabelDB(); db.insertOrReplaceRecord(evt.getEventType(), evt.getID(), evt.getTimestamp() /*evtUtils.getTimestamp()*/, evt.getProducerID(), subscribersPackageName, subscriptionSensorReadings); if(D)Log.d(TAG, "insertOrReplaceRecord("+evt.getEventType()+", "+evt.getID()+", "+evt.getTimestamp()+", "+evt.getProducerID()+", "+subscribersPackageName+", "+subscriptionSensorReadings+")"); db.close(); //If there are no EventProducers send a TransformationManagerRequest //TODO: Due to lack in restore DB - erwaehnen in der Bachelorthesis if(advertisementHashMap.get(subscriptionSensorReadings)==null){ sendEventTransformationRequest(subscriptionSensorReadings); if(D)Log.d(TAG,"sendTransfromtionRequest("+subscriptionSensorReadings+");"); } if(D_ROUTING)printAdvertisementsAndSubscriptions(); //Unsubscription } else if(evt.getEventType().equals(ManagementEvent.UNSUBSCRIPTION)) { if(D)Log.d(TAG, "Unsubscription event from "+evt.getProducerID()); String unsubscribersPackageName = ((Unsubscription)evt).getPackageName(); String unsubscriptionSensorReadings = ((Unsubscription)evt).getUnsubscriptionSensorReadings(); //Check if Event is already subscribed if(subscriberChannelHashMap.containsKey(unsubscriptionSensorReadings)){ List<String> tempList = subscriberChannelHashMap.get(unsubscriptionSensorReadings); if(tempList.contains(unsubscribersPackageName)){ //Check all effected producers and send a StartEvent if no one is already subscribed to it unsubscriptionCheckWithAllAvailableEventsThatMatch(unsubscriptionSensorReadings); //Important: Check before removing! tempList.remove(unsubscribersPackageName); if(D)Log.d(TAG,"Unsubscription successful: EventTypeShort: "+getLastStringAfterDot(unsubscriptionSensorReadings)+", PackageNameShort: "+getLastStringAfterDot(unsubscribersPackageName)); //Unsubscription successful write to database db.openWritabelDB(); db.insertOrReplaceRecord(evt.getEventType(), evt.getID(), evt.getTimestamp() /*evtUtils.getTimestamp() */, evt.getProducerID(), unsubscribersPackageName, unsubscriptionSensorReadings); if(D)Log.d(TAG, "insertRecord("+evt.getEventType()+", "+evt.getID()+", "+evt.getTimestamp()+", "+evt.getProducerID()+", "+unsubscribersPackageName+", "+unsubscriptionSensorReadings+")"); db.close(); } if(tempList.isEmpty()){ // delete key from HashMap if there are no more subscriptions for this EventType subscriberChannelHashMap.remove(unsubscriptionSensorReadings); if(D)Log.d(TAG,"No more Subscribers delte Entry in subscribersHashMap for EventTypeShort: "+getLastStringAfterDot(unsubscriptionSensorReadings)); } } if(D_ROUTING)printAdvertisementsAndSubscriptions(); //Announcement } else if(evt.getEventType().equals(ManagementEvent.ANNOUNCEMENT)){ int announcement = ((Announcement)evt).getAnnouncement(); String packageName = ((Announcement)evt).getPackageName(); String eventType = ((Announcement)evt).getTransmittedEventType(); String sender = ((Announcement)evt).getProducerID(); printAnnouncement(evt); switch (announcement) { case Announcement.SENSOR_CONNECTED: case Announcement.SENSOR_DISCONNECTED: // Distribute announcement via LocalBroadcastManager for SensorConfigurationActivity sendToManagementChannel(evt, getPackageName()); // Distribute announcement to subscribed consumers List<String> receiverPackageNameList = getSubscribersListForEventType(eventType); if(receiverPackageNameList!=null){ sendAnnouncementToRecieverList(announcement, eventType, receiverPackageNameList); } // store state for future subscriptions sensorConnectivityAnnouncement.put(eventType, announcement); if(D_ANNOUNCEMENT)Log.d(TAG,"Announcement Received: "+announcement+" from: "+sender); break; case Announcement.GET_ALL_AVAILABLE_EVENT_TYPES: sendAllAvailableEventTypes(packageName); if(D_ANNOUNCEMENT)Log.d(TAG,"Announcement Received: sendAllAvailableEventTypes from: "+sender); break; case Announcement.DATABASE_CLEAR_ALL: if(D_ANNOUNCEMENT)Log.d(TAG_ANNOUNCEMENT, "Announcement Received: DATABASE_CLEAR_ALL from: "+sender); db.openWritabelDB(); db.deleteAll(); db.close(); break; case Announcement.DATABASE_SHOW_WITH_ALL_SUBSCRIPTIONS_AND_UNSUBSCRIPTIONS: if(D_ANNOUNCEMENT)Log.d(TAG_ANNOUNCEMENT, "Announcement Received: DATABASE_SHOW_WITH_ALL_SUBSCRIPTIONS_AND_UNSUBSCRIPTIONS from: "+sender); db.openReadableDB(); Cursor c = db.getAllRecords(); if(c.moveToFirst()){ if(D_ANNOUNCEMENT)Log.d(TAG_ANNOUNCEMENT,"c.moveToFirst() == "+c.moveToFirst()); while(!c.isAfterLast()){ displayRecord(c); c.moveToNext(); } } db.close(); break; default: break; } } }; } /** * Sends an EventTransformationsRequest for the given event type and all available events. * @param requested event type */ public void sendEventTransformationRequest(String subscriptionSensorReadings) { String[] allAvailableEvents = getAllAvailableEvents(); // Create request EventTransformationRequest request = createRequestEvent(EventTransformationRequest.TYPE_REQUEST_TRANSFORMATION, allAvailableEvents, subscriptionSensorReadings); // Broadcast event locally Intent i = new Intent(); i.putExtra(Event.PARCELABLE_EXTRA_EVENT_TYPE, request.getEventType()); i.putExtra(Event.PARCELABLE_EXTRA_EVENT, request); i.setAction(AbstractChannel.LOCAL_MANAGEMENT); LocalBroadcastManager.getInstance(this).sendBroadcast(i); } /** * Sends all available event types from the advertisementHashMap as an announcement using the package names for explicit addressing. * @param packageName used to setPackageName(packageName) */ private void sendAllAvailableEventTypes(String packageName) { String[] availableEventTypes = getAllAvailableEvents(); Announcement announcement = new Announcement( evtUtils.getEventID(), evtUtils.getTimestamp(), TAG, "", getPackageName(), Announcement.ALL_AVAILABLE_EVENT_TYPES); Intent intent = new Intent(); intent.putExtra(Event.PARCELABLE_EXTRA_EVENT_TYPE, announcement.getEventType()); intent.putExtra(Event.PARCELABLE_EXTRA_EVENT, announcement); intent.putExtra(Event.PARCELABLE_EXTRA_AVAILABLE_EVENTS, availableEventTypes); if(D)Log.d(TAG,"availableEventTypes String[]"+availableEventTypes); //Implicit addressing intent.setAction(AbstractChannel.MANAGEMENT); //Explicit addressing intent.setPackage(packageName); getApplicationContext().sendBroadcast(intent); } /** * Sends a StopEvent to all producers who have exactly one subscriber now and will have zero after removing. * @param unsubscriptionSensorReadings event type that gets unsubscribed */ private void unsubscriptionCheckWithAllAvailableEventsThatMatch(String unsubscriptionSensorReadings) { String[] allAvailableEventTypes = getAllAvailableEvents(); List<String> matchUnsubscriptionAvailableEventTypes = new ArrayList<String>(); if(allAvailableEventTypes == null)return; //Get all availableEvents that start with channel subscription for(int i=0;i<allAvailableEventTypes.length;i++){ if(allAvailableEventTypes[i].startsWith(unsubscriptionSensorReadings)){ matchUnsubscriptionAvailableEventTypes.add(allAvailableEventTypes[i]); } } //Needs to check with each possible matching event, due to the tree structure and possibility to unsubscribe on a node or leaf //Send a StopEvent to all producers, who have exactly one subscribers yet and will have zero after removing for(int j=0;j<matchUnsubscriptionAvailableEventTypes.size();j++){ //StopEvent to all producers only if no other channel is subscribed on this EventType already if(getSubscribersListForEventType(matchUnsubscriptionAvailableEventTypes.get(j)).size() == 1){ sendStopEventToAllProducersForEventType(matchUnsubscriptionAvailableEventTypes.get(j)); } } } /** * Sends a StartEvent to all producers, who have zero subscriber now and will have one after removing. * @param subscriptionSensorReadings EventType that gets subscribed for */ private void subscriptionCheckWithAllAvailableEventsThatMatch(String subscriptionSensorReadings) { String[] allAvailableEventTypes = getAllAvailableEvents(); List<String> matchSubscriptionAvailableEventTypes = new ArrayList<String>(); if(allAvailableEventTypes==null)return; //Get all availableEvents that start with channel subscription for(int i=0;i<allAvailableEventTypes.length;i++){ if(allAvailableEventTypes[i].startsWith(subscriptionSensorReadings)){ matchSubscriptionAvailableEventTypes.add(allAvailableEventTypes[i]); } } //Needs to check with each possible event, due to the tree structure and possibility to subscribe on a node or leaf //Send a StartEvent to all producers, who have no subscribers yet and will have exactly 1 after subscription for(int j=0;j<matchSubscriptionAvailableEventTypes.size();j++){ //StartEvent to all producers only if no other channel is subscribed on this EventType already if(getSubscribersListForEventType(matchSubscriptionAvailableEventTypes.get(j)) == null){ sendStartEventToAllProducersForEventType(matchSubscriptionAvailableEventTypes.get(j)); } } } /** * Sends a StopEvent to all producers in the advertismentHashMap for the given event type. * @param eventType */ private void sendStopEventToAllProducersForEventType(String eventType) { List<ProducerDetails> producersDetailsList = advertisementHashMap.get(eventType); if(producersDetailsList==null)return; for(int i=0;i<producersDetailsList.size();i++){ sendStopEvent(producersDetailsList.get(i).getProducerID(), eventType, producersDetailsList.get(i).getProducerPackageName()); } } /** * Sends a StartEvent to all producers in the advertismentHashMap for the given event type * @param eventType */ private void sendStartEventToAllProducersForEventType(String eventType) { List<ProducerDetails> producersDetailsList = advertisementHashMap.get(eventType); if(producersDetailsList==null)return; for(int i=0;i<producersDetailsList.size();i++){ sendStartEvent(producersDetailsList.get(i).getProducerID(), eventType, producersDetailsList.get(i).getProducerPackageName()); } } /** * Different checks if the given Event is valid. Announcements are sent accordingly to the violation. * @param evt The Event that has to be checked * @return returns true if all checks are passed successful */ public boolean isManagementEventValid(Event evt) { String packageName = null; String transmittedEventType =null; //discard invalid EventTypes if(evt.getEventType()== null)return false; //Advertisement if(evt.getEventType().equals(ManagementEvent.JSON_DATA_EXCHANGE)){ packageName = ((JSONDataExchange)evt).getPackageName(); transmittedEventType = ((JSONDataExchange)evt).getDataExchangeEventType(); String json = ((JSONDataExchange)evt).getJSONEncodedData(); if(json==null){ sendAnnouncement(Announcement.INVALID_EVENT_TYPE_ARGUMENTS, transmittedEventType, packageName); return false; } } //Advertisement if(evt.getEventType().equals(ManagementEvent.ADVERTISEMENT)){ packageName = ((Advertisement)evt).getPackageName(); transmittedEventType = ((Advertisement)evt).getAdvertisedEventType(); String json = ((Advertisement)evt).getJSONEncodedProperties(); if(json==null){ sendAnnouncement(Announcement.INVALID_EVENT_TYPE_ARGUMENTS, transmittedEventType, packageName); return false; } //Unadvertisement }else if(evt.getEventType().equals(ManagementEvent.UNADVERTISEMENT)){ packageName = ((Unadvertisement)evt).getPackageName(); transmittedEventType = ((Unadvertisement)evt).getUnadvertisedEventType(); //Subscription }else if(evt.getEventType().equals(ManagementEvent.SUBSCRIPITON)){ packageName = ((Subscription)evt).getPackageName(); transmittedEventType = ((Subscription)evt).getSubscriptionSensorReadings(); /* //Check if application(packageName) has permission to subscribe to this EventType if(!securityManager.hasPermission(packageName, transmittedEventType)){ sendAnnouncement(ManagementEvent.SUBSCRIPTION_UNSUCCESSFULL_NO_PERMISSION, transmittedEventType, packageName); return false; } */ //Unsubscription }else if(evt.getEventType().equals(ManagementEvent.UNSUBSCRIPTION)){ packageName = ((Unsubscription)evt).getPackageName(); transmittedEventType = ((Unsubscription)evt).getUnsubscriptionSensorReadings(); //Announcement }else if(evt.getEventType().equals(ManagementEvent.ANNOUNCEMENT)){ packageName = ((Announcement)evt).getPackageName(); //none transmitted, set to valid value to support the testing scheme transmittedEventType = Event.EVENT_ROOT; } // If any Event variables are null if(evt.getID() == null || evt.getProducerID() == null || evt.getTimestamp()==null){ Log.w(TAG,"Error at least one Event argument is null"); sendAnnouncement(Announcement.INVALID_EVENT_TYPE_ARGUMENTS, transmittedEventType, packageName); return false; } //If EventType does not follow conventions if(!doesEventTypeMatchConventions(transmittedEventType)){ Log.w(TAG,"Error EVENT_TYPE_DOES_NOT_MATCH_NAME_CONVENTION"); sendAnnouncement(Announcement.EVENT_TYPE_DOES_NOT_MATCH_NAME_CONVENTION, transmittedEventType, packageName); return false; } //Check if application(packageName) is installed on device if(!isPackageInstalled(packageName)){ //Probably not useful to send this announcement Log.w(TAG, "PackageName invalid:"+packageName); sendAnnouncement(Announcement.MANAGEMENTEVENT_UNSUCCESSFULL_APPLICATION_NOT_INSTALLED, transmittedEventType, packageName); return false; } return true; } /** * Check if the event type matches event type conventions * @param eventType * @return returns true if check is passed */ public boolean doesEventTypeMatchConventions(String eventType){ if(eventType == null)return false; if(eventType.startsWith(Event.EVENT_ROOT))return true; return false; } /** * Sends an announcement event to the given announcement receiver package name ManagementReceiver * @param typeOfAnnouncement Types defined in ManagmentEvent.STRING * @param transmittedEventType * @param announcementReceiverPackageName Used for explicit addressing - setPackageName(packageName) */ private void sendAnnouncement(int typeOfAnnouncement, String transmittedEventType, String announcementReceiverPackageName){ //if no packageName is set do not send an announcement if(announcementReceiverPackageName==null) return; Announcement announcement = new Announcement( evtUtils.getEventID(), evtUtils.getTimestamp(), TAG, transmittedEventType, announcementReceiverPackageName, typeOfAnnouncement); sendToManagementChannel(announcement, announcementReceiverPackageName); /*Intent intent = new Intent(); intent.putExtra(Event.PARCELABLE_EXTRA_EVENT_TYPE, announcement.getEventType()); intent.putExtra(Event.PARCELABLE_EXTRA_EVENT, announcement); //Implicit addressing intent.setAction(ReadingChannels.MANAGEMENT); //Explicit addressing printAnnouncement(announcement); intent.setPackage(announcementReceiverPackageName); getApplicationContext().sendBroadcast(intent);*/ } /** * Sends announcements events to the given receiver package names list * @param typeOfAnnouncement Types defined in ManagmentEvent.STRING * @param eventType * @param listOfRecievers List of receiver package names used to explicit address ManagementReceivers */ private void sendAnnouncementToRecieverList(int typeOfAnnouncement, String eventType, List<String> listOfRecievers){ for(int i=0;i<listOfRecievers.size();i++){ sendAnnouncement(typeOfAnnouncement, eventType, listOfRecievers.get(i)); } } /** * Sends a start event to the given package names ManagementReceiver * @param eventProducerID * @param startEventType * @param packageName Receivers package name used to explicit address ManagementReceivers */ private void sendStartEvent(String eventProducerID, String startEventType, String packageName){ StartProducer startEvent = new StartProducer( evtUtils.getEventID(), evtUtils.getTimestamp(), TAG, eventProducerID, startEventType); sendToManagementChannel(startEvent, packageName); Log.i(TAG, "StartProducer Sensor: "+eventProducerID+", EventTypeShort: "+getLastStringAfterDot(startEventType)+", PackageNameShort: "+getLastStringAfterDot(packageName)); } /** * Sends a StopEvent to the given package names ManagementReceiver * @param eventProducerID * @param stopEventType * @param packageName Receivers package name used to explicit address ManagementReceiver */ private void sendStopEvent(String eventProducerID, String stopEventType, String packageName){ StopProducer stopEvent = new StopProducer( evtUtils.getEventID(), evtUtils.getTimestamp(), TAG, eventProducerID, stopEventType); sendToManagementChannel(stopEvent, packageName); Log.i(TAG, "StopProducer Sensor: "+eventProducerID+", EventTypeShort: "+getLastStringAfterDot(stopEventType)+", PackageNameShort: "+getLastStringAfterDot(packageName)); } /** * Sends an event to the local or global management channel depending on * the packageName. If the packageName equals the myHealthHub package name, * the event is send locally. * @param event that needs to be send * @param packageName of the receiver */ private void sendToManagementChannel(Event evt, String packageName) { Intent intent = new Intent(); intent.putExtra(Event.PARCELABLE_EXTRA_EVENT_TYPE, evt.getEventType()); intent.putExtra(Event.PARCELABLE_EXTRA_EVENT, evt); // use local management channel for internal sensor modules if(packageName.equals(getPackageName())) { if(D)Log.d(TAG, "Sending on local management channel:"+evt.getEventType()); intent.setAction(AbstractChannel.LOCAL_MANAGEMENT); LocalBroadcastManager.getInstance(this).sendBroadcast(intent); // use global management channel for external sensor modules (i.e. other applications) } else { if(D)Log.d(TAG, "Sending on global management channel:"+evt.getEventType()); //Implicit addressing intent.setAction(AbstractChannel.MANAGEMENT); //Explicit addressing intent.setPackage(packageName); getApplicationContext().sendBroadcast(intent); } } /** * Creates a EventTransformationRequest * @param requestType * @param advertisedEvents * @param eventSubscription * @return EventTransformationRequest */ private EventTransformationRequest createRequestEvent(int requestType, String[] advertisedEvents, String eventSubscription) { return new EventTransformationRequest( evtUtils.getEventID(), evtUtils.getTimestamp(), TAG, requestType, advertisedEvents, eventSubscription); } /** * Get all available events from the advertismentHashMap * @return String[] containing all available event types */ public String[] getAllAvailableEvents(){ //Android documentation: The set does not support adding Set<String> availableEvents = advertisementHashMap.keySet(); if(availableEvents==null)return null; String[] events = availableEvents.toArray(new String[availableEvents.size()]); for(int i=0;i<events.length;i++){ if(D||D_ROUTING)Log.d(TAG,"String["+i+"] = Value: "+events[i]); } return events; } /** * Checks the subscribers permission for the channel/event type with a list of allowed subscribers for the channel/event type * @param eventType * @param allowedSubscribersPackageNamesList */ public void checkPermissionsForEventType(String eventType, List<String> allowedSubscribersPackageNamesList){ List<String> subscribersPackageNames = subscriberChannelHashMap.get(eventType); List<String> toBeUnsubscribedPackageNamesList = new ArrayList<String>(); //If there are subscribers verify them with allowedSubscribersPackageNamesList if(subscribersPackageNames!=null){ for(int i=0;i<subscribersPackageNames.size();i++){ //Check if subscriber still has the permission if(allowedSubscribersPackageNamesList.contains(subscribersPackageNames.get(i))){ if(D)Log.d(TAG,"Permission verified successfull" + subscribersPackageNames.get(i)); }else{ if(D)Log.d(TAG,"Permission not verified - unsubscribe" + subscribersPackageNames.get(i)); sendAnnouncement(Announcement.SECURITY_PERMISSION_REMOVED, eventType, subscribersPackageNames.get(i)); toBeUnsubscribedPackageNamesList.add(subscribersPackageNames.get(i)); } } } sendUnsubscriptionsForAllInvalidSubscribers(eventType, toBeUnsubscribedPackageNamesList); } /** * Sends an Unsubscription event for all subscribers package names in the list * @param eventType * @param toBeUnsubscribedPackageNamesList Package names to be removed from the subscribersHashMap */ private void sendUnsubscriptionsForAllInvalidSubscribers(String eventType, List<String> toBeUnsubscribedPackageNamesList) { for(int i=0;i<toBeUnsubscribedPackageNamesList.size();i++){ sendUnsubscription(eventType, toBeUnsubscribedPackageNamesList.get(i)); } } /** * Sends an Unsubscription event to the subscribers package name for the given event type * @param eventType * @param toBeUnsubscribedPackageName */ private void sendUnsubscription(String eventType, String toBeUnsubscribedPackageName){ Unsubscription unsubcribe = new Unsubscription(evtUtils.getEventID(), evtUtils.getTimestamp(), TAG, toBeUnsubscribedPackageName, eventType); Intent intent = new Intent(); intent.putExtra(Event.PARCELABLE_EXTRA_EVENT_TYPE, unsubcribe.getEventType()); intent.putExtra(Event.PARCELABLE_EXTRA_EVENT, unsubcribe); intent.setAction(AbstractChannel.MANAGEMENT); sendBroadcast(intent); } /** * Parses event type filed and returns String array representing * the tree structure of the event type. myHealhAssistant prefix * is removed. * @param EVENT_TYPE Event type. * @return String[] including event tree. */ private String[] parseEventType(String eventType) { // Return null if not myHealthAssistant prefix if(!eventType.startsWith(Event.EVENT_ROOT)) return null; // Remove prefix eventType = eventType.substring(Event.EVENT_ROOT.length()+1, eventType.length()); // Store fields into String array String[] eventTree = eventType.split("\\."); return eventTree; } /** * Get all subscribers (for each step in the event tree) for the event type, according to the tree structure and the possibility to subscribe to a node or leaf * * @return: a list of package names or null if there are no receivers */ private List<String> getSubscribersListForEventType(String eventType){ // Parse event type into an event tree String[] eventTree = parseEventType(eventType); // Discard invalid events if(eventTree == null) { Log.e(TAG, "Invalid incoming event type: "+eventType); return null; } List<String> listOfReceivers = new ArrayList<String>(); List<String> tempSubscriberList; String channelName = Event.EVENT_ROOT; //Build a list of receivers referring to the event tree subscriptions for(int i=0;i<eventTree.length;i++){ channelName=(channelName+"."+eventTree[i]); //Log.d(TAG,"Search key for HashMap: "+channelName); tempSubscriberList = subscriberChannelHashMap.get(channelName); if(tempSubscriberList!=null){ //Log.d(TAG,"Length HashMap result: "+tempSubscriberList.size()); listOfReceivers.addAll(tempSubscriberList); } } if(listOfReceivers.size()!=0){ return listOfReceivers; } return null; } /** * Verifies if the package is installed using the PackageManager and the given package name * @param packageName * @return Returns true if package is installed */ public boolean isPackageInstalled(String packageName) { if(packageName==null)return false; PackageManager pm = getPackageManager(); try { PackageInfo info = pm.getPackageInfo(packageName, PackageManager.GET_META_DATA); } catch (NameNotFoundException e) { return false; } return true; } /** * SecurityManager: quick and dirty implementation for testing only */ private class SecurityManager{ private HashMap<String, List<String>> permissionHashMap; private List<String> listOfPermissionApplication01 = new ArrayList<String>(); private List<String> listOfPermissionApplication02 = new ArrayList<String>(); public SecurityManager(){ permissionHashMap = new HashMap<String, List<String>>(); listOfPermissionApplication01.add(SensorReadingEvent.READING_EVENT); listOfPermissionApplication01.add(SensorReadingEvent.ACCELEROMETER); listOfPermissionApplication02.add(SensorReadingEvent.HEART_RATE); permissionHashMap.put("com.example.myhealthhubsetpackage.application01", listOfPermissionApplication01); permissionHashMap.put("com.example.myhealthhubsetpackage.application02", listOfPermissionApplication02); } /** * Checks if a application has permission to subscribe on channel */ private boolean hasPermission(String packageName, String channel){ List<String> tempList = new ArrayList<String>(); tempList = permissionHashMap.get(packageName); if(tempList!= null){ if(tempList.contains(channel)){ if(D)Log.d(TAG,"True: Permission is avaiable: "+channel); return true; } } if(D)Log.d(TAG,"False: Permission is avaiable: "+channel); return false; } } /** EventTransformation event receiver */ public class ResponseReceiver extends BroadcastReceiver{ @Override public void onReceive(Context context, Intent intent) { // Skip if not a event transformation response if(!intent.getStringExtra(Event.PARCELABLE_EXTRA_EVENT_TYPE).equals(EventTransformationResponse.EVENT_TYPE)) return; // Get and print event EventTransformationResponse response = intent.getParcelableExtra(Event.PARCELABLE_EXTRA_EVENT); if(D)Log.d(TAG, "Got result "+response.isTransformationFound()+" for request ID: "+response.getID()+"."); } } /** * Returns the last String separated by "." * @param name * @return Returns last String separated by "." */ private String getLastStringAfterDot(String name){ if(name.contains(".") && name.length()>=3){ String[] nameSplit = name.split("\\."); return nameSplit[nameSplit.length-1]; } return "Error String does not contain '.' or is to short)"; } /** * Used for connecting a producerID with a package name to explicit address the producer * @author Jens * */ private class ProducerDetails{ private String ProducerID; private String ProducerPackageName; public ProducerDetails(String producerID, String producerPackageName){ ProducerID = producerID; ProducerPackageName = producerPackageName; } public String getProducerID() { return ProducerID; } public void setProducerID(String producerID) { ProducerID = producerID; } public String getProducerPackageName() { return ProducerPackageName; } public void setProducerPackageName(String producerPackageName) { ProducerPackageName = producerPackageName; } } @Override public void onCreate() { Log.i(TAG, getPackageName()); // Initialize event RECEIVER mEventReceiver = new EventReceiver(); getApplication().registerReceiver(mEventReceiver, sensorReadingsChannel); LocalBroadcastManager.getInstance(this).registerReceiver(mEventReceiver, sensorReadingsChannel); // Notification Receiver mNotificationReceiver = new NotificationReceiver(); getApplication().registerReceiver(mNotificationReceiver, notificationChannel); // Management Receiver mManagementReceiver = new ManagementReceiver(); getApplication().registerReceiver(mManagementReceiver, managementReceiverChannel); LocalBroadcastManager.getInstance(this).registerReceiver(mManagementReceiver, managementReceiverChannel); mResponseReceiver = new ResponseReceiver(); LocalBroadcastManager.getInstance(this).registerReceiver(mResponseReceiver, mResponseReceiverChannel); subscriberChannelHashMap = new HashMap<String, List<String>>(); advertisementHashMap = new HashMap<String, List<ProducerDetails>>(); sensorConnectivityAnnouncement = new HashMap<String, Integer>(); //securityManager = new SecurityManager(); evtUtils = new EventUtils(NotificationEvent.EVENT_TYPE, TAG); //mTransformationManager = new TransformationManager(this, AbstractChannel.LOCAL_MANAGEMENT); db = new DBAdapterSubscriptions(this); restoreSubscriptionsFromDB(); } /** * Starts to restore the subscriberHashMap from a database */ private void restoreSubscriptionsFromDB() { Log.i(TAG,"Restore Subscriptions From DB"); db.openReadableDB(); Cursor c = db.getAllRecords(); if(c.moveToFirst()){ while(!c.isAfterLast()){ sendSubscription(c); c.moveToNext(); } } db.close(); printAdvertisementsAndSubscriptions(); } /** * Creates Subscriptions * @param c Cursor fetched from database with the necessary information to create a Subscription */ private void sendSubscription(Cursor c) { String eventType = c.getString(1); String eventID = c.getString(2); String timeStamp = c.getString(3); String producerID = c.getString(4); String packageName = c.getString(5); String subscribedEventType = c.getString(6); Intent intent = new Intent(); if(eventType.equals(ManagementEvent.SUBSCRIPITON)){ Subscription subscribe = new Subscription(eventID, timeStamp, producerID, packageName, subscribedEventType); intent.putExtra(Event.PARCELABLE_EXTRA_EVENT_TYPE, subscribe.getEventType()); intent.putExtra(Event.PARCELABLE_EXTRA_EVENT, subscribe); if(D_ANNOUNCEMENT)Log.d(TAG_ANNOUNCEMENT, "Subscription sent: "+producerID+", packageNameShort: "+getLastStringAfterDot(packageName)+", subscribedEventTypeShort: "+getLastStringAfterDot(subscribedEventType)); intent.setAction(AbstractChannel.MANAGEMENT); intent.setPackage(getPackageName()); sendBroadcast(intent); } //No need to send Unsubscription else if(eventType.equals(ManagementEvent.UNSUBSCRIPTION)){ Unsubscription unsubscribe = new Unsubscription(eventID, timeStamp, producerID, packageName, subscribedEventType); //intent.putExtra(Event.PARCELABLE_EXTRA_EVENT_TYPE, unsubscribe.getEventType()); //intent.putExtra(Event.PARCELABLE_EXTRA_EVENT, unsubscribe); if(D_ANNOUNCEMENT)Log.d(TAG_ANNOUNCEMENT, "Unsubscription restored but not sent: "+producerID+", packageNameShort: "+getLastStringAfterDot(packageName)+", subscribedEventTypeShort: "+getLastStringAfterDot(subscribedEventType)); } } @Override public IBinder onBind(Intent intent) { Log.d(TAG, "onBind(): entered..."); return null; } public void onUnbind() { if(D)Log.d(TAG, "onUnbind(): entered..."); } public void onDestroy() { if(D)Log.d(TAG, "onDestroy() entered..."); getApplication().unregisterReceiver(mEventReceiver); getApplication().unregisterReceiver(mNotificationReceiver); } //TODO: Can be removed after testing /** * Prints an announcement to LogCat using TAG_ANNOUNCEMENT * @param evt */ public void printAnnouncement(Event evt) { int announcement = ((Announcement)evt).getAnnouncement(); String packageName = ((Announcement)evt).getPackageName(); String eventType = ((Announcement)evt).getTransmittedEventType(); String sender = ((Announcement)evt).getProducerID(); if(D_ANNOUNCEMENT)Log.d(TAG_ANNOUNCEMENT, "Announcement Details: "+sender+", AnnouncementType: "+announcement+", PackageNameShort: "+getLastStringAfterDot(packageName)+", EventTypeShort: "+getLastStringAfterDot(eventType)); } /** * Prints an database entry to LogCat using TAG_ANNOUNCEMENT * @param c */ private void displayRecord(Cursor c) { Log.d(TAG,"DisplayRecord: "); Log.d(TAG, ""+DBAdapterSubscriptions.KEY_ROWID+" : "+c.getString(0)+"\n" +DBAdapterSubscriptions.KEY_EVENT_TYPE+" : "+c.getString(1)+"\n" +DBAdapterSubscriptions.KEY_EVENT_ID+" : "+c.getString(2)+"\n" +DBAdapterSubscriptions.KEY_TIMESTAMP+" : "+c.getString(3)+"\n" +DBAdapterSubscriptions.KEY_PRODUCER_ID+" : "+c.getString(4)+"\n" +DBAdapterSubscriptions.KEY_PACKAGE_NAME+" : "+c.getString(5)+"\n" +DBAdapterSubscriptions.KEY_READING_EVENT_TYPE+" : "+c.getString(6)+"\n" ); } /** * Prints lists of advertised and subscribed events. */ private void printAdvertisementsAndSubscriptions() { Log.d(TAG_ROUTING, "--\nList of Advertisements:"); Log.d(TAG_ROUTING, "======================="); getAllAvailableEvents(); Log.d(TAG_ROUTING, "\nList of Subscriptions:"); Log.d(TAG_ROUTING, "======================"); String output = ""; Iterator<Entry<String, List<String>>> it = subscriberChannelHashMap.entrySet().iterator(); while(it.hasNext()) { Entry<String, List<String>> e = it.next(); output += e.getKey() +"\t | "; for(String channel : e.getValue()) { output += channel + ", "; } output += "\n"; } Log.d(TAG_ROUTING, output+"\n--"); } }